├── LICENSE ├── README.md ├── bitmaps ├── accelMock1.bmp ├── accelMock2.bmp ├── batt.bmp ├── coolant.bmp ├── iat.bmp ├── mock1.bmp ├── mock2.bmp ├── mockBattVolts.bmp ├── mockO2.bmp ├── mockOilTemp.bmp ├── o2.bmp ├── oil.bmp ├── oil2.bmp ├── robothead.bmp ├── robotheadNoEyesForShiftyEyes.bmp ├── robotmeterlogo.bmp ├── template_size.bmp └── template_size_color.bmp ├── brzclockgauge └── brzclockgauge.ino ├── config └── gauges ├── graphicsscratchpad └── graphicsScratchPad.ino ├── mockupbitmaps ├── accel1.bmp ├── accel2.bmp ├── accel3.bmp ├── dualbar.bmp ├── layout-landscape.bmp ├── layout.bmp ├── loggingpage.bmp ├── roundsingle.bmp ├── roundsingle2.bmp ├── singlebar.bmp └── sizetemplate.bmp ├── modularTFTgauge ├── gauges └── modularTFTgauge.ino ├── oledOBDgaugeSmall └── oledOBDgaugeSmall.ino ├── oledOBDgaugesSimpleIrvinedLibTest └── oledOBDgaugesSimpleIrvinedLibTest.ino ├── oledOBDgaugesSmallIrvinedLib-Boost └── oledOBDgaugesSmallIrvinedLib-Boost.ino └── oledOBDgaugesSmallIrvinedLib └── oledOBDgaugesSmallIrvinedLib.ino /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, stirobot 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the {organization} nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | arduinoModularTFTgauges 2 | ======================= 3 | 4 | Modular (configurable via a config file) gauges for 1.8" and other common tft boards 5 | -------------------------------------------------------------------------------- /bitmaps/accelMock1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stirobot/arduinoModularTFTgauges/b65521b477ae7ec4a5b2101e16eddf6a834583fa/bitmaps/accelMock1.bmp -------------------------------------------------------------------------------- /bitmaps/accelMock2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stirobot/arduinoModularTFTgauges/b65521b477ae7ec4a5b2101e16eddf6a834583fa/bitmaps/accelMock2.bmp -------------------------------------------------------------------------------- /bitmaps/batt.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stirobot/arduinoModularTFTgauges/b65521b477ae7ec4a5b2101e16eddf6a834583fa/bitmaps/batt.bmp -------------------------------------------------------------------------------- /bitmaps/coolant.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stirobot/arduinoModularTFTgauges/b65521b477ae7ec4a5b2101e16eddf6a834583fa/bitmaps/coolant.bmp -------------------------------------------------------------------------------- /bitmaps/iat.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stirobot/arduinoModularTFTgauges/b65521b477ae7ec4a5b2101e16eddf6a834583fa/bitmaps/iat.bmp -------------------------------------------------------------------------------- /bitmaps/mock1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stirobot/arduinoModularTFTgauges/b65521b477ae7ec4a5b2101e16eddf6a834583fa/bitmaps/mock1.bmp -------------------------------------------------------------------------------- /bitmaps/mock2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stirobot/arduinoModularTFTgauges/b65521b477ae7ec4a5b2101e16eddf6a834583fa/bitmaps/mock2.bmp -------------------------------------------------------------------------------- /bitmaps/mockBattVolts.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stirobot/arduinoModularTFTgauges/b65521b477ae7ec4a5b2101e16eddf6a834583fa/bitmaps/mockBattVolts.bmp -------------------------------------------------------------------------------- /bitmaps/mockO2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stirobot/arduinoModularTFTgauges/b65521b477ae7ec4a5b2101e16eddf6a834583fa/bitmaps/mockO2.bmp -------------------------------------------------------------------------------- /bitmaps/mockOilTemp.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stirobot/arduinoModularTFTgauges/b65521b477ae7ec4a5b2101e16eddf6a834583fa/bitmaps/mockOilTemp.bmp -------------------------------------------------------------------------------- /bitmaps/o2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stirobot/arduinoModularTFTgauges/b65521b477ae7ec4a5b2101e16eddf6a834583fa/bitmaps/o2.bmp -------------------------------------------------------------------------------- /bitmaps/oil.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stirobot/arduinoModularTFTgauges/b65521b477ae7ec4a5b2101e16eddf6a834583fa/bitmaps/oil.bmp -------------------------------------------------------------------------------- /bitmaps/oil2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stirobot/arduinoModularTFTgauges/b65521b477ae7ec4a5b2101e16eddf6a834583fa/bitmaps/oil2.bmp -------------------------------------------------------------------------------- /bitmaps/robothead.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stirobot/arduinoModularTFTgauges/b65521b477ae7ec4a5b2101e16eddf6a834583fa/bitmaps/robothead.bmp -------------------------------------------------------------------------------- /bitmaps/robotheadNoEyesForShiftyEyes.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stirobot/arduinoModularTFTgauges/b65521b477ae7ec4a5b2101e16eddf6a834583fa/bitmaps/robotheadNoEyesForShiftyEyes.bmp -------------------------------------------------------------------------------- /bitmaps/robotmeterlogo.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stirobot/arduinoModularTFTgauges/b65521b477ae7ec4a5b2101e16eddf6a834583fa/bitmaps/robotmeterlogo.bmp -------------------------------------------------------------------------------- /bitmaps/template_size.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stirobot/arduinoModularTFTgauges/b65521b477ae7ec4a5b2101e16eddf6a834583fa/bitmaps/template_size.bmp -------------------------------------------------------------------------------- /bitmaps/template_size_color.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stirobot/arduinoModularTFTgauges/b65521b477ae7ec4a5b2101e16eddf6a834583fa/bitmaps/template_size_color.bmp -------------------------------------------------------------------------------- /brzclockgauge/brzclockgauge.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | //gauge for replacing clock in a brz/frs 4 | //3 buttons 5 | //00 = mode change 6 | //hours = show peak for 10 seconds 7 | //minutes = reset peak for that gauge page 8 | //uses obd II uart adapter 9 | //use the simplest arduino 10 | 11 | /* parts list: 12 | clock 13 | arduino (cheaper for smaller one) 14 | wires 15 | obd II module 16 | 7 segment serial device 17 | */ 18 | 19 | 20 | 21 | //This is a character buffer that will store the data from the serial port 22 | char rxData[115]; 23 | char rxIndex=0; 24 | int buttonModepin = 13; 25 | int buttonPeakpin = 12; 26 | int buttonResetpin = 11; 27 | String modeList[] = { 28 | "obdbrzoiltempf", "obdafr", "obdvolts"}; 29 | //names must be 4 characters long...some alphas don't print ("m") 30 | String modeNames[] = { 31 | "xOIL", "xAFx", "xULT"}; 32 | String modeNames2[] = {"Fxxx", "xxxx", "xxxx"}; 33 | int warnLevels[] = { 34 | 212, 220, 15}; 35 | int warnSign[] = { 36 | 1,1,1}; //1 for high, 2 for low (in cases like oil pressure) 37 | int peaks[] = { 38 | 0,0,0}; 39 | int mode = 1; 40 | int modes = 2; //actually this means there are 3 modes...0 is the first of the array 41 | 42 | SoftwareSerial LCDSerial(9, 10); 43 | 44 | void setup(){ 45 | Serial.begin(9600); 46 | LCDSerial.begin(9600); 47 | delay(10); 48 | LCDSerial.print("v"); //reset the display 49 | //flash custom title 50 | LCDSerial.print("xxxx"); 51 | //flash name of gauge 52 | LCDSerial.print("v"); 53 | LCDSerial.print("xNOT"); 54 | delay(400); 55 | LCDSerial.print("xOTx"); 56 | delay(300); 57 | LCDSerial.print("xTxA"); 58 | delay(300); 59 | LCDSerial.print("xxAx"); 60 | delay(300); 61 | LCDSerial.print("xAxC"); 62 | delay(300); 63 | LCDSerial.print("xxCL"); 64 | delay(300); 65 | LCDSerial.print("xCLC"); 66 | Serial.println("ATZ"); 67 | getResponse(); 68 | Serial.println("ATDP"); 69 | getResponse(); 70 | Serial.println("ATE0"); 71 | getResponse(); 72 | Serial.println("AT SH 7E0"); 73 | delay(2000); 74 | getResponse(); 75 | LCDSerial.print("v"); 76 | Serial.flush(); 77 | 78 | pinMode(buttonModepin, INPUT); 79 | pinMode(buttonPeakpin, INPUT); 80 | pinMode(buttonResetpin, INPUT); 81 | } 82 | 83 | void loop(){ 84 | //loop to control modes, etc 85 | LCDSerial.print("xxxx"); 86 | LCDSerial.print(modeNames[mode]); 87 | delay(800); 88 | LCDSerial.print(modeNames2[mode]); 89 | delay(800); 90 | LCDSerial.print("v"); 91 | while ( (digitalRead(buttonModepin) == LOW) ){ 92 | 93 | if (digitalRead(buttonPeakpin) == HIGH){ //hold down the peaks button to show the peaks 94 | LCDSerial.print("xxxx"); 95 | if ( ( (int)peaks[mode]/1000) == 0){ 96 | LCDSerial.print("x"); 97 | } 98 | if ( ( (int)peaks[mode]/100) == 0){ 99 | LCDSerial.print("x"); 100 | } 101 | if ( ( (int)peaks[mode]/10) == 0){ 102 | LCDSerial.print("x"); 103 | } 104 | if ( ( (int)peaks[mode]) == 0){ 105 | LCDSerial.print("x"); 106 | } 107 | LCDSerial.print(peaks[mode]); 108 | while ( (digitalRead(buttonPeakpin) == HIGH) ){ 109 | } 110 | } 111 | 112 | if (digitalRead(buttonResetpin) == HIGH){ 113 | LCDSerial.print("xxxx"); 114 | LCDSerial.print("RXST"); 115 | peaks[mode] = 0; 116 | while ( (digitalRead(buttonResetpin) == HIGH) ){//if you hold down the peak reset pin...wait a sec and then hit the peak pin...resets obdii and screen 117 | if ( digitalRead(buttonPeakpin) == HIGH ){ 118 | Serial.println("ATZ"); 119 | getResponse(); 120 | Serial.println("ATDP"); 121 | getResponse(); 122 | Serial.println("ATE0"); 123 | getResponse(); 124 | delay(2000); 125 | LCDSerial.print("v"); 126 | Serial.flush(); 127 | } 128 | } 129 | } 130 | 131 | int value = getOBDIIvalue(modeList[mode]); 132 | if (value > peaks[mode]){ 133 | peaks[mode] = value; 134 | } 135 | 136 | if ( ( (int)value/1000) == 0){ 137 | LCDSerial.print("x"); 138 | } 139 | if ( ( (int)value/100) == 0){ 140 | LCDSerial.print("x"); 141 | } 142 | if ( ( (int)value/10) == 0){ 143 | LCDSerial.print("x"); 144 | } 145 | if ( ( (int)value) == 0){ 146 | LCDSerial.print("x"); 147 | } 148 | LCDSerial.print(value); 149 | 150 | if ( ( (value > warnLevels[mode]) && (warnSign[mode] == 1) ) || ( (value < warnLevels[mode]) && (warnSign[mode] == 0) ) ){ 151 | LCDSerial.print("xxxx"); 152 | delay(45); 153 | LCDSerial.print(value); 154 | } 155 | } 156 | while ( (digitalRead(buttonModepin) == HIGH) ){ 157 | } 158 | if (mode >= modes){ 159 | mode = 0; 160 | } 161 | else mode++; 162 | } 163 | 164 | //from: https://forum.sparkfun.com/viewtopic.php?f=14&t=38253 165 | void getResponse(void){ 166 | char c; 167 | do { 168 | if (Serial.available() > 0) 169 | { 170 | c = Serial.read(); 171 | if ((c != '>') && (c != '\r') && (c != '\n')) //Keep these out of our buffer 172 | { 173 | rxData[rxIndex++] = c; //Add whatever we receive to the buffer 174 | } 175 | } 176 | } 177 | while (c != '>'); //The ELM327 ends its response with this char so when we get it we exit out. 178 | rxData[rxIndex++] = '\0'; //Converts the array into a string 179 | //Serial.print("rxData: "); 180 | //Serial.println(rxData); 181 | rxIndex = 0; //Set this to 0 so next time we call the read we get a "clean buffer 182 | } 183 | 184 | long int getOBDIIvalue(String whichSensor){ 185 | /*what is working: 186 | speed - works 187 | rpms - works 188 | coolant - reads in F as 10 and nothing else 189 | boost - can't test yet 190 | iat and maf - can't tell/don't really care 191 | volts - works (maybe add decimal?) 192 | oiltemp(f/c) - haven't tested (shouldn't work on many cars) 193 | brz oil temp - in F shows -72 and nothing else 194 | brz fuel left - shows 1 and nothing else 195 | */ 196 | Serial.flush(); 197 | long int value = 0; 198 | if (whichSensor.indexOf("obdspeedkph") >= 0){ 199 | Serial.println("010D"); //mode 1 0D PID 200 | //getResponse(); //command echoed 201 | getResponse(); //value 202 | value = strtol(&rxData[6],0,16) ; //convert the string to integer 203 | } 204 | if (whichSensor.indexOf("obdspeedmph") >= 0){ 205 | Serial.println("010D"); //mode 1 0D PID 206 | getResponse(); //value 207 | value = strtol(&rxData[6],0,16)/1.6 ; //convert the string to integer 208 | } 209 | if (whichSensor.indexOf("obdrpms") >= 0){ 210 | Serial.println("010C"); //mode 1 0C PID (rpm) 211 | //Serial.println("getting rpm"); 212 | getResponse(); //value 213 | value = ((strtol(&rxData[6],0,16)*256)+strtol(&rxData[9],0,16))/4; //aka ((A*256)+B)/4 214 | //Serial.println("rpm ="); 215 | //Serial.println(value); 216 | } 217 | if (whichSensor.indexOf("obdcoolantc") >=0){ 218 | Serial.println("O1O5"); 219 | getResponse(); 220 | value = (strtol(&rxData[6],0,16)-40); //aka A-40 221 | } 222 | if (whichSensor.indexOf("obdcoolantf") >=0){ 223 | //Serial.println("coolantf"); 224 | Serial.println("O1O5"); //gives raw data of "?" 225 | getResponse(); 226 | value = ((strtol(&rxData[6],0,16))-40)*1.8+32; //aka A-40 227 | //Serial.print("value of coolantf "); 228 | //Serial.print(value); 229 | } 230 | if (whichSensor.indexOf("obdboost") >= 0){ 231 | Serial.println("0265"); //intake manifold abs pressure 232 | getResponse(); 233 | value = (strtol(&rxData[6],0,16)); //aka A 234 | } 235 | if (whichSensor.indexOf("obdafr") >= 0){ 236 | Serial.println("0134"); //afr reading (readings aren't great) 237 | getResponse(); 238 | value = ((strtol(&rxData[6],0,16)*256)+strtol(&rxData[9],0,16))/32768*14.7; //(A*256+B)/32768*14.7 239 | } 240 | if (whichSensor.indexOf("obdiat") >= 0){ 241 | Serial.println("O1OF"); 242 | getResponse(); 243 | value = (strtol(&rxData[6],0,16)-40); //aka A-40 244 | } 245 | if (whichSensor.indexOf("obdmaf") >= 0){ 246 | Serial.println("0110"); 247 | getResponse(); 248 | value = ((strtol(&rxData[6],0,16)*256)+strtol(&rxData[9],0,16))/100; //aka ((A*256)+B)/100 249 | } 250 | if (whichSensor.indexOf("obdvolts") >= 0){ 251 | Serial.println("0142"); 252 | //Serial.println("getting volts"); 253 | getResponse(); 254 | value = ((strtol(&rxData[6],0,16)*256)+strtol(&rxData[9],0,16))/1000; //aka ((A*256)+B)/100 255 | //Serial.println("volts is:"); 256 | //Serial.println(value); 257 | } 258 | if (whichSensor.indexOf("obdoiltempc") >= 0){ 259 | Serial.println("015C"); 260 | getResponse(); 261 | value = strtol(&rxData[6],0,16)-40; //aka (A-40) 262 | } 263 | if (whichSensor.indexOf("obdoiltempf") >= 0){ 264 | Serial.println("015C"); 265 | getResponse(); 266 | value = (strtol(&rxData[6],0,16)-40)*1.8+32; //aka (A-40) *1.8 267 | } 268 | 269 | //nonstandard/experiemental PIDs 270 | if (whichSensor.indexOf("obdbrzoiltempc") >= 0){ 271 | // Serial1.println("AT SH 7E0"); 272 | //Serial1.flush(); 273 | Serial.println("2101"); 274 | getResponse(); 275 | value = ((float)strtol(&rxData[109],0,16) - 40); //29th byte - 40 (?) 276 | //Serial1.println("AT D"); 277 | //Serial1.println("AT E0"); 278 | //delay(40); 279 | //Serial1.println("ATSP6"); 280 | } 281 | if (whichSensor.indexOf("obdbrzoiltempf") >= 0){ //works 282 | //Serial1.println("AT SH 7E0"); 283 | //Serial1.flush(); 284 | //getResponse(); 285 | Serial.println("2101"); 286 | getResponse(); 287 | //Serial.println("brz oil temp"); 288 | delay(40); 289 | //Serial.println(&rxData[109]); 290 | //Serial.println((float)strtol(&rxData[109],0,16)); 291 | value = ((float)strtol(&rxData[109],0,16) - 40) * 1.8 + 32; 292 | //Serial.println(value); 293 | //Serial1.println("AT D"); //these two lines make the next 2101 reading get cut off 294 | //Serial1.println("AT E0"); 295 | //Serial1.flush(); 296 | //Serial1.println("ATSP6");//doesn't work and is slow (probing for protocol takes work) 297 | //getResponse(); 298 | //Serial1.flush(); 299 | } 300 | 301 | delay(100); 302 | return value; 303 | } 304 | 305 | -------------------------------------------------------------------------------- /config/gauges: -------------------------------------------------------------------------------- 1 | splash:autox.bmp 2 | 3 | #all of the config items for a page have to be kept in order or defaults might be use (at best) 4 | 5 | #colorscheme use these colors -> yellow, red, green, black, blue, white, magenta 6 | background:black 7 | outline:red 8 | fill:red 9 | textdefault:blue 10 | alert:white 11 | severe:red 12 | 13 | #pin config 14 | #sensorName:pin 15 | #legal sensor names: 16 | # oiltemp 17 | # oilpressure 18 | # boostpressure 19 | # temperature 20 | # accelx 21 | # accely 22 | # obdoiltempf 23 | # obdoiltempc 24 | # obdbrzoiltempc 25 | # obdbrzoiltempf 26 | # obdspeedkph 27 | # obdspeedmph 28 | # obdvolts 29 | # obdcoolant 30 | # obdafr //not yet 31 | # obdmaf //in grams/sec 32 | # obdiat //in deg C 33 | # fake 34 | #obd sensors don't have pins associated with them 35 | 36 | #page (aka mode) config 37 | #as many pages as you want...the sketch will flip through until EOF and start again 38 | #each sensor is configured per page 39 | #obd sensors don't have pin assignments after them 40 | #page types: 41 | # twobar - two horizontal bar graphs with text 42 | # onebar - one horizontal bar graph with text 43 | # cross - cross chart for accelerometer 44 | # round - 1 round gauge for one sensor 45 | #sensor*text can be about 8 chars long on the one sensor pages...a little longer on the others (due to font size) 46 | #There is a "fake" sensor...give it a pin number that is the max value you want...allows for easy testing. 47 | 48 | #a page called logging will log the given parameters and display the first 4 as plain text 49 | #because of the way logging closes and opens a file...make sure logging is always the last page... 50 | #pages after logging will be skipped 51 | pagetype:twobar 52 | sensor1:fake 53 | sensor2:fake 54 | sensor1pin:300 55 | sensor2pin:100 56 | sensor1text:Oil Temp 57 | sensor2text:Water 58 | sensor1max:300 59 | sensor2max:100 60 | sensor1alert:190 61 | sensor2alert:0 62 | sensor1units:F 63 | sensor2units:F 64 | 65 | pagetype:accel 66 | sensor1:accelx 67 | sensor1pin:8 68 | sensor2:accely 69 | sensor2pin:9 70 | 71 | pagetype:round 72 | sensor1:fake 73 | sensor1pin:300 74 | sensor1text:Oil T 75 | sensor1max:300 76 | sensor1alert:190 77 | sensor1units:F 78 | 79 | pagetype:round 80 | sensor1:fake 81 | sensor1pin:250 82 | sensor1text:Oil Pressure 83 | sensor1max:250 84 | sensor1alert:200 85 | sensor1units:Psi 86 | 87 | pagetype:onebar 88 | sensor1:fake 89 | sensor1pin:300 90 | sensor1text:Oil Temp 91 | sensor1max:300 92 | sensor1alert:250 93 | sensor1units:F 94 | 95 | pagetype:onebar 96 | sensor1:fake 97 | sensor1pin:21 98 | sensor1text:Boost 99 | sensor1max:21 100 | sensor1alert:19 101 | sensor1units:Psi 102 | 103 | pagetype:round 104 | sensor1:fake 105 | sensor1pin:21 106 | sensor1text:Boost 107 | sensor1max:21 108 | sensor1alert:18 109 | sensor1units:Psi 110 | 111 | allgauges: 112 | pagetype:logging 113 | monitorinterval:40 114 | sensor1:fake 115 | sensor2:fake 116 | sensor3:fake 117 | sensor4:fake 118 | sensor5:fake 119 | sensor6:fake 120 | sensor1pin:300 121 | sensor2pin:200 122 | sensor3pin:250 123 | sensor4pin:100 124 | sensor5pin:20 125 | sensor6pin:350 126 | sensor1alert:200 127 | sensor2alert:150 128 | sensor3alert:200 129 | sensor4alert:90 130 | sensor5alert:18 131 | sensor6alert:300 132 | sensor1severe:255 133 | sensor2severe:175 134 | sensor3severe:240 135 | sensor4severe:99 136 | sensor5severe:20 137 | sensor6severe:340 -------------------------------------------------------------------------------- /graphicsscratchpad/graphicsScratchPad.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | //pin reference for tft from; 9 | /*http://webshed.org/wiki/18tftbreakout 10 | eBay Board Adafruit Board Arduino conections 11 | VCC VCC 5V 12 | BKL LITE GND on eBay, 5V on Adafruit 13 | RESET RESET 8 14 | RS D/C 9 15 | MISO MISO 12 (50 for mega) 16 | MOSI MOSI 11 (51 for mega) 17 | SCLK SCLK 13 (52 for mega) 18 | LCD CS TFT CS 10 (53 for mega) 19 | SD CS CARD CS 4 20 | GND GND GND 21 | */ 22 | #define SD_CS 4 23 | #define LCD_CS 53 24 | #define LCD_DC 9 25 | #define LCD_RST 8 26 | 27 | Adafruit_ST7735 tft = Adafruit_ST7735(LCD_CS, LCD_DC, LCD_RST); 28 | 29 | uint16_t background = ST7735_BLACK; 30 | uint16_t outline = ST7735_WHITE; 31 | uint16_t fill = ST7735_BLUE; 32 | uint16_t textdefault = ST7735_RED; 33 | uint16_t alert = ST7735_YELLOW; 34 | 35 | void setup(){ 36 | Serial.begin(9600); //debugging to serial console 37 | tft.initR(INITR_BLACKTAB); 38 | tft.fillScreen(background); 39 | tft.setRotation(1); 40 | tft.fillScreen(background); 41 | } 42 | 43 | void loop(){ 44 | /* 45 | //logging layout 46 | tft.setCursor(40, 5); 47 | tft.setTextColor(outline); 48 | tft.setTextSize(2); 49 | tft.println("Logging"); 50 | tft.setTextSize(1); 51 | tft.setCursor(10, 40); 52 | tft.println("obdoiltemp:"); 53 | tft.setCursor(110, 40); 54 | tft.println("210"); 55 | tft.setCursor(10, 60); 56 | tft.println("obdvolts:"); 57 | tft.setCursor(110, 60); 58 | tft.println("13.3"); 59 | tft.setCursor(10, 80); 60 | tft.println("oilPsi:"); 61 | tft.setCursor(110, 80); 62 | tft.println("85"); 63 | tft.setCursor(10, 100); 64 | tft.println("obdrpms:"); 65 | tft.setCursor(110, 100); 66 | tft.println("2503"); 67 | */ 68 | 69 | /* 70 | //single bar layout 71 | tft.setCursor(0, 5); 72 | tft.setTextColor(outline); 73 | tft.setTextSize(2); 74 | tft.println("Oil Temp"); 75 | tft.fillRect(0, 40, 68, 40, fill); 76 | tft.setCursor(0, 100); 77 | tft.println("210"); 78 | tft.setCursor(50,100); 79 | tft.println("F"); 80 | */ 81 | 82 | /* 83 | //double bar 84 | tft.setTextSize(1); 85 | tft.setTextColor(textdefault); 86 | tft.setCursor(0,0); 87 | tft.println("Oil Temp"); 88 | tft.setCursor(0,70); 89 | tft.println("Coolant TEmp"); 90 | tft.fillRect(0,20,68,30, fill); 91 | tft.fillRect(0,90,30,30, fill); 92 | 93 | tft.setCursor(100,0); 94 | tft.println("120"); 95 | tft.setCursor(100,70); 96 | tft.println("79"); 97 | */ 98 | 99 | //accelerometer 100 | tft.setTextSize(1); 101 | tft.drawRect(60,0,40,128,outline); 102 | tft.drawRect(0,44,160,40,outline); 103 | tft.drawRect(60,44,40,40,background);//empty the center line 104 | tft.fillCircle(115,64,17,fill);//x ball 105 | tft.fillCircle(80,70,17,fill);//y ball 106 | 107 | tft.setCursor(0,0); 108 | tft.println("x: 0.5"); 109 | tft.setCursor(110,0); 110 | tft.println("y: 0.3"); 111 | tft.setCursor(0,100); 112 | tft.println("px: 0.5"); 113 | tft.setCursor(110,100); 114 | tft.println("py: -0.8"); //will have to use abs() compare to get peaks here 115 | 116 | //round 117 | /*tft.setTextSize(2); 118 | tft.setTextColor(textdefault); 119 | tft.setCursor(0, 2); 120 | tft.println("Oil Temp"); 121 | tft.drawCircle(80, 70, 50, textdefault); 122 | tft.drawCircle(80, 70, 49, textdefault); 123 | tft.setCursor(65,60); 124 | tft.println("210"); 125 | 126 | tft.fillCircle(80,113,5,fill); //no calc for the zero position 127 | float rad = 0.0; 128 | for (int i = 0; i <= 270; i+=5){ 129 | rad = i * PI / 180; 130 | //works for lower left quadrant 131 | //upper left is 80-sin(i)*43, 70-cos(i)*43 132 | //upper right is 80+sin(i)*43, 70+cos(i)*43 133 | //need special cases for 0, 90, 180 deg (because sin(0)=0 134 | tft.fillCircle( (80-((int)(sin(rad)*43.0) ) ), (70+( (int)(cos(rad)*43.0))), 5 , fill ); 135 | } 136 | */ 137 | delay(10000); 138 | 139 | //accel cross 140 | 141 | } 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /mockupbitmaps/accel1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stirobot/arduinoModularTFTgauges/b65521b477ae7ec4a5b2101e16eddf6a834583fa/mockupbitmaps/accel1.bmp -------------------------------------------------------------------------------- /mockupbitmaps/accel2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stirobot/arduinoModularTFTgauges/b65521b477ae7ec4a5b2101e16eddf6a834583fa/mockupbitmaps/accel2.bmp -------------------------------------------------------------------------------- /mockupbitmaps/accel3.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stirobot/arduinoModularTFTgauges/b65521b477ae7ec4a5b2101e16eddf6a834583fa/mockupbitmaps/accel3.bmp -------------------------------------------------------------------------------- /mockupbitmaps/dualbar.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stirobot/arduinoModularTFTgauges/b65521b477ae7ec4a5b2101e16eddf6a834583fa/mockupbitmaps/dualbar.bmp -------------------------------------------------------------------------------- /mockupbitmaps/layout-landscape.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stirobot/arduinoModularTFTgauges/b65521b477ae7ec4a5b2101e16eddf6a834583fa/mockupbitmaps/layout-landscape.bmp -------------------------------------------------------------------------------- /mockupbitmaps/layout.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stirobot/arduinoModularTFTgauges/b65521b477ae7ec4a5b2101e16eddf6a834583fa/mockupbitmaps/layout.bmp -------------------------------------------------------------------------------- /mockupbitmaps/loggingpage.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stirobot/arduinoModularTFTgauges/b65521b477ae7ec4a5b2101e16eddf6a834583fa/mockupbitmaps/loggingpage.bmp -------------------------------------------------------------------------------- /mockupbitmaps/roundsingle.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stirobot/arduinoModularTFTgauges/b65521b477ae7ec4a5b2101e16eddf6a834583fa/mockupbitmaps/roundsingle.bmp -------------------------------------------------------------------------------- /mockupbitmaps/roundsingle2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stirobot/arduinoModularTFTgauges/b65521b477ae7ec4a5b2101e16eddf6a834583fa/mockupbitmaps/roundsingle2.bmp -------------------------------------------------------------------------------- /mockupbitmaps/singlebar.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stirobot/arduinoModularTFTgauges/b65521b477ae7ec4a5b2101e16eddf6a834583fa/mockupbitmaps/singlebar.bmp -------------------------------------------------------------------------------- /mockupbitmaps/sizetemplate.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stirobot/arduinoModularTFTgauges/b65521b477ae7ec4a5b2101e16eddf6a834583fa/mockupbitmaps/sizetemplate.bmp -------------------------------------------------------------------------------- /modularTFTgauge/gauges: -------------------------------------------------------------------------------- 1 | splash:autox.bmp 2 | 3 | #all of the config items for a page have to be kept in order or defaults might be use (at best) 4 | 5 | #colorscheme use these colors -> yellow, red, green, black, blue, white, magenta 6 | background:black 7 | outline:red 8 | fill:blue 9 | textdefault:blue 10 | alert:yellow 11 | severe:red 12 | 13 | #pin config 14 | #sensorName:pin 15 | #legal sensor names: 16 | # oiltemp 17 | # oilpressure 18 | # boostpressure 19 | # temperature 20 | # accelx 21 | # accely 22 | # obdoiltempf 23 | # obdoiltempc 24 | # obdbrzoiltempc 25 | # obdbrzoiltempf 26 | # obdspeedkph 27 | # obdspeedmph 28 | # obdvolts 29 | # obdcoolant 30 | # obdafr //not yet 31 | # obdmaf //in grams/sec 32 | # obdiat //in deg C 33 | # fake 34 | #obd sensors don't have pins associated with them 35 | 36 | #page (aka mode) config 37 | #as many pages as you want...the sketch will flip through until EOF and start again 38 | #each sensor is configured per page 39 | #obd sensors don't have pin assignments after them 40 | #page types: 41 | # twobar - two horizontal bar graphs with text 42 | # onebar - one horizontal bar graph with text 43 | # cross - cross chart for accelerometer 44 | # round - 1 round gauge for one sensor 45 | #sensor*text can be about 8 chars long on the one sensor pages...a little longer on the others (due to font size) 46 | #There is a "fake" sensor...give it a pin number that is the max value you want...allows for easy testing. 47 | 48 | #a page called logging will log the given parameters and display the first 4 as plain text 49 | #because of the way logging closes and opens a file...make sure logging is always the last page... 50 | #pages after logging will be skipped 51 | pagetype:accel 52 | sensor1:accelx 53 | sensor1pin:8 54 | sensor2:accely 55 | sensor2pin:9 56 | 57 | pagetype:twobar 58 | sensor1:obdbrzoiltempf 59 | sensor2:obdcoolantf 60 | sensor1pin:0 61 | sensor2pin:0 62 | sensor1text:Oil Temp 63 | sensor2text:Coolant 64 | sensor1max:380 65 | sensor2max:380 66 | sensor1alert:210 67 | sensor2alert:210 68 | sensor1units:F 69 | sensor2units:F 70 | 71 | pagetype:round 72 | sensor1:obdrpms 73 | sensor1pin:0 74 | sensor1text:RPM 75 | sensor1max:8000 76 | sensor1alert:7000 77 | sensor1units:rpm 78 | 79 | pagetype:round 80 | sensor1:obdbrzoiltempf 81 | sensor1pin:0 82 | sensor1text:Oil Temp 83 | sensor1max:380 84 | sensor1alert:210 85 | sensor1units:F 86 | 87 | pagetype:onebar 88 | sensor1:obdvolts 89 | sensor1pin:0 90 | sensor1text:Voltage 91 | sensor1max:20 92 | sensor1alert:15 93 | sensor1units:V 94 | 95 | pagetype:round 96 | sensor1:obdbrzfuelleft 97 | sensor1pin:0 98 | sensor1text:Fuel Left 99 | sensor1max:100 100 | sensor1alert:110 101 | sensor1units:% 102 | 103 | pagetype:onebar 104 | sensor1:obdspeedmph 105 | sensor1pin:0 106 | sensor1text:Speed 107 | sensor1max:110 108 | sensor1alert:55 109 | sensor1units:mph 110 | 111 | pagetype:twobar 112 | sensor1:obdiat 113 | sensor2:obdmaf 114 | sensor1pin:0 115 | sensor2pin:0 116 | sensor1text:IAT 117 | sensor2text:MAF 118 | sensor1max:215 119 | sensor2max:655 120 | sensor1alert:200 121 | sensor2alert:500 122 | sensor1units:C 123 | sensor2units:g/sec 124 | 125 | #monitor intervals that are too small will make refreshes stuttery 126 | allgauges: 127 | pagetype:logging 128 | monitorinterval:25 129 | sensor1:obdbrzoiltempf 130 | sensor2:obdcoolantf 131 | sensor3:obdvolts 132 | sensor4:obdspeedmph 133 | sensor5:obdrpms 134 | sensor6:obdbrzfuelleft 135 | sensor1pin:0 136 | sensor2pin:0 137 | sensor3pin:0 138 | sensor4pin:0 139 | sensor5pin:0 140 | sensor6pin:0 141 | sensor1alert:210 142 | sensor2alert:190 143 | sensor3alert:13 144 | sensor4alert:90 145 | sensor5alert:5000 146 | sensor6alert:110 147 | sensor1severe:300 148 | sensor2severe:210 149 | sensor3severe:15 150 | sensor4severe:99 151 | sensor5severe:6500 152 | sensor6severe:110 -------------------------------------------------------------------------------- /modularTFTgauge/modularTFTgauge.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | /*modular gauges... 8 | a new start to the 1.8" tft based gauges 9 | most things are configured in the SD card config file, "gauges" 10 | 11 | Modular 12 | 3 types of gauge 13 | many types of sensor 14 | you choose the order 15 | you choose the peaks/warns/etc. 16 | */ 17 | 18 | /* TODO's 19 | short: 20 | -logging done properly to file 21 | -debug obd II stuffs 22 | -fix 0 glitch on bar charts 23 | -make check for obd II and if it isn't there then don't freeze up 24 | long: 25 | -find an elegant solution to negative warnings (oil pressure) 26 | -code cleanup 27 | -more error catching 28 | -make s**t fucking awesome 29 | */ 30 | 31 | //pin reference for tft from; 32 | /*http://webshed.org/wiki/18tftbreakout 33 | eBay Board Adafruit Board Arduino conections 34 | VCC VCC 5V 35 | BKL LITE GND on eBay, 5V on Adafruit 36 | RESET RESET 8 37 | RS D/C 9 38 | MISO MISO 12 (50 for mega) 39 | MOSI MOSI 11 (51 for mega) 40 | SCLK SCLK 13 (52 for mega) 41 | LCD CS TFT CS 10 (53 for mega) 42 | SD CS CARD CS 4 43 | GND GND GND 44 | */ 45 | 46 | /* Other connections 47 | 4 wire for accelerometer 48 | 10 for tft 49 | 2 wire for uart obd (+1 for gnd) 50 | obd II db9 - pre-assembled 5' cable (so the obd II uart device should be co-located with the mega) 51 | Connector styles available: 52 | spade - 1 53 | jst - 2 54 | molex - 4 (but large) 55 | rj45 - 8 pin 56 | */ 57 | 58 | #define SD_CS 4 59 | #define LCD_CS 53 60 | #define LCD_DC 9 61 | #define LCD_RST 8 62 | 63 | //1.8" tft 64 | #define LCDx 160 65 | #define LCDy 128 66 | 67 | /* 68 | 2.2" 240 x 320 69 | */ 70 | 71 | int chipSelect = 10; //for adafruit SD shields + tfts 72 | Adafruit_ST7735 tft = Adafruit_ST7735(LCD_CS, LCD_DC, LCD_RST); 73 | 74 | int buttonApin = 13; 75 | int fakeSensor = 0; 76 | 77 | File config; 78 | uint16_t background = ST7735_BLACK; 79 | uint16_t outline = ST7735_WHITE; 80 | uint16_t fill = ST7735_BLUE; 81 | uint16_t textdefault = ST7735_RED; 82 | uint16_t alert = ST7735_YELLOW; 83 | uint16_t severe = ST7735_YELLOW; 84 | 85 | //This is a character buffer that will store the data from the serial port 86 | char rxData[115]; 87 | char rxIndex=0; 88 | 89 | String sensorMonitor[6]; 90 | int monitorpin[6]; 91 | int monitoralert[6]; 92 | int monitorsevere[6]; 93 | int monitorinterval = 30; 94 | boolean alerting = false; 95 | int a = 0; 96 | 97 | 98 | void setup() { 99 | //read some basic settings from the SD card 100 | Serial.begin(9600); 101 | tft.initR(INITR_BLACKTAB); 102 | tft.fillScreen(background); 103 | tft.setRotation(1); 104 | 105 | Serial.print("SD card start\n"); 106 | if (!SD.begin(SD_CS)){ 107 | Serial.println("failed to initialize SD"); 108 | return; 109 | } 110 | Serial.println("SD OK"); 111 | config = SD.open("gauges"); 112 | //get name of splash from config file and display it 113 | String splash = searchFile("splash"); 114 | //Serial.println("splash"+ splash); 115 | unsigned int splashLen = splash.length()-1; 116 | char splashc[splashLen]; 117 | splash.toCharArray(splashc, (splashLen)); 118 | config.close(); 119 | bmpDraw(splashc, 0, 0); 120 | 121 | Serial1.begin(9600); //spi for the display, serial for debug, serial for OBD II 122 | 123 | //read and assign color configs 124 | config = SD.open("gauges"); 125 | background = textColorToColor(searchFile("background")); 126 | outline = textColorToColor(searchFile("outline")); 127 | fill = textColorToColor(searchFile("fill")); 128 | textdefault = textColorToColor(searchFile("textdefault")); 129 | alert = textColorToColor(searchFile("alert")); 130 | severe = textColorToColor(searchFile("severe")); 131 | 132 | searchFile("allgauges"); 133 | monitorinterval = searchFile("monitorinterval").toInt(); 134 | sensorMonitor[0] = searchFile("sensor1"); 135 | sensorMonitor[1] = searchFile("sensor2"); 136 | sensorMonitor[2] = searchFile("sensor3"); 137 | sensorMonitor[3] = searchFile("sensor4"); 138 | sensorMonitor[4] = searchFile("sensor5"); 139 | sensorMonitor[5] = searchFile("sensor6"); 140 | monitorpin[0] = searchFile("sensor1pin").toInt(); 141 | monitorpin[1] = searchFile("sensor2pin").toInt(); 142 | monitorpin[2] = searchFile("sensor3pin").toInt(); 143 | monitorpin[3] = searchFile("sensor4pin").toInt(); 144 | monitorpin[4] = searchFile("sensor5pin").toInt(); 145 | monitorpin[5] = searchFile("sensor6pin").toInt(); 146 | monitoralert[0] = searchFile("sensor1alert").toInt(); 147 | monitoralert[1] = searchFile("sensor2alert").toInt(); 148 | monitoralert[2] = searchFile("sensor3alert").toInt(); 149 | monitoralert[3] = searchFile("sensor4alert").toInt(); 150 | monitoralert[4] = searchFile("sensor5alert").toInt(); 151 | monitoralert[5] = searchFile("sensor6alert").toInt(); 152 | monitorsevere[0] = searchFile("sensor1severe").toInt(); 153 | monitorsevere[1] = searchFile("sensor2severe").toInt(); 154 | monitorsevere[2] = searchFile("sensor3severe").toInt(); 155 | monitorsevere[3] = searchFile("sensor4severe").toInt(); 156 | monitorsevere[4] = searchFile("sensor5severe").toInt(); 157 | monitorsevere[5] = searchFile("sensor6severe").toInt(); 158 | 159 | config.close(); 160 | config = SD.open("gauges"); 161 | delay(2000); 162 | Serial1.println("ATZ"); //begin OBDII UART 163 | getResponse2(); 164 | delay(1000); 165 | //delay(20); 166 | //getResponse(); 167 | // Serial1.println("ATDP");//tell which protocol...the brz is ATDPAUTO, ISO 15765-4 (CAN 11/500) 168 | // getResponse(); 169 | // Serial1.println("ATDPN");//number of the protocol 170 | // getResponse(); 171 | //Serial1.flush(); 172 | //delay(100); 173 | Serial1.println("ATE0"); //echo off 174 | getResponse2(); 175 | delay(1000); 176 | //Serial1.flush(); 177 | //delay(100); 178 | Serial1.println("AT SH 7E0"); //header specific to the brz oil temp reading 179 | getResponse2(); //won't work because of "OK" ? 180 | delay(1000); 181 | Serial1.println("0105"); 182 | getResponse2(); 183 | Serial.println((strtol(&rxData[6],0,16))-40); //this works, but reading it down in the code doesn't?!?! 184 | /*Serial1.println("0-20"); 185 | Serial1.println("0100"); //what pids are supported 01-20 186 | getResponse(); 187 | Serial1.println("21-40"); 188 | Serial1.println("0120"); //what other pids are supported 20-40 189 | getResponse(); 190 | Serial1.println("41-60"); 191 | Serial1.println("0140"); //40-60 192 | getResponse(); 193 | Serial1.println("61-80"); 194 | Serial1.println("0160"); //60-80 195 | getResponse();*/ 196 | delay(2000); 197 | Serial1.flush(); //TRY THIS on and off 198 | pinMode(buttonApin, INPUT); 199 | Serial.println("end of setup"); 200 | tft.fillScreen(background); 201 | } 202 | 203 | void loop() { 204 | int peaksensor[6]; 205 | String sensor[6]; 206 | String sensorText[4]; 207 | unsigned int sensorPin[6]; 208 | unsigned int sensorMax[4]; 209 | unsigned int sensorAlert[6]; 210 | unsigned int sensorSevere[6]; 211 | String sensorUnits[2]; 212 | //read config file for next page 213 | String pagetype = searchFile("pagetype"); 214 | Serial.println(pagetype); 215 | if (pagetype.indexOf("twobar") >= 0){//2 sensors displayed in 2 bar charts 216 | alerting = false; 217 | peaksensor[0] = 0; 218 | peaksensor[1] = 0; 219 | sensor[0] = searchFile("sensor1"); 220 | sensor[1] = searchFile("sensor2"); 221 | sensorPin[0] = searchFile("sensor1pin").toInt(); 222 | sensorPin[1] = searchFile("sensor2pin").toInt(); 223 | sensorText[0] = searchFile("sensor1text"); 224 | sensorText[1] = searchFile("sensor2text"); 225 | sensorMax[0] = searchFile("sensor1max").toInt(); 226 | sensorMax[1] = searchFile("sensor2max").toInt(); 227 | sensorAlert[1] = searchFile("sensor1alert").toInt(); 228 | sensorAlert[1] = searchFile("sensor2alert").toInt(); 229 | sensorUnits[0] = searchFile("sensor1units"); 230 | sensorUnits[1] = searchFile("sensor2units"); 231 | tft.fillScreen(background); 232 | tft.setTextSize(1); 233 | tft.setTextColor(textdefault); 234 | tft.setCursor(0,0); 235 | tft.println(sensorText[0]); 236 | tft.setCursor(0,70); 237 | tft.println(sensorText[1]); 238 | tft.setCursor(107,0); 239 | tft.println("|"); 240 | tft.setCursor(107,70); 241 | tft.println("|"); 242 | tft.setCursor(145,0); 243 | tft.println(sensorUnits[0]); 244 | tft.setCursor(145,70); 245 | tft.println(sensorUnits[1]); 246 | long val1; 247 | long valOld1 = 0; 248 | long val2; 249 | long valOld2 = 0; 250 | uint16_t barColor1; 251 | uint16_t barColor2; 252 | Serial.println("twobar init done"); 253 | while ( (digitalRead(buttonApin) == LOW) && (alerting == false) ){ 254 | //alerting = monitorSensors(); 255 | 256 | Serial.println(buttonApin); 257 | val1 = getSensorReading(sensor[0], sensorPin[0]); 258 | val2 = getSensorReading(sensor[1], sensorPin[1]); 259 | //write value 260 | tft.setCursor(90,0); //blank old value first 261 | tft.setTextColor(background); 262 | tft.println(valOld1); 263 | tft.setCursor(90,0); 264 | tft.setTextColor(textdefault); 265 | tft.println(val1); 266 | tft.setCursor(90,70); //blank old value first 267 | tft.setTextColor(background); 268 | tft.println(valOld2); 269 | tft.setCursor(90,70); 270 | tft.setTextColor(textdefault); 271 | tft.println(val2); 272 | if (peaksensor[0] < val1){ 273 | tft.setTextColor(background); 274 | tft.setCursor(115,0); 275 | tft.println(peaksensor[0]); 276 | tft.setTextColor(textdefault); 277 | peaksensor[0] = val1; 278 | tft.setCursor(115,0); 279 | tft.println(peaksensor[0]); 280 | } 281 | if (peaksensor[1] < val2){ 282 | tft.setTextColor(background); 283 | tft.setCursor(115,70); 284 | tft.println(peaksensor[1]); 285 | tft.setTextColor(textdefault); 286 | peaksensor[1] = val2; 287 | tft.setCursor(115,70); 288 | tft.println(peaksensor[1]); 289 | } 290 | //pick the bar color1 291 | if (val1 >= sensorAlert[1]){ 292 | if(barColor1 != alert){ 293 | barColor1 = alert; 294 | valOld1 = 0; 295 | } 296 | } 297 | if (val1 <= sensorAlert[1]) { 298 | if(barColor1 != fill){ 299 | barColor1 = fill; 300 | if(val1 <= valOld1){ 301 | valOld1 = 0; 302 | } 303 | } 304 | } 305 | //pick the bar color2 306 | if (val2 >= sensorAlert[1]){ 307 | if(barColor2 != alert){ 308 | barColor2 = alert; 309 | valOld2 = 0; 310 | } 311 | } 312 | if (val2 <= sensorAlert[1]) { 313 | if(barColor2 != fill){ 314 | barColor2 = fill; 315 | if(val2 <= valOld1){ 316 | valOld2 = 0; 317 | } 318 | } 319 | } 320 | //draw bar1 321 | if (val1 >= valOld1){//if the bar is longer...add 322 | tft.fillRect( ( ( (float)LCDx/sensorMax[0])*valOld1 - 1), 20, ( ((float)LCDx/sensorMax[0])*(val1-valOld1) + 1), 30, barColor1 ); 323 | } 324 | if (val1 < valOld1){//if the bar is shorter...erase 325 | tft.fillRect( ( (float)LCDx/sensorMax[0]*val1), 20, ( (float)LCDx/sensorMax[0]*valOld1), 30, background ); 326 | } 327 | valOld1 = val1; 328 | //draw bar2 329 | if (val2 >= valOld2){//if the bar is longer...add 330 | tft.fillRect( ( ( (float)LCDx/sensorMax[1])*valOld2 - 1), 90, ( ((float)LCDx/sensorMax[1])*(val2-valOld2) + 1), 30, barColor2 ); 331 | } 332 | if (val2 < valOld2){//if the bar is shorter...erase 333 | tft.fillRect( ( (float)LCDx/sensorMax[1]*val2), 90, ( (float)LCDx/sensorMax[1]*valOld2), 30, background ); 334 | } 335 | valOld2 = val2; 336 | } 337 | } 338 | 339 | 340 | else if (pagetype.indexOf("onebar") >=0){//1 sensor 1 bar chart...bigger fonts 341 | alerting = false; 342 | Serial.println("onebar"); 343 | peaksensor[0] = 0; 344 | sensor[0] = searchFile("sensor1"); 345 | sensorPin[0] = searchFile("sensor1pin").toInt(); 346 | sensorText[0] = searchFile("sensor1text"); 347 | sensorMax[0] = searchFile("sensor1max").toInt(); 348 | sensorAlert[0] = searchFile("sensor1alert").toInt(); 349 | sensorUnits[0] = searchFile("sensor1units"); 350 | //draw template stuff 351 | tft.fillScreen(background); 352 | tft.setTextSize(2); 353 | tft.setCursor(0,5); 354 | tft.setTextColor(textdefault); 355 | tft.println(sensorText[0]); 356 | tft.setCursor(110,100); 357 | tft.println(sensorUnits[0]); 358 | tft.setCursor(45,100); 359 | tft.println("|"); 360 | long val; 361 | long valOld = 0; 362 | uint16_t barColor; 363 | //loop to show the display and check for the button press 364 | while ( (digitalRead(buttonApin) == LOW) && (alerting == false) ){ 365 | //alerting = monitorSensors(); 366 | //get value 367 | val = getSensorReading(sensor[0], sensorPin[0]); 368 | //write value 369 | tft.setCursor(0,100); //blank old value first 370 | tft.setTextColor(background); 371 | tft.println(valOld); 372 | tft.setCursor(0,100); 373 | tft.setTextColor(textdefault); 374 | tft.println(val); 375 | if (peaksensor[0] < val){ 376 | tft.setTextColor(background); 377 | tft.setCursor(60,100); 378 | tft.println(peaksensor[0]); 379 | tft.setTextColor(textdefault); 380 | peaksensor[0] = val; 381 | tft.setCursor(60,100); 382 | tft.println(peaksensor[0]); 383 | } 384 | //pick the bar color ///somehow this isnt right 385 | if (val >= sensorAlert[0]){ 386 | if(barColor != alert){ 387 | barColor = alert; 388 | valOld = 0; 389 | } 390 | } 391 | if (val <= sensorAlert[0]) { 392 | if(barColor != fill){ 393 | barColor = fill; 394 | if(val <= valOld){ 395 | valOld = 0; 396 | } 397 | } 398 | } 399 | //draw bar 400 | if (val >= valOld){//if the bar is longer...add 401 | tft.fillRect( ( ( (float)LCDx/sensorMax[0])*valOld - 1), 40, ( ((float)LCDx/sensorMax[0])*(val-valOld) + 1), 40, barColor ); 402 | } 403 | if (val < valOld){//if the bar is shorter...erase 404 | tft.fillRect( ( (float)LCDx/sensorMax[0]*val), 40, ( (float)LCDx/sensorMax[0]*valOld), 40, background ); 405 | } 406 | valOld = val; 407 | } 408 | 409 | } 410 | 411 | else if (pagetype.indexOf("round") >= 0){ 412 | alerting = false; 413 | peaksensor[0] = 0; 414 | sensor[0] = searchFile("sensor1"); 415 | sensorPin[0] = searchFile("sensor1pin").toInt(); 416 | sensorText[0] = searchFile("sensor1text"); 417 | sensorMax[0] = searchFile("sensor1max").toInt(); 418 | sensorAlert[0] = searchFile("sensor1alert").toInt(); 419 | tft.fillScreen(background); 420 | tft.setTextSize(2); 421 | tft.setTextColor(textdefault); 422 | tft.setCursor(0, 2); 423 | tft.println(sensorText[0]); 424 | tft.drawCircle(80, 70, 50, textdefault); 425 | tft.drawCircle(80, 70, 49, textdefault); 426 | long val; 427 | long valOld = 0; 428 | uint16_t barColor; 429 | int angle = 0; 430 | float rad = 0; 431 | while ((digitalRead(buttonApin) == LOW) && (alerting == false)){ 432 | //alerting = monitorSensors(); 433 | 434 | val = getSensorReading(sensor[0], sensorPin[0]); 435 | tft.setTextSize(2); 436 | tft.setCursor(64,60); 437 | tft.setTextColor(background); 438 | tft.println(valOld); 439 | tft.setTextColor(textdefault); 440 | tft.setCursor(64,60); 441 | tft.println(val); 442 | if (peaksensor[0] < val){ 443 | tft.setTextSize(1); 444 | tft.setTextColor(background); 445 | tft.setCursor(64,78); 446 | tft.println(peaksensor[0]); 447 | tft.setTextColor(textdefault); 448 | peaksensor[0] = val; 449 | tft.setCursor(64,78); 450 | tft.println(peaksensor[0]); 451 | } 452 | 453 | if (val >= sensorMax[0]){ 454 | barColor = alert; 455 | } 456 | else { 457 | barColor = fill; 458 | } 459 | if (val > valOld){//if the bar is longer...add 460 | //270/sensorMax[0] gives scaling for a 270 degree gauge 461 | for(angle = ((float)valOld*270/sensorMax[0]); angle <= (((float)val*270/sensorMax[0])); angle+=1){ //the "+=1" can be changed for more "fill in" of the arc (gets noticeable at 5) 462 | rad = angle * PI / 180; 463 | tft.fillCircle( (80-((int)(sin(rad)*43.0) ) ), (70+( (int)(cos(rad)*43.0))), 5,barColor); 464 | } 465 | } 466 | if (val < valOld){//if the bar is shorter...erase 467 | for(angle = (((float)valOld*270/sensorMax[0])); angle >= ((float)val*270/sensorMax[0]); angle-=1){ //the "+=1" can be changed for more "fill in" of the arc (gets noticeable at 5) 468 | rad = angle * PI / 180; 469 | tft.fillCircle( (80-((int)(sin(rad)*43.0) ) ), (70+( (int)(cos(rad)*43.0))), 5,background); 470 | } 471 | } 472 | valOld = val; 473 | } 474 | } 475 | 476 | 477 | else if (pagetype.indexOf("accel") >= 0){//cross bar type chart for accelerometer 478 | alerting = false; 479 | sensor[0] = searchFile("sensor1"); 480 | sensorPin[0] = searchFile("sensorPin[0]").toInt(); 481 | sensor[1] = searchFile("sensor2"); 482 | sensorPin[1] = searchFile("sensorPin[1]").toInt(); 483 | //long xval, yval; 484 | long xval = 0; 485 | long yval = 0; 486 | long xvalold = 0; 487 | long yvalold = 0; 488 | long xpeak = 0; 489 | long ypeak = 0; 490 | tft.fillScreen(background); 491 | tft.setTextSize(1); 492 | /*tft.drawRect(60,0,40,LCDy,outline); 493 | tft.drawRect(0,44,LCDx,40,outline); 494 | tft.drawRect(60,44,40,40,background);//empty the center line 495 | */ 496 | tft.setTextColor(outline); 497 | tft.setCursor(0,0); 498 | tft.println("x:"); 499 | tft.setCursor(110,0); 500 | tft.println("y:"); 501 | tft.setCursor(0,120); 502 | tft.println("px:"); 503 | tft.setCursor(110,120); 504 | tft.println("py:"); 505 | 506 | while ( (digitalRead(buttonApin) == LOW) && (alerting == false) ){ 507 | //alerting = monitorSensors(); 508 | 509 | /*xval = getSensorReading(sensor[0], sensorPin[0]); 510 | yval = getSensorReading(sensor[1], sensorPin[1]); 511 | */ 512 | xval = (xval *6+getSensorReading(sensor[0], sensorPin[0]))/7; 513 | yval = (yval *6+getSensorReading(sensor[1], sensorPin[1]))/7; 514 | 515 | tft.setTextColor(background); 516 | tft.setCursor(10, 0); 517 | tft.println((float)xvalold/100); 518 | tft.setTextColor(textdefault); 519 | tft.setCursor(10, 0); 520 | tft.println((float)xval/100); 521 | tft.setTextColor(background); 522 | tft.setCursor(120, 0); 523 | tft.println((float)yvalold/100); 524 | tft.setTextColor(textdefault); 525 | tft.setCursor(120, 0); 526 | tft.println((float)yval/100); 527 | if (abs(xpeak) <= abs(xval)){ 528 | tft.setTextColor(background); 529 | tft.setCursor(14,120); 530 | tft.println((float)xpeak/100); 531 | tft.setTextColor(textdefault); 532 | xpeak = xval; 533 | tft.setCursor(14,120); 534 | tft.println((float)xpeak/100); 535 | } 536 | if (abs(ypeak) <= abs(yval)){ 537 | tft.setTextColor(background); 538 | tft.setCursor(124,120); 539 | tft.println((float)ypeak/100); 540 | tft.setTextColor(textdefault); 541 | ypeak = yval; 542 | tft.setCursor(124,120); 543 | tft.println((float)ypeak/100); 544 | } 545 | 546 | /*tft.fillCircle(80-(float)80/120*xvalold,64,5,background); //x old ball 547 | tft.fillCircle(80-(float)80/120*xval,64,5,fill); //x ball 548 | tft.fillCircle(80,64+(float)64/120*yvalold,5,background); //y old ball 549 | tft.fillCircle(80,64+(float)64/120*yval,5,fill); //y ball 550 | */ 551 | 552 | //1 ball...uniball...oneballin... 553 | tft.fillCircle(80-(float)80/120*xvalold,64+(float)64/120*yvalold,10,background);//oldball 554 | tft.fillCircle(80-(float)80/120*xval,64+(float)64/120*yval,10,fill);//newball 555 | 556 | xvalold = xval; 557 | yvalold = yval; 558 | } 559 | } 560 | 561 | else if (pagetype.indexOf("logging") >= 0){//up to 4 sensors shown...log everything to file 562 | bool logging = true; 563 | alerting = false; 564 | int ct = 0; 565 | while ((digitalRead(buttonApin) == HIGH)){ 566 | } 567 | while ((digitalRead(buttonApin) == LOW) && (ct <= 100)){ 568 | ct++; 569 | delay(10); 570 | } 571 | if (ct <= 100){ 572 | logging = false; 573 | } 574 | peaksensor[0]=0; 575 | peaksensor[1]=0; 576 | peaksensor[2]=0; 577 | peaksensor[3]=0; 578 | peaksensor[4]=0; 579 | peaksensor[5]=0; 580 | //close the settings file 581 | config.close(); 582 | //draw a blank logging page here: 583 | tft.fillScreen(background); 584 | tft.setTextColor(textdefault); 585 | tft.setTextSize(2); 586 | tft.setCursor(40, 5); 587 | if (logging == true){ 588 | tft.println("Logging"); 589 | } 590 | if (logging == false){ 591 | tft.println("Sensors"); 592 | } 593 | tft.setTextSize(1); 594 | tft.setCursor(10, 40); 595 | tft.println(sensorMonitor[0]); 596 | tft.setCursor(10, 50); 597 | tft.println(sensorMonitor[1]); 598 | tft.setCursor(10, 60); 599 | tft.println(sensorMonitor[2]); 600 | tft.setCursor(10, 70); 601 | tft.println(sensorMonitor[3]); 602 | tft.setCursor(10, 80); 603 | tft.println(sensorMonitor[4]); 604 | tft.setCursor(10, 90); 605 | tft.println(sensorMonitor[5]); 606 | 607 | //open a new logging file 608 | long v1, v2, v3, v4, v5, v6; 609 | long v1o = 0; 610 | long v2o = 0; 611 | long v3o = 0; 612 | long v4o = 0; 613 | long v5o = 0; 614 | long v6o = 0; 615 | 616 | while (digitalRead(buttonApin) == LOW){ 617 | v1 = getSensorReading(sensorMonitor[0], monitorpin[0]); 618 | v2 = getSensorReading(sensorMonitor[1], monitorpin[1]); 619 | v3 = getSensorReading(sensorMonitor[2], monitorpin[2]); 620 | v4 = getSensorReading(sensorMonitor[3], monitorpin[3]); 621 | v5 = getSensorReading(sensorMonitor[4], monitorpin[4]); 622 | v6 = getSensorReading(sensorMonitor[5], monitorpin[5]); 623 | 624 | //destory old stuff 625 | tft.setTextColor(background); 626 | tft.setCursor(100,40); 627 | tft.println(v1o); 628 | tft.setCursor(100,50); 629 | tft.println(v2o); 630 | tft.setCursor(100,60); 631 | tft.println(v3o); 632 | tft.setCursor(100,70); 633 | tft.println(v4o); 634 | tft.setCursor(100,80); 635 | tft.println(v5o); 636 | tft.setCursor(100,90); 637 | tft.println(v6o); 638 | 639 | //test for alert and severe levels 640 | //and print new values 641 | 642 | if (v1 >= monitorsevere[0]){ 643 | tft.setTextColor(severe); 644 | } 645 | else if (v1 >= monitoralert[0]){ 646 | tft.setTextColor(alert); 647 | } 648 | else { 649 | tft.setTextColor(outline); 650 | } 651 | tft.setCursor(100,40); 652 | tft.println(v1); 653 | if (v2 >= monitorsevere[1]){ 654 | tft.setTextColor(severe); 655 | } 656 | else if (v2 >= monitoralert[1]){ 657 | tft.setTextColor(alert); 658 | } 659 | else { 660 | tft.setTextColor(outline); 661 | } 662 | tft.setCursor(100,50); 663 | tft.println(v2); 664 | if (v3 >= monitorsevere[2]){ 665 | tft.setTextColor(severe); 666 | } 667 | else if (v3 >= monitoralert[2]){ 668 | tft.setTextColor(alert); 669 | } 670 | else { 671 | tft.setTextColor(outline); 672 | } 673 | tft.setCursor(100,60); 674 | tft.println(v3); 675 | if (v4 >= monitorsevere[3]){ 676 | tft.setTextColor(severe); 677 | } 678 | else if (v4 >= monitoralert[3]){ 679 | tft.setTextColor(alert); 680 | } 681 | else { 682 | tft.setTextColor(outline); 683 | } 684 | tft.setCursor(100,70); 685 | tft.println(v4); 686 | if (v5 >= monitorsevere[4]){ 687 | tft.setTextColor(severe); 688 | } 689 | else if (v5 >= monitoralert[4]){ 690 | tft.setTextColor(alert); 691 | } 692 | else { 693 | tft.setTextColor(outline); 694 | } 695 | tft.setCursor(100,80); 696 | tft.println(v5); 697 | if (v6 >= monitorsevere[5]){ 698 | tft.setTextColor(severe); 699 | } 700 | else if (v6 >= monitoralert[5]){ 701 | tft.setTextColor(alert); 702 | } 703 | else { 704 | tft.setTextColor(outline); 705 | } 706 | tft.setCursor(100,90); 707 | tft.println(v6); 708 | 709 | if (peaksensor[0] < v1){ 710 | tft.setTextColor(background); 711 | tft.setCursor(125,40); 712 | tft.println(peaksensor[0]); 713 | tft.setTextColor(textdefault); 714 | peaksensor[0] = v1; 715 | tft.setCursor(125,40); 716 | tft.println(peaksensor[0]); 717 | } 718 | if (peaksensor[1] < v2){ 719 | tft.setTextColor(background); 720 | tft.setCursor(125,50); 721 | tft.println(peaksensor[1]); 722 | tft.setTextColor(textdefault); 723 | peaksensor[1] = v2; 724 | tft.setCursor(125,50); 725 | tft.println(peaksensor[1]); 726 | } 727 | if (peaksensor[2] < v3){ 728 | tft.setTextColor(background); 729 | tft.setCursor(125,60); 730 | tft.println(peaksensor[2]); 731 | tft.setTextColor(textdefault); 732 | peaksensor[2] = v3; 733 | tft.setCursor(125,60); 734 | tft.println(peaksensor[2]); 735 | } 736 | if (peaksensor[3] < v4){ 737 | tft.setTextColor(background); 738 | tft.setCursor(125,70); 739 | tft.println(peaksensor[3]); 740 | tft.setTextColor(textdefault); 741 | peaksensor[3] = v4; 742 | tft.setCursor(125,70); 743 | tft.println(peaksensor[3]); 744 | } 745 | if (peaksensor[4] < v5){ 746 | tft.setTextColor(background); 747 | tft.setCursor(125,80); 748 | tft.println(peaksensor[4]); 749 | tft.setTextColor(textdefault); 750 | peaksensor[4] = v5; 751 | tft.setCursor(125,80); 752 | tft.println(peaksensor[4]); 753 | } 754 | if (peaksensor[5] < v6){ 755 | tft.setTextColor(background); 756 | tft.setCursor(125,90); 757 | tft.println(peaksensor[5]); 758 | tft.setTextColor(textdefault); 759 | peaksensor[5] = v6; 760 | tft.setCursor(125,90); 761 | tft.println(peaksensor[5]); 762 | } 763 | v1o = v1; 764 | v2o = v2; 765 | v3o = v3; 766 | v4o = v4; 767 | v5o = v5; 768 | v6o = v6; 769 | if (logging == true){ 770 | //log stuff here 771 | } 772 | } 773 | //close file 774 | //reopen the config file 775 | config = SD.open("gauges"); 776 | } 777 | 778 | } 779 | 780 | //called regularly to see if anything went severe...if so jump to the logging page 781 | boolean monitorSensors(){ 782 | a++; 783 | if ((a == 1) && (getSensorReading(sensorMonitor[0], monitorpin[0]) >= monitorsevere[0])){ 784 | tft.setTextSize(3); 785 | tft.fillScreen(severe); 786 | tft.setCursor(0, 20); 787 | tft.println("WARNING!"); 788 | delay(1000); 789 | //go to the logging page 790 | searchFile("allgauges"); 791 | return (true); 792 | } 793 | else if ((a == monitorinterval) && (getSensorReading(sensorMonitor[1], monitorpin[1]) >= monitorsevere[1])){ 794 | tft.setTextSize(3); 795 | tft.fillScreen(severe); 796 | tft.setCursor(0, 20); 797 | tft.println("WARNING!"); 798 | delay(1000); 799 | //go to the logging page 800 | searchFile("allgauges"); 801 | return (true); 802 | } 803 | else if ((a == monitorinterval*2) && (getSensorReading(sensorMonitor[2], monitorpin[2]) >= monitorsevere[2])){ 804 | tft.setTextSize(3); 805 | tft.fillScreen(severe); 806 | tft.setCursor(0, 20); 807 | tft.println("WARNING!"); 808 | delay(1000); 809 | //go to the logging page 810 | searchFile("allgauges"); 811 | return (true); 812 | } 813 | else if ((a == monitorinterval*3) && (getSensorReading(sensorMonitor[3], monitorpin[3]) >= monitorsevere[3])){ 814 | tft.setTextSize(3); 815 | tft.fillScreen(severe); 816 | tft.setCursor(0, 20); 817 | tft.println("WARNING!"); 818 | delay(1000); 819 | //go to the logging page 820 | searchFile("allgauges"); 821 | return (true); 822 | } 823 | else if ((a == monitorinterval*4) && (getSensorReading(sensorMonitor[4], monitorpin[4]) >= monitorsevere[4])){ 824 | tft.setTextSize(3); 825 | tft.fillScreen(severe); 826 | tft.setCursor(0, 20); 827 | tft.println("WARNING!"); 828 | delay(1000); 829 | //go to the logging page 830 | searchFile("allgauges"); 831 | return (true); 832 | } 833 | else if ((a == monitorinterval*5) && (getSensorReading(sensorMonitor[5], monitorpin[5]) >= monitorsevere[5])){ 834 | tft.setTextSize(3); 835 | tft.fillScreen(severe); 836 | tft.setCursor(0, 20); 837 | tft.println("WARNING!"); 838 | delay(1000); 839 | //go to the logging page 840 | searchFile("allgauges"); 841 | return (true); 842 | } 843 | if (a >= monitorinterval*5){ 844 | a = 0; 845 | return false; 846 | } 847 | else return false; 848 | //return false; //for testing you could just return false and not worry about checking everything 849 | } 850 | 851 | long int getOBDIIvalue(String whichSensor){ 852 | /*what is working: 853 | speed - works 854 | rpms - works 855 | coolant - reads in F as 10 and nothing else 856 | boost - can't test yet 857 | iat and maf - can't tell/don't really care 858 | volts - works (maybe add decimal?) 859 | oiltemp(f/c) - haven't tested (shouldn't work on many cars) 860 | brz oil temp - in F shows -72 and nothing else 861 | brz fuel left - shows 1 and nothing else 862 | */ 863 | //Serial1.flush(); 864 | long int value = 0; 865 | if (whichSensor.indexOf("obdspeedkph") >= 0){ 866 | Serial1.println("010D"); //mode 1 0D PID 867 | //getResponse(); //command echoed 868 | getResponse2(); //value 869 | value = strtol(&rxData[6],0,16) ; //convert the string to integer 870 | } 871 | if (whichSensor.indexOf("obdspeedmph") >= 0){ //works, but has bleedover issues 872 | Serial1.println("010D"); //mode 1 0D PID 873 | //getResponse(); 874 | getResponse2(); //value 875 | value = strtol(&rxData[6],0,16)/1.6 ; //convert the string to integer 876 | } 877 | if (whichSensor.indexOf("obdrpms") >= 0){ //working 878 | Serial1.println("010C"); //mode 1 0C PID (rpm) 879 | //Serial.println("getting rpm"); 880 | //getResponse(); //value 881 | getResponse2(); 882 | value = ((strtol(&rxData[6],0,16)*256)+strtol(&rxData[9],0,16))/4; //aka ((A*256)+B)/4 883 | //Serial.println("rpm ="); 884 | //Serial.println(value); 885 | } 886 | if (whichSensor.indexOf("obdcoolantc") >=0){ 887 | Serial.println("coolantc"); 888 | Serial1.print("O105\r"); 889 | getResponse2(); 890 | //Serial.println(&rxData[6]); 891 | //Serial.println((float)strtol(&rxData[6],0,16)); 892 | value = (strtol(&rxData[6],0,16))-40; //aka A-40 893 | Serial.print("value of coolantc "); 894 | Serial.print(value); 895 | } 896 | if (whichSensor.indexOf("obdcoolantf") >=0){ //not working...05 or 67 both return junk 897 | Serial.println("coolantf"); 898 | Serial1.print("O105\r"); //gives raw data of "?" 899 | getResponse2(); 900 | //Serial1.flush(); 901 | //Serial.println(&rxData[6]); 902 | //Serial.println((float)strtol(&rxData[6],0,16)); 903 | value = ((strtol(&rxData[6],0,16))-40)*1.8+32; //aka A-40 904 | Serial.print("value of coolantf "); 905 | Serial.print(value); 906 | } 907 | if (whichSensor.indexOf("obdboost") >= 0){ 908 | Serial1.println("0265"); //intake manifold abs pressure ... doesn't work with brz 909 | getResponse2(); 910 | value = (strtol(&rxData[6],0,16)); //aka A 911 | } 912 | if (whichSensor.indexOf("obdiat") >= 0){ //not supported on the BRZ ecu 913 | Serial1.println("O1OF"); 914 | getResponse2(); 915 | value = (strtol(&rxData[6],0,16)-40); //aka A-40 916 | } 917 | if (whichSensor.indexOf("obdmaf") >= 0){//I think this works 918 | Serial1.println("0110"); 919 | getResponse2(); 920 | value = ((strtol(&rxData[6],0,16)*256)+strtol(&rxData[9],0,16))/100; //aka ((A*256)+B)/100 921 | } 922 | if (whichSensor.indexOf("obdvolts") >= 0){ //works perfectly 923 | Serial1.println("0142"); 924 | //Serial.println("getting volts"); 925 | //getResponse(); 926 | getResponse2(); 927 | value = ((strtol(&rxData[6],0,16)*256)+strtol(&rxData[9],0,16))/1000; //aka ((A*256)+B)/100 928 | //Serial.println("volts is:"); 929 | //Serial.println(value); 930 | } 931 | if (whichSensor.indexOf("obdoiltempc") >= 0){ 932 | Serial1.println("015C"); 933 | getResponse2(); 934 | value = strtol(&rxData[6],0,16)-40; //aka (A-40) 935 | } 936 | if (whichSensor.indexOf("obdoiltempf") >= 0){ 937 | Serial1.println("015C"); 938 | getResponse2(); 939 | value = (strtol(&rxData[6],0,16)-40)*1.8+32; //aka (A-40) *1.8 940 | } 941 | if (whichSensor.indexOf("obdafr") >= 0){ 942 | Serial.println("0134"); //afr reading (readings aren't great) 943 | getResponse(); 944 | value = ((strtol(&rxData[6],0,16)*256)+strtol(&rxData[9],0,16))/32768*14.7; //(A*256+B)/32768*14.7 945 | } 946 | 947 | //nonstandard/experiemental PIDs 948 | if (whichSensor.indexOf("obdbrzoiltempc") >= 0){ 949 | Serial1.println("2101"); 950 | getResponse2(); 951 | value = ((float)strtol(&rxData[109],0,16) - 40); //29th byte - 40 (?) 952 | } 953 | if (whichSensor.indexOf("obdbrzoiltempf") >= 0){ //works 954 | Serial1.println("2101"); 955 | getResponse2(); 956 | Serial.println("brz oil temp"); 957 | value = ((float)strtol(&rxData[109],0,16) - 40) * 1.8 + 32; 958 | Serial.println(value); 959 | } 960 | if (whichSensor.indexOf("obdbrzfuelleft") >= 0){ //not working 961 | Serial.println("brz fuel left"); 962 | Serial1.println("AT SH 7C0"); 963 | getResponse2(); 964 | Serial1.println("2129"); 965 | value = ((float)strtol(&rxData[6],0,16)*13.2)/100; // (A*13.2)/100 966 | Serial1.println("AT SH 7E0"); //header specific to the brz oil temp reading 967 | getResponse2(); 968 | } 969 | delay(100); 970 | Serial1.flush(); 971 | memset(rxData,0,sizeof(rxData)); //blank the array 972 | return value; 973 | } 974 | 975 | int getSensorReading(String sensorName, int pinNumber){ 976 | //if the pin number is 0 it is obd II...look it up with the obd II lib 977 | if (pinNumber == 0){ 978 | Serial.println("getting OBDII value"); 979 | return(getOBDIIvalue(sensorName)); 980 | } 981 | //else call the appropriate Analog to digital conversion function on the appropirate pin 982 | else { 983 | Serial.println("fake sensor"); 984 | if (sensorName.indexOf("fakeaccel") >= 0){ 985 | return random(-1500,1500); 986 | } 987 | if (sensorName.indexOf("fake") >= 0){ 988 | return lookup_fake_random_sensor(pinNumber); 989 | } 990 | if (sensorName.indexOf("oiltemp") >= 0){ 991 | return lookup_oil_temp(pinNumber); 992 | } 993 | if (sensorName.indexOf("oilpressure") >= 0){ 994 | return lookup_oil_psi(pinNumber); 995 | } 996 | if (sensorName.indexOf("accelx") >= 0){ 997 | return getAccelerometerData(pinNumber); 998 | } 999 | if (sensorName.indexOf("accely") >= 0){ 1000 | return getAccelerometerData(pinNumber); 1001 | } 1002 | if (sensorName.indexOf("boostpressure") >= 0){ 1003 | return lookup_boost(pinNumber); 1004 | } 1005 | if (sensorName.indexOf("temperature") >= 0){ 1006 | return lookup_temp(pinNumber); 1007 | } 1008 | 1009 | } 1010 | } 1011 | 1012 | 1013 | //from: https://forum.sparkfun.com/viewtopic.php?f=14&t=32457&start=60 and https://forum.sparkfun.com/viewtopic.php?f=14&t=38253 1014 | void getResponse2(void){ 1015 | char c; 1016 | int start=millis(); 1017 | //If nothing is currently available do nothing and break after 3 seconds 1018 | while(Serial1.available()==0){if(millis()-start>3000){break;}} 1019 | do { 1020 | if (Serial1.available() > 0) 1021 | { 1022 | c = Serial1.read(); 1023 | if ((c != '>') && (c != '\r') && (c != '\n')) //Keep these out of our buffer 1024 | { 1025 | rxData[rxIndex++] = c; //Add whatever we receive to the buffer 1026 | } 1027 | } 1028 | } 1029 | while (c != '>'); //The ELM327 ends its response with this char so when we get it we exit out. 1030 | rxData[rxIndex++] = '\0'; //Converts the array into a string 1031 | Serial.print("rxData(in getResponse2): "); 1032 | Serial.println(rxData); 1033 | rxIndex = 0; //Set this to 0 so next time we call the read we get a "clean" buffer 1034 | } 1035 | 1036 | void getResponse(void){ 1037 | char obdIn=0; 1038 | int i=0; 1039 | int start=millis(); 1040 | //If nothing is currently available do nothing and break after 3 seconds 1041 | while(Serial1.available()==0){if(millis()-start>3000){break;}} 1042 | while(Serial1.available()){ 1043 | //check to see if end of line/message 1044 | if (Serial1.peek()=='\r'){ 1045 | obdIn=Serial1.read(); 1046 | rxData[i]='\0'; 1047 | Serial.println(rxData); 1048 | i=0; 1049 | } 1050 | // The prompt is sometimes the only thing recieved so this needs to be taken care of 1051 | else if(Serial1.peek()=='>'){ 1052 | obdIn=Serial1.read(); 1053 | //Serial.write(obdIn); 1054 | } 1055 | // Add next character to string 1056 | else{ 1057 | obdIn=Serial1.read(); 1058 | rxData[i++]=obdIn; 1059 | } 1060 | } 1061 | Serial.print("rxData(in getResponse): "); 1062 | Serial.println(rxData); 1063 | rxIndex=0; 1064 | } 1065 | 1066 | uint16_t textColorToColor(String color){ 1067 | Serial.println(color); 1068 | if (color.indexOf("red") >= 0){ 1069 | return ST7735_RED; 1070 | } 1071 | else if (color.indexOf("magenta") >= 0){ 1072 | return ST7735_MAGENTA; 1073 | } 1074 | else if (color.indexOf("blue") >= 0){ 1075 | return ST7735_BLUE; 1076 | } 1077 | else if (color.indexOf("green") >= 0){ 1078 | return ST7735_GREEN; 1079 | } 1080 | else if(color.indexOf("black") >= 0){ 1081 | return ST7735_BLACK; 1082 | } 1083 | else if (color.indexOf("white") >= 0){ 1084 | return ST7735_WHITE; 1085 | } 1086 | else if (color.indexOf("yellow") >=0){ 1087 | return ST7735_YELLOW; 1088 | } 1089 | else { 1090 | return ST7735_WHITE; 1091 | } 1092 | } 1093 | 1094 | String searchFile(String searchFor){ //finds some substring + : and returns the value after the : 1095 | if (!SD.exists("gauges")){ 1096 | Serial.println("config file not found try reformatting sd card"); 1097 | return("error"); 1098 | } 1099 | //set pos to start of file 1100 | //loop and read a line and check 1101 | String line; 1102 | //Serial.println(config.available()); 1103 | while (config.available()){ 1104 | line = config.readStringUntil('\n'); 1105 | if (line.startsWith("#")){ //skip comments 1106 | } 1107 | else if (line.startsWith(searchFor)){ 1108 | int colonPos = line.indexOf(":"); 1109 | return( line.substring( line.indexOf(":")+1, line.indexOf("\n")-3 ) ); 1110 | } 1111 | } 1112 | } 1113 | 1114 | //fake sensor for testing 1115 | int lookup_fake_random_sensor(int max){ 1116 | randomSeed(analogRead(0)); 1117 | int mod = (random(-5,5)); 1118 | //for increment 1119 | fakeSensor+=mod; 1120 | if (fakeSensor >= max){ 1121 | fakeSensor = 1; 1122 | } 1123 | if (fakeSensor < 0){ 1124 | fakeSensor = 1; 1125 | } 1126 | // Serial.println("lookup_fake_random_sensor"); 1127 | // Serial.println(fakeSensor); 1128 | return fakeSensor; 1129 | } 1130 | 1131 | //sensor code 1132 | int getAccelerometerData (int axis){ 1133 | int zerog = 512; 1134 | int rc = analogRead(axis); 1135 | int top =( (zerog - rc) ) ; 1136 | float frtrn = (((float)top/(float)154)*100); //158Vint jumps are 1g for the ADXL213AE (original accel) 1137 | //154Vint jumps are 1g for the ADXL322 (updated one) 1138 | int rtrn = (int)frtrn; 1139 | return rtrn; 1140 | } 1141 | 1142 | //from the arudino playground: http://playground.arduino.cc/Main/Smooth by Paul 1143 | int smooth(int data, float filterVal, float smoothedVal){ 1144 | 1145 | 1146 | if (filterVal > 1){ // check to make sure param's are within range 1147 | filterVal = .99; 1148 | } 1149 | else if (filterVal <= 0){ 1150 | filterVal = 0; 1151 | } 1152 | 1153 | smoothedVal = (data * (1 - filterVal)) + (smoothedVal * filterVal); 1154 | 1155 | return (int)smoothedVal; 1156 | } 1157 | 1158 | //oil temp 1159 | long lookup_oil_temp(int oilTempPin){ 1160 | long tval = analogRead(oilTempPin); 1161 | tval = tval * 1000; //added an extra 0 1162 | if (tval <= 11500){ 1163 | return (9999); 1164 | } 1165 | if (tval >= 68100){ 1166 | return (0); 1167 | } 1168 | if ((tval <= 68000)&&(tval > 39600)){ 1169 | return (long)(((tval-134266)*10)/(-473)); 1170 | } 1171 | if ((tval <= 39600)&&(tval > 28200)){ 1172 | return (long)(((tval-115600)*10)/(-380)); 1173 | } 1174 | if ((tval <= 28200)&&(tval > 19700)){ 1175 | return (long)(((tval-93366)*10)/(-283)); 1176 | } 1177 | if ((tval <= 19700)&&(tval > 11600)){ 1178 | return (long)(((tval-54800)*10)/(-135)); 1179 | } 1180 | } 1181 | 1182 | //oil pressure 1183 | long lookup_oil_psi(int psiPin){ 1184 | long psival = analogRead(psiPin); 1185 | if (psival > 722){ 1186 | return (0); 1187 | } 1188 | if (psival < 257){ 1189 | return(9999); 1190 | } 1191 | if ((psival <= 722)&&(psival > 619)) { 1192 | return 1747 - (psival*240)/100; 1193 | } 1194 | if ((psival <= 619)&&(psival > 520)) { 1195 | return 1802 - (psival*250)/100; 1196 | } 1197 | if ((psival <= 520)&&(psival > 411)) { 1198 | return 1694 - (psival*230)/100; 1199 | } 1200 | if ((psival <= 411)&&(psival > 257)){ 1201 | return 1418 - (psival*160)/100; 1202 | } 1203 | } 1204 | 1205 | long lookup_boost(int boostPin){ 1206 | long boost = analogRead(boostPin); 1207 | //boost = ( (boost-106000) / 259000 ); 1208 | // boost = ( (( boost * 398) / 1000) + 2); //2 is the y intercept 1209 | //398 changed to 378 for slope...because slope was too steep 1210 | boost = ( (( boost * 378) / 1000) - 4); ///10; //get rid of the divide by ten when adding decimals on display 1211 | return boost; 1212 | } 1213 | 1214 | long lookup_temp(int tempPin){ 1215 | long tval = analogRead(tempPin); 1216 | tval = tval * 100; 1217 | //tval = (long)(tval - (long)117588); 1218 | //return tval; 1219 | if (tval < 8900){ 1220 | return (9999); 1221 | } 1222 | if (tval > 96000){ 1223 | return (0); 1224 | } 1225 | if ((tval <= 96000)&&(tval > 93221)){ 1226 | return (((tval-101577)*10)/(-172)); 1227 | } 1228 | if ((tval <= 93221)&&(tval > 89610)){ 1229 | return (((tval-104201)*10)/(-226)); 1230 | } 1231 | if ((tval <= 89610)&&(tval > 85125)){ 1232 | return (((tval-107738)*10)/(-280)); 1233 | } 1234 | if ((tval <= 85125)&&(tval > 79139)){ 1235 | return (((tval-112264)*10)/(-335)); 1236 | } 1237 | if ((tval <= 79139)&&(tval > 70799)){ 1238 | return (((tval-117588)*10)/(-388)); 1239 | } 1240 | if ((tval <= 70799)&&(tval > 62470)){ 1241 | return (((tval-121441)*10)/(-421)); 1242 | } 1243 | if ((tval <= 62470)&&(tval > 53230)){ 1244 | return (((tval-122367)*10)/(-428)); 1245 | } 1246 | if ((tval <= 53230)&&(tval > 43707)){ 1247 | return (((tval-118651)*10)/(-405)); 1248 | } 1249 | if ((tval <= 43707)&&(tval > 36471)){ 1250 | return (((tval-111349)*10)/(-366)); 1251 | } 1252 | if ((tval <= 36471)&&(tval > 30685)){ 1253 | return (((tval-102232)*10)/(-321)); 1254 | } 1255 | if ((tval <= 30685)&&(tval > 24800)){ 1256 | return (((tval-9078)*10)/(-270)); 1257 | } 1258 | if ((tval <= 24800)&&(tval > 20000)){ 1259 | return (((tval-78575)*10)/(-220)); 1260 | } 1261 | if ((tval <= 20000)&&(tval > 15851)){ 1262 | return (((tval-66507)*10)/(-175)); 1263 | } 1264 | if ((tval <= 15851)&&(tval > 12380)){ 1265 | return (((tval-55300)*10)/(-137)); 1266 | } 1267 | if ((tval <= 12380)&&(tval > 9085)){ 1268 | return (((tval-41752)*10)/(-94)); 1269 | } 1270 | } 1271 | 1272 | 1273 | //bmp drawing code from adafruit 1274 | #define BUFFPIXEL 20 1275 | 1276 | void bmpDraw(char *filename, uint8_t x, uint8_t y) { 1277 | 1278 | File bmpFile; 1279 | int bmpWidth, bmpHeight; // W+H in pixels 1280 | uint8_t bmpDepth; // Bit depth (currently must be 24) 1281 | uint32_t bmpImageoffset; // Start of image data in file 1282 | uint32_t rowSize; // Not always = bmpWidth; may have padding 1283 | uint8_t sdbuffer[3*BUFFPIXEL]; // pixel buffer (R+G+B per pixel) 1284 | uint8_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer 1285 | boolean goodBmp = false; // Set to true on valid header parse 1286 | boolean flip = true; // BMP is stored bottom-to-top 1287 | int w, h, row, col; 1288 | uint8_t r, g, b; 1289 | uint32_t pos = 0, startTime = millis(); 1290 | 1291 | if((x >= tft.width()) || (y >= tft.height())) return; 1292 | 1293 | Serial.println(); 1294 | Serial.print("Loading image '"); 1295 | Serial.print(filename); 1296 | Serial.println('\''); 1297 | 1298 | // Open requested file on SD card 1299 | if ((bmpFile = SD.open(filename)) == NULL) { 1300 | Serial.print("File not found"); 1301 | return; 1302 | } 1303 | 1304 | // Parse BMP header 1305 | if(read16(bmpFile) == 0x4D42) { // BMP signature 1306 | Serial.print("File size: "); 1307 | Serial.println(read32(bmpFile)); 1308 | (void)read32(bmpFile); // Read & ignore creator bytes 1309 | bmpImageoffset = read32(bmpFile); // Start of image data 1310 | Serial.print("Image Offset: "); 1311 | Serial.println(bmpImageoffset, DEC); 1312 | // Read DIB header 1313 | Serial.print("Header size: "); 1314 | Serial.println(read32(bmpFile)); 1315 | bmpWidth = read32(bmpFile); 1316 | bmpHeight = read32(bmpFile); 1317 | if(read16(bmpFile) == 1) { // # planes -- must be '1' 1318 | bmpDepth = read16(bmpFile); // bits per pixel 1319 | Serial.print("Bit Depth: "); 1320 | Serial.println(bmpDepth); 1321 | if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed 1322 | 1323 | goodBmp = true; // Supported BMP format -- proceed! 1324 | Serial.print("Image size: "); 1325 | Serial.print(bmpWidth); 1326 | Serial.print('x'); 1327 | Serial.println(bmpHeight); 1328 | 1329 | // BMP rows are padded (if needed) to 4-byte boundary 1330 | rowSize = (bmpWidth * 3 + 3) & ~3; 1331 | 1332 | // If bmpHeight is negative, image is in top-down order. 1333 | // This is not canon but has been observed in the wild. 1334 | if(bmpHeight < 0) { 1335 | bmpHeight = -bmpHeight; 1336 | flip = false; 1337 | } 1338 | 1339 | // Crop area to be loaded 1340 | w = bmpWidth; 1341 | h = bmpHeight; 1342 | if((x+w-1) >= tft.width()) w = tft.width() - x; 1343 | if((y+h-1) >= tft.height()) h = tft.height() - y; 1344 | 1345 | // Set TFT address window to clipped image bounds 1346 | tft.setAddrWindow(x, y, x+w-1, y+h-1); 1347 | 1348 | for (row=0; row= sizeof(sdbuffer)) { // Indeed 1368 | bmpFile.read(sdbuffer, sizeof(sdbuffer)); 1369 | buffidx = 0; // Set index to beginning 1370 | } 1371 | 1372 | // Convert pixel from BMP to TFT format, push to display 1373 | b = sdbuffer[buffidx++]; 1374 | g = sdbuffer[buffidx++]; 1375 | r = sdbuffer[buffidx++]; 1376 | tft.pushColor(tft.Color565(r,g,b)); 1377 | } // end pixel 1378 | } // end scanline 1379 | Serial.print("Loaded in "); 1380 | Serial.print(millis() - startTime); 1381 | Serial.println(" ms"); 1382 | } // end goodBmp 1383 | } 1384 | } 1385 | 1386 | bmpFile.close(); 1387 | if(!goodBmp) Serial.println("BMP format not recognized."); 1388 | } 1389 | 1390 | // These read 16- and 32-bit types from the SD card file. 1391 | // BMP data is stored little-endian, Arduino is little-endian too. 1392 | // May need to reverse subscript order if porting elsewhere. 1393 | 1394 | uint16_t read16(File f) { 1395 | uint16_t result; 1396 | ((uint8_t *)&result)[0] = f.read(); // LSB 1397 | ((uint8_t *)&result)[1] = f.read(); // MSB 1398 | return result; 1399 | } 1400 | 1401 | uint32_t read32(File f) { 1402 | uint32_t result; 1403 | ((uint8_t *)&result)[0] = f.read(); // LSB 1404 | ((uint8_t *)&result)[1] = f.read(); 1405 | ((uint8_t *)&result)[2] = f.read(); 1406 | ((uint8_t *)&result)[3] = f.read(); // MSB 1407 | return result; 1408 | } 1409 | 1410 | 1411 | 1412 | 1413 | 1414 | 1415 | 1416 | 1417 | 1418 | -------------------------------------------------------------------------------- /oledOBDgaugeSmall/oledOBDgaugeSmall.ino: -------------------------------------------------------------------------------- 1 | //obdII gauge that reuses a lot of code from my other projects 2 | //set up to use the SPI 128x32 OLED display from adafruit 3 | 4 | //TODO: 5 | //fix PIDs or delete them (coolant/IAT) 6 | //test peak recall (fix...isn't really working...wrong voltage range??) 7 | //test warning function (set one low and test that way) 8 | 9 | //hardware TODO: 10 | //take protective strip off 11 | //test tinting plastic to appear red/amber 12 | //desoldier buttons and wire up 13 | //desoldier led backlight 14 | //wire up power 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #define OLED_MOSI 9 22 | #define OLED_CLK 10 23 | #define OLED_DC 11 24 | #define OLED_CS 12 25 | #define OLED_RESET 13 26 | 27 | /* Uncomment this block to use hardware SPI 28 | #define OLED_DC 6 29 | #define OLED_CS 7 30 | #define OLED_RESET 8 31 | Adafruit_SSD1306 display(OLED_DC, OLED_RESET, OLED_CS); 32 | */ 33 | 34 | Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS); 35 | 36 | //This is a character buffer that will store the data from the serial port 37 | char rxData[115]; 38 | char rxIndex=0; 39 | int buttonV; 40 | 41 | //String modeList[] = {"obdbrzoiltempf", "obdafr", "obdvolts"}; 42 | String curMode = "obdbrzoiltempf"; 43 | int warnLevels[] = {212, 220, 15, 220, 300}; 44 | int warnSign[] = {1,1,1,1,1}; //1 for high, 0 for low (in cases like oil pressure) 45 | float peaks[] = {0,0,0,0,0}; 46 | float curValue[] = {0,0,0,0,0}; 47 | float previousReading[] = {0,0,0,0,0}; 48 | int mode = 0; 49 | int modes = 4; //0 is the first of the array 50 | 51 | 52 | //store other bmps here: 53 | static const unsigned char PROGMEM robothead [] = { 54 | 0b00000000, 0b00111100, 0b00000000, 0b00000000, // #### 55 | 0b00000000, 0b01111110, 0b00000000, 0b00000000, // ###### 56 | 0b00000000, 0b01111110, 0b00000000, 0b00000000, // ###### 57 | 0b00000000, 0b01111110, 0b00000000, 0b00000000, // ###### 58 | 0b00000000, 0b00111100, 0b00000000, 0b00000000, // #### 59 | 0b00000000, 0b00011000, 0b00000000, 0b00000000, // ## 60 | 0b00000000, 0b00011000, 0b00000000, 0b00000000, // ## 61 | 0b00000000, 0b00011000, 0b00000000, 0b00000000, // ## 62 | 0b00000000, 0b00011000, 0b00000000, 0b00000000, // ## 63 | 0b00000000, 0b00011000, 0b00000000, 0b00000000, // ## 64 | 0b00000000, 0b00011000, 0b00000000, 0b00000000, // ## 65 | 0b00000000, 0b00011000, 0b00000000, 0b00000000, // ## 66 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 67 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 68 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 69 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 70 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 71 | 0b11110000, 0b00111100, 0b00001111, 0b10000000, // #### #### ##### 72 | 0b11110000, 0b00111100, 0b00001111, 0b10000000, // #### #### ##### 73 | 0b11110000, 0b00111100, 0b00001111, 0b10000000, // #### #### ##### 74 | 0b11110000, 0b00111100, 0b00001111, 0b10000000, // #### #### ##### 75 | 0b11110000, 0b00111100, 0b00001111, 0b10000000, // #### #### ##### 76 | 0b11110000, 0b00111100, 0b00001111, 0b10000000, // #### #### ##### 77 | 0b11110000, 0b00111100, 0b00001111, 0b10000000, // #### #### ##### 78 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 79 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 80 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 81 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 82 | 0b11100000, 0b00000000, 0b00000111, 0b10000000, // ### #### 83 | 0b11100000, 0b00000000, 0b00000111, 0b10000000, // ### #### 84 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 85 | }; 86 | 87 | static const unsigned char PROGMEM batt [] = { 88 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 89 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 90 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 91 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 92 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 93 | 0b00000001, 0b11110000, 0b00011111, 0b00000000, // ##### ##### 94 | 0b00000010, 0b00001000, 0b00100000, 0b10000000, // # # # # 95 | 0b00000010, 0b00001000, 0b00100000, 0b10000000, // # # # # 96 | 0b00000010, 0b00001000, 0b00100000, 0b10000000, // # # # # 97 | 0b00000010, 0b00001000, 0b00100000, 0b10000000, // # # # # 98 | 0b00000010, 0b00001000, 0b00100000, 0b10000000, // # # # # 99 | 0b00011111, 0b11111111, 0b11111111, 0b11110000, // ######################### 100 | 0b00011110, 0b00000000, 0b00000000, 0b11110000, // #### #### 101 | 0b00011110, 0b00000000, 0b00000000, 0b11110000, // #### #### 102 | 0b00011110, 0b00000000, 0b00000000, 0b11110000, // #### #### 103 | 0b00010000, 0b01000000, 0b00000000, 0b00010000, // # # # 104 | 0b00010000, 0b01000000, 0b00000000, 0b00010000, // # # # 105 | 0b00010000, 0b01000000, 0b00000000, 0b00010000, // # # # 106 | 0b00010011, 0b11111000, 0b00111111, 0b10010000, // # ####### ####### # 107 | 0b00010000, 0b01000000, 0b00000000, 0b00010000, // # # # 108 | 0b00010000, 0b01000000, 0b00000000, 0b00010000, // # # # 109 | 0b00010000, 0b01000000, 0b00000000, 0b00010000, // # # # 110 | 0b00010000, 0b00000000, 0b00000000, 0b00010000, // # # 111 | 0b00011110, 0b00000000, 0b00000000, 0b11110000, // #### #### 112 | 0b00011110, 0b00000000, 0b00000000, 0b11110000, // #### #### 113 | 0b00011110, 0b00000000, 0b00000000, 0b11110000, // #### #### 114 | 0b00011111, 0b11111111, 0b11111111, 0b11110000, // ######################### 115 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 116 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 117 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 118 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 119 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 120 | }; 121 | 122 | static const unsigned char PROGMEM o2 [] = { 123 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 124 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 125 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 126 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 127 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 128 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 129 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 130 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 131 | 0b00000001, 0b11111000, 0b00000000, 0b00000000, // ###### 132 | 0b00000011, 0b11111110, 0b00000000, 0b00000000, // ######### 133 | 0b00000111, 0b00000111, 0b00000000, 0b00000000, // ### ### 134 | 0b00001100, 0b00000011, 0b00000000, 0b00000000, // ## ## 135 | 0b00001100, 0b00000011, 0b00000000, 0b00000000, // ## ## 136 | 0b00011000, 0b00000001, 0b10000000, 0b00000000, // ## ## 137 | 0b00011000, 0b00000001, 0b11111000, 0b00000000, // ## ###### 138 | 0b00011000, 0b00000001, 0b11111100, 0b00000000, // ## ####### 139 | 0b00011000, 0b00000001, 0b10001110, 0b00000000, // ## ## ### 140 | 0b00011000, 0b00000001, 0b10000110, 0b00000000, // ## ## ## 141 | 0b00001100, 0b00000011, 0b00000110, 0b00000000, // ## ## ## 142 | 0b00001100, 0b00000011, 0b00000110, 0b00000000, // ## ## ## 143 | 0b00001110, 0b00001110, 0b00000100, 0b00000000, // ### ### # 144 | 0b00000111, 0b11111100, 0b00001100, 0b00000000, // ######### ## 145 | 0b00000001, 0b11111000, 0b00011000, 0b00000000, // ###### ## 146 | 0b00000000, 0b00000000, 0b00110000, 0b00000000, // ## 147 | 0b00000000, 0b00000000, 0b01100000, 0b00000000, // ## 148 | 0b00000000, 0b00000000, 0b11000000, 0b00000000, // ## 149 | 0b00000000, 0b00000001, 0b10000000, 0b00000000, // ## 150 | 0b00000000, 0b00000011, 0b11111111, 0b00000000, // ########## 151 | 0b00000000, 0b00000011, 0b11111111, 0b00000000, // ########## 152 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 153 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 154 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 155 | }; 156 | 157 | 158 | static const unsigned char PROGMEM oil [] = { 159 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 160 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 161 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 162 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 163 | 0b01000000, 0b00001110, 0b00000000, 0b00000000, // # ### 164 | 0b01100000, 0b00011111, 0b00000000, 0b11100000, // ## ##### ### 165 | 0b01111000, 0b00001110, 0b00000011, 0b10000000, // #### ### ### 166 | 0b01111100, 0b00000100, 0b00001101, 0b00000000, // ##### # ## # 167 | 0b01111111, 0b11111111, 0b11111110, 0b01000000, // ###################### # 168 | 0b00010111, 0b11111111, 0b11111110, 0b00010000, // # ################## # 169 | 0b00001111, 0b11111111, 0b11111100, 0b00010000, // ################## # 170 | 0b00001111, 0b11111111, 0b11111100, 0b00011000, // ################## ## 171 | 0b00000111, 0b11111111, 0b11111000, 0b00111100, // ################ #### 172 | 0b00000111, 0b11111111, 0b11110000, 0b00111100, // ############### #### 173 | 0b00000111, 0b11111111, 0b11110000, 0b00111100, // ############### #### 174 | 0b00000111, 0b11111111, 0b11100000, 0b00011000, // ############## ## 175 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 176 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 177 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 178 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 179 | 0b00000000, 0b11011111, 0b11100000, 0b00000000, // ## ######## 180 | 0b00000000, 0b11011111, 0b11100000, 0b00000000, // ## ######## 181 | 0b00000000, 0b00011100, 0b00000000, 0b00000000, // ### 182 | 0b00000000, 0b00011100, 0b00000000, 0b00000000, // ### 183 | 0b00000000, 0b00011100, 0b00000000, 0b00000000, // ### 184 | 0b00000000, 0b00011111, 0b11000000, 0b00000000, // ####### 185 | 0b00000000, 0b00011111, 0b11000000, 0b00000000, // ####### 186 | 0b00000000, 0b00011100, 0b00000000, 0b00000000, // ### 187 | 0b00000000, 0b00011100, 0b00000000, 0b00000000, // ### 188 | 0b00000000, 0b00011100, 0b00000000, 0b00000000, // ### 189 | 0b00000000, 0b00011100, 0b00000000, 0b00000000, // ### 190 | 0b00000000, 0b00011100, 0b00000000, 0b00000000, // ### 191 | }; 192 | 193 | static const unsigned char PROGMEM coolant [] = { 194 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 195 | 0b00111111, 0b10000000, 0b00000000, 0b00000000, // ####### 196 | 0b00111000, 0b00000011, 0b10000000, 0b00000000, // ### ### 197 | 0b00111000, 0b00000011, 0b10000000, 0b00000000, // ### ### 198 | 0b00111000, 0b00000011, 0b11111110, 0b00000000, // ### ######### 199 | 0b00111111, 0b00000011, 0b11111110, 0b00000000, // ###### ######### 200 | 0b00111000, 0b00000011, 0b11111110, 0b00000000, // ### ######### 201 | 0b00111000, 0b00000011, 0b10000000, 0b00000000, // ### ### 202 | 0b00111000, 0b00000011, 0b10000000, 0b00000000, // ### ### 203 | 0b00111000, 0b00000011, 0b11111110, 0b00000000, // ### ######### 204 | 0b00000000, 0b00000011, 0b11111110, 0b00000000, // ######### 205 | 0b00000000, 0b00000011, 0b11111110, 0b00000000, // ######### 206 | 0b00000000, 0b00000011, 0b10000000, 0b00000000, // ### 207 | 0b00000000, 0b00000011, 0b10000000, 0b00000000, // ### 208 | 0b00000000, 0b00000011, 0b10000000, 0b00000000, // ### 209 | 0b00000000, 0b00000011, 0b10000111, 0b11110000, // ### ####### 210 | 0b00000111, 0b11110011, 0b10011100, 0b00011100, // ####### ### ### ### 211 | 0b00011100, 0b00011111, 0b11110000, 0b00000110, // ### ######### ## 212 | 0b01110000, 0b00000111, 0b11100000, 0b00000011, // ### ###### ## 213 | 0b11000000, 0b00000011, 0b10000000, 0b00000001, // ## ### # 214 | 0b10000000, 0b00000111, 0b11000000, 0b00000000, // # ##### 215 | 0b00000000, 0b00000111, 0b11000000, 0b00000000, // ##### 216 | 0b00000000, 0b00000111, 0b11000000, 0b00000000, // ##### 217 | 0b00000000, 0b00000111, 0b11000000, 0b00000000, // ##### 218 | 0b00000111, 0b11110011, 0b10000111, 0b11110000, // ####### ### ####### 219 | 0b00011100, 0b00011100, 0b00011100, 0b00011100, // ### ### ### ### 220 | 0b01110000, 0b00000110, 0b01110000, 0b00000110, // ### ## ### ## 221 | 0b11000000, 0b00000011, 0b11000000, 0b00000011, // ## #### ## 222 | 0b10000000, 0b00000001, 0b10000000, 0b00000001, // # ## # 223 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 224 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 225 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 226 | }; 227 | 228 | static const unsigned char PROGMEM intake [] = { 229 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 230 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 231 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 232 | 0b00000000, 0b00000000, 0b00001100, 0b00000000, // ## 233 | 0b00000000, 0b00000000, 0b01111100, 0b00000000, // ##### 234 | 0b00000000, 0b00000011, 0b11110100, 0b00000000, // ###### # 235 | 0b00000000, 0b00111111, 0b10000100, 0b00000000, // ####### # 236 | 0b00000001, 0b11111000, 0b10000100, 0b00000000, // ###### # # 237 | 0b00001111, 0b01001000, 0b10111111, 0b11111111, // #### # # # ############## 238 | 0b00001100, 0b01111111, 0b11000111, 0b11111111, // ## ######### ########### 239 | 0b00001111, 0b11001000, 0b10000111, 0b11111111, // ###### # # ########### 240 | 0b00001100, 0b01001011, 0b11111111, 0b10000011, // ## # # ########### ## 241 | 0b00001111, 0b11111100, 0b10000111, 0b10011111, // ########## # #### ##### 242 | 0b00001100, 0b01001000, 0b10000111, 0b10011111, // ## # # # #### ##### 243 | 0b00001111, 0b11111111, 0b11111111, 0b10011111, // ##################### ##### 244 | 0b00001100, 0b01001000, 0b10000111, 0b10000011, // ## # # # #### ## 245 | 0b00001111, 0b11111000, 0b10000111, 0b10011111, // ######### # #### ##### 246 | 0b00001100, 0b01001111, 0b11111111, 0b10011111, // ## # ############# ##### 247 | 0b00001111, 0b11001000, 0b10000111, 0b10011111, // ###### # # #### ##### 248 | 0b00001100, 0b01111111, 0b11000111, 0b10011111, // ## ######### #### ##### 249 | 0b00001111, 0b01001000, 0b10111111, 0b11111111, // #### # # # ############## 250 | 0b00001100, 0b11111000, 0b10000111, 0b11111111, // ## ##### # ########### 251 | 0b00001110, 0b01001111, 0b10000111, 0b11111111, // ### # ##### ########### 252 | 0b00001111, 0b11001000, 0b11110111, 0b11111111, // ###### # #### ########### 253 | 0b00000011, 0b11111100, 0b10001111, 0b11111111, // ######## # ############ 254 | 0b00000000, 0b01111111, 0b10000100, 0b00000000, // ######## # 255 | 0b00000000, 0b00001111, 0b11110100, 0b00000000, // ######## # 256 | 0b00000000, 0b00000011, 0b11111100, 0b00000000, // ######## 257 | 0b00000000, 0b00000000, 0b01111100, 0b00000000, // ##### 258 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 259 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 260 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 261 | }; 262 | 263 | void setup() { 264 | pinMode(A0, INPUT_PULLUP); 265 | //3 buttons connected as such: http://tronixstuff.com/2011/01/11/tutorial-using-analog-input-for-multiple-buttons/ 266 | //use 15 Kohm resistors 267 | //no buttons is 1010 268 | //button nearest gnd is 300 269 | //middle button is 454 270 | //last button is 555 271 | Serial.begin(9600); 272 | display.begin(SSD1306_SWITCHCAPVCC); 273 | display.display(); 274 | display.clearDisplay(); 275 | 276 | //show flash screen 277 | display.drawBitmap(0, 0, robothead, 32, 32, 1); 278 | display.display(); 279 | 280 | display.setCursor(36,0); 281 | display.setTextSize(2); 282 | display.setTextColor(WHITE); 283 | display.println("Not A"); 284 | display.setCursor(36,15); 285 | display.println("Clock"); 286 | display.display(); 287 | 288 | //shifty eyes 289 | /* for (int i; i < 8; i++){ 290 | display.fillRect(8, 22, 2, 2, WHITE); 291 | display.fillRect(18, 22, 2, 2, WHITE); 292 | display.display(); 293 | delay(500); 294 | display.fillRect(8, 22, 2, 2, BLACK); 295 | display.fillRect(18, 22, 2, 2, BLACK); 296 | display.display(); 297 | display.fillRect(4, 22, 2, 2, WHITE); 298 | display.fillRect(14, 22, 2, 2, WHITE); 299 | display.display(); 300 | delay(500); 301 | display.fillRect(4, 22, 2, 2, BLACK); 302 | display.fillRect(14, 22, 2, 2, BLACK); 303 | display.display(); 304 | } 305 | */ 306 | //temporary stuff to test button setup 307 | /* 308 | display.clearDisplay(); 309 | display.display(); 310 | int tempVal; 311 | while(true){ 312 | tempVal = analogRead(0); 313 | display.setCursor(36,0); 314 | display.setTextSize(2); 315 | display.setTextColor(WHITE); 316 | display.println(tempVal); 317 | display.display(); 318 | delay(100); 319 | display.setCursor(36,0); 320 | display.setTextSize(2); 321 | display.setTextColor(BLACK); 322 | display.println(tempVal); 323 | display.display(); 324 | } 325 | */ 326 | //end temp stuff for testing buttons 327 | 328 | //set up OBD II stuffs 329 | display.fillRect(8, 21, 2, 2, WHITE); 330 | display.fillRect(18, 21, 2, 2, WHITE); 331 | display.display(); 332 | Serial.println("ATZ"); 333 | getResponse(); 334 | delay(1000); 335 | display.fillRect(8, 21, 2, 2, BLACK); 336 | display.fillRect(18, 21, 2, 2, BLACK); 337 | display.display(); 338 | display.fillRect(4, 21, 2, 2, WHITE); 339 | display.fillRect(14, 21, 2, 2, WHITE); 340 | display.display(); 341 | ///Serial.println("ATDP"); 342 | //getResponse(); 343 | delay(1000); 344 | display.fillRect(8, 21, 2, 2, WHITE); 345 | display.fillRect(18, 21, 2, 2, WHITE); 346 | display.display(); 347 | Serial.println("ATE0"); 348 | getResponse(); 349 | delay(1000); 350 | display.fillRect(8, 22, 2, 2, BLACK); 351 | display.fillRect(18, 22, 2, 2, BLACK); 352 | display.display(); 353 | display.fillRect(4, 22, 2, 2, WHITE); 354 | display.fillRect(14, 22, 2, 2, WHITE); 355 | display.display(); 356 | Serial.println("AT SH 7E0"); 357 | getResponse(); 358 | delay(1000); 359 | //block to test out the oil temp reading 360 | /****** 361 | for (int g=0;g<=3;g++){ 362 | Serial.println("2101"); 363 | getResponse(); 364 | Serial.flush(); 365 | display.clearDisplay(); 366 | display.display(); 367 | display.setCursor(0,0); 368 | display.println(((float)strtol(&rxData[109],0,16) - 40) * 1.8 + 32); 369 | display.display(); 370 | delay(1000); 371 | } 372 | */ 373 | 374 | //put first mode icon and unit here 375 | display.clearDisplay(); 376 | display.drawBitmap(0, 0, oil, 32, 32, 1); 377 | display.setCursor(110,11); 378 | //display.println("F"); 379 | display.display(); 380 | } 381 | 382 | void loop() { 383 | buttonV = analogRead(A0); 384 | while ( (analogRead(A0) <= 430) || (analogRead(A0) >= 490) ){ //not mode button 385 | buttonV = analogRead(A0); 386 | if ( (buttonV <= 500) && (buttonV >= 600) ){ //hold down the peaks button to show the peaks of this mode (545) 387 | while ( (buttonV <= 500) && (buttonV >= 600) ){ //debounce 388 | //display peaks for this "mode" here 389 | display.fillRect(48,0,80,32,BLACK); //black area between icon and unit 390 | display.setTextSize(3); 391 | display.setTextColor(WHITE); 392 | display.setCursor(48,10); 393 | display.println(peaks[mode]); 394 | display.display(); 395 | buttonV = analogRead(A0); 396 | delay(50); 397 | } 398 | display.fillRect(48,0,80,32,BLACK); //black area between icon and unit 399 | getVal(); 400 | updateVal(); //just incase it doesn't draw below because the values stay the same 401 | display.display(); 402 | buttonV = analogRead(A0); 403 | } 404 | 405 | //hold reset button here to reset peak of specific mode (300) 406 | if ( (buttonV <= 325) && (buttonV >= 285) ){ //hold down the reset button to reseet the peaks of this mode (3??) 407 | while ( (buttonV <= 325) && (buttonV >= 285) ){ //debounce 408 | display.fillRect(48,0,80,32,BLACK); //black area between icon and unit 409 | display.setTextSize(3); 410 | display.setCursor(48,10); 411 | display.setTextColor(WHITE); 412 | display.println("RST"); 413 | display.display(); 414 | buttonV = analogRead(A0); 415 | delay(50); 416 | } 417 | //reset peak specific to this mode 418 | display.fillRect(48,0,80,32,BLACK); //black area between icon and unit 419 | getVal(); 420 | updateVal(); //just incase it doesn't draw below because the values stay the same 421 | display.display(); 422 | peaks[mode] = 0; 423 | buttonV = analogRead(A0); 424 | } 425 | 426 | //display the value here...no conditionals...just print the value (for now??) 427 | //only print if it changes to avoid flickering 428 | getVal(); 429 | if ( abs(curValue[mode]-previousReading[mode]) > 0 ){ 430 | updateVal(); 431 | } 432 | //delay(100); 433 | //check for warning values here (for this mode only) 434 | if ( ( (curValue[mode] > warnLevels[mode]) && (warnSign[mode] == 1) ) || ( (curValue[mode] < warnLevels[mode]) && (warnSign[mode] == 0) ) ){ 435 | //do a warning thing here 436 | warn(); 437 | } 438 | } 439 | while ( (analogRead(A0) >= 430) && (analogRead(A0) <= 490) ){ //mode button 440 | } 441 | if (mode == modes){ 442 | mode = 0; 443 | } 444 | else { 445 | mode++; 446 | } 447 | //upon switching modes blank screen and display that mode's icon 448 | //also print the unit of measurement if used 449 | //but first reset the OBDII stuff just in case (might not be necessary) 450 | /*Serial.println("ATZ"); 451 | getResponse(); 452 | delay(500); 453 | Serial.println("ATE0"); 454 | getResponse(); 455 | delay(500); 456 | Serial.println("AT SH 7E0"); 457 | getResponse(); 458 | delay(500);*/ 459 | display.clearDisplay(); 460 | display.setTextSize(3); 461 | display.setTextColor(WHITE); 462 | if (mode == 0){//oil temp 463 | display.drawBitmap(0, 0, oil, 32, 32, 1); 464 | display.setCursor(110,11); 465 | //display.println("F"); 466 | display.display(); 467 | } 468 | if (mode == 1){//AFR 469 | display.drawBitmap(0, 0, o2, 32, 32, 1); 470 | display.display(); 471 | } 472 | if (mode == 2){//Volts 473 | display.drawBitmap(0, 0, batt, 32, 32, 1); 474 | //display.setCursor(110,11); 475 | //display.println("V"); 476 | display.display(); 477 | } 478 | if (mode == 3){//Coolant 479 | display.drawBitmap(0, 0, coolant, 32, 32, 1); 480 | display.setCursor(110,11); 481 | //display.println("F"); 482 | display.display(); 483 | } 484 | if (mode == 4){ 485 | display.drawBitmap(0, 0, intake, 32, 32, 1); 486 | display.setCursor(110,11); 487 | //display.println("F"); 488 | display.display(); 489 | } 490 | getVal(); 491 | updateVal(); //if you don't update here and the value hasn't changed you get blank value 492 | } 493 | 494 | void warn(){ 495 | //a border around the screen flashes as a warning 496 | for (int a=1;a<=3;a++){ 497 | display.drawRect(0,0,128,32,WHITE); 498 | delay(100); 499 | display.drawRect(0,0,128,32,BLACK); 500 | } 501 | return; 502 | } 503 | 504 | void getVal(){ 505 | if (mode == 0){ 506 | curValue[mode] = getOBDIIvalue("obdbrzoiltempf");//modeList[mode]); 507 | } 508 | else if (mode == 1){ 509 | curValue[mode] = getOBDIIvalue("obdafr"); 510 | } 511 | else if (mode == 2){ 512 | curValue[mode] = getOBDIIvalue("obdvolts"); 513 | } 514 | else if (mode == 3){ 515 | curValue[mode] = getOBDIIvalue("obdcoolantf"); 516 | } 517 | else if (mode == 4){ 518 | curValue[mode] = getOBDIIvalue("obdiat"); 519 | } 520 | if (curValue[mode] > peaks[mode]){ 521 | peaks[mode] = curValue[mode]; 522 | } 523 | } 524 | 525 | void updateVal(){ 526 | display.setTextSize(3); 527 | //draw old value 528 | display.setTextColor(BLACK); 529 | display.setCursor(50,12); 530 | display.println(previousReading[mode]); 531 | display.display(); 532 | //draw new value 533 | display.setTextColor(WHITE); 534 | display.setCursor(50,12); 535 | if ( (mode == 1) || (mode == 2) ){ //AFR should show the decimal (others could be added to this list) 536 | display.println(curValue[mode]); 537 | } 538 | else { //everything else should print an int value 539 | display.println((int)curValue[mode]); 540 | } 541 | display.display(); 542 | previousReading[mode] = curValue[mode]; 543 | return; 544 | } 545 | 546 | //from: https://forum.sparkfun.com/viewtopic.php?f=14&t=38253 547 | void getResponse(void){ 548 | char c; 549 | //int start=millis(); 550 | //If nothing is currently available do nothing and break after 3 seconds 551 | //while(Serial.available()==0){if(millis()-start>3000){break;}} 552 | do { 553 | if (Serial.available() > 0) 554 | { 555 | c = Serial.read(); 556 | if ((c != '>') && (c != '\r') && (c != '\n')) //Keep these out of our buffer 557 | { 558 | rxData[rxIndex++] = c; //Add whatever we receive to the buffer 559 | } 560 | } 561 | } 562 | while (c != '>'); //The ELM327 ends its response with this char so when we get it we exit out. 563 | rxData[rxIndex++] = '\0'; //Converts the array into a string 564 | //Serial.print("rxData: "); 565 | //Serial.println(rxData); 566 | rxIndex = 0; //Set this to 0 so next time we call the read we get a "clean" buffer 567 | } 568 | 569 | float getOBDIIvalue(String whichSensor){ 570 | //Serial.flush(); 571 | float value = 0; 572 | if (whichSensor.indexOf("obdspeedkph") >= 0){ 573 | Serial.println("010D"); //mode 1 0D PID 574 | //getResponse(); //command echoed 575 | getResponse(); //value 576 | value = strtol(&rxData[6],0,16) ; //convert the string to integer 577 | } 578 | if (whichSensor.indexOf("obdspeedmph") >= 0){ 579 | Serial.println("010D"); //mode 1 0D PID 580 | getResponse(); //value 581 | value = strtol(&rxData[6],0,16)/1.6 ; //convert the string to integer 582 | } 583 | if (whichSensor.indexOf("obdrpms") >= 0){ 584 | Serial.println("010C"); //mode 1 0C PID (rpm) 585 | //Serial.println("getting rpm"); 586 | getResponse(); //value 587 | value = ((strtol(&rxData[6],0,16)*256)+strtol(&rxData[9],0,16))/4; //aka ((A*256)+B)/4 588 | //Serial.println("rpm ="); 589 | //Serial.println(value); 590 | } 591 | if (whichSensor.indexOf("obdcoolantc") >=0){ 592 | Serial.println("O1O5"); 593 | getResponse(); 594 | value = (strtol(&rxData[6],0,16)-40); //aka A-40 595 | } 596 | if (whichSensor.indexOf("obdcoolantf") >=0){ 597 | //Serial.println("coolantf"); 598 | Serial.println("O1O5"); //gives raw data of "?" 599 | getResponse(); 600 | value = ((strtol(&rxData[6],0,16))-40)*1.8+32; //aka A-40 601 | //Serial.print("value of coolantf "); 602 | //Serial.print(value); 603 | } 604 | if (whichSensor.indexOf("obdboost") >= 0){ 605 | Serial.println("0265"); //intake manifold abs pressure 606 | getResponse(); 607 | value = (strtol(&rxData[6],0,16)); //aka A 608 | } 609 | if (whichSensor.indexOf("obdafr") >= 0){ 610 | Serial.println("0134"); //afr reading (readings aren't great) 611 | getResponse(); 612 | value = ((float)(strtol(&rxData[6],0,16)*256)+strtol(&rxData[9],0,16))/32768*14.7; //(A*256+B)/32768*14.7 613 | } 614 | if (whichSensor.indexOf("obdiat") >= 0){ 615 | Serial.println("O1OF"); 616 | getResponse(); 617 | value = (strtol(&rxData[6],0,16)-40); //aka A-40 618 | } 619 | if (whichSensor.indexOf("obdmaf") >= 0){ 620 | Serial.println("0110"); 621 | getResponse(); 622 | value = ((strtol(&rxData[6],0,16)*256)+strtol(&rxData[9],0,16))/100; //aka ((A*256)+B)/100 623 | } 624 | if (whichSensor.indexOf("obdvolts") >= 0){ 625 | Serial.println("0142"); 626 | //Serial.println("getting volts"); 627 | getResponse(); 628 | value = ((float)(strtol(&rxData[6],0,16)*256)+strtol(&rxData[9],0,16))/1000; //aka ((A*256)+B)/100 629 | //Serial.println("volts is:"); 630 | //Serial.println(value); 631 | } 632 | if (whichSensor.indexOf("obdoiltempc") >= 0){ 633 | Serial.println("015C"); 634 | getResponse(); 635 | value = strtol(&rxData[6],0,16)-40; //aka (A-40) 636 | } 637 | if (whichSensor.indexOf("obdoiltempf") >= 0){ 638 | Serial.println("015C"); 639 | getResponse(); 640 | value = (strtol(&rxData[6],0,16)-40)*1.8+32; //aka (A-40) *1.8 641 | } 642 | 643 | //nonstandard/experiemental PIDs 644 | if (whichSensor.indexOf("obdbrzoiltempc") >= 0){ 645 | //Serial.println("AT SH 7E0"); 646 | //Serial1.flush(); 647 | Serial.println("2101"); 648 | getResponse(); 649 | value = ((float)strtol(&rxData[109],0,16) - 40); //29th byte - 40 (?) 650 | //Serial1.println("AT D"); 651 | //Serial1.println("AT E0"); 652 | //delay(40); 653 | //Serial1.println("ATSP6"); 654 | } 655 | if (whichSensor.indexOf("obdbrzoiltempf") >= 0){ //works 656 | //Serial.println("AT SH 7E0"); //TRY 657 | //Serial1.flush(); 658 | //getResponse(); 659 | Serial.println("2101"); 660 | getResponse(); //try getResponse2() 661 | //Serial.println("brz oil temp"); 662 | //delay(40); 663 | //Serial.println(&rxData[109]); 664 | //Serial.println((float)strtol(&rxData[109],0,16)); 665 | value = ((float)strtol(&rxData[109],0,16) - 40) * 1.8 + 32; 666 | //Serial.println(value); //TRY 667 | } 668 | 669 | delay(100); 670 | Serial.flush(); 671 | memset(rxData,0,sizeof(rxData)); //blank the array 672 | return value; 673 | } 674 | -------------------------------------------------------------------------------- /oledOBDgaugesSimpleIrvinedLibTest/oledOBDgaugesSimpleIrvinedLibTest.ino: -------------------------------------------------------------------------------- 1 | // oledOBDgaugesSimpleIrvinedLibTest.ino 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #define ELM_TIMEOUT 9000 8 | #define ELM_BAUD_RATE 9600 9 | #define ELM_PORT Serial 10 | 11 | #define OLED_MOSI 9 12 | #define OLED_CLK 10 13 | #define OLED_DC 11 14 | #define OLED_CS 12 15 | #define OLED_RESET 13 16 | 17 | Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS); 18 | char rxData[115]; 19 | char rxIndex=0; 20 | 21 | float value = 0; 22 | unsigned int ratio = 0; 23 | float previousValue = 0; 24 | byte Status; 25 | byte StatusOld; 26 | 27 | Elm327 Elm; 28 | byte status; 29 | 30 | void setup() { 31 | status=Elm.begin(); 32 | display.begin(SSD1306_SWITCHCAPVCC); 33 | display.display(); 34 | display.clearDisplay(); 35 | display.display(); 36 | 37 | 38 | //did the obd ii init correctly 39 | display.setCursor(10, 10); 40 | display.println(status); 41 | display.display(); 42 | //Elm.runCommand("AT SH 7E0",rxData,110); 43 | delay(1000); 44 | display.clearDisplay(); 45 | 46 | } 47 | 48 | void loop() { 49 | char data[130]; 50 | //Elm.getVoltage(value); 51 | //Elm.intakeAirTemperature(value); 52 | //Elm.coolantTemperature(value); 53 | //value=value*1.8+32; 54 | //Elm.engineRPM(value); 55 | //Elm.timingAdvance(value); 56 | //Elm.o2WRCurrent("34", ratio, value); 57 | Status = Elm.runCommand("2101",data,130); 58 | value = ((float)strtol(&data[109],0,16) - 40) * 1.8 + 32; 59 | display.setCursor(10,10); 60 | display.setTextColor(BLACK); 61 | display.println(previousValue); 62 | display.setCursor(10,20); 63 | display.println(data[109]); 64 | display.display(); 65 | display.setCursor(10,10); 66 | display.setTextColor(WHITE); 67 | display.println(value); 68 | display.setCursor(10,20); 69 | display.println(data[109]); 70 | display.display(); 71 | delay(100); 72 | previousValue = value; 73 | StatusOld = Status; 74 | } 75 | 76 | //01F 0: 61 01 00 00 00 00 1: 55 66 55 4C 65 4C 00 2: 00 00 00 00 0D 2A 54 3: 21 21 00 7A 0A A4 13 4: 6C 30 BC 4C 00 z0 00 77 | //01F 0: 61 01 00 00 00 00 1: 55 66 60 4A 65 7E 00 2: 00 00 00 00 09 26 51 3: 21 21 00 41 05zFC 09 4: E5 31 2B 76 00 00 00 78 | //117? 118? because of extra line feed characters that need to be skipped -------------------------------------------------------------------------------- /oledOBDgaugesSmallIrvinedLib-Boost/oledOBDgaugesSmallIrvinedLib-Boost.ino: -------------------------------------------------------------------------------- 1 | //obdII gauge that reuses a lot of code from my other projects 2 | //set up to use the SPI 128x32 OLED display from adafruit 3 | 4 | //TODO: 5 | //write a function that periodically scans all monitored values 6 | //test warning function (set one low and test that way) 7 | 8 | //TODO (add boost): 9 | //new graphic 10 | //remove AT command for BRZ 11 | //new warn level 12 | //new calc 13 | //new PID?? 14 | //try on regular arduino?s 15 | 16 | //hardware TODO: 17 | //test tinting plastic to appear red/amber 18 | //desoldier buttons and wire up 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #define ELM_TIMEOUT 9000 26 | #define ELM_BAUD_RATE 9600 27 | #define ELM_PORT Serial 28 | 29 | #define OLED_MOSI 9 30 | #define OLED_CLK 10 31 | #define OLED_DC 11 32 | #define OLED_CS 12 33 | #define OLED_RESET 13 34 | 35 | Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS); 36 | 37 | int buttonV; 38 | 39 | Elm327 Elm; 40 | byte Status; 41 | 42 | int warnLevels[] = { 43 | 160, 220, 15, 220, 300}; 44 | int warnSign[] = { 45 | 1,1,1,1,1}; //1 for high, 0 for low (in cases like oil pressure) 46 | float peaks[] = { 47 | 0,0,0,0,0}; 48 | float curValue[] = { 49 | 0,0,0,0,0}; 50 | float previousReading[] = { 51 | 0,0,0,0,0}; 52 | int mode = 0; 53 | int modes = 4; //0 is the first of the array 54 | 55 | static const unsigned char PROGMEM robothead [] = { 56 | 0b00000000, 0b00111100, 0b00000000, 0b00000000, // #### 57 | 0b00000000, 0b01111110, 0b00000000, 0b00000000, // ###### 58 | 0b00000000, 0b01111110, 0b00000000, 0b00000000, // ###### 59 | 0b00000000, 0b01111110, 0b00000000, 0b00000000, // ###### 60 | 0b00000000, 0b00111100, 0b00000000, 0b00000000, // #### 61 | 0b00000000, 0b00011000, 0b00000000, 0b00000000, // ## 62 | 0b00000000, 0b00011000, 0b00000000, 0b00000000, // ## 63 | 0b00000000, 0b00011000, 0b00000000, 0b00000000, // ## 64 | 0b00000000, 0b00011000, 0b00000000, 0b00000000, // ## 65 | 0b00000000, 0b00011000, 0b00000000, 0b00000000, // ## 66 | 0b00000000, 0b00011000, 0b00000000, 0b00000000, // ## 67 | 0b00000000, 0b00011000, 0b00000000, 0b00000000, // ## 68 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 69 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 70 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 71 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 72 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 73 | 0b11110000, 0b00111100, 0b00001111, 0b10000000, // #### #### ##### 74 | 0b11110000, 0b00111100, 0b00001111, 0b10000000, // #### #### ##### 75 | 0b11110000, 0b00111100, 0b00001111, 0b10000000, // #### #### ##### 76 | 0b11110000, 0b00111100, 0b00001111, 0b10000000, // #### #### ##### 77 | 0b11110000, 0b00111100, 0b00001111, 0b10000000, // #### #### ##### 78 | 0b11110000, 0b00111100, 0b00001111, 0b10000000, // #### #### ##### 79 | 0b11110000, 0b00111100, 0b00001111, 0b10000000, // #### #### ##### 80 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 81 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 82 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 83 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 84 | 0b11100000, 0b00000000, 0b00000111, 0b10000000, // ### #### 85 | 0b11100000, 0b00000000, 0b00000111, 0b10000000, // ### #### 86 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 87 | }; 88 | 89 | static const unsigned char PROGMEM batt [] = { 90 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 91 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 92 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 93 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 94 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 95 | 0b00000001, 0b11110000, 0b00011111, 0b00000000, // ##### ##### 96 | 0b00000010, 0b00001000, 0b00100000, 0b10000000, // # # # # 97 | 0b00000010, 0b00001000, 0b00100000, 0b10000000, // # # # # 98 | 0b00000010, 0b00001000, 0b00100000, 0b10000000, // # # # # 99 | 0b00000010, 0b00001000, 0b00100000, 0b10000000, // # # # # 100 | 0b00000010, 0b00001000, 0b00100000, 0b10000000, // # # # # 101 | 0b00011111, 0b11111111, 0b11111111, 0b11110000, // ######################### 102 | 0b00011110, 0b00000000, 0b00000000, 0b11110000, // #### #### 103 | 0b00011110, 0b00000000, 0b00000000, 0b11110000, // #### #### 104 | 0b00011110, 0b00000000, 0b00000000, 0b11110000, // #### #### 105 | 0b00010000, 0b01000000, 0b00000000, 0b00010000, // # # # 106 | 0b00010000, 0b01000000, 0b00000000, 0b00010000, // # # # 107 | 0b00010000, 0b01000000, 0b00000000, 0b00010000, // # # # 108 | 0b00010011, 0b11111000, 0b00111111, 0b10010000, // # ####### ####### # 109 | 0b00010000, 0b01000000, 0b00000000, 0b00010000, // # # # 110 | 0b00010000, 0b01000000, 0b00000000, 0b00010000, // # # # 111 | 0b00010000, 0b01000000, 0b00000000, 0b00010000, // # # # 112 | 0b00010000, 0b00000000, 0b00000000, 0b00010000, // # # 113 | 0b00011110, 0b00000000, 0b00000000, 0b11110000, // #### #### 114 | 0b00011110, 0b00000000, 0b00000000, 0b11110000, // #### #### 115 | 0b00011110, 0b00000000, 0b00000000, 0b11110000, // #### #### 116 | 0b00011111, 0b11111111, 0b11111111, 0b11110000, // ######################### 117 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 118 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 119 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 120 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 121 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 122 | }; 123 | 124 | static const unsigned char PROGMEM o2 [] = { 125 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 126 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 127 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 128 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 129 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 130 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 131 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 132 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 133 | 0b00000001, 0b11111000, 0b00000000, 0b00000000, // ###### 134 | 0b00000011, 0b11111110, 0b00000000, 0b00000000, // ######### 135 | 0b00000111, 0b00000111, 0b00000000, 0b00000000, // ### ### 136 | 0b00001100, 0b00000011, 0b00000000, 0b00000000, // ## ## 137 | 0b00001100, 0b00000011, 0b00000000, 0b00000000, // ## ## 138 | 0b00011000, 0b00000001, 0b10000000, 0b00000000, // ## ## 139 | 0b00011000, 0b00000001, 0b11111000, 0b00000000, // ## ###### 140 | 0b00011000, 0b00000001, 0b11111100, 0b00000000, // ## ####### 141 | 0b00011000, 0b00000001, 0b10001110, 0b00000000, // ## ## ### 142 | 0b00011000, 0b00000001, 0b10000110, 0b00000000, // ## ## ## 143 | 0b00001100, 0b00000011, 0b00000110, 0b00000000, // ## ## ## 144 | 0b00001100, 0b00000011, 0b00000110, 0b00000000, // ## ## ## 145 | 0b00001110, 0b00001110, 0b00000100, 0b00000000, // ### ### # 146 | 0b00000111, 0b11111100, 0b00001100, 0b00000000, // ######### ## 147 | 0b00000001, 0b11111000, 0b00011000, 0b00000000, // ###### ## 148 | 0b00000000, 0b00000000, 0b00110000, 0b00000000, // ## 149 | 0b00000000, 0b00000000, 0b01100000, 0b00000000, // ## 150 | 0b00000000, 0b00000000, 0b11000000, 0b00000000, // ## 151 | 0b00000000, 0b00000001, 0b10000000, 0b00000000, // ## 152 | 0b00000000, 0b00000011, 0b11111111, 0b00000000, // ########## 153 | 0b00000000, 0b00000011, 0b11111111, 0b00000000, // ########## 154 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 155 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 156 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 157 | }; 158 | 159 | 160 | static const unsigned char PROGMEM boost [] = { 161 | 0b00000000, 0b00000000, 0b00001111, 0b11111110, // ########### 162 | 0b00000000, 0b00111111, 0b11111000, 0b11110010, // ########### #### # 163 | 0b00000001, 0b11111111, 0b11111000, 0b11110010, // ############## #### # 164 | 0b00000111, 0b11110000, 0b00000000, 0b11110010, // ####### #### # 165 | 0b00001111, 0b00000000, 0b00000000, 0b11110010, // #### #### # 166 | 0b00111110, 0b00000000, 0b00000000, 0b11110010, // ##### #### # 167 | 0b01111100, 0b00011111, 0b10000000, 0b11110010, // ##### ###### #### # 168 | 0b01111000, 0b00111111, 0b11111000, 0b11110010, // #### ########### #### # 169 | 0b11110000, 0b01111000, 0b11111111, 0b11111110, // #### #### ############### 170 | 0b11100001, 0b11001100, 0b11111111, 0b11111110, // ### ### ## ############### 171 | 0b11000001, 0b10000101, 0b10011011, 0b00000000, // ## ## # ## ## ## 172 | 0b11000001, 0b10000111, 0b00011001, 0b10000000, // ## ## ### ## ## 173 | 0b11100001, 0b10000110, 0b00011001, 0b10000000, // ### ## ## ## ## 174 | 0b01100001, 0b10111110, 0b00011001, 0b10000000, // ## ## ##### ## ## 175 | 0b01111000, 0b11000010, 0b00110001, 0b10000000, // #### ## # ## ## 176 | 0b01111000, 0b11110011, 0b11110001, 0b10000000, // #### #### ###### ## 177 | 0b00111000, 0b00111111, 0b11000011, 0b10000000, // ### ######## ### 178 | 0b00011100, 0b00000000, 0b00000111, 0b10000000, // ### #### 179 | 0b00001110, 0b00000000, 0b00001111, 0b00000000, // ### #### 180 | 0b00001111, 0b11111111, 0b11111111, 0b00000000, // #################### 181 | 0b00000011, 0b11111111, 0b11111000, 0b00000000, // ############### 182 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 183 | 0b00011111, 0b11000001, 0b11110000, 0b11100000, // ####### ##### ### 184 | 0b00011111, 0b11100111, 0b11111000, 0b11100000, // ######## ######## ### 185 | 0b00011100, 0b11100111, 0b00111000, 0b11100000, // ### ### ### ### ### 186 | 0b00011100, 0b11100111, 0b00000000, 0b11100000, // ### ### ### ### 187 | 0b00011100, 0b11100111, 0b11100000, 0b11100000, // ### ### ###### ### 188 | 0b00011111, 0b11100011, 0b11110000, 0b11100000, // ######## ###### ### 189 | 0b00011111, 0b11000000, 0b11111000, 0b11100000, // ####### ##### ### 190 | 0b00011100, 0b00000111, 0b00111000, 0b11100000, // ### ### ### ### 191 | 0b00011100, 0b00000111, 0b00111000, 0b11100000, // ### ### ### ### 192 | 0b00011100, 0b00000011, 0b11110000, 0b11100000, // ### ###### ### 193 | }; 194 | 195 | static const unsigned char PROGMEM coolant [] = { 196 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 197 | 0b00111111, 0b10000000, 0b00000000, 0b00000000, // ####### 198 | 0b00111000, 0b00000011, 0b10000000, 0b00000000, // ### ### 199 | 0b00111000, 0b00000011, 0b10000000, 0b00000000, // ### ### 200 | 0b00111000, 0b00000011, 0b11111110, 0b00000000, // ### ######### 201 | 0b00111111, 0b00000011, 0b11111110, 0b00000000, // ###### ######### 202 | 0b00111000, 0b00000011, 0b11111110, 0b00000000, // ### ######### 203 | 0b00111000, 0b00000011, 0b10000000, 0b00000000, // ### ### 204 | 0b00111000, 0b00000011, 0b10000000, 0b00000000, // ### ### 205 | 0b00111000, 0b00000011, 0b11111110, 0b00000000, // ### ######### 206 | 0b00000000, 0b00000011, 0b11111110, 0b00000000, // ######### 207 | 0b00000000, 0b00000011, 0b11111110, 0b00000000, // ######### 208 | 0b00000000, 0b00000011, 0b10000000, 0b00000000, // ### 209 | 0b00000000, 0b00000011, 0b10000000, 0b00000000, // ### 210 | 0b00000000, 0b00000011, 0b10000000, 0b00000000, // ### 211 | 0b00000000, 0b00000011, 0b10000111, 0b11110000, // ### ####### 212 | 0b00000111, 0b11110011, 0b10011100, 0b00011100, // ####### ### ### ### 213 | 0b00011100, 0b00011111, 0b11110000, 0b00000110, // ### ######### ## 214 | 0b01110000, 0b00000111, 0b11100000, 0b00000011, // ### ###### ## 215 | 0b11000000, 0b00000011, 0b10000000, 0b00000001, // ## ### # 216 | 0b10000000, 0b00000111, 0b11000000, 0b00000000, // # ##### 217 | 0b00000000, 0b00000111, 0b11000000, 0b00000000, // ##### 218 | 0b00000000, 0b00000111, 0b11000000, 0b00000000, // ##### 219 | 0b00000000, 0b00000111, 0b11000000, 0b00000000, // ##### 220 | 0b00000111, 0b11110011, 0b10000111, 0b11110000, // ####### ### ####### 221 | 0b00011100, 0b00011100, 0b00011100, 0b00011100, // ### ### ### ### 222 | 0b01110000, 0b00000110, 0b01110000, 0b00000110, // ### ## ### ## 223 | 0b11000000, 0b00000011, 0b11000000, 0b00000011, // ## #### ## 224 | 0b10000000, 0b00000001, 0b10000000, 0b00000001, // # ## # 225 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 226 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 227 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 228 | }; 229 | 230 | static const unsigned char PROGMEM intake [] = { 231 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 232 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 233 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 234 | 0b00000000, 0b00000000, 0b00001100, 0b00000000, // ## 235 | 0b00000000, 0b00000000, 0b01111100, 0b00000000, // ##### 236 | 0b00000000, 0b00000011, 0b11110100, 0b00000000, // ###### # 237 | 0b00000000, 0b00111111, 0b10000100, 0b00000000, // ####### # 238 | 0b00000001, 0b11111000, 0b10000100, 0b00000000, // ###### # # 239 | 0b00001111, 0b01001000, 0b10111111, 0b11111111, // #### # # # ############## 240 | 0b00001100, 0b01111111, 0b11000111, 0b11111111, // ## ######### ########### 241 | 0b00001111, 0b11001000, 0b10000111, 0b11111111, // ###### # # ########### 242 | 0b00001100, 0b01001011, 0b11111111, 0b10000011, // ## # # ########### ## 243 | 0b00001111, 0b11111100, 0b10000111, 0b10011111, // ########## # #### ##### 244 | 0b00001100, 0b01001000, 0b10000111, 0b10011111, // ## # # # #### ##### 245 | 0b00001111, 0b11111111, 0b11111111, 0b10011111, // ##################### ##### 246 | 0b00001100, 0b01001000, 0b10000111, 0b10000011, // ## # # # #### ## 247 | 0b00001111, 0b11111000, 0b10000111, 0b10011111, // ######### # #### ##### 248 | 0b00001100, 0b01001111, 0b11111111, 0b10011111, // ## # ############# ##### 249 | 0b00001111, 0b11001000, 0b10000111, 0b10011111, // ###### # # #### ##### 250 | 0b00001100, 0b01111111, 0b11000111, 0b10011111, // ## ######### #### ##### 251 | 0b00001111, 0b01001000, 0b10111111, 0b11111111, // #### # # # ############## 252 | 0b00001100, 0b11111000, 0b10000111, 0b11111111, // ## ##### # ########### 253 | 0b00001110, 0b01001111, 0b10000111, 0b11111111, // ### # ##### ########### 254 | 0b00001111, 0b11001000, 0b11110111, 0b11111111, // ###### # #### ########### 255 | 0b00000011, 0b11111100, 0b10001111, 0b11111111, // ######## # ############ 256 | 0b00000000, 0b01111111, 0b10000100, 0b00000000, // ######## # 257 | 0b00000000, 0b00001111, 0b11110100, 0b00000000, // ######## # 258 | 0b00000000, 0b00000011, 0b11111100, 0b00000000, // ######## 259 | 0b00000000, 0b00000000, 0b01111100, 0b00000000, // ##### 260 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 261 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 262 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 263 | }; 264 | 265 | void setup() { 266 | pinMode(A0, INPUT_PULLUP); 267 | Status=Elm.begin(); 268 | //3 buttons connected as such: http://tronixstuff.com/2011/01/11/tutorial-using-analog-input-for-multiple-buttons/ 269 | //use 15 Kohm resistors 270 | //no buttons is 1010 271 | //button nearest gnd is 300 272 | //middle button is 454 273 | //last button is 555 274 | //Serial.begin(9600); 275 | display.begin(SSD1306_SWITCHCAPVCC); 276 | display.display(); 277 | display.clearDisplay(); 278 | display.display(); 279 | 280 | //show flash screen 281 | display.drawBitmap(0, 0, robothead, 32, 32, 1); 282 | display.display(); 283 | 284 | display.setCursor(36,0); 285 | display.setTextSize(2); 286 | display.setTextColor(WHITE); 287 | display.println("Not A"); 288 | display.setCursor(36,15); 289 | display.println("Clock"); 290 | display.display(); 291 | 292 | //temporary stuff to test button setup 293 | /* 294 | display.clearDisplay(); 295 | display.display(); 296 | int tempVal; 297 | while(true){ 298 | tempVal = analogRead(0); 299 | display.setCursor(36,0); 300 | display.setTextSize(2); 301 | display.setTextColor(WHITE); 302 | display.println(tempVal); 303 | display.display(); 304 | delay(100); 305 | display.setCursor(36,0); 306 | display.setTextSize(2); 307 | display.setTextColor(BLACK); 308 | display.println(tempVal); 309 | display.display(); 310 | //no button 1013-1017 311 | //a button 15 (no resistor...just wire resistance) 312 | //b button 302 313 | //c button 457 314 | //d button 556 315 | } */ 316 | 317 | //end temp stuff for testing buttons 318 | 319 | //set up OBD II stuffs 320 | display.fillRect(8, 21, 2, 2, WHITE); 321 | display.fillRect(18, 21, 2, 2, WHITE); 322 | display.display(); 323 | getOBDIIvalue("obdboost"); //do the first reading here because it takes a sec or two display.fillRect(8, 21, 2, 2, BLACK); 324 | display.fillRect(8, 21, 2, 2, BLACK); 325 | display.fillRect(18, 21, 2, 2, BLACK); 326 | display.display(); 327 | display.fillRect(4, 21, 2, 2, WHITE); 328 | display.fillRect(14, 21, 2, 2, WHITE); 329 | display.display(); 330 | delay(1000); 331 | display.fillRect(4, 21, 2, 2, BLACK); 332 | display.fillRect(14, 21, 2, 2, BLACK); 333 | display.display(); 334 | display.fillRect(8, 22, 2, 2, WHITE); 335 | display.fillRect(18, 22, 2, 2, WHITE); 336 | display.display(); 337 | delay(1000); 338 | display.fillRect(8, 22, 2, 2, BLACK); 339 | display.fillRect(18, 22, 2, 2, BLACK); 340 | display.display(); 341 | display.fillRect(4, 21, 2, 2, WHITE); 342 | display.fillRect(14, 21, 2, 2, WHITE); 343 | display.display(); 344 | delay(500); 345 | 346 | //put first mode icon and unit here 347 | display.clearDisplay(); 348 | display.drawBitmap(0, 0, boost, 32, 32, 1); 349 | display.display(); 350 | } 351 | 352 | void loop() { 353 | buttonV = analogRead(A0); 354 | while ( (analogRead(A0) <= 430) || (analogRead(A0) >= 490) ){ //not mode button (not between 430 and 490) 355 | buttonV = analogRead(A0); 356 | if ( (buttonV >= 500) && (buttonV <= 600) ){ //hold down the peaks button to show the peaks of this mode (555ish) 357 | while ( (buttonV >= 500) && (buttonV <= 600) ){ //debounce 358 | //display peaks for this "mode" here 359 | display.fillRect(48,0,80,32,BLACK); //black area between icon and unit 360 | display.setTextSize(3); 361 | display.setTextColor(WHITE); 362 | display.setCursor(48,10); 363 | display.println(peaks[mode]); 364 | display.display(); 365 | buttonV = analogRead(A0); 366 | delay(50); 367 | } 368 | display.fillRect(48,0,80,32,BLACK); //black area between icon and unit 369 | getVal(); 370 | updateVal(); //just incase it doesn't draw below because the values stay the same 371 | display.display(); 372 | buttonV = analogRead(A0); 373 | } 374 | 375 | //hold reset button here to reset peak of specific mode 376 | if ( (buttonV <= 325) && (buttonV >= 285) ){ //hold down the reset button to reseet the peaks of this mode (300ish) 377 | while ( (buttonV <= 325) && (buttonV >= 285) ){ //debounce 378 | display.fillRect(48,0,80,32,BLACK); //black area between icon and unit 379 | display.setTextSize(3); 380 | display.setCursor(48,10); 381 | display.setTextColor(WHITE); 382 | display.println("RST"); 383 | display.display(); 384 | buttonV = analogRead(A0); 385 | delay(50); 386 | } 387 | //reset peak specific to this mode 388 | display.fillRect(48,0,80,32,BLACK); //black area between icon and unit 389 | getVal(); 390 | updateVal(); //just incase it doesn't draw below because the values stay the same 391 | display.display(); 392 | peaks[mode] = 0; 393 | buttonV = analogRead(A0); 394 | } 395 | 396 | //display the value here...no conditionals...just print the value 397 | //only print if it changes to avoid flickering 398 | getVal(); 399 | if ( abs(curValue[mode]-previousReading[mode]) > 0 ){ 400 | updateVal(); 401 | } 402 | 403 | //TODO: fix this...not working 404 | //check for warning values here (for this mode only) 405 | //if ( ( (curValue[mode] > warnLevels[mode]) && (warnSign[mode] == 1) ) || ( (curValue[mode] < warnLevels[mode]) && (warnSign[mode] == 0) ) ){ 406 | if (curValue[mode] >= warnLevels[mode]){ 407 | //do a warning thing here 408 | display.println("WARN"); 409 | display.display(); 410 | warn(); 411 | } 412 | } 413 | while ( (analogRead(A0) >= 430) && (analogRead(A0) <= 490) ){ //mode button 414 | } 415 | if (mode == modes){ 416 | mode = 0; 417 | } 418 | else { 419 | mode++; 420 | } 421 | //upon switching modes blank screen and display that mode's icon 422 | //also print the unit of measurement if used 423 | display.clearDisplay(); 424 | display.setTextSize(3); 425 | display.setTextColor(WHITE); 426 | if (mode == 0){//boost 427 | display.drawBitmap(0, 0, boost, 32, 32, 1); 428 | display.display(); 429 | } 430 | if (mode == 1){//AFR 431 | display.drawBitmap(0, 0, o2, 32, 32, 1); 432 | display.display(); 433 | } 434 | if (mode == 2){//Volts 435 | display.drawBitmap(0, 0, batt, 32, 32, 1); 436 | display.display(); 437 | } 438 | if (mode == 3){//Coolant 439 | display.drawBitmap(0, 0, coolant, 32, 32, 1); 440 | display.display(); 441 | } 442 | if (mode == 4){ 443 | display.drawBitmap(0, 0, intake, 32, 32, 1); 444 | display.display(); 445 | } 446 | getVal(); 447 | updateVal(); //if you don't update here and the value hasn't changed you get blank value 448 | } 449 | 450 | void warn(){ 451 | //a border around the screen flashes as a warning 452 | for (int a=1;a>=3;a++){ 453 | display.drawRect(0,0,127,31,WHITE); 454 | delay(100); 455 | display.drawRect(0,0,127,31,BLACK); 456 | } 457 | return; 458 | } 459 | 460 | void getVal(){ 461 | if (mode == 0){ 462 | curValue[mode] = getOBDIIvalue("obdboost");//modeList[mode]); 463 | } 464 | else if (mode == 1){ 465 | curValue[mode] = getOBDIIvalue("obdafr"); 466 | } 467 | else if (mode == 2){ 468 | curValue[mode] = getOBDIIvalue("obdvolts"); 469 | } 470 | else if (mode == 3){ 471 | curValue[mode] = getOBDIIvalue("obdcoolantf"); 472 | } 473 | else if (mode == 4){ 474 | curValue[mode] = getOBDIIvalue("obdiat"); 475 | } 476 | if (curValue[mode] > peaks[mode]){ 477 | peaks[mode] = curValue[mode]; 478 | } 479 | } 480 | 481 | void updateVal(){ 482 | display.setTextSize(3); 483 | //draw old value 484 | display.setTextColor(BLACK); 485 | display.setCursor(50,12); 486 | if ( (mode ==0) || (mode == 1) || (mode == 2) ){ //AFR should show the decimal (others could be added to this list) 487 | display.println(previousReading[mode]); 488 | } 489 | else { //everything else should print an int value 490 | display.println((int)previousReading[mode]); 491 | } 492 | display.display(); 493 | //draw new value 494 | display.setTextColor(WHITE); 495 | display.setCursor(50,12); 496 | if ( (mode == 0) || (mode == 1) || (mode == 2) ){ //AFR should show the decimal (others could be added to this list) 497 | display.println(curValue[mode]); 498 | } 499 | else { //everything else should print an int value 500 | display.println((int)curValue[mode]); 501 | } 502 | display.display(); 503 | previousReading[mode] = curValue[mode]; 504 | //delay(100); 505 | return; 506 | } 507 | 508 | float getOBDIIvalue(String whichSensor){ 509 | //Serial.flush(); 510 | float value = 0; 511 | char data[130]; 512 | if (whichSensor.indexOf("obdcoolantf") >=0){ 513 | Elm.coolantTemperature(value); 514 | value=value*1.8+32; 515 | } 516 | if (whichSensor.indexOf("obdafr") >= 0){ 517 | Status = Elm.runCommand("0134",data,20); 518 | value = ((float)(strtol(&data[6],0,16)*256)+strtol(&data[9],0,16))/32768*14.7; //(A*256+B)/32768*14.7 519 | } 520 | if (whichSensor.indexOf("obdiat") >= 0){ //USED 521 | Elm.intakeAirTemperature(value); 522 | value=value*1.8+32; 523 | } 524 | 525 | if (whichSensor.indexOf("obdvolts") >= 0){ //USED 526 | Elm.getVoltage(value); 527 | } 528 | 529 | if (whichSensor.indexOf("obdbrzoiltempf") >= 0){ //works and USED 530 | Status = Elm.runCommand("2101",data,130); 531 | value = ((float)strtol(&data[109],0,16) - 40) * 1.8 + 32; 532 | } 533 | 534 | if (whichSensor.indexOf("obdboost") >= 0) { 535 | Status = Elm.runCommand("010B",data,20); //intake absolute manifold pressure 536 | value = ((float)(strtol(&data[6],0,16))*.145 - 14.69); 537 | } 538 | 539 | //delay(100); 540 | return value; 541 | } 542 | 543 | -------------------------------------------------------------------------------- /oledOBDgaugesSmallIrvinedLib/oledOBDgaugesSmallIrvinedLib.ino: -------------------------------------------------------------------------------- 1 | //obdII gauge that reuses a lot of code from my other projects 2 | //set up to use the SPI 128x32 OLED display from adafruit 3 | 4 | //TODO: 5 | //write a function that periodically scans all monitored values 6 | //test peak recall (fix...isn't really working...wrong voltage range??) 7 | //test warning function (set one low and test that way) 8 | 9 | //hardware TODO: 10 | //test tinting plastic to appear red/amber 11 | //desoldier buttons and wire up 12 | //desoldier led backlight 13 | //wire up power to come from OBD II 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #define ELM_TIMEOUT 9000 21 | #define ELM_BAUD_RATE 9600 22 | #define ELM_PORT Serial 23 | 24 | #define OLED_MOSI 9 25 | #define OLED_CLK 10 26 | #define OLED_DC 11 27 | #define OLED_CS 12 28 | #define OLED_RESET 13 29 | 30 | Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS); 31 | 32 | int buttonV; 33 | 34 | Elm327 Elm; 35 | byte Status; 36 | 37 | int warnLevels[] = { 38 | 100, 220, 15, 220, 300}; 39 | int warnSign[] = { 40 | 1,1,1,1,1}; //1 for high, 0 for low (in cases like oil pressure) 41 | float peaks[] = { 42 | 0,0,0,0,0}; 43 | float curValue[] = { 44 | 0,0,0,0,0}; 45 | float previousReading[] = { 46 | 0,0,0,0,0}; 47 | int mode = 0; 48 | int modes = 4; //0 is the first of the array 49 | 50 | static const unsigned char PROGMEM robothead [] = { 51 | 0b00000000, 0b00111100, 0b00000000, 0b00000000, // #### 52 | 0b00000000, 0b01111110, 0b00000000, 0b00000000, // ###### 53 | 0b00000000, 0b01111110, 0b00000000, 0b00000000, // ###### 54 | 0b00000000, 0b01111110, 0b00000000, 0b00000000, // ###### 55 | 0b00000000, 0b00111100, 0b00000000, 0b00000000, // #### 56 | 0b00000000, 0b00011000, 0b00000000, 0b00000000, // ## 57 | 0b00000000, 0b00011000, 0b00000000, 0b00000000, // ## 58 | 0b00000000, 0b00011000, 0b00000000, 0b00000000, // ## 59 | 0b00000000, 0b00011000, 0b00000000, 0b00000000, // ## 60 | 0b00000000, 0b00011000, 0b00000000, 0b00000000, // ## 61 | 0b00000000, 0b00011000, 0b00000000, 0b00000000, // ## 62 | 0b00000000, 0b00011000, 0b00000000, 0b00000000, // ## 63 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 64 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 65 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 66 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 67 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 68 | 0b11110000, 0b00111100, 0b00001111, 0b10000000, // #### #### ##### 69 | 0b11110000, 0b00111100, 0b00001111, 0b10000000, // #### #### ##### 70 | 0b11110000, 0b00111100, 0b00001111, 0b10000000, // #### #### ##### 71 | 0b11110000, 0b00111100, 0b00001111, 0b10000000, // #### #### ##### 72 | 0b11110000, 0b00111100, 0b00001111, 0b10000000, // #### #### ##### 73 | 0b11110000, 0b00111100, 0b00001111, 0b10000000, // #### #### ##### 74 | 0b11110000, 0b00111100, 0b00001111, 0b10000000, // #### #### ##### 75 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 76 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 77 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 78 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 79 | 0b11100000, 0b00000000, 0b00000111, 0b10000000, // ### #### 80 | 0b11100000, 0b00000000, 0b00000111, 0b10000000, // ### #### 81 | 0b11111111, 0b11111111, 0b11111111, 0b10000000, // ######################### 82 | }; 83 | 84 | static const unsigned char PROGMEM batt [] = { 85 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 86 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 87 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 88 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 89 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 90 | 0b00000001, 0b11110000, 0b00011111, 0b00000000, // ##### ##### 91 | 0b00000010, 0b00001000, 0b00100000, 0b10000000, // # # # # 92 | 0b00000010, 0b00001000, 0b00100000, 0b10000000, // # # # # 93 | 0b00000010, 0b00001000, 0b00100000, 0b10000000, // # # # # 94 | 0b00000010, 0b00001000, 0b00100000, 0b10000000, // # # # # 95 | 0b00000010, 0b00001000, 0b00100000, 0b10000000, // # # # # 96 | 0b00011111, 0b11111111, 0b11111111, 0b11110000, // ######################### 97 | 0b00011110, 0b00000000, 0b00000000, 0b11110000, // #### #### 98 | 0b00011110, 0b00000000, 0b00000000, 0b11110000, // #### #### 99 | 0b00011110, 0b00000000, 0b00000000, 0b11110000, // #### #### 100 | 0b00010000, 0b01000000, 0b00000000, 0b00010000, // # # # 101 | 0b00010000, 0b01000000, 0b00000000, 0b00010000, // # # # 102 | 0b00010000, 0b01000000, 0b00000000, 0b00010000, // # # # 103 | 0b00010011, 0b11111000, 0b00111111, 0b10010000, // # ####### ####### # 104 | 0b00010000, 0b01000000, 0b00000000, 0b00010000, // # # # 105 | 0b00010000, 0b01000000, 0b00000000, 0b00010000, // # # # 106 | 0b00010000, 0b01000000, 0b00000000, 0b00010000, // # # # 107 | 0b00010000, 0b00000000, 0b00000000, 0b00010000, // # # 108 | 0b00011110, 0b00000000, 0b00000000, 0b11110000, // #### #### 109 | 0b00011110, 0b00000000, 0b00000000, 0b11110000, // #### #### 110 | 0b00011110, 0b00000000, 0b00000000, 0b11110000, // #### #### 111 | 0b00011111, 0b11111111, 0b11111111, 0b11110000, // ######################### 112 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 113 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 114 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 115 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 116 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 117 | }; 118 | 119 | static const unsigned char PROGMEM o2 [] = { 120 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 121 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 122 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 123 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 124 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 125 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 126 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 127 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 128 | 0b00000001, 0b11111000, 0b00000000, 0b00000000, // ###### 129 | 0b00000011, 0b11111110, 0b00000000, 0b00000000, // ######### 130 | 0b00000111, 0b00000111, 0b00000000, 0b00000000, // ### ### 131 | 0b00001100, 0b00000011, 0b00000000, 0b00000000, // ## ## 132 | 0b00001100, 0b00000011, 0b00000000, 0b00000000, // ## ## 133 | 0b00011000, 0b00000001, 0b10000000, 0b00000000, // ## ## 134 | 0b00011000, 0b00000001, 0b11111000, 0b00000000, // ## ###### 135 | 0b00011000, 0b00000001, 0b11111100, 0b00000000, // ## ####### 136 | 0b00011000, 0b00000001, 0b10001110, 0b00000000, // ## ## ### 137 | 0b00011000, 0b00000001, 0b10000110, 0b00000000, // ## ## ## 138 | 0b00001100, 0b00000011, 0b00000110, 0b00000000, // ## ## ## 139 | 0b00001100, 0b00000011, 0b00000110, 0b00000000, // ## ## ## 140 | 0b00001110, 0b00001110, 0b00000100, 0b00000000, // ### ### # 141 | 0b00000111, 0b11111100, 0b00001100, 0b00000000, // ######### ## 142 | 0b00000001, 0b11111000, 0b00011000, 0b00000000, // ###### ## 143 | 0b00000000, 0b00000000, 0b00110000, 0b00000000, // ## 144 | 0b00000000, 0b00000000, 0b01100000, 0b00000000, // ## 145 | 0b00000000, 0b00000000, 0b11000000, 0b00000000, // ## 146 | 0b00000000, 0b00000001, 0b10000000, 0b00000000, // ## 147 | 0b00000000, 0b00000011, 0b11111111, 0b00000000, // ########## 148 | 0b00000000, 0b00000011, 0b11111111, 0b00000000, // ########## 149 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 150 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 151 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 152 | }; 153 | 154 | 155 | static const unsigned char PROGMEM oil [] = { 156 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 157 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 158 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 159 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 160 | 0b01000000, 0b00001110, 0b00000000, 0b00000000, // # ### 161 | 0b01100000, 0b00011111, 0b00000000, 0b11100000, // ## ##### ### 162 | 0b01111000, 0b00001110, 0b00000011, 0b10000000, // #### ### ### 163 | 0b01111100, 0b00000100, 0b00001101, 0b00000000, // ##### # ## # 164 | 0b01111111, 0b11111111, 0b11111110, 0b01000000, // ###################### # 165 | 0b00010111, 0b11111111, 0b11111110, 0b00010000, // # ################## # 166 | 0b00001111, 0b11111111, 0b11111100, 0b00010000, // ################## # 167 | 0b00001111, 0b11111111, 0b11111100, 0b00011000, // ################## ## 168 | 0b00000111, 0b11111111, 0b11111000, 0b00111100, // ################ #### 169 | 0b00000111, 0b11111111, 0b11110000, 0b00111100, // ############### #### 170 | 0b00000111, 0b11111111, 0b11110000, 0b00111100, // ############### #### 171 | 0b00000111, 0b11111111, 0b11100000, 0b00011000, // ############## ## 172 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 173 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 174 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 175 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 176 | 0b00000000, 0b11011111, 0b11100000, 0b00000000, // ## ######## 177 | 0b00000000, 0b11011111, 0b11100000, 0b00000000, // ## ######## 178 | 0b00000000, 0b00011100, 0b00000000, 0b00000000, // ### 179 | 0b00000000, 0b00011100, 0b00000000, 0b00000000, // ### 180 | 0b00000000, 0b00011100, 0b00000000, 0b00000000, // ### 181 | 0b00000000, 0b00011111, 0b11000000, 0b00000000, // ####### 182 | 0b00000000, 0b00011111, 0b11000000, 0b00000000, // ####### 183 | 0b00000000, 0b00011100, 0b00000000, 0b00000000, // ### 184 | 0b00000000, 0b00011100, 0b00000000, 0b00000000, // ### 185 | 0b00000000, 0b00011100, 0b00000000, 0b00000000, // ### 186 | 0b00000000, 0b00011100, 0b00000000, 0b00000000, // ### 187 | 0b00000000, 0b00011100, 0b00000000, 0b00000000, // ### 188 | }; 189 | 190 | static const unsigned char PROGMEM coolant [] = { 191 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 192 | 0b00111111, 0b10000000, 0b00000000, 0b00000000, // ####### 193 | 0b00111000, 0b00000011, 0b10000000, 0b00000000, // ### ### 194 | 0b00111000, 0b00000011, 0b10000000, 0b00000000, // ### ### 195 | 0b00111000, 0b00000011, 0b11111110, 0b00000000, // ### ######### 196 | 0b00111111, 0b00000011, 0b11111110, 0b00000000, // ###### ######### 197 | 0b00111000, 0b00000011, 0b11111110, 0b00000000, // ### ######### 198 | 0b00111000, 0b00000011, 0b10000000, 0b00000000, // ### ### 199 | 0b00111000, 0b00000011, 0b10000000, 0b00000000, // ### ### 200 | 0b00111000, 0b00000011, 0b11111110, 0b00000000, // ### ######### 201 | 0b00000000, 0b00000011, 0b11111110, 0b00000000, // ######### 202 | 0b00000000, 0b00000011, 0b11111110, 0b00000000, // ######### 203 | 0b00000000, 0b00000011, 0b10000000, 0b00000000, // ### 204 | 0b00000000, 0b00000011, 0b10000000, 0b00000000, // ### 205 | 0b00000000, 0b00000011, 0b10000000, 0b00000000, // ### 206 | 0b00000000, 0b00000011, 0b10000111, 0b11110000, // ### ####### 207 | 0b00000111, 0b11110011, 0b10011100, 0b00011100, // ####### ### ### ### 208 | 0b00011100, 0b00011111, 0b11110000, 0b00000110, // ### ######### ## 209 | 0b01110000, 0b00000111, 0b11100000, 0b00000011, // ### ###### ## 210 | 0b11000000, 0b00000011, 0b10000000, 0b00000001, // ## ### # 211 | 0b10000000, 0b00000111, 0b11000000, 0b00000000, // # ##### 212 | 0b00000000, 0b00000111, 0b11000000, 0b00000000, // ##### 213 | 0b00000000, 0b00000111, 0b11000000, 0b00000000, // ##### 214 | 0b00000000, 0b00000111, 0b11000000, 0b00000000, // ##### 215 | 0b00000111, 0b11110011, 0b10000111, 0b11110000, // ####### ### ####### 216 | 0b00011100, 0b00011100, 0b00011100, 0b00011100, // ### ### ### ### 217 | 0b01110000, 0b00000110, 0b01110000, 0b00000110, // ### ## ### ## 218 | 0b11000000, 0b00000011, 0b11000000, 0b00000011, // ## #### ## 219 | 0b10000000, 0b00000001, 0b10000000, 0b00000001, // # ## # 220 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 221 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 222 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 223 | }; 224 | 225 | static const unsigned char PROGMEM intake [] = { 226 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 227 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 228 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 229 | 0b00000000, 0b00000000, 0b00001100, 0b00000000, // ## 230 | 0b00000000, 0b00000000, 0b01111100, 0b00000000, // ##### 231 | 0b00000000, 0b00000011, 0b11110100, 0b00000000, // ###### # 232 | 0b00000000, 0b00111111, 0b10000100, 0b00000000, // ####### # 233 | 0b00000001, 0b11111000, 0b10000100, 0b00000000, // ###### # # 234 | 0b00001111, 0b01001000, 0b10111111, 0b11111111, // #### # # # ############## 235 | 0b00001100, 0b01111111, 0b11000111, 0b11111111, // ## ######### ########### 236 | 0b00001111, 0b11001000, 0b10000111, 0b11111111, // ###### # # ########### 237 | 0b00001100, 0b01001011, 0b11111111, 0b10000011, // ## # # ########### ## 238 | 0b00001111, 0b11111100, 0b10000111, 0b10011111, // ########## # #### ##### 239 | 0b00001100, 0b01001000, 0b10000111, 0b10011111, // ## # # # #### ##### 240 | 0b00001111, 0b11111111, 0b11111111, 0b10011111, // ##################### ##### 241 | 0b00001100, 0b01001000, 0b10000111, 0b10000011, // ## # # # #### ## 242 | 0b00001111, 0b11111000, 0b10000111, 0b10011111, // ######### # #### ##### 243 | 0b00001100, 0b01001111, 0b11111111, 0b10011111, // ## # ############# ##### 244 | 0b00001111, 0b11001000, 0b10000111, 0b10011111, // ###### # # #### ##### 245 | 0b00001100, 0b01111111, 0b11000111, 0b10011111, // ## ######### #### ##### 246 | 0b00001111, 0b01001000, 0b10111111, 0b11111111, // #### # # # ############## 247 | 0b00001100, 0b11111000, 0b10000111, 0b11111111, // ## ##### # ########### 248 | 0b00001110, 0b01001111, 0b10000111, 0b11111111, // ### # ##### ########### 249 | 0b00001111, 0b11001000, 0b11110111, 0b11111111, // ###### # #### ########### 250 | 0b00000011, 0b11111100, 0b10001111, 0b11111111, // ######## # ############ 251 | 0b00000000, 0b01111111, 0b10000100, 0b00000000, // ######## # 252 | 0b00000000, 0b00001111, 0b11110100, 0b00000000, // ######## # 253 | 0b00000000, 0b00000011, 0b11111100, 0b00000000, // ######## 254 | 0b00000000, 0b00000000, 0b01111100, 0b00000000, // ##### 255 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 256 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 257 | 0b00000000, 0b00000000, 0b00000000, 0b00000000, // 258 | }; 259 | 260 | void setup() { 261 | pinMode(A0, INPUT_PULLUP); 262 | Status=Elm.begin(); 263 | //3 buttons connected as such: http://tronixstuff.com/2011/01/11/tutorial-using-analog-input-for-multiple-buttons/ 264 | //use 15 Kohm resistors 265 | //no buttons is 1010 266 | //button nearest gnd is 300 267 | //middle button is 454 268 | //last button is 555 269 | //Serial.begin(9600); 270 | display.begin(SSD1306_SWITCHCAPVCC); 271 | display.display(); 272 | display.clearDisplay(); 273 | display.display(); 274 | 275 | //show flash screen 276 | display.drawBitmap(0, 0, robothead, 32, 32, 1); 277 | display.display(); 278 | 279 | display.setCursor(36,0); 280 | display.setTextSize(2); 281 | display.setTextColor(WHITE); 282 | display.println("Not A"); 283 | display.setCursor(36,15); 284 | display.println("Clock"); 285 | display.display(); 286 | 287 | //temporary stuff to test button setup 288 | /* 289 | display.clearDisplay(); 290 | display.display(); 291 | int tempVal; 292 | while(true){ 293 | tempVal = analogRead(0); 294 | display.setCursor(36,0); 295 | display.setTextSize(2); 296 | display.setTextColor(WHITE); 297 | display.println(tempVal); 298 | display.display(); 299 | delay(100); 300 | display.setCursor(36,0); 301 | display.setTextSize(2); 302 | display.setTextColor(BLACK); 303 | display.println(tempVal); 304 | display.display(); 305 | //no button 1013-1017 306 | //a button 15 (no resistor...just wire resistance) 307 | //b button 302 308 | //c button 457 309 | //d button 556 310 | } */ 311 | 312 | //end temp stuff for testing buttons 313 | 314 | //set up OBD II stuffs 315 | display.fillRect(8, 21, 2, 2, WHITE); 316 | display.fillRect(18, 21, 2, 2, WHITE); 317 | display.display(); 318 | getOBDIIvalue("obdbrzoiltempf"); //do the first reading here because it takes a sec or two display.fillRect(8, 21, 2, 2, BLACK); 319 | display.fillRect(8, 21, 2, 2, BLACK); 320 | display.fillRect(18, 21, 2, 2, BLACK); 321 | display.display(); 322 | display.fillRect(4, 21, 2, 2, WHITE); 323 | display.fillRect(14, 21, 2, 2, WHITE); 324 | display.display(); 325 | delay(1000); 326 | display.fillRect(4, 21, 2, 2, BLACK); 327 | display.fillRect(14, 21, 2, 2, BLACK); 328 | display.display(); 329 | display.fillRect(8, 22, 2, 2, WHITE); 330 | display.fillRect(18, 22, 2, 2, WHITE); 331 | display.display(); 332 | delay(1000); 333 | display.fillRect(8, 22, 2, 2, BLACK); 334 | display.fillRect(18, 22, 2, 2, BLACK); 335 | display.display(); 336 | display.fillRect(4, 21, 2, 2, WHITE); 337 | display.fillRect(14, 21, 2, 2, WHITE); 338 | display.display(); 339 | delay(500); 340 | 341 | //put first mode icon and unit here 342 | display.clearDisplay(); 343 | display.drawBitmap(0, 0, oil, 32, 32, 1); 344 | display.display(); 345 | } 346 | 347 | void loop() { 348 | buttonV = analogRead(A0); 349 | while ( (analogRead(A0) <= 430) || (analogRead(A0) >= 490) ){ //not mode button (not between 430 and 490) 350 | buttonV = analogRead(A0); 351 | if ( (buttonV >= 500) && (buttonV <= 600) ){ //hold down the peaks button to show the peaks of this mode (555ish) 352 | while ( (buttonV >= 500) && (buttonV <= 600) ){ //debounce 353 | //display peaks for this "mode" here 354 | display.fillRect(48,0,80,32,BLACK); //black area between icon and unit 355 | display.setTextSize(3); 356 | display.setTextColor(WHITE); 357 | display.setCursor(48,10); 358 | display.println(peaks[mode]); 359 | display.display(); 360 | buttonV = analogRead(A0); 361 | delay(50); 362 | } 363 | display.fillRect(48,0,80,32,BLACK); //black area between icon and unit 364 | getVal(); 365 | updateVal(); //just incase it doesn't draw below because the values stay the same 366 | display.display(); 367 | buttonV = analogRead(A0); 368 | } 369 | 370 | //hold reset button here to reset peak of specific mode 371 | if ( (buttonV <= 325) && (buttonV >= 285) ){ //hold down the reset button to reseet the peaks of this mode (300ish) 372 | while ( (buttonV <= 325) && (buttonV >= 285) ){ //debounce 373 | display.fillRect(48,0,80,32,BLACK); //black area between icon and unit 374 | display.setTextSize(3); 375 | display.setCursor(48,10); 376 | display.setTextColor(WHITE); 377 | display.println("RST"); 378 | display.display(); 379 | buttonV = analogRead(A0); 380 | delay(50); 381 | } 382 | //reset peak specific to this mode 383 | display.fillRect(48,0,80,32,BLACK); //black area between icon and unit 384 | getVal(); 385 | updateVal(); //just incase it doesn't draw below because the values stay the same 386 | display.display(); 387 | peaks[mode] = 0; 388 | buttonV = analogRead(A0); 389 | } 390 | 391 | //display the value here...no conditionals...just print the value 392 | //only print if it changes to avoid flickering 393 | getVal(); 394 | if ( abs(curValue[mode]-previousReading[mode]) > 0 ){ 395 | updateVal(); 396 | } 397 | 398 | //TODO: fix this...not working 399 | //check for warning values here (for this mode only) 400 | //if ( ( (curValue[mode] > warnLevels[mode]) && (warnSign[mode] == 1) ) || ( (curValue[mode] < warnLevels[mode]) && (warnSign[mode] == 0) ) ){ 401 | if (curValue[mode] >= warnLevels[mode]){ 402 | //do a warning thing here 403 | display.println("WARN"); 404 | display.display(); 405 | warn(); 406 | } 407 | } 408 | while ( (analogRead(A0) >= 430) && (analogRead(A0) <= 490) ){ //mode button 409 | } 410 | if (mode == modes){ 411 | mode = 0; 412 | } 413 | else { 414 | mode++; 415 | } 416 | //upon switching modes blank screen and display that mode's icon 417 | //also print the unit of measurement if used 418 | display.clearDisplay(); 419 | display.setTextSize(3); 420 | display.setTextColor(WHITE); 421 | if (mode == 0){//oil temp 422 | display.drawBitmap(0, 0, oil, 32, 32, 1); 423 | display.display(); 424 | } 425 | if (mode == 1){//AFR 426 | display.drawBitmap(0, 0, o2, 32, 32, 1); 427 | display.display(); 428 | } 429 | if (mode == 2){//Volts 430 | display.drawBitmap(0, 0, batt, 32, 32, 1); 431 | display.display(); 432 | } 433 | if (mode == 3){//Coolant 434 | display.drawBitmap(0, 0, coolant, 32, 32, 1); 435 | display.display(); 436 | } 437 | if (mode == 4){ 438 | display.drawBitmap(0, 0, intake, 32, 32, 1); 439 | display.display(); 440 | } 441 | getVal(); 442 | updateVal(); //if you don't update here and the value hasn't changed you get blank value 443 | } 444 | 445 | void warn(){ 446 | //a border around the screen flashes as a warning 447 | for (int a=1;a>=3;a++){ 448 | display.drawRect(0,0,127,31,WHITE); 449 | delay(100); 450 | display.drawRect(0,0,127,31,BLACK); 451 | } 452 | return; 453 | } 454 | 455 | void getVal(){ 456 | if (mode == 0){ 457 | curValue[mode] = getOBDIIvalue("obdbrzoiltempf");//modeList[mode]); 458 | } 459 | else if (mode == 1){ 460 | curValue[mode] = getOBDIIvalue("obdafr"); 461 | } 462 | else if (mode == 2){ 463 | curValue[mode] = getOBDIIvalue("obdvolts"); 464 | } 465 | else if (mode == 3){ 466 | curValue[mode] = getOBDIIvalue("obdcoolantf"); 467 | } 468 | else if (mode == 4){ 469 | curValue[mode] = getOBDIIvalue("obdiat"); 470 | } 471 | if (curValue[mode] > peaks[mode]){ 472 | peaks[mode] = curValue[mode]; 473 | } 474 | } 475 | 476 | void updateVal(){ 477 | display.setTextSize(3); 478 | //draw old value 479 | display.setTextColor(BLACK); 480 | display.setCursor(50,12); 481 | if ( (mode == 1) || (mode == 2) ){ //AFR should show the decimal (others could be added to this list) 482 | display.println(previousReading[mode]); 483 | } 484 | else { //everything else should print an int value 485 | display.println((int)previousReading[mode]); 486 | } 487 | display.display(); 488 | //draw new value 489 | display.setTextColor(WHITE); 490 | display.setCursor(50,12); 491 | if ( (mode == 1) || (mode == 2) ){ //AFR should show the decimal (others could be added to this list) 492 | display.println(curValue[mode]); 493 | } 494 | else { //everything else should print an int value 495 | display.println((int)curValue[mode]); 496 | } 497 | display.display(); 498 | previousReading[mode] = curValue[mode]; 499 | //delay(100); 500 | return; 501 | } 502 | 503 | float getOBDIIvalue(String whichSensor){ 504 | //Serial.flush(); 505 | float value = 0; 506 | char data[130]; 507 | if (whichSensor.indexOf("obdcoolantf") >=0){ 508 | Elm.coolantTemperature(value); 509 | value=value*1.8+32; 510 | } 511 | if (whichSensor.indexOf("obdafr") >= 0){ 512 | Status = Elm.runCommand("0134",data,20); 513 | value = ((float)(strtol(&data[6],0,16)*256)+strtol(&data[9],0,16))/32768*14.7; //(A*256+B)/32768*14.7 514 | } 515 | if (whichSensor.indexOf("obdiat") >= 0){ //USED 516 | Elm.intakeAirTemperature(value); 517 | value=value*1.8+32; 518 | } 519 | 520 | if (whichSensor.indexOf("obdvolts") >= 0){ //USED 521 | Elm.getVoltage(value); 522 | } 523 | 524 | if (whichSensor.indexOf("obdbrzoiltempf") >= 0){ //works and USED 525 | Status = Elm.runCommand("2101",data,130); 526 | value = ((float)strtol(&data[109],0,16) - 40) * 1.8 + 32; 527 | } 528 | 529 | //delay(100); 530 | return value; 531 | } 532 | 533 | --------------------------------------------------------------------------------