Go Back   EcoModder Forum > EcoModding > Instrumentation > OpenGauge / MPGuino FE computer
Register Now
 Register Now
 

Reply  Post New Thread
 
Submit Tools LinkBack Thread Tools
Old 04-03-2008, 08:07 PM   #1 (permalink)
dcb
needs more cowbell
 
dcb's Avatar
 
Join Date: Feb 2008
Location:
Posts: 5,032

pimp mobile - '81 suzuki gs 250 t
90 day: 96.29 mpg (US)

schnitzel - '01 Volkswagen Golf TDI
90 day: 53.56 mpg (US)
Thanks: 156
Thanked 264 Times in 207 Posts
Opengauge/MPGuino development: Freeduino signal processing

Here is what I put together to simulate a working signal processor. It *SHOULD* be possible to hook your soundcard output to the freeduino and come up with similiar readings. Hope HEX is ok, should be quicker than decimal, but I can live with decimal too.

Code:
//program to send dummy data over the serial port for prototyping the gui(s).
void setup() 
{ 
  Serial.begin(9600); 
} 
 
int number = 0; // dummy injector high and low values parsed from http://planetchampions.org/diympggauge/i1.wav
unsigned long injHiMS[]={69002,117777,101972,138435,148117,174988,98775,164693,165873,176190,113628,148571,120702,58276,39501,37891,38435,37369,37006,37142,39433,62879,71179,71995,77074,95215,86281,75419};
unsigned long injCount[]={37,40,34,51,37,43,48,50,42,46,49,38,37,39,38,37,37,36,34,33,32,32,31,32,31,32,32,33};
unsigned long vssCount[]={0,2,6,10,13,15,18,20,22,25,25,27,28,29,28,28,28,26,26,25,24,23,24,23,24,24,24,24};
 
void loop() 
{ 
  Serial.print(injHiMS[number], HEX);    
  Serial.print(","); 
  Serial.print(injCount[number], HEX);    
  Serial.print(","); 
  Serial.println(vssCount[number], HEX);    
 
  if(number == 27) { 
    // loop forever 
    while(true) { 
      continue; 
    } 
  } 
  number++; 
  delay(1000); 
}
Here is the output from the Arduino monitor serial port function in the ide (one line prints out a second):
10D8A,25,0
1CC11,28,2
18E54,22,6
21CC3,33,A
24295,25,D
2AB8C,2B,F
181D7,30,12
28355,32,14
287F1,2A,16
2B03E,2E,19
1BBDC,31,19
2445B,26,1B
1D77E,25,1C
E3A4,27,1D
9A4D,26,1C
9403,25,1C
9623,25,1C
91F9,24,1A
908E,22,1A
9116,21,19
9A09,20,18
F59F,20,17
1160B,1F,18
1193B,20,17
12D12,1F,18
173EF,20,18
15109,20,18
1269B,21,18

__________________
WINDMILLS DO NOT WORK THAT WAY!!!
  Reply With Quote
Alt Today
Popular topics

Other popular topics in this forum...

   
Old 04-04-2008, 07:28 AM   #2 (permalink)
dcb
needs more cowbell
 
dcb's Avatar
 
Join Date: Feb 2008
Location:
Posts: 5,032

pimp mobile - '81 suzuki gs 250 t
90 day: 96.29 mpg (US)

schnitzel - '01 Volkswagen Golf TDI
90 day: 53.56 mpg (US)
Thanks: 156
Thanked 264 Times in 207 Posts
Quote:
Originally Posted by s2man View Post
I thought we were sending three values from the controller: 1) VSS pulse count per second (or other interval). 2) Injector pulse count per second. 3) Injector pulse width. Which cycles are you referring to?
Three is probably good enough and what I have the dummy signal generator doing above. The other value was the elapsed time according to the freeduino, but in thinking about it we probably don't need it.

Quote:
Originally Posted by s2man View Post
data will be sent as characters, one byte each, via serial communication.
Can we use the above output format?

Quote:
Originally Posted by s2man View Post
Gathering these data will use all of three our timer/counters.
Is there a way to just use one timer to figure out when a second has passed? Coyote mentioned that an interrupt could be made to occur when the injector goes hi and again when low, so it should be a matter or recording the "current time" on the injectorHI interrupt and subtracting it from the "current time" on the injectorLO interrupt and adding it to this seconds totals. I.e. borrow the code from millis() and see if we can make a micros() function? I can look into that if you like.

My understanding is that external interrputs are handled by specific functions, not necessarily timers.


so very rough sketch (assuming we can come up with micros()):

Code:
unsigned long injHiMS
unsigned long injCount
unsigned long vssCount

unsigned long injHiStart
processInjHi(){
  injHiStart = micros();
}

processInjLo(){
  injHiMS += micros()-injHiStart 
  injCount ++
}

processvssHI(){
  vssCount++
}

processOneSecondEvent(){
//copy and reset the values first thing in case an interrupt occurs
// serial comm (or LCD displaying) is going to take awhile 
//and shouldn't be top priority.
  unsigned long tmpInjHiMS = injHiMS
  injHiMS=0
  unsigned long tmpInjCount = injCount
  injCount=0
  unsigned long tmpvssCount = vssCount
  vssCount=0

  Serial.print(tmpIinjHiMS, HEX);    
  Serial.print(","); 
  Serial.print(tmpInjCount, HEX);    
  Serial.print(","); 
  Serial.println(tmpvssCount, HEX); 
}

unsigned long micros(){
uhh....
}
See also: http://www.arduino.cc/en/Reference/AttachInterrupt
__________________
WINDMILLS DO NOT WORK THAT WAY!!!

Last edited by dcb; 04-04-2008 at 07:59 AM..
  Reply With Quote
Old 04-04-2008, 10:35 AM   #3 (permalink)
I"m not lurking!
 
s2man's Avatar
 
Join Date: Jan 2008
Location: Kansas City, MO
Posts: 128

Porthos - '96 Chevrolet Cavalier
90 day: 31.3 mpg (US)
Thanks: 0
Thanked 1 Time in 1 Post
Quote:
Originally Posted by dcb View Post
Three is probably good enough and what I have the dummy signal generator doing above. The other value was the elapsed time according to the freeduino, but in thinking about it we probably don't need it.
I gotcha. We're just using different terms for the same data. Elapsed time is no problem. millis() rolls over about every 9 hours, but I doubt anyone will drive more than 9hrs straight.

Quote:
Originally Posted by dcb View Post
Can we use the above output format?
Sure we can.

Quote:
Originally Posted by dcb View Post
Is there a way to just use one timer to figure out when a second has passed?
Yep, [delete, delete, see below]

Quote:
Originally Posted by dcb View Post
I.e. borrow the code from millis() and see if we can make a micros() function? I can look into that if you like.

My understanding is that external interrupts are handled by specific functions, not necessarily timers.
Ah, yes. Good thought. That would free up a timer, but would be less accurate. +-1ms out of one second is minimal, but +-1ms error out of the injector pulse could be major. That's why I suggested the 16bit timer for the injector pulse width. micros() would be better than millis(), but isn't that why we've got the timers? Perhaps we should use a timer on the injector pulse width, and code the one-second timer and/or the VSS counter. Or, we could the timer/counters now for expediency, and code our own later if we need to free them up. Hmm, lot's of solutions.

Your code sketch lays things out pretty well. I think we should put the Injector pulse width in an array, then average the array before sending it to the Palm. Nevermind. I see you're totaling the microseconds.

I'm working a river clean up this weekend, so I'll be offline. No coding or testing But I'll be camping and boating
__________________
Roll on,
Stew

  Reply With Quote
Old 04-05-2008, 12:41 AM   #4 (permalink)
dcb
needs more cowbell
 
dcb's Avatar
 
Join Date: Feb 2008
Location:
Posts: 5,032

pimp mobile - '81 suzuki gs 250 t
90 day: 96.29 mpg (US)

schnitzel - '01 Volkswagen Golf TDI
90 day: 53.56 mpg (US)
Thanks: 156
Thanked 264 Times in 207 Posts
Quote:
Originally Posted by s2man View Post
millis() rolls over about every 9 hours
Ok, I think I have microSeconds just about figured out, see below code.
1. on the start of a timed event, save microSeconds()
2. at the end of a timed event, call elapsedMicroSeconds(startMicroSeconds)

It was a lot harder than it looks It digs into wiring.c and AVR, but it also demonstrates how simply the arduino integrates with them, once you know where to look.

Quote:
Originally Posted by s2man View Post
micros() would be better than millis(), but isn't that why we've got the timers?
We now have microseconds, well close enough anyway. I still don't quite get the timer interrupts myself, and the more we do with one timer, the more PWM pins we leave for future expansion. You can time a whole lot of things accurately with microSeconds without knowing anything about timer interrupts or how many timers you have or what else they are connected to.

I'm kind of tempted to say our main loop should be written like delay() with the loop guts in the middle, I used this technique below also, most things come back in 1000ms, a few were in 1001ms, don't know if a timer interrupt every second would actually be any more accurate with the other injector and vss interrupts going on.


Quote:
Originally Posted by s2man View Post
I'm working a river clean up this weekend, so I'll be offline. No coding or testing But I'll be camping and boating
No fair, I want to go too!

Code:
/*
 * microSeconds, convert timer0 register and the timer 0 overflow
 * count (defined in wiring.c) into a microsecond value 
 * for more accurate timing needs.  
 */

//overflow counter used by millis()
extern volatile unsigned long timer0_overflow_count;

//will reset after 71.5 minutes, so don't time anything longer than that
//about 4 microsecond resolution @ 16mhz
unsigned long microSeconds (void){
    return ((timer0_overflow_count << 8) + TCNT0) * 4;
}

//return the elapsed microseconds, accounting for overflows
unsigned long elapsedMicroseconds(unsigned long startMicroSeconds ){
  unsigned long msec = microSeconds();
  if(msec >= startMicroSeconds)
    return msec-startMicroSeconds;
  return 4294967295 - (startMicroSeconds-msec);
}

void setup (void){
    Serial.begin(9600);
}

unsigned long looptime=1000;
void loop (void){
  unsigned long loopStart=millis();
 
  
  unsigned long start=microSeconds();
  Serial.print(elapsedMicroseconds(start));
  Serial.print(",");
  Serial.print(millis());
  Serial.print(",");
  Serial.print(microSeconds());
  Serial.print(",");
  Serial.print(elapsedMicroseconds(start));
  Serial.print(",");

  while (millis()-loopStart < looptime);
  
  //below lines are for testing, 
  //there should not be anything outside the timed loop
  //at runtime
  Serial.print(millis()-loopStart);  //testing only, messes up actual loop timing out here
  Serial.print(",");
  Serial.println(elapsedMicroseconds(start));
}
Output:
4,0,2304,7376,1000,1003852
4,1014,1020620,15556,1000,1002320
4,2026,2032344,15556,1000,1003324
4,3039,3045068,15556,1000,1003332
0,4051,4057808,15552,1000,1002288
0,5063,5069500,15556,1000,1002340
4,6075,6081244,15556,1000,1003320
4,7088,7093972,15556,1000,1003316
4,8100,8106692,15556,1000,1002328
4,9112,9118424,15556,1000,1003328
4,10125,10132196,17636,1000,1003348
4,11138,11144948,17636,1000,1003304
4,12150,12157652,17636,1000,1002308
0,13162,13169364,17636,1000,1003352
4,14175,14182124,17636,1000,1003336
4,15187,15194864,17636,1000,1002296
4,16199,16206564,17636,1000,1002308
4,17211,17218276,17636,1000,1003340
4,18224,18231020,17636,1000,1003328
4,19236,19243752,17636,1000,1002296
4,20248,20255452,17636,1000,1003348
4,21261,21268204,17636,1000,1003308
4,22274,22280916,17636,1000,1003348
4,23286,23293668,17636,1000,1002304
4,24298,24305372,17636,1000,1003340
4,25311,25318120,17636,1000,1003336
4,26323,26330860,17636,1000,1002300
4,27335,27342564,17636,1000,1002296
4,28347,28354264,17636,1000,1003328
4,29360,29366996,17636,1000,1003336
4,30372,30379736,17636,1000,1002320
4,31384,31391460,17636,1000,1003336
4,32397,32404200,17636,1000,1003336
4,33410,33416936,17640,1000,1003344
4,34422,34429684,17636,1000,1002288
4,35434,35441376,17636,1000,1003348
4,36447,36454128,17636,1000,1003296
4,37459,37466828,17636,1000,1002336
0,38471,38478564,17636,1000,1002300
4,39483,39490272,17636,1000,1003320
0,40496,40502996,17632,1000,1003332
4,41508,41515736,17636,1000,1002296
4,42520,42527436,17636,1000,1003356
0,43533,43540192,17636,1000,1003348
4,44546,44552944,17640,1000,1003332
__________________
WINDMILLS DO NOT WORK THAT WAY!!!

Last edited by dcb; 04-05-2008 at 12:47 AM..
  Reply With Quote
Old 04-05-2008, 10:14 AM   #5 (permalink)
dcb
needs more cowbell
 
dcb's Avatar
 
Join Date: Feb 2008
Location:
Posts: 5,032

pimp mobile - '81 suzuki gs 250 t
90 day: 96.29 mpg (US)

schnitzel - '01 Volkswagen Golf TDI
90 day: 53.56 mpg (US)
Thanks: 156
Thanked 264 Times in 207 Posts
putting it together

Code:
/* draft of signal processor for the opengauge project, untested 

 sends the injector open time (in microseconds), the number of injector
 pulses, and the number of vss tics out the serial port once a second.
*/

//overflow counter used by millis()
extern volatile unsigned long timer0_overflow_count;

//will reset after 71.5 minutes, so don't time anything longer than that
//about 4 microsecond resolution @ 16mhz
unsigned long microSeconds (void){
    return ((timer0_overflow_count << 8) + TCNT0) * 4;
}

//return the elapsed microseconds, accounting for overflows
unsigned long elapsedMicroseconds(unsigned long startMicroSeconds ){
  unsigned long msec = microSeconds();
  if(msec >= startMicroSeconds)
    return msec-startMicroSeconds;
  return 4294967295 - (startMicroSeconds-msec);//someone check my work here
}

//use pins 2 and 3 because that is how the arduino is set up
//we use timer0 for ALL our event timing.
int injectorPin = 2;           // connected to the injector signal
int vssPin = 3;                // connected to the vss signal
int ledPin = 13;               // display one second heartbeep


unsigned long injHiMS;
unsigned long injCount;
unsigned long vssCount;

unsigned long injHiStart;

void processInjChange(void){
  detachInterrupt(0);
  boolean injHI=digitalRead(injectorPin);
  if(injHI){
    injHiStart = microSeconds();
  }else{
    injHiMS += elapsedMicroseconds(injHiStart); 
    injCount++;
  }
  //really should re-attach the interrupt after the injector settle time
  attachInterrupt(0, processInjChange, CHANGE);
}

void processvssHI(void){
  vssCount++;
}



void setup (void){
  Serial.begin(9600);
  pinMode(injectorPin, INPUT); 
  pinMode(vssPin, INPUT);      
  attachInterrupt(0, processInjChange, CHANGE);
  attachInterrupt(1, processvssHI, RISING);
}

unsigned long looptime=1000;
void loop (void){
  unsigned long loopStart=millis();
  digitalWrite(ledPin,HIGH);  //heartbeat indicator

// buffer the values to send and reset them
  unsigned long tmpInjHiMS = injHiMS;
  injHiMS=0;
  unsigned long tmpInjCount = injCount;
  injCount=0;
  unsigned long tmpvssCount = vssCount;
  vssCount=0;



//send the values out the serial port.  
//LCD display routines triggered here also
  Serial.print(tmpInjHiMS, HEX);    
  Serial.print(","); 
  Serial.print(tmpInjCount, HEX);    
  Serial.print(","); 
  Serial.println(tmpvssCount, HEX); 



//heartbeat indicator off.  
//If the led is mostly on then way too much time is spent 
//sending/displaying the data  
  digitalWrite(ledPin,LOW);  
  while (millis()-loopStart < looptime);
}
__________________
WINDMILLS DO NOT WORK THAT WAY!!!

Last edited by dcb; 04-27-2008 at 12:19 PM.. Reason: more updates
  Reply With Quote
Old 04-05-2008, 01:09 PM   #6 (permalink)
dcb
needs more cowbell
 
dcb's Avatar
 
Join Date: Feb 2008
Location:
Posts: 5,032

pimp mobile - '81 suzuki gs 250 t
90 day: 96.29 mpg (US)

schnitzel - '01 Volkswagen Golf TDI
90 day: 53.56 mpg (US)
Thanks: 156
Thanked 264 Times in 207 Posts
Other notes:

1. the basic signal processor is 3458 bytes (of a 14336 byte maximum). If I take out any references to serial, it goes down to 1922 bytes.

2. the main loop is taking about 6 milliseconds, without any vss or injector interrupts, but with serial transmission of "0,0,0" before it waits for the second to be over.

3. it might be better to use microseconds to control the main loop or otherwise detect that the 9 hour millis rollover has occured and adjust accordingly, it should be able to run forever without breaking, not 9 hours.
__________________
WINDMILLS DO NOT WORK THAT WAY!!!
  Reply With Quote
Old 04-16-2008, 09:40 AM   #7 (permalink)
dcb
needs more cowbell
 
dcb's Avatar
 
Join Date: Feb 2008
Location:
Posts: 5,032

pimp mobile - '81 suzuki gs 250 t
90 day: 96.29 mpg (US)

schnitzel - '01 Volkswagen Golf TDI
90 day: 53.56 mpg (US)
Thanks: 156
Thanked 264 Times in 207 Posts
More notes:
Software might need to reject pulses that are too short, and/or disable pin 2 interrupts briefly after an injector pulse to filter out oscillations:
http://www.ecomodder.com/forum/showt...9906#post19906


Cannot have both LOW and HIGH interrupts on same pin, need to utilize CHANGE interrupt somehow:
http://www.ecomodder.com/forum/showt...9907#post19907

__________________
WINDMILLS DO NOT WORK THAT WAY!!!
  Reply With Quote
Reply  Post New Thread


Thread Tools




Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2019, vBulletin Solutions Inc.
Content Relevant URLs by vBSEO 3.5.2
All content copyright EcoModder.com