All pastes #2118313 Raw Edit

Untitled

public c v1 · immutable
#2118313 ·published 2012-02-17 03:10 UTC
rendered paste body
#include <LiquidCrystal.h>/* *   Boost Gauge project for my Nissan Stagea *   To Do: *          1. Fix the boost bar graph scaling to re-read the values after its been changed in the menu - DONE *          2. Move the alarm code and all the calculation code out of the display printing routine. - DONE *             - Perhaps move the display printing into a suborutine? - LATER? *          3. Read/Write EEPROM for saving etc variable. Make sure to handle the case where there is no data in EEPROM. *             - http://arduino.cc/playground/Code/EEPROMWriteAnything  *          3. Think of a better way to do the menus and tidy things up. Code is pretty nasty right now. *          4. Add a peak value feature with adjustable timeout. *          5. Fix display errors when graph scale is set low and boost significantly higher causes it to wrap to the first line. *//* *LCD Pinout            Cable Pin header    Arduino Pin *1 - GND                1 *2 - +5V                2 *3 - Contrast           3 *4 - RS                 4                  2 *5 - RW                 5                  3 *6 - E(Enable)          6                  4 *7 - DB0 *8 - DB1 *9 - DB2 *10 - DB3 *11 - DB4               7                  5 *12 - DB5               8                  6 *13 - DB6               9                  7 *14 - DB7               10                 8 *15 - Backlight +5V     11                 NC *16 - Backlight GND     12                 NC */// LiquidCrystal lcd(rs, rw, enable, d4, d5, d6, d7)  - 4 bit modeLiquidCrystal    lcd(2,   3,      4,  5,  6,  7,  8);// LiquidCrystal lcd(rs, rw, enable, d0, d1, d2, d3, d4, d5, d6, d7) - 8 bit mode//LiquidCrystal    lcd(2,   3,      4,  5,  6,  7,  8,  9, 10, 11, 12);// Analog 0-5v Sensor inword Analog1pin = A5;int Analog1Raw = 0;int Analog1mV = 0;float Analog1AFR = 0;// Shift Regsiter pins for Button Input#define ShiftData  9#define ShiftClock 10  #define ShiftLatch 11// Other pins#define BuzzerPin 12// Stored config#define CONFIG_START 0#define CONFIG_VERSION stageav1/* -- This shit doesnt work....struct ConfigStruct {  int BoostMin;  // BoostMin for graph Scaling  int BoostMax;  // BoostMax for graph Scaling  int BoostAlarm;// Alarm for audible/visual boost warning};ConfigStruct Config = { 0 , 0 , 0 };Config.BoostMin = 0;Config.BootMax = 500;Config.BoostAlarm = 300;*/// Variable for buttonsunsigned int buttonScanInterval = 100;    // Interval between checking for button pressunsigned long buttonScanLastms = 0;       // Last time we lookedbyte ButtonBits = 255;                    // B11111111unsigned int ButtonRepeatDelay = 200;     // 300ms delay for button repeat unsigned long ButtonRepeatLastms = 0;     // Last time a button was pressed// Variables for tracking menu states  :: 0 - Run (no menu), 1 - Display Menubyte MenuState = 0;byte SubMenu = 0;                    // Used to track what SubMenu we're inunsigned int MenuTimeout = 10000;    // 10 second timeout for menus// Text display timer variablesunsigned int timerTextInterval = 100;    // interval between sensor data updatesunsigned long timerTextLastms = 0;       // Last time we looked// mV for boost min and max. This is used for the bar graphint BoostMin = 0;int BoostMax = 500;   // 17 psiint BoostAlarm = 300; // 10 psi// Bar Graph magicunsigned int timerBarGraphInterval = 10;  // interval between bar graph updatesunsigned long timerBarGraphLastms = 0;    // Last time we lookedint LCDWidth = 16;                        // LCD Display width in charsint LCDPixelWidth = 5;                    // Each char is 5 pixels wideint LCDBars = LCDWidth * LCDPixelWidth;   // This is the number of pixels we have to useint mVPerBar = BoostMax / LCDBars;        // Bar graph magic calculationsint mVPerChar = mVPerBar * LCDPixelWidth; //mV per full charint BarGraphValue = 0;                    // This variable is used further down when printing the bar graphint BarGraphWritten = 0;                  // This variable is used to track how much whitespace we need to print after the bar to clear the display.const float kpa2psi = 0.145037738;void setup(){//  lcd.begin(24, 4);    lcd.begin(16, 2);  // Setup our custom chars for the bar graph  byte bar1[8] = {    B10000,    B10000,    B10000,    B10000,    B10000,    B10000,    B10000,    B10000,  };  lcd.createChar(1, bar1);    byte bar2[8] = {    B11000,    B11000,    B11000,    B11000,    B11000,    B11000,    B11000,    B11000,  };  lcd.createChar(2, bar2);    byte bar3[8] = {    B11100,    B11100,    B11100,    B11100,    B11100,    B11100,    B11100,    B11100,  };  lcd.createChar(3, bar3);    byte bar4[8] = {    B11110,    B11110,    B11110,    B11110,    B11110,    B11110,    B11110,    B11110,  };  lcd.createChar(4, bar4);    byte bar5[8] = {    B11111,    B11111,    B11111,    B11111,    B11111,    B11111,    B11111,    B11111,  };  lcd.createChar(5, bar5);      byte leftArrow[8] = {    B00010,    B00110,    B01111,    B11111,    B01111,    B00110,    B00010,  };  lcd.createChar(6, leftArrow);    byte rightArrow[8] = {    B01000,    B01100,    B11110,    B11111,    B11110,    B01100,    B01000,  };  lcd.createChar(7, rightArrow);    // Smiley - just for fun  byte smile[8] = {    B10001,    B00000,    B00100,    B01100,    B00000,    B10001,    B01110,  };  lcd.createChar(8, smile);    lcd.begin(16, 2);    Serial.begin(9600);  // Set Pin modes     pinMode(BuzzerPin, OUTPUT);            // alarm buzzer  digitalWrite(BuzzerPin, LOW);          // Initially, off.    pinMode (Analog1pin, INPUT);    // boost sensor in    // Set Shift Register Pin Modes  pinMode(ShiftData, INPUT);  pinMode(ShiftClock, OUTPUT);  pinMode(ShiftLatch, OUTPUT);    lcd.clear();  lcd.setCursor(0,0);  lcd.print ("Boost Gauge...");  delay(500);  lcd.clear();}void loop(){    // Get the current ms value to compare timers with.  unsigned long currentMillis = millis();   //////////////////////////  //  Button Input/Menus  //  //////////////////////////    // Scan for button presses at the defined interval  if (currentMillis - buttonScanLastms > buttonScanInterval)  {    buttonScanLastms = currentMillis;        // Reset to "all-on"    // ButtonBits = 255; // B11111111        // Reset to "all-off"    ButtonBits = 0;           // Delay for key repeat - Delay the rescan if we've had a keypress detected within the ButtonRepeat time.    if (currentMillis - ButtonRepeatLastms > ButtonRepeatDelay)    {      /*      Using shift register example from http://arduino.cc/en/Tutorial/ShftIn12      */      //Pulse the latch pin high to collect parallel data.      digitalWrite(ShiftLatch,1);      delayMicroseconds(20);      //Drop the latch low to start shifting data into the MCU serially.      digitalWrite(ShiftLatch,0);            // Collect the data into a byte var.      ButtonBits = shiftIn(ShiftData, ShiftClock, MSBFIRST);      // Serial.println(ButtonBits, BIN);    }                    if (ButtonBits == B00000000)        // No buttons pressed    {      // We can use this section for timeout code if necessary later.    }        else if (ButtonBits == B10000000)  // Escape (Top Left)    {      ButtonRepeatLastms = currentMillis;      // If we're not in a Menu, set the MenuState, and then print the main menu.      if (MenuState == 0)      {        MenuState = 1;      // Set this flag to say we're in a menu        SubMenu = 0;        // Reset this to be main menu        WriteMenu(SubMenu);                      }      // If we're in a menu, set MenuState to 0 and clear the display in preperation for sensor view.      else if (MenuState > 0)      {        MenuState = 0;      // Set this flag to say we're not in a menu        lcd.clear();      }    }    else if (ButtonBits == B01000000)  // Up (Top Middle)    {      ButtonRepeatLastms = currentMillis;      // If We're in a Menu      if (MenuState > 0)      {        // And we're in Menu 1 (Graph MaxBoost)        if (SubMenu == 1)        {          BoostMax = BoostMax + 5;          mVPerBar = BoostMax / LCDBars;        // Bar graph magic calculations          mVPerChar = mVPerBar * LCDPixelWidth; //mV per full char        }        // And we're in Menu 2 (Boost Alarm)        else if (SubMenu == 2)        {          BoostAlarm = BoostAlarm + 5;        }                WriteMenu(SubMenu);      }    }    else if (ButtonBits == B00100000)  // Enter (Top Right)    {      ButtonRepeatLastms = currentMillis;    }    else if (ButtonBits == B00010000)  // Not used    {      ButtonRepeatLastms = currentMillis;    }    else if (ButtonBits == B00001000)  // Right (Bottom Right)    {      ButtonRepeatLastms = currentMillis;      // If we're in a menu, Increment the SubMenu variable and print the menu.      if (MenuState > 0)      {        SubMenu++;        WriteMenu(SubMenu);      }    }    else if (ButtonBits == B00000100)  // Down (Bottom Middle)    {      ButtonRepeatLastms = currentMillis;      // If We're in a Menu      if (MenuState > 0)      {        // And we're in Menu 1 (Graph MaxBoost)        if (SubMenu == 1)        {          BoostMax = BoostMax - 5;          mVPerBar = BoostMax / LCDBars;        // Bar graph magic calculations          mVPerChar = mVPerBar * LCDPixelWidth; //mV per full char        }        // And we're in Menu 2 (Boost Alarm)        else if (SubMenu == 2)        {          BoostAlarm = BoostAlarm - 5;        }                WriteMenu(SubMenu);      }    }    else if (ButtonBits == B00000010)  //Left (Bottom Left)    {      ButtonRepeatLastms = currentMillis;      // If we're in a menu, Decrement the SubMenu variable and print the menu.      if (MenuState > 0)      {        SubMenu--;        WriteMenu(SubMenu);      }    }    else if (ButtonBits == B00000001)  // Not Used    {      ButtonRepeatLastms = currentMillis;    }    else    {        // Do Nothing if some idiot presses more than one button at a time.    }    }     //////////////////////////////////////  //        Bar Graph / Alarm        //  /////////////////////////////////////  if (currentMillis - timerBarGraphLastms > timerBarGraphInterval)  {    timerBarGraphLastms = currentMillis;        //Read our sensor "Analog1"    Analog1Raw = analogRead(Analog1pin);        // Turn the alarm on or off.    if (Analog1Raw < BoostAlarm)   digitalWrite(12, LOW);        // Everything is fine...    if (Analog1Raw >= BoostAlarm)   digitalWrite(12, HIGH);        // Alarm!!        // We only want to print the bar graph stuff if we're not in a menu.    if (MenuState == 0) {          lcd.setCursor (0,1);      BarGraphValue = Analog1Raw;      BarGraphWritten = 0;            // To speed bar graph drawing, each full char is equivelent to 1/16th of the scale      // Print a full char for every full 1/16th of the scale and then print out a single part char for the remainder.      while (BarGraphValue > mVPerChar)      {              lcd.write(5);                                  // Write full blocks each representing 1x mvPerChar.        BarGraphValue = BarGraphValue - mVPerChar;     // Drop the remaining BarGraphValue by what we've printed        BarGraphWritten++;                             // Increment the char printed counter      }            // Print the appropriate 'part char' representing the remainder BarGraphValue.      if (BarGraphValue > ( 3 * mVPerBar))      {        lcd.write(4);      }      else if (BarGraphValue > ( 2 * mVPerBar))      {        lcd.write(3);      }      else if (BarGraphValue > ( 1 * mVPerBar))      {       lcd.write(2);      }      else if (BarGraphValue > ( 0 * mVPerBar))      {       lcd.write(1);          }            BarGraphWritten++;    //Increment the chars printed counter.              // Print whitespace to the end of the line. Always prints over whats there. May be inefficient on LCD IO.      while ((BarGraphWritten - LCDWidth) < 0)      {        lcd.write(" ");        BarGraphWritten++;      }    }      } //if (currentMillis - timerBarGraphLastms > timerBarGraphInterval)    /////////////////////////////  //       Text Display      //  /////////////////////////////  if (currentMillis - timerTextLastms > timerTextInterval && MenuState == 0 )  {    timerTextLastms = currentMillis;        //Debugging - Print the pin Voltage. 0-5000     /*     lcd.setCursor(12,0);    if (Analog1mV<1000) lcd.print(' ');    if (Analog1mV<100) lcd.print(' ');    if (Analog1mV<10) lcd.print(' ');    lcd.print(Analog1mV);    */        // Map it to mV.    //Analog1mV = map(Analog1Raw, 0, 1023, 0, 5000);        //psi=(0.04+((Analog1mV/1000)/(0.004*5)))*kpa2psi    // float Analog1mVx = Analog1mV;    //float Analog1Psi = (0.04+((Analog1mVx/1000)/(0.004*5)))*kpa2psi;        float Analog1Psi = Raw2PSI(Analog1Raw);    lcd.setCursor(0,0);    if (Analog1Psi<10) lcd.print(' ');    lcd.print (Analog1Psi);    lcd.print ("psi");    } // if (currentMillis - timerTextLastms > timerTextInterval)  }// Self explanitoryvoid WriteMenu (int menuID) {  // Clear the screen ready for menus  lcd.clear();  if (menuID == 0)  {    lcd.setCursor(0,0);    lcd.print("<  Main  Menu  >");    lcd.setCursor(0,1);    lcd.print("Esc | Enter=Save");  }  else if (menuID == 1)  {    lcd.setCursor(0,0);    lcd.print("<Graph MaxBoost>");    lcd.setCursor(0,1);    lcd.print(Raw2PSI(BoostMax));    lcd.print ("psi");  }  else if (menuID == 2)  {    lcd.setCursor(0,0);    lcd.print("< Boost  Alarm >");    lcd.setCursor(0,1);    lcd.print(Raw2PSI(BoostAlarm));    lcd.print ("psi");  }  // Unknown Menu ID.. oh noes!  else  {    lcd.setCursor(0,0);    lcd.print("<  Undef Menu  >");    lcd.setCursor(0,1);    lcd.print("menuID: ");    lcd.print(menuID);  }}float Raw2PSI(int value){  float result;  result = map(value, 0, 1023, 0, 5000);  result = (0.04+((result/1000)/(0.004*5)))*kpa2psi;  return result;}/* void padding( int number, byte width ) {  int currentMax = 10;  char returnString[width];    for (byte i = 0; i < width-1; i++){    if (number < currentMax) {	returnString[i]=("0");    }    currentMax *= 10;  }  // ToDo: Loop over the rest of the string, add to returnString and return  Serial.print(number);} */