View Single Post
Old 06-13-2015, 10:41 PM   #70 (permalink)
Theitguy
EcoModding Lurker
 
Join Date: Jun 2015
Location: Australia
Posts: 18
Thanks: 3
Thanked 0 Times in 0 Posts
Ugh,

No matter what i do it still will only display the odo distance....

i just want to constantly display the speed on the LED display...

could you have a look for me?
I have attached the LEDVssSpeed routine just under the VssBaseinfopage..

[code]#include <LiquidCrystal.h> //support library for character LCDs
#include <Wire.h> //support library for I2C

#define numButtons 5 //numButtons should be 1 more than the actual number of buttons present to account for an idle state
#define numPages 3 //the number of information/menu pages - used to define the size of the function pointer arrays
#define numLEDpages 3

#define vssPulsesPerUnitDistance 2485 //vehicle-specific calibration information
#define vssTimeOut 250000 //how many microseconds to wait before deciding the car is stopped when receiving no VSS pulses (only affects displayed speed)

#define injectorOnePin 11
#define injectorOneActiveState HIGH //whether the injector input is active high or low (valid values HIGH and LOW)
#define injectorMicrosecsPerUnitVolume 200000000
#define injectorTimeOut 125000 //how many microseconds to wait before deciding the injectors aren't firing

#define lcdBacklightPin 10

#define distanceUnits "Kilometer"
#define distanceUnitsShort "Km"
#define speedUnits "Kilometer/Hour"
#define speedUnitsShort "KpH"
#define volumeUnits "Litre"
#define volumeUnitsShort "L"
#define flowUnits "Litres/Hour"
#define flowUnitsShort "LpH"
#define fuelEconomyUnits "Kilometers/Litre"
#define fuelEconomyUnitsShort "KpL"
#define engineSpeedUnits "Rev/Min"
#define engineSpeedUnitsShort "RpM"


typedef void (*fptype)(); //support for function pointers

int buttonState = 0; //variables used for UI button handling
int buttonPressed = 0;
/* buttonFunctions is an array of function pointers used to make the software functionality of the physical buttons
change depending on context. It is a 2D array, the first coordinate being the page number, the second being the
button functions (no buttons pressed, button1 pressed, button2 pressed and so on).*/
const fptype buttonFunctions [numPages] [numButtons] = { {&buttonVoidAction, &buttonVoidAction, &buttonVoidAction, &buttonVoidAction, &buttonNextPage},
{&buttonVoidAction, &buttonResetInjCumulative, &buttonVoidAction, &buttonVoidAction, &buttonNextPage},
{&buttonVoidAction, &buttonResetVssPulseCount, &buttonVoidAction, &buttonVoidAction, &buttonNextPage} };

int displayBrightness = 512; //sets illumination brightness on displays, 0 (off) to 1023 (full bright)

/* renderPage is an array of function pointers used to select which text and data to send to the LCD display. Each
pointer in the array corresponds to a page-print-function that can be called to print text and data to the display.*/
const fptype renderPage [numPages] = {&mpgBasicPage, &injectorBaseInfoPage, &vssBaseInfoPage};
int currentPage = 0; //which page to actively display
unsigned long screenUpdatePeriod = 100; //the time (in ms) to wait between LCD updates
unsigned long lastScreenUpdate = 0; //when the screen was last updated

const fptype LEDrenderPage [numLEDpages] = {&LEDnumVehicleSpeed};



const byte firstSaa1064Address = 0x70; //8-bit address with ADR tied to ground
const byte defaultSaa1064ControlByte = 0x37; //control byte: 9 mA drive current, no segment test, all digits active, multiplexed
unsigned long lastLedUpdate = 0;
unsigned long ledUpdatePeriod = 10;

unsigned long injOnToggleTime = 0; //variables used for injector pulsewidth and frequency measurement
unsigned long injCyclePeriod = 0;
unsigned long injLastOnToggleTime = 0;
unsigned long injOnInterval = 0;
unsigned long injCumulativeOnTime = 0;

unsigned long vssCyclePeriod = 0; //variables used for vehicle speed and distance measurement
unsigned long vssLastOnTime = 0;
unsigned long vssPulseCount = 0;
const float vssCyclePeriodToSpeedNumerator = 3600000000 / vssPulsesPerUnitDistance;

LiquidCrystal lcd( 8, 9, 4, 5, 6, 7 );


/*================================================= ================================================== ================*/
//The setup routine (runs at startup) and main program (loops constantly):

void setup()
{
attachInterrupt(0,singleInjectorInterrupt,CHANGE); //injector PWM measuring interrupt (pin 2)
attachInterrupt(1,basicVssInterrupt,RISING); //VSS measuring interrupt (pin 3)
pinMode(10,OUTPUT); //pin 11 is PWM backlight control for the LCD

Wire.begin(); //analog 4 and 5 are used for SDA and SCL of the I2C port

lcd.begin(16,2); //initialize the LCD as 16x2 characters
lcd.clear();
}


void loop()
{
buttonState = readAnalogButtonArray();
if(buttonState == 0) buttonPressed = 0; //this section takes action once per button press
else if(buttonPressed == 0)
{
buttonFunctions[currentPage][buttonState]();
buttonPressed = 1;
}

if(millis() >= lastScreenUpdate + screenUpdatePeriod) //this section updates the LCD screen at regular intervals
{
renderPage[currentPage]();
analogWrite(lcdBacklightPin, (displayBrightness << 4));
lastScreenUpdate = millis();
}

if(millis() >= lastLedUpdate + ledUpdatePeriod)
{
ledDisplayNumerical(firstSaa1064Address, (10*vssPulseCount)/vssPulsesPerUnitDistance, 0x32);
lastLedUpdate = millis();
}
}


/*================================================= ================================================== ================*/
//The following routines are interrupts.

void singleInjectorInterrupt()
{
if(digitalRead(injectorOnePin) == injectorOneActiveState)
{
injOnToggleTime = micros();
injCyclePeriod = injOnToggleTime - injLastOnToggleTime;
injLastOnToggleTime = injOnToggleTime;
}
else
{
injOnInterval = micros() - injOnToggleTime;
if(injOnInterval > 50000) { injOnInterval = 0; } //reject any erroneously long injector pulses
injCumulativeOnTime = injCumulativeOnTime + injOnInterval;
}
}


void basicVssInterrupt() //this interrupt counts pulses (distance) and measures cycle time (speed)
{
unsigned long vssNow = micros();
vssCyclePeriod = vssNow - vssLastOnTime;
vssLastOnTime = vssNow;
vssPulseCount++;
}


/*================================================= ================================================== ================*/
//The following are button-press functions, called to perform an action when a button is pressed.

void buttonVoidAction() { } // do nothing


void buttonNextPage()
{
lcd.clear();
currentPage++;
if(currentPage >= numPages) {currentPage = 0;}
if(currentPage < 0) {currentPage = 0;}
}


void buttonResetInjCumulative()
{
injCumulativeOnTime = 0;
}


void buttonResetVssPulseCount()
{
vssPulseCount = 0;
}


/*================================================= ================================================== ================*/
/* The following are LCD page-render functions. Each function should contain the commands necessary to print a page of
information to the LCD display.*/

void injectorBaseInfoPage() /*for 16x2 character displays. prints "### us" on the top line and "### ###" on the bottom.
cumulative microsecs, current pulse on microsecs and cycle microsecs, respectively*/
{
lcd.clear();

lcd.setCursor(0,0);
lcd.print(injCumulativeOnTime);
lcd.setCursor(14,0);
lcd.print("us");

if(micros() < injOnToggleTime + injectorTimeOut)
{
lcd.setCursor(0,1);
lcd.print(injOnInterval);

lcd.setCursor(8,1);
lcd.print(injCyclePeriod);
}
else
{
lcd.setCursor(0,1);
lcd.print("---");

lcd.setCursor(8,1);
lcd.print("---");
}
}


void vssBaseInfoPage() /*for 16x2 character displays. prints "### p ### Mi" on the top line and "### ### MPH" on
the bottom. pulses, miles, pulselength and speed respectively.*/
{
float vssSpeed = 0;
float distance = ( float(vssPulseCount) / float(vssPulsesPerUnitDistance) );
if(vssCyclePeriod != 0) {vssSpeed = ( vssCyclePeriodToSpeedNumerator / float(vssCyclePeriod) );}
if(micros() > vssLastOnTime + vssTimeOut) {vssSpeed = 0;}

lcd.clear();

lcd.setCursor(0,0);
lcd.print(vssPulseCount);
lcd.setCursor(6,0);
lcd.print("p");

lcd.setCursor(8,0);
lcd.print(distance);
lcd.setCursor(14,0);
lcd.print(distanceUnitsShort);

lcd.setCursor(0,1);
lcd.print(vssCyclePeriod);

lcd.setCursor(8,1);
lcd.print(vssSpeed);
lcd.setCursor(13,1);
lcd.print(speedUnitsShort);
}

void LEDnumVehicleSpeed()
{

float LEDvssSpeed = 0;
float distance = ( float(vssPulseCount) / float(vssPulsesPerUnitDistance) );
if(vssCyclePeriod != 0) {LEDvssSpeed = ( vssCyclePeriodToSpeedNumerator / float(vssCyclePeriod) );}
if(micros() > vssLastOnTime + vssTimeOut) {LEDvssSpeed = 0;}

ledDisplayNumerical(firstSaa1064Address,LEDvssSpee d, 0x32);
}

/*void LEDnumVehicleSpeed()
{
ledDisplayNumerical(firstSaa1064Address, (10*vssPulseCount)/vssPulsesPerUnitDistance, 0x32);
}*/










void mpgBasicPage() //for 16x2 character displays. prints "Trip: ### MPG" on the top line and "Inst: ### MPG" on the bottom
{
float tripMpg = ( (float(vssPulseCount) / vssPulsesPerUnitDistance) / (float(injCumulativeOnTime) / injectorMicrosecsPerUnitVolume) );
float instantMpg = ( (vssCyclePeriodToSpeedNumerator/float(vssCyclePeriod)) / float(3600000000 / (injectorMicrosecsPerUnitVolume)*(float(injOnInter val)/float(injCyclePeriod)))); //that's MPH/GPH fyi

lcd.clear();

lcd.setCursor(0,0);
lcd.print("Trip: ");
lcd.print(tripMpg);
lcd.setCursor(13,0);
lcd.print(fuelEconomyUnitsShort);

lcd.setCursor(0,1);
lcd.print("Inst: ");
if(micros() < injOnToggleTime + injectorTimeOut) {lcd.print(instantMpg);}
else if(micros() > vssLastOnTime + vssTimeOut) {lcd.print("0.00");}
else{lcd.print("---");}
lcd.setCursor(13,1);
lcd.print(fuelEconomyUnitsShort);
}


/*================================================= ================================================== ================*/
//The following are functions for and related to displaying data on LED displays (7-segment numerical, bar graph, etc)

void saa1064Update(byte addy, byte ctrl, byte data0, byte data1, byte data2, byte data3) //This function controls an SAA1064 I2C LED driver
{
Wire.beginTransmission(addy >> 1); //bit-shift the 8-bit address to 7-bit for wire.h
Wire.write(0x00); //byte-address pointer
Wire.write(ctrl); //control register byte
Wire.write(data0); //first display output byte (7 segs + decimal, 8 discreet LEDs or whatever)
Wire.write(data1); //second display output byte
Wire.write(data2); //third display output byte
Wire.write(data3); //fourth display output byte
Wire.endTransmission();
}


void ledDisplayNumerical(byte addr, int value, byte forceDig_dpSelect) //This routine formats numerical variables for display on a 4-digit 7-segment display
{
byte ctrlByte = (defaultSaa1064ControlByte & 0x0F) | ((displayBrightness >> 3) & 0x70);

byte digitOne = findSegs(value % 10); //break value up into its component numerical digits and convert them to 7-segment font codes
byte digitTwo = findSegs((value % 100) / 10);
byte digitThree = findSegs((value % 1000) / 100);
byte digitFour = findSegs((value % 10000) / 1000);

if((value < 1000) && ((forceDig_dpSelect & 0x80) == 0)) {digitFour = 0x00;} //the upper four bits of forceDig_dpSelect disable leading zero blanking digit by digit
if((value < 100) && ((forceDig_dpSelect & 0x40) == 0)) {digitThree = 0x00;}
if((value < 10) && ((forceDig_dpSelect & 0x20) == 0)) {digitTwo = 0x00;}
if((value < 1) && ((forceDig_dpSelect & 0x10) == 0)) {digitOne = 0x00;}

digitOne = digitOne | ((forceDig_dpSelect << 7) & 0x80); //the lower four bits of forceDig_dpSelect activate the decimal points
digitTwo = digitTwo | ((forceDig_dpSelect << 6) & 0x80);
digitThree = digitThree | ((forceDig_dpSelect << 5) & 0x80);
digitFour = digitFour | ((forceDig_dpSelect << 4) & 0x80);

//send digits serially to display chip. digit order is a matter of hardware wiring. play around with it if yours isn't coming out right
saa1064Update(addr, ctrlByte, digitFour, digitTwo, digitThree, digitOne);
}


byte findSegs(int alpha) //this routine converts a single digit decimal into a byte to drive a 7-segment display
{
switch(alpha)
{
case 0:
return 0x3F; /*These byte values are designed for a SAA1064 wired with P1-8 connected to a, b, c, d, e, f, g, dp of the first
digit (or pair of digits if multiplexing), respectively. P9-16 are similarly connected to the second digit */
case 1:
return 0x06;

case 2:
return 0x5B;

case 3:
return 0x4F;

case 4:
return 0x66;

case 5:
return 0x6D;

case 6:
return 0x7D;

case 7:
return 0x07;

case 8:
return 0x7F;

case 9:
return 0x6F;

default:
return 0x00;
}
}


/*================================================= ================================================== ================*/
//The following are miscellaneous functions.

int readAnalogButtonArray() //this function converts the value from the button voltage divider to a useful value
{
int analogIn = analogRead(0);

if(analogIn > 120)
{
if(analogIn > 380)
{
if(analogIn > 640)
{
if(analogIn > 900)
{
return 4;
}
return 3;
}
return 2;
}
return 1;
}
return 0;
}

[code]
  Reply With Quote