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
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(¤t);} //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(¤t);} //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..
|
|
|
Today
|
|
|
Other popular topics in this forum...
|
|
|
05-24-2008, 01:23 AM
|
#132 (permalink)
|
EcoModding Lurker
Join Date: Jan 2008
Location: us
Posts: 14
Thanks: 0
Thanked 0 Times in 0 Posts
|
Quote:
Originally Posted by Mr. Cheap
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.
|
|
|
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
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?
|
|
|
05-24-2008, 11:17 PM
|
#134 (permalink)
|
Batman Junior
Join Date: Nov 2007
Location: 1000 Islands, Ontario, Canada
Posts: 22,534
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.
|
|
|
05-27-2008, 12:06 PM
|
#135 (permalink)
|
SuperMID designer
Join Date: Mar 2008
Location: Yokohama, JAPAN
Posts: 37
Thanks: 0
Thanked 13 Times in 2 Posts
|
Quote:
Originally Posted by dcb
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
|
|
|
05-27-2008, 01:51 PM
|
#136 (permalink)
|
needs more cowbell
Join Date: Feb 2008
Location: ÿ
Posts: 5,038
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..
|
|
|
05-27-2008, 04:02 PM
|
#137 (permalink)
|
EcoModding Apprentice
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
|
Quote:
Originally Posted by dcb
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..
|
|
|
05-27-2008, 09:07 PM
|
#138 (permalink)
|
Awesomeness personified
Join Date: Dec 2007
Location: Columbia, MO
Posts: 642
Thanks: 0
Thanked 28 Times in 18 Posts
|
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.
|
|
|
05-27-2008, 10:10 PM
|
#139 (permalink)
|
EcoModding Lurker
Join Date: Jan 2008
Location: us
Posts: 14
Thanks: 0
Thanked 0 Times in 0 Posts
|
Quote:
Originally Posted by dcb
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?
|
|
|
05-27-2008, 10:19 PM
|
#140 (permalink)
|
SuperMID designer
Join Date: Mar 2008
Location: Yokohama, JAPAN
Posts: 37
Thanks: 0
Thanked 13 Times in 2 Posts
|
Quote:
Originally Posted by Mr. Cheap
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
|
|
|
|