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

Reply  Post New Thread
 
Submit Tools LinkBack Thread Tools
Old 05-23-2008, 10:30 PM   #131 (permalink)
EcoModding Lurker
 
Join Date: May 2008
Location: Central New Mexico
Posts: 18

Bun - '02 Ford Focus ZTS
90 day: 31.3 mpg (US)
Thanks: 0
Thanked 0 Times in 0 Posts
Enjoy your break, dcb. I'm really impatient though. I couldn't wait for you to finish your break so I wrote number 2 myself. It seems to provide more stable reading over some conditions like coasting in neutral, othertimes I'm not sure if the reading are indeed better. Maybe I need to build 2 guinos so I can compare head to head.

Strangely, Yoshi's code suggestion seems to shrink the program from 7764 bytes to 7548 bytes. ( 6914 bytes to 6788 bytes in the version on page one )

I'm now testing in a 2002 Ford Focus. I use 15500 pulses/mile (this the doubled value) and 351562500 uS per gallon. (calculated from 4 injectors of 16lb) The readings seem quite reasonable.
EDIT:
Quote:
Originally Posted by diesel_john View Post
The very conservative approach Ford uses to calculate the injector size for the factory engine uses the O.E. typically safe 0.80 duty cycle limit.

So a 19 lb/hr Ford rating is at 80% duty cycle.
This would mean that my 16lb injectors are actually 20lb injectors for calculation. The uS per gallon I used was inflating the displayed milage by 25%
Update 5-24-08
I calculated that I should actually use 281250000 uS per gallon. I tested on the interstate where tests are more repeatable. I know from my fuel log that the car gets 37mpg @ 70mph and 30 mpg @ 80mph approximately. This revised calibration is very close. Mileage does vary, so I assume this is accurate data. My previous calculation was suspiciously high.

On the Caravan, I connected the wrong side of the injector due to an incorrect wiring diagram. I did actually observe a pulse when the injector turned on, but the guino would not measure the duty cycle correctly. I calibrated the fuel consumption to be reasonable, but the uS per gallon is incorrect.

Injector data : http://forums.focaljet.com/zetec-tun...low-rates.html
Ecu pinout : http://www.focusfanatics.com/forum/s...d.php?t=159134


Code:
//CHANGE THESE VALUES FOR YOUR CAR/TASTE 
#define vssPulsesPerMile 15500ul 
#define microSecondsPerGallon 351562500ul //injector flow rate 
//#define microSecondsPerGallon 372000000ul //injector flow rate 
//#define microSecondsPerGallon 2070744000ul //injector flow rate 
                                        //258843000 
#define numberOfCylinders 4  
#define numberOfInjectors 4 
#define rotationPerInjection 720 // degrees

#define tankSize 13300  //in 1000ths of a gallon, this is 13.3 gallons 
byte brightness[]={0,85,170,255}; //middle button cycles through these brightness settings 
#define brightnessLength (sizeof(brightness)/sizeof(byte)) //array size 
byte brightnessIdx=2; 
#define contrast 15 
#define currentTripResetTimeout 15  //minutes 
#define injectorSettleTime 15  //microseconds 
//DONT CHANGE ANYTHING BELOW THIS LINE 
//(well, change at your own risk anyway) 

//Vehicle Interface Pins 
#define InjectorOpenPin 2 
#define InjectorClosedPin 3 
#define VSSPin 14 //analog 0 

//LCD Pins 
#define DIPin 4 // register select RS 
#define DB4Pin 7  
#define DB5Pin 8  
#define DB6Pin 12  
#define DB7Pin 13 
#define ContrastPin 6 
#define EnablePin 5  
#define BrightnessPin 9 

#define lbuttonPin 17 // Left Button, on analog 3,   
#define mbuttonPin 18 // Middle Button, on analog 4  
#define rbuttonPin 19 // Right Button, on analog 5  

#define vssBit 1     //  pin14 is a bitmask 1 on port C   
#define lbuttonBit 8 //  pin17 is a bitmask 8 on port C   
#define mbuttonBit 16 // pin18 is a bitmask 16 on port C   
#define rbuttonBit 32 // pin19 is a bitmask 32 on port C   
#define injTimeOutus 1500000ul // if injector is "open" this long then the car is off   
#define backLightTimeOutus 20000000ul //time out before turning off backlight   
#define loopsPerSecond 2 // how many times will we try and loop in a second



unsigned long maxLoopLength = 0; //see if we are overutilizing the CPU 


#define buttonsUp   lbuttonBit + mbuttonBit + rbuttonBit  // start with the buttons in the right state 
byte buttonState = buttonsUp; 

//overflow counter used by millis() 
extern volatile unsigned long timer0_overflow_count; 
unsigned long microSeconds (void){ 
  unsigned long tmp_timer0_overflow_count;
  byte tmp_tcnt0;
  cli(); //disable interrupts
  tmp_timer0_overflow_count = timer0_overflow_count;
  tmp_tcnt0 = TCNT0;
  sei(); // enable interrupts
  return ((tmp_timer0_overflow_count << 8) + tmp_tcnt0) * 4; 
}
unsigned long elapsedMicroseconds(unsigned long startMicroSeconds ){ 
  unsigned long msec = microSeconds(); 
  if(msec >= startMicroSeconds) 
    return msec-startMicroSeconds; 
  return 4294967295 - (startMicroSeconds-msec); 
} 

//Trip prototype 
class Trip{ 
public: 
  unsigned long loopCount; //how long has this trip been running 
  unsigned long injPulses; //rpm 
  unsigned long injHiSec;// seconds the injector has been open 
  unsigned long injHius;// microseconds, fractional part of the injectors open  
  unsigned long vssPulses;//from the speedo 
   
  //these functions actually return in thousandths,  
  unsigned long miles();   
  unsigned long gallons(); 
  unsigned long mpg();   
  unsigned long mph();   
  void loadNextDummyTrip(); 

  unsigned long time(); //mmm.ss   
   
  void update(Trip t); 
  void reset(); 
  Trip(); 
}; 

//LCD prototype 
class LCD{ 
public: 
  LCD( ) ; 
  void gotoXY(byte x, byte y); 
  void print(char * string); 
  void init(); 
  void tickleEnable(); 
  void cmdWriteSet(); 
  void LcdCommandWrite(byte value); 
  void LcdDataWrite(byte value); 
  byte pushNibble(byte value); 
}; 

//main objects we will be working with: 
volatile boolean running=true; //keep track if we are running or not 
volatile boolean injectorOpen=true; //keep track if we are running or not 
volatile unsigned long injHiStart; //for timing injector pulses 
volatile unsigned long injLowStart; //for measuring injector duty
volatile unsigned long injOnTime; //on time for instant consumption
volatile unsigned long injCycleTime; //total time for instant consumption, rpm
volatile unsigned long vssHiStart; //for instant mph
volatile unsigned long vssCycleTime; //for instant mph

LCD lcd; 
Trip tmpTrip; 
Trip instant; 
Trip current; 
Trip tank; 

void processInjOpen(void){ 
  injHiStart = microSeconds(); 
  injectorOpen=true; 
} 

void processInjClosed(void){ 
  injOnTime = elapsedMicroseconds(injHiStart); 
  injCycleTime = elapsedMicroseconds(injLowStart); 
  injLowStart = microSeconds();
  if(running==true){ 
    tmpTrip.injHius += injOnTime;
    tmpTrip.injPulses++; 
  }else 
    running=true; 
  injectorOpen=false; 
} 

//attach the vss/buttons interrupt 
ISR( PCINT1_vect ){  
  static byte vsspinstate=0; 
  byte p = PINC;//bypassing digitalRead for interrupt performance 
  if ((p & vssBit) != (vsspinstate & vssBit)){ 
    tmpTrip.vssPulses++; 
    if( p&vssBit )// compare only rising edges
    { // I wouldn't expect the vss to give exactly 50% duty cycle
        vssCycleTime = elapsedMicroseconds(vssHiStart); 
        vssHiStart = microSeconds(); 
    }
  } 
  vsspinstate = p; 
  buttonState &= p; 
}  

void setup (void){  
  pinMode(BrightnessPin,OUTPUT); 
  analogWrite(BrightnessPin,255-brightness[brightnessIdx]); 
  lcd.init(); 
  pinMode(ContrastPin,OUTPUT); 
  analogWrite(ContrastPin,contrast); 

  lcd.print("OpenGauge       "); 
  lcd.gotoXY(0,1); 
  lcd.print("         MPGuino"); 
  pinMode(InjectorOpenPin, INPUT);  
  pinMode(InjectorClosedPin, INPUT);  
  pinMode(VSSPin, INPUT);       
  attachInterrupt(0, processInjOpen, FALLING); 
  attachInterrupt(1, processInjClosed, RISING); 

  pinMode( lbuttonPin, INPUT );  
  pinMode( mbuttonPin, INPUT );  
  pinMode( rbuttonPin, INPUT ); 
   

  //"turn on" the internal pullup resistors 
  digitalWrite( lbuttonPin, HIGH);  
  digitalWrite( mbuttonPin, HIGH);  
  digitalWrite( rbuttonPin, HIGH);  
//  digitalWrite( VSSPin, HIGH);  

  //low level interrupt enable stuff 
  PCICR |= (1 << PCIE1);  
  PCMSK1 |= (1 << PCINT8);  
  PCMSK1 |= (1 << PCINT11);  
  PCMSK1 |= (1 << PCINT12);  
  PCMSK1 |= (1 << PCINT13);      

  delay(1500); 
}  

typedef void (* DisplayFx)(void);//type for display function pointers 

byte screen=0; 
#define looptime 1000000ul/loopsPerSecond //1/2 second 
//void (*displayFunc)(void)=updateDisplay0; 
DisplayFx displayFuncs[] ={updateDisplay0,updateDisplay1,updateDisplay2,updateDisplay3,updateDisplay4,updateDisplay5,updateDisplay6,updateDisplay7,updateDisplay8}; 
char *  displayFuncNames[] ={"Main ","Instant ","Current ","Tank ","Instant raw Data ","Current raw Data ","Tank raw Data ","CPU Monitor ", "Pulse Timer "}; 
#define displayFuncSize (sizeof(displayFuncs)/sizeof(DisplayFx)) //array size 


void loop (void){  
  while(true){ 
    unsigned long loopStart=microSeconds(); 

    instant.reset();           //clear instant 

       
    if(running!=false){ 
      instant.update(tmpTrip);   //"copy" of tmpTrip in instant now 
      tmpTrip.reset();           //reset tmpTrip first so we don't lose too many interrupts 
      current.update(instant);   //use instant to update current 
      tank.update(instant);      //use instant to update tank 
    } 

    displayFuncs[screen]();    //call the appropriate display routine 

    lcd.gotoXY(0,0);   
//see if any buttons were pressed, display a brief message if so 
      if(!(buttonState&lbuttonBit) && !(buttonState&mbuttonBit)){// left and middle = tank reset 
          tank.reset(); 
          lcd.print("Tank Reset "); 
      }else if(!(buttonState&mbuttonBit) && !(buttonState&rbuttonBit)){// right and middle = current reset 
          current.reset(); 
          lcd.print("Current Reset "); 
      }else if(!(buttonState&lbuttonBit)){ //left is rotate through screeens to the left 
        if(screen!=0) 
          screen=(screen-1); 
        else 
          screen=displayFuncSize-1; 
        lcd.print(displayFuncNames[screen]); 
      }else if(!(buttonState&mbuttonBit)){ //middle is cycle through brightness settings 
        brightnessIdx = (brightnessIdx + 1) % brightnessLength; 
        analogWrite(BrightnessPin,255-brightness[brightnessIdx]); 
        lcd.print("Brightness "); 
        lcd.LcdDataWrite('0' + brightnessIdx); 
        lcd.print(" "); 
      }else if(!(buttonState&rbuttonBit)){//right is rotate through screeens to the left 
        screen=(screen+1)%displayFuncSize; 
        lcd.print(displayFuncNames[screen]); 
      } 

      buttonState=buttonsUp;//reset the buttons 
       
      //see if the engine is running or not, cars seem to hold the injector low (open) with the key off. 
      unsigned long loopX=elapsedMicroseconds(injHiStart); 
      if(injectorOpen==true){ 
        if(loopX > injTimeOutus){ 
          running=false; 
          tmpTrip.reset(); 
        } 
        if(loopX > backLightTimeOutus) 
           analogWrite(BrightnessPin,255-brightness[0]); 
      } 
      if(running==true) 
         analogWrite(BrightnessPin,255-brightness[brightnessIdx]); 


      //keep track of how long the loops take before we go int waiting. 
      loopX=elapsedMicroseconds(loopStart); 
      if(loopX>maxLoopLength) maxLoopLength = loopX; 
       
      while (elapsedMicroseconds(loopStart) < (looptime));//wait for the end of a second to arrive 
  } 

}  


char fBuff[7];//used by format 
//format a number into NNN.NN  the number should already be representing thousandths 
char* format(unsigned long num){ 
  unsigned long d = 10000; 
  long t; 
  byte dp=3; 
  byte l=6; 

  //123456 = 123.46 
  if(num>9999999){ 
    d=100000; 
    dp=99; 
    num/=100; 
  }else if(num>999999){ 
    dp=4; 
    num/=10; 
  } 
     
  unsigned long val = num/10; 
  if ((num - (val * 10)) >= 5)  //will the first unprinted digit be greater than 4? 
    val += 1;   //round up val 
   
  for(byte x = 0; x < l; x++){ 
    if(x==dp)      //time to poke in the decimal point? 
      fBuff[x]='.'; 
    else{ 
      t = val/d;   
      fBuff[x]= '0' + t%10;//poke the ascii character for the digit. 
      val-= t*d; 
      d/=10;       
    } 
  } 
  fBuff[6]= 0;         //good old zero terminated strings  
  return fBuff; 
} 



void updateDisplay0() {//draw the main screen 
  lcd.gotoXY(0,0); 
  lcd.LcdDataWrite(7); //special IN character 
  lcd.print(format(instant.mpg())); 
  lcd.LcdDataWrite(0); //half of the M/G symbol 
  lcd.LcdDataWrite(1); //other half of the M/G symbol 
  lcd.print(format(current.mpg())); 
//  lcd.print(format(instant.mph())); 
  lcd.LcdDataWrite(6); //special CU character 
  lcd.gotoXY(0,1); 
  lcd.LcdDataWrite(5); //special MI character 
  lcd.print(format(tank.miles())); 
  lcd.LcdDataWrite(2); //half of the TK symbol 
  lcd.LcdDataWrite(3); //other half of the TK symbol 
  //lcd.print(format(memoryTest())); 
  lcd.print(format(tank.gallons())); 
  lcd.LcdDataWrite(4); //special GA character 
} 

void updateDisplay1(void){tDisplay(&instant);}   //display instant trip formatted data.   
void updateDisplay2(void){tDisplay(&current);}   //display current trip formatted data.   
void updateDisplay3(void){tDisplay(&tank);}      //display tank trip formatted data.   
void updateDisplay4(void){rawDisplay(&instant);} //display instant trip "raw" injector and vss data.   
void updateDisplay5(void){rawDisplay(&current);} //display current trip "raw" injector and vss data.   
void updateDisplay6(void){rawDisplay(&tank);}    //display tank trip "raw" injector and vss data.   
void updateDisplay7(void){ 
  lcd.gotoXY(0,0);lcd.print("C%");lcd.print(format(maxLoopLength*1000/(looptime/100)));lcd.print(" T"); lcd.print(format(tank.time()));
  unsigned long mem = memoryTest(); 
  mem*=1000; 
  lcd.gotoXY(0,1);lcd.print("FREE MEM: ");lcd.print(format(mem)); 
}    //display max cpu utilization and ram.   

void updateDisplay8(void){ 
  lcd.gotoXY(0,0);
  lcd.print("ss");
  lcd.print(format(vssCycleTime)); 
  lcd.print("rm"); lcd.print(format(rpm()*1000));
  lcd.gotoXY(0,1);
  
  lcd.print("on"); lcd.print(format(injOnTime));
  lcd.print("ij"); lcd.print(format(injCycleTime));
}    //display max cpu utilization and ram.   


//arduino doesn't do well with types defined in a script as parameters, so have to pass as void * and use -> notation. 
void tDisplay( void * r){ //display trip functions.   
  Trip *t = (Trip *)r; 
  lcd.gotoXY(0,0);lcd.print("MH");lcd.print(format(t->mph()));lcd.print("MG");lcd.print(format(t->mpg())); 
  lcd.gotoXY(0,1);lcd.print("MI");lcd.print(format(t->miles()));lcd.print("GA");lcd.print(format(t->gallons())); 
} 

void rawDisplay(void * r){ 
  Trip *t = (Trip *)r; 
  lcd.gotoXY(0,0);lcd.print("IJ");lcd.print(format(t->injHiSec*1000));lcd.print("uS");lcd.print(format(t->injHius*1000)); 
  lcd.gotoXY(0,1);lcd.print("IC");lcd.print(format(t->injPulses*1000));lcd.print("VC");lcd.print(format(t->vssPulses*1000)); 
} 


Trip::Trip(){ 
} 

unsigned long Trip::miles(){ 
  return (vssPulses*1000)/vssPulsesPerMile; 
} 

unsigned long Trip::mph(){ 
  if(loopCount == 0)
     return 0;
  if( vssPulses == 0 )
     return 0;
     
  if( vssPulses < 20 )// slow speed instant
  { // the leading 2 because vssCycleTime is rising to rising, 
     return 2*360000000/ ((vssCycleTime/100) * (vssPulsesPerMile/100)); 
  }
  if(vssPulses<1000) 
    return loopsPerSecond*((vssPulses*3600000)/(vssPulsesPerMile*loopCount)); 
  return loopsPerSecond*((vssPulses*3600)/(vssPulsesPerMile*loopCount/1000)); 
} 

unsigned long  Trip::gallons(){ 
  if(injHiSec<4000) //will overflow here 
    return ((injHiSec*1000000) + injHius)/(microSecondsPerGallon/1000); 
  else   
      return ((injHiSec*1000))/(microSecondsPerGallon/1000000); 
} 

unsigned long  Trip::mpg(){ 
   
  if(vssPulses==0) return 0; 
  if(injPulses==0) return 999999000; //who doesn't like to see 999999?  :) 

  unsigned long mi=miles(); 
  unsigned long gal=gallons(); 
  
  if( injPulses< 50 ) // instant
  {
    gal = (( (injOnTime*10000)/ (injCycleTime/100) )*1000) / (microSecondsPerGallon/1000); 
    if( gal==0 ) gal=1;
    return (mph()*10000/(36*gal));  
  }
  if( injHiSec<4 ) // prevent overflow 
  { 
    gal = ((injHiSec*1000000000) + (injHius*1000))/(microSecondsPerGallon/1000); // 1e-6 gals 
    if (gal==0) gal=1;//default to a millionth of a gallon so not division by zero 
    return mi*1000000/gal; // 1e3 mi * 1e6 / 1e-6 gal = 1e3 mpg 
  } 
  if (gal==0) gal=1;//default to a thousandth of a gallon so not division by zero 
  return mi*1000/gal; // 1e3 mi * 1e3 / 1e3 gal = 1e3 mpg 
} 

//return the seconds as a time mmm.ss, eventually hhh:mm too 
unsigned long Trip::time(){ 
//  return seconds*1000; 
  byte d = 60; 
  unsigned long seconds = loopCount/loopsPerSecond;
//  if(seconds/60 > 999) d = 3600; //scale up to hours.minutes if we get past 999 minutes 
  return ((seconds/d)*1000) + ((seconds%d) * 10);  
} 

unsigned long rpm(){ 
  return rotationPerInjection*1000000 / (6*injCycleTime) ;
} 


void Trip::update(Trip t){ 
  loopCount++;  //we call update once per loop
  injPulses+=t.injPulses; 
  vssPulses+=t.vssPulses; 
  if(t.injPulses != 0){//chasing ghosts 
    injHius+=t.injHius; 
    if (injHius>=1000000){  //rollover into the injHiSec counter 
      injHiSec++; 
      injHius-=1000000; 
    } 
  } 
} 

void Trip::reset(){ 
  loopCount=0; 
  injPulses=0; 
  injHius=0; 
  injHiSec=0; 
  vssPulses=0; 
} 


//LCD functions 
LCD::LCD(){ 
} 
//x=0..16, y= 0..1 
void LCD::gotoXY(byte x, byte y){ 
  byte dr=x+0x80; 
  if (y==1)  
    dr += 0x40; 
  if (y==2)  
    dr += 0x14; 
  if (y==3)  
    dr += 0x54; 
  lcd.LcdCommandWrite(dr);   
} 

void LCD::print(char * string){ 
  byte x = 0; 
  char c = string[x]; 
  while(c != 0){ 
    lcd.LcdDataWrite(c);  
    x++; 
    c = string[x]; 
  } 
} 


//do the lcd initialization voodoo 
void LCD::init(){ 
  pinMode(EnablePin,OUTPUT);  
  pinMode(DIPin,OUTPUT);  
  pinMode(DB4Pin,OUTPUT);  
  pinMode(DB5Pin,OUTPUT);  
  pinMode(DB6Pin,OUTPUT);  
  pinMode(DB7Pin,OUTPUT);  
  delay(500); 

  LcdCommandWrite(B00000010);  // 4 bit operation   

  LcdCommandWrite(B00101000);// 4-bit interface, 2 display lines, 5x8 font  
  LcdCommandWrite(B00001100);  // display control:  
  LcdCommandWrite(B00000110);  // entry mode set: increment automatically, no display shift  


  LcdCommandWrite(B01000000);  // set cgram 
  //create some custom characters 
  byte chars[]={ //if you squint, you can kind of see the characters below.  see the 'N' in the lower right? 
  //     M/,G          T,K        GA     MI     CU     IN 
    B00101,B00000,B00000,B00000,B01100,B10100,B01100,B11100, 
    B00111,B00100,B00000,B00000,B10000,B11100,B10000,B01000, 
    B00101,B01000,B00111,B10100,B10100,B10100,B10000,B01000, 
    B00101,B10000,B00010,B11000,B01100,B10100,B01100,B11100, 
    B00000,B01100,B00010,B10100,B00010,B00111,B00101,B01001, 
    B00001,B10000,B00010,B10100,B00101,B00010,B00101,B01101, 
    B00010,B10100,B00000,B00000,B00111,B00010,B00101,B01011, 
    B00100,B01100,B00000,B00000,B00101,B00111,B00111,B01001}; 
     
    for(byte x=0;x<8;x++)   
      for(byte y=0;y<8;y++)   
          LcdDataWrite(chars[y*8+x]); //write the character data to the character generator ram  

  LcdCommandWrite(B00000001);  // clear display, set cursor position to zero    

  LcdCommandWrite(B10000000);  // set dram to zero  

}   

void  LCD::tickleEnable(){  
  // send a pulse to enable  
  digitalWrite(EnablePin,HIGH);  
  delayMicroseconds(1);  // pause 1 ms according to datasheet  
  digitalWrite(EnablePin,LOW);  
  delayMicroseconds(1);  // pause 1 ms according to datasheet  
}   

void LCD::cmdWriteSet(){  
  digitalWrite(EnablePin,LOW);  
  delayMicroseconds(1);  // pause 1 ms according to datasheet  
  digitalWrite(DIPin,0);  
}  

byte LCD::pushNibble(byte value){  
  digitalWrite(DB7Pin, value & 128);  
  value <<= 1;  
  digitalWrite(DB6Pin, value & 128);  
  value <<= 1;  
  digitalWrite(DB5Pin, value & 128);  
  value <<= 1;  
  digitalWrite(DB4Pin, value & 128);  
  value <<= 1;  
  return value; 
} 

void LCD::LcdCommandWrite(byte value){  
  value=pushNibble(value); 
  cmdWriteSet();  
  tickleEnable();  
  value=pushNibble(value); 
  cmdWriteSet();  
  tickleEnable();  
  delay(5);  
}  

void LCD::LcdDataWrite(byte value){  
  digitalWrite(DIPin, HIGH);  
  value=pushNibble(value); 
  tickleEnable();  
  value=pushNibble(value); 
  tickleEnable();  
  delay(5);  
}  


// this function will return the number of bytes currently free in RAM 
int memoryTest() { 
  int byteCounter = 0; // initialize a counter 
  byte *byteArray; // create a pointer to a byte array 
  while ( (byteArray = (byte*) malloc (byteCounter * sizeof(byte))) != NULL ) { 
    byteCounter++; // if allocation was successful, then up the count for the next try 
    free(byteArray); // free memory after allocating it 
  } 
  free(byteArray); // also free memory after the function finishes 
  return byteCounter; // send back the highest number of bytes successfully allocated 
}


Last edited by Mr. Cheap; 05-24-2008 at 03:38 PM..
  Reply With Quote
Alt Today
Popular topics

Other popular topics in this forum...

   
Old 05-24-2008, 01:23 AM   #132 (permalink)
EcoModding Lurker
 
Join Date: Jan 2008
Location: us
Posts: 14

grnsat - '95 Saturn SL1

metro - '95 Geo Metro LSi
Thanks: 0
Thanked 0 Times in 0 Posts
Quote:
Originally Posted by Mr. Cheap View Post
On the Caravan, I connected the wrong side of the injector due to an incorrect wiring diagram. I did actually observe a pulse when the injector turned on, but the guino would not measure the duty cycle correctly. I calibrated the fuel consumption to be reasonable, but the uS per gallon is incorrect.
What kind of readings did you see? At this point, I really don't know why my uS readings are so low. I set up a new screen so I could watch a few things from the other screens, including an average uS display (injHius/injPulses, in current trip). I'd said before that I'd see 36 pulses, and around 34000uS.. which would be less than 1ms per pulses, which as far as I know, isn't very likely. With my display I see an average of 975uS per pulse. That just has to be too low.

I just went out and tried tapping into the other injector wire, and got no pulses.. I was really hoping i'd just used the wrong wire..

I guess my status is: built, testing, accurate vss, accurate injection count, way off uS.
  Reply With Quote
Old 05-24-2008, 03:14 AM   #133 (permalink)
EcoModding Lurker
 
Join Date: May 2008
Location: Central New Mexico
Posts: 18

Bun - '02 Ford Focus ZTS
90 day: 31.3 mpg (US)
Thanks: 0
Thanked 0 Times in 0 Posts
Quote:
Originally Posted by mosier View Post
What kind of readings did you see?
I didn't record instant measurements from the caravan but I do remember seeing 20,000 to 30,000 uS at lower engine speeds. I did record 19.234046 seconds of injecting, 38222 injection cycles, and 70429 vss pulses over a 4.5 mile, 10-12 minute trip.

19 sec / 660 sec = 2.9% duty cycle
19234046 uS / 38222 injections = 503 uS / injection

At idle the focus generates a 3mS pulse every 172mS. 1.7% duty cycle.

Reading this thread I would assume that your car uses "peak and hold" injectors. Maybe the "peak" part of the injection cycle is being measured while the "hold" is not?
Attached Thumbnails
Click image for larger version

Name:	injector-high-side.jpg
Views:	83
Size:	97.4 KB
ID:	792  
  Reply With Quote
Old 05-24-2008, 11:17 PM   #134 (permalink)
Batman Junior
 
MetroMPG's Avatar
 
Join Date: Nov 2007
Location: 1000 Islands, Ontario, Canada
Posts: 22,534

Blackfly - '98 Geo Metro
Team Metro
Last 3: 70.09 mpg (US)

MPGiata - '90 Mazda Miata
90 day: 54.46 mpg (US)

Appliance car Mirage - '14 Mitsubishi Mirage ES (base)
90 day: 57.73 mpg (US)
Thanks: 4,082
Thanked 6,979 Times in 3,614 Posts
Quote:
Well, I don't know about all y'all, but I think I might just have a useable mpg gauge here
Congrats, dcb.

Quote:
This looks like a reasonable place to regroup. Can we get a status check from everyone with hardware when you get a chance? I'd like to know if you are hung up on the build or the installation
I'm not hung up, so much as behind schedule. I spent this week's tinker time on an unplanned rebuild of the ForkenSwift's control arm mounts. So my MPGuino is still only half built. Next week... sigh.

Enjoy your break.
__________________
Project MPGiata! Mods for getting 50+ MPG from a 1990 Miata
Honda mods: Ecomodding my $800 Honda Fit 5-speed beater
Mitsu mods: 70 MPG in my ecomodded, dirt cheap, 3-cylinder Mirage.
Ecodriving test: Manual vs. automatic transmission MPG showdown



EcoModder
has launched a forum for the efficient new Mitsubishi Mirage
www.MetroMPG.com - fuel efficiency info for Geo Metro owners
www.ForkenSwift.com - electric car conversion on a beer budget
  Reply With Quote
Old 05-27-2008, 12:06 PM   #135 (permalink)
SuperMID designer
 
Yoshi's Avatar
 
Join Date: Mar 2008
Location: Yokohama, JAPAN
Posts: 37
Thanks: 0
Thanked 13 Times in 2 Posts
Quote:
Originally Posted by dcb View Post
But your idea of an external signal generater has got me thinking, It actually might be worth the effort to build a dynamic test device that could run different profiles and have the guino spit out the lcd data out the serial port, and have the test device confirm that the serial data looks right (aka regression test).
Just FYI...
I use following pulse simulator.
It has ATmega8 and 16X2 LCD. The program is written in AVR assembler.
If you like, I'm willing to post the source and schematics.

Regards,
Yoshi
Attached Thumbnails
Click image for larger version

Name:	simulator.jpg
Views:	94
Size:	24.0 KB
ID:	810  
  Reply With Quote
Old 05-27-2008, 01:51 PM   #136 (permalink)
dcb
needs more cowbell
 
dcb's Avatar
 
Join Date: Feb 2008
Location: ÿ
Posts: 5,038

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: 158
Thanked 269 Times in 212 Posts
Mr. Cheap, that's awesome Is there any making sense of the actual numbers vs calculated?

mosier, do you get a voltage reading on that injector wire with the engine off but the ignition on (you shouldn't)? How far off is the consumption? Mine in the car is currently reading low by about half.

Yoshi, thanks for the tips.

Other updates: Updated code w/serial prints for the LCD data for logging/automated testing and to use the updated microSeconds() function from Yoshi.

Did some experimenting with progmem, it looks promising for reducing the ram usage, but nothing in the released code yet.

Also want to add better button management.

I know awillard has "dibs" on the hardwired signal generator, but I've got two dunios on my desk at the moment so I really think I should give this a shot since it seem so simple (to me anyway) and flexable, and with a computer in the loop it can run all kinds of test scenarios without regard for size limitations:

__________________
WINDMILLS DO NOT WORK THAT WAY!!!

Last edited by dcb; 05-27-2008 at 02:36 PM..
  Reply With Quote
Old 05-27-2008, 04:02 PM   #137 (permalink)
EcoModding Apprentice
 
awillard69's Avatar
 
Join Date: Feb 2008
Location: Streamwood, IL
Posts: 105

Dakota - '00 Dodge Dakota Club Cab, Sport
90 day: 18.57 mpg (US)

Jeep - '01 Jeep Wrangler TJ Sport
90 day: 18.46 mpg (US)
Thanks: 0
Thanked 1 Time in 1 Post
Cool

Quote:
Originally Posted by dcb View Post
I know awillard has "dibs" on the hardwired signal generator
My "dibs" only cover the fact that I don't currently have a second *duino sitting around.

I spent time boxing up my setup. It's a bit larger than I expected, but spacious enough for my prototyping.

A few pics of the effort, none of the enclosure yet.

__________________


Last edited by awillard69; 05-27-2008 at 04:21 PM..
  Reply With Quote
Old 05-27-2008, 09:07 PM   #138 (permalink)
Awesomeness personified
 
AndrewJ's Avatar
 
Join Date: Dec 2007
Location: Columbia, MO
Posts: 642

Harold - '94 Honda Civic CX
90 day: 54.51 mpg (US)

Margot - '08 Surly Big Dummy
Thanks: 0
Thanked 28 Times in 18 Posts
Send a message via AIM to AndrewJ
Got my 'Guino hooked up in the car.

I can't tell what all the data is though...

Would someone mind "decoding" all the little icons and abbreviations for me?

On the "Current Data" screen I'm seeing

IJ049.00uS879812
IC001.54VC001.00

I'm just needing to know what the "IJ" "uS" "IC" and "VC" mean.

So far I'm guessing IC is injector cycles, but beyond that I'm afraid I'm a little to dumb to figure much out

Also, the "IN" "H/G" "CU" "HI" "TK" and "GA" on the main screen mean.
__________________
"I got 350 heads on a 305 engine. I get 10 miles to the gallon. I ain't got no good intentions." - The Drive By Truckers.

  Reply With Quote
Old 05-27-2008, 10:10 PM   #139 (permalink)
EcoModding Lurker
 
Join Date: Jan 2008
Location: us
Posts: 14

grnsat - '95 Saturn SL1

metro - '95 Geo Metro LSi
Thanks: 0
Thanked 0 Times in 0 Posts
Quote:
Originally Posted by dcb View Post
mosier, do you get a voltage reading on that injector wire with the engine off but the ignition on (you shouldn't)? How far off is the consumption? Mine in the car is currently reading low by about half.
I haven't had a chance to check voltage at the injector, but i'll try to get it done.

At a 55mph cruise, resetting current trip while in the cruise, holding that speed for a few miles, i get around 126mpg. I'd guess my car gets a little over 45, maybe up to 50mpg, at that speed. So I'm off by i guess 2.5. The mpg reading is using the microsecondspergallon variable, which we haven't proven yet. In my case, I don't think it's as easy as just doubling or halving a value.

My main concern is my uS per pulse really doesn't vary very much at all. I think the least I've seen on average is around 950uS at idle, and a little over 1000uS at other cruise speeds. I haven't seen anyone out there quote less than 1ms for any car, and most of what I've read says that most peak and hold injectors take at least that just to open.

I wonder if I were to hook up right at the ecu (as you had done initially). I went ahead and hooked up at the injector since it didn't work for you, and at the time, I thought our cars were going to be identical. Peak and hold injectors are supposed to have a resistor I believe.. I'm not sure if the resistor is in the ecu, or somewhere between the ecu and injector (i read some hondas can be converted to peak hold by grabbing a resistor box from an earlier honda). if the latter, then maybe that extra resistance is screwing with my reading?
  Reply With Quote
Old 05-27-2008, 10:19 PM   #140 (permalink)
SuperMID designer
 
Yoshi's Avatar
 
Join Date: Mar 2008
Location: Yokohama, JAPAN
Posts: 37
Thanks: 0
Thanked 13 Times in 2 Posts
Quote:
Originally Posted by Mr. Cheap View Post
Enjoy your break, dcb. I'm really impatient though. I couldn't wait for you to finish your break so I wrote number 2 myself. It seems to provide more stable reading over some conditions like coasting in neutral, othertimes I'm not sure if the reading are indeed better. Maybe I need to build 2 guinos so I can compare head to head.
Thank you comments.
Have you seen more stable readings with the cli()/sei(0 function?
My suggestion is to place cli()/sei() codes for another interrupt driven variables, such as vssPulse and injector pulses as well.

Regards,
Yoshi

  Reply With Quote
Reply  Post New Thread




Similar Threads
Thread Thread Starter Forum Replies Last Post
My kingdom for a giant, heated workspace MetroMPG The Lounge 14 12-12-2010 10:08 AM
Motorcycle manufacturers beginning to release MPG info MetroMPG Motorcycles / Scooters 1 04-03-2008 06:23 PM



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