test-display-UEDan.ino 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. #include <SoftwareSerial.h>
  2. #include <Wire.h>
  3. #include <LiquidCrystal_I2C.h>
  4. //TEST UNITS
  5. //4th byte is # of packets you idiot.
  6. //double check checksum byte you jackass.
  7. byte ReqData[31] = {128, 16, 240, 26, 168, 0, 0, 0, 16, 0, 0, 19, 0, 0, 70, 0, 1, 33, 0, 0, 100, 2, 9, 199, 2, 1, 104, 0, 0, 20, 130}; // add throttle
  8. byte ReqDataSize = 31;
  9. //END TEST UNITS
  10. //variables for MPG:
  11. int mpgECUbytes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  12. byte mpgReqData[31] = {128, 16, 240, 26, 168, 0, 0, 0, 16, 0, 0, 19, 0, 0, 70, 0, 1, 33, 0, 0, 100, 2, 9, 199, 2, 1, 104, 0, 0, 20, 130}; // add throttle
  13. byte mpgReqDataSize = 31;
  14. //variables for IAM
  15. int iamECUbytes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  16. byte iamReqData[31] = {128, 16, 240, 26, 168, 0, 0, 0, 16, 0, 0, 19, 0, 0, 70, 0, 1, 33, 0, 0, 100, 2, 9, 199, 2, 1, 104, 0, 0, 20, 130}; // add throttle
  17. byte iamReqDataSize = 31;
  18. //variables for sear selector
  19. int case4ECUbytes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  20. byte case4ReqData[31] = {128, 16, 240, 8, 168, 0, 0, 0, 70, 2, 12, 96, 228}; // AFR && FBKC
  21. byte case4ReqDataSize = 13;
  22. //4th byte is # of packets you idiot && double check checksum byte you jackass.
  23. byte swtVal = 0;
  24. byte selMode = 1;
  25. byte readBytes;
  26. int ECUbytes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  27. unsigned long prvTime;
  28. unsigned long curTime;
  29. int milli;
  30. int milesPerHour;
  31. double airFuelR;
  32. double fbkc;
  33. double airFlowG;
  34. double milesPerGallon;
  35. //Declare LCD as lcd and I2C address
  36. LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
  37. //Rx/Tx pins used for SSM
  38. SoftwareSerial sendSerial = SoftwareSerial(10, 11); //Rx, Tx
  39. void setup() {
  40. //TEST SETUP
  41. pinMode(13, OUTPUT);
  42. pinMode(12, INPUT);
  43. //END TEST SETUP
  44. //Setup Start
  45. Serial.begin(115200); //for diagnostics
  46. Serial.println("Serial Started");
  47. while (!Serial) {
  48. // wait
  49. }
  50. lcd.begin(16, 2); //Start LCD
  51. lcd.backlight(); //Set LCD Backlight ON
  52. lcd.setCursor(0, 0); //start at col 1 row 1
  53. lcd.print("LCD start");
  54. delay(500);
  55. lcd.clear();
  56. Serial.println("starting SSM Serial");
  57. sendSerial.begin(4800); //SSM uses 4800 8N1 baud rate
  58. while (!sendSerial) {
  59. //wait
  60. delay(50);
  61. }
  62. //Serial.println("Ready!");
  63. delay(50);
  64. lcd.setCursor(0, 0);
  65. lcd.print("Mode 1");
  66. lcd.setCursor(0, 1);
  67. lcd.print("MPG: ");
  68. readBytes = ((mpgReqDataSize - 7) / 3);
  69. writeSSM(mpgReqData, mpgReqDataSize, sendSerial); //send intial SSM poll
  70. delay (2);
  71. }
  72. void loop() {
  73. curTime = millis();
  74. milli = curTime - prvTime;
  75. if (milli > 250) {
  76. sendSerial.flush();
  77. //delay(5);
  78. // Serial.print("SentTime:");
  79. // Serial.println(milli);
  80. ssmWriteSel();
  81. //writeSSM(ReqData, ReqDataSize, sendSerial);
  82. //Serial.print("Timer Popped | ");
  83. //Serial.println(sendSerial.available());
  84. prvTime = millis();
  85. }
  86. if (sendSerial.available()) {
  87. readECU(ECUbytes, readBytes, false);
  88. prvTime = curTime;
  89. lcdPrintSel();
  90. /*
  91. milesPerHour = (ECUbytes[0] * 0.621371192); //P9 0x000010
  92. airFuelR = ((ECUbytes[2] / 128.00) * 14.7); //P58 0x000046
  93. airFlowG = (((ECUbytes[1] * 256.00) + ECUbytes[7]) / 100.00); //P12 0x000013 and 0x000014
  94. milesPerGallon = (milesPerHour / 3600.00) / (airFlowG / (airFuelR) / 2800.00);
  95. Serial.print("MPH:");
  96. Serial.print(milesPerHour, 0);
  97. Serial.print(" | ");
  98. Serial.print("Mass airflow/s:");
  99. Serial.print(airFlowG);
  100. Serial.print(" | ");
  101. Serial.print("AFR: ");
  102. Serial.print(airFuelR);
  103. Serial.print(" | ");
  104. Serial.print("MPG:");
  105. Serial.print(milesPerGallon);
  106. Serial.print(" | ");
  107. Serial.print("Cruise:"); //0x000121
  108. Serial.print(ECUbytes[3], BIN);
  109. Serial.print(" | ");
  110. Serial.print("Defogger:");
  111. Serial.print(ECUbytes[4], BIN); //0x000064
  112. Serial.print(" | ");
  113. Serial.print("Gear:"); //0x0209C7
  114. Serial.print(ECUbytes[5]);
  115. Serial.print(" | ");
  116. Serial.print("IAM:"); //0x020168
  117. Serial.println(ECUbytes[6]);
  118. */
  119. }
  120. //Mode switch read
  121. if (digitalRead(12) == 1) {
  122. if (selMode == 4) {
  123. selMode = 0;
  124. }
  125. selMode++;
  126. //Serial.println("Mode plus");
  127. //printMode(selMode);
  128. delay(500);
  129. lcd.clear();
  130. switch (selMode)
  131. {
  132. case 1: //Fuel Economy
  133. lcd.setCursor(0, 0);
  134. lcd.print("Mode 1");
  135. lcd.setCursor(0, 1);
  136. lcd.print("MPG: ");
  137. digitalWrite(13, HIGH);
  138. readBytes = ((mpgReqDataSize - 7) / 3);
  139. break;
  140. case 2: //IAM
  141. lcd.setCursor(0, 0);
  142. lcd.print("Mode 2");
  143. lcd.setCursor(0, 1);
  144. lcd.print("IAM: ");
  145. digitalWrite(13, LOW);
  146. readBytes = ((iamReqDataSize - 7) / 3);
  147. break;
  148. case 3: //Miles per hour
  149. lcd.setCursor(0, 0);
  150. lcd.print("Mode 3");
  151. digitalWrite(13, HIGH);
  152. lcd.setCursor(0, 1);
  153. lcd.print("MPH: ");
  154. readBytes = ((mpgReqDataSize - 7) / 3);
  155. break;
  156. case 4: //Air:fuel Ratio
  157. lcd.setCursor(0, 0);
  158. lcd.print("Mode 4 FBKC:");
  159. lcd.setCursor(0, 1);
  160. lcd.print("AFR: ");
  161. digitalWrite(13, LOW);
  162. readBytes = ((case4ReqDataSize - 7) / 3);
  163. break;
  164. }
  165. }
  166. }
  167. void ssmWriteSel() {
  168. switch (selMode)
  169. {
  170. case 1: //Fuel Economy
  171. writeSSM(mpgReqData, mpgReqDataSize, sendSerial);
  172. break;
  173. case 2: //IAM
  174. writeSSM(iamReqData, iamReqDataSize, sendSerial);
  175. break;
  176. case 3: //Miles per hour
  177. writeSSM(mpgReqData, mpgReqDataSize, sendSerial);
  178. break;
  179. case 4: //Air:fuel Ratio
  180. writeSSM(case4ReqData, case4ReqDataSize, sendSerial);
  181. break;
  182. }
  183. }
  184. void lcdPrintSel() {
  185. switch (selMode)
  186. {
  187. case 1: //Fuel Economy
  188. milesPerHour = (ECUbytes[0] * 0.621371192); //P9 0x000010
  189. airFuelR = ((ECUbytes[2] / 128.00) * 14.7); //P58 0x000046
  190. airFlowG = (((ECUbytes[1] * 256.00) + ECUbytes[7]) / 100.00); //P12 0x000013 and 0x000014
  191. milesPerGallon = (milesPerHour / 3600.00) / (airFlowG / (airFuelR) / 2800.00);
  192. lcd.setCursor(5, 1);
  193. lcd.print(milesPerGallon, 2);
  194. if (milesPerGallon < 20) {
  195. lcd.setCursor(14, 1);
  196. lcd.print("=(");
  197. }
  198. else if (milesPerGallon > 20) {
  199. lcd.setCursor(14, 1);
  200. lcd.print("=)");
  201. }
  202. break;
  203. case 2: //IAM
  204. lcd.setCursor(5, 1);
  205. lcd.print(ECUbytes[6]);
  206. digitalWrite(13, LOW);
  207. break;
  208. case 3: //Miles per hour
  209. milesPerHour = (ECUbytes[0] * 0.621371192); //P9 0x000010
  210. lcd.setCursor(5, 1);
  211. lcd.print(milesPerHour);
  212. digitalWrite(13, HIGH);
  213. break;
  214. case 4: //Air:fuel Ratio
  215. airFuelR = ((ECUbytes[0] / 128.00) * 14.7); //P58 0x000046
  216. fbkc = ((ECUbytes[0] * 0.3515625)-45);
  217. lcd.setCursor(5, 1);
  218. lcd.print(airFuelR);
  219. lcd.setCursor(11, 1);
  220. lcd.print(fbkc, 2);
  221. digitalWrite(13, LOW);
  222. break;
  223. }
  224. }
  225. /* returns the 8 least significant bits of an input byte*/
  226. byte CheckSum(byte sum) {
  227. byte counter = 0;
  228. byte power = 1;
  229. for (byte n = 0; n < 8; n++) {
  230. counter += bitRead(sum, n) * power;
  231. power = power * 2;
  232. }
  233. return counter;
  234. }
  235. /*writes data over the software serial port
  236. the &digiSerial passes a reference to the external
  237. object so that we can control it outside of the function*/
  238. void writeSSM(byte data[], byte length, SoftwareSerial &digiSerial) {
  239. //Serial.println(F("Sending packet... "));
  240. for (byte x = 0; x < length; x++) {
  241. digiSerial.write(data[x]);
  242. }
  243. //Serial.println(F("done sending."));
  244. }
  245. //this will change the values in dataArray, populating them with values respective of the poll array address calls
  246. boolean readECU(int* dataArray, byte dataArrayLength, boolean nonZeroes)
  247. {
  248. byte data = 0;
  249. boolean isPacket = false;
  250. byte sumBytes = 0;
  251. byte checkSumByte = 0;
  252. byte dataSize = 0;
  253. byte bytePlace = 0;
  254. byte zeroesLoopSpot = 0;
  255. byte loopLength = 20;
  256. for (byte j = 0; j < loopLength; j++)
  257. {
  258. data = sendSerial.read();
  259. delay(2);
  260. if (data == 128 && dataSize == 0) { //0x80 or 128 marks the beginning of a packet
  261. isPacket = true;
  262. j = 0;
  263. //Serial.println("Begin Packet");
  264. }
  265. //terminate function and return false if no response is detected
  266. if (j == (loopLength - 1) && isPacket != true)
  267. {
  268. return false;
  269. }
  270. if (isPacket == true && data != -1) {
  271. Serial.print(data); // for debugging: shows in-packet data
  272. Serial.print(" ");
  273. if (bytePlace == 3) { // how much data is coming
  274. dataSize = data;
  275. loopLength = data + 6;
  276. }
  277. if (bytePlace > 4 && bytePlace - 5 < dataArrayLength && nonZeroes == false)
  278. {
  279. dataArray[bytePlace - 5] = data;
  280. }
  281. else if (bytePlace > 4 && zeroesLoopSpot < dataArrayLength / 2 && nonZeroes == true && data != 0 && bytePlace < dataSize + 4)
  282. {
  283. dataArray[zeroesLoopSpot] = data;
  284. dataArray[zeroesLoopSpot + (dataArrayLength / 2)] = bytePlace;
  285. zeroesLoopSpot++;
  286. }
  287. bytePlace += 1; //increment bytePlace
  288. //once the data is all recieved, checksum and re-set counters
  289. // Serial.print("byte place: ");
  290. // Serial.println(bytePlace);
  291. if (bytePlace == dataSize + 5) {
  292. checkSumByte = CheckSum(sumBytes); //the 8 least significant bits of sumBytes
  293. if (data != checkSumByte) {
  294. Serial.println(F("checksum error"));
  295. return false;
  296. }
  297. // Serial.println("Checksum is good");
  298. isPacket = false;
  299. sumBytes = 0;
  300. bytePlace = 0;
  301. checkSumByte = 0;
  302. dataSize = 0;
  303. return true;
  304. }
  305. else {
  306. sumBytes += data; // this is to compare with the checksum byte
  307. //Serial.print(F("sum: "));
  308. //Serial.println(sumBytes);
  309. }
  310. }
  311. }
  312. Serial.println("");
  313. }