-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathobduino32KMega.pde
3918 lines (3496 loc) · 103 KB
/
obduino32KMega.pde
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* OBDuino32K (Requres Atmega328 for your Arduino)
Copyright (C) 2008-2009
Main coding/ISO/ELM: Fr�d�ric (aka Magister on ecomodder.com)
LCD part: Dave (aka dcb on ecomodder.com), optimized by Fr�d�ric
ISO Communication Protocol: Russ, Antony, Mike
Features: Mike, Antony
Bugs & Fixes: Antony, Fr�d�ric, Mike
Latest Changes(June 9th, 2009):
ISO 9141 re-init, ECU polling, Car alarm and other tweaks by Antony
June 24, 1009:
Added three parameters to the mix, removed unrequired RPM call,
added off and full to backlight levels, added waste PIDs: Antony
June 25, 2009:
Use the metric parameter for fuel price and tank size: Antony
June 27, 2009:
Minor corrections and tweaks: Antony
July 23, 2009:
New menuing system for parameters, and got rid of display flicker: Antony
Sept 01, 2009:
Better handling of 14230 protocol. Tweak in clear button routine: Antony
To-Do:
Bugs:
Fix code to retrieve stored trouble codes.
Features Requested:
Aero-Drag calculations?
SD Card logging
Add another Fake PID to track max values ( Speed, RPM, Tank KM's, etc...)
Other:
Add a variable for the age of the last reading of a PID, for the chance it
could be reused. (Great for RPM, SPEED, since they are used multiple
times in one loop of the program)
Add a "dirty" flag to tank data when the obduino detects that it has been
disconnected from the car to indicate that the data may no longer be complete
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
// Compilation modifiers:
// The following will cause the compiler to add or remove features from the
// OBDuino build this keeps the build size down, will not allow 'on the fly'
// changes. Some features are dependent on other features.
// Comment for normal build
// Uncomment for a debug build
//#define DEBUG
// Comment to build for a Duemilanove or compatible (ATmega328P)
// Uncomment to build for a Mega (ATmega1280)
#define MEGA
// Comment for normal build
// Uncomment to enable GPS. NOTE: requires that MEGA be set as well
#define ENABLE_GPS
// Comment for normal build
// Uncomment to enable VDIP1 flash storage module. NOTE: requires that MEGA be set as well
#define ENABLE_VDIP
// Comment for normal build
// Uncomment to enable power-fail detection (currently only useful if VDIP is enabled)
#define ENABLE_PWRFAILDETECT
// Comment to use MC33290 ISO K line chip
// Uncomment to use ELM327
#define ELM
// Comment out to use only the ISO 9141 K line
// Uncomment to also use the ISO 9141 L line
// This option requires additional wiring to function!
// Most newer cars do NOT require this
//#define useL_Line
// Uncomment only one of the below init sequences if using ISO
//#define ISO_9141
//#define ISO_14230_fast
//#define ISO_14230_slow
// Comment out to just try the PIDs without need to find ECU
// Uncomment to use ECU polling to see if car is On or Off
//#define useECUState
// Comment out if ISO 9141 does not need to reinit
// Uncomment define below to force reinitialization of ISO 9141 after no ECU communication
// this requires ECU polling
//#define do_ISO_Reinit
// Comment out to use the PID screen when the car is off (This will interfere with ISO reinit process)
// Uncomment to use the Car Alarm Screen when the car is off
//#define carAlarmScreen
#undef int
#include <stdio.h>
#include <limits.h>
#include <avr/eeprom.h>
#include <avr/pgmspace.h>
// Define serial ports so they can be easily switched for the Mega vs Duemilanove, etc
#ifdef MEGA
#define HOST Serial
#define HOST_BAUD_RATE 38400
#define OBD2 Serial1
#define OBD2_BAUD_RATE 38400
#define GPS Serial2
#define GPS_BAUD_RATE 57600
#define VDIP Serial3
#define VDIP_BAUD_RATE 9600
byte logActive = 0; // Flag used in logging state machine
#else
#define OBD2 Serial
#define OBD2_BAUD_RATE 38400
#endif
// LCD pin assignments
#ifdef MEGA // LCD pins for an Arduino Mega
#define DIPin 54 // register select RS
#define DB4Pin 56
#define DB5Pin 57
#define DB6Pin 58
#define DB7Pin 59
#define ContrastPin 6
#define EnablePin 55
#define BrightnessPin 5
#else // LCD Pins same as mpguino for a Duemilanove or equivalent
#define DIPin 4 // register select RS
#define DB4Pin 7
#define DB5Pin 8
#define DB6Pin 12
#define DB7Pin 13
#define ContrastPin 6
#define EnablePin 5
#define BrightnessPin 9
#endif
// LCD prototypes
void lcd_gotoXY(byte x, byte y);
void lcd_print(char *string);
void lcd_print_P(char *string); // To work with string in flash and PSTR()
void lcd_cls_print_P(char *string); // Clear screen and display string
void lcd_cls();
void lcd_init();
void lcd_tickleEnable();
void lcd_commandWriteSet();
void lcd_commandWrite(byte value);
void lcd_dataWrite(byte value);
void lcd_pushNibble(byte value);
// Memory prototypes
void params_load(void);
void params_save(void);
// Others prototypes
byte menu_selection(char ** menu, byte arraySize);
byte menu_select_yes_no(byte p);
void long_to_dec_str(long value, char *decs, byte prec);
int memoryTest(void);
void test_buttons(void);
void get_cost(char *retbuf, byte ctrip);
#ifdef ENABLE_GPS
void printFloat( double f, int digits=2 );
#endif
#define KEY_WAIT 1000 // Wait for potential other key press
#define ACCU_WAIT 500 // Only accumulate data so often.
#define BUTTON_DELAY 125
// use analog pins as digital pins for buttons
#ifdef MEGA // Button pins for Arduino Mega
#define lbuttonPin 62 // Left Button, on analog 8
#define mbuttonPin 63 // Middle Button, on analog 9
#define rbuttonPin 64 // Right Button, on analog 10
//#define buttonGnd 65 // Pin to supply 0V
#define lbuttonBit 1 // pin62 is a bitmask 1 on port K
#define mbuttonBit 2 // pin63 is a bitmask 2 on port K
#define rbuttonBit 4 // pin64 is a bitmask 4 on port K
#else // Button pins for Duemilanove or equivalent
#define lbuttonPin 17 // Left Button, on analog 3
#define mbuttonPin 18 // Middle Button, on analog 4
#define rbuttonPin 19 // Right Button, on analog 5
#define lbuttonBit 8 // pin17 is a bitmask 8 on port C
#define mbuttonBit 16 // pin18 is a bitmask 16 on port C
#define rbuttonBit 32 // pin19 is a bitmask 32 on port C
#endif
#define buttonsUp 0 // start with the buttons in the 'not pressed' state
byte buttonState = buttonsUp;
// Easy to read macros
#define LEFT_BUTTON_PRESSED (buttonState&lbuttonBit)
#define MIDDLE_BUTTON_PRESSED (buttonState&mbuttonBit)
#define RIGHT_BUTTON_PRESSED (buttonState&rbuttonBit)
#define brightnessLength 7 //array size
const byte brightness[brightnessLength]={
0xFF,
0xFF/brightnessLength*(brightnessLength-1),
0xFF/brightnessLength*(brightnessLength-2),
0xFF/brightnessLength*(brightnessLength-3),
0xFF/brightnessLength*(brightnessLength-4),
0xFF/brightnessLength*(brightnessLength-5),
0x00}; // right button cycles through these brightness settings (off to on full)
byte brightnessIdx=2;
/* LCD Display parameters */
/* Adjust LCD_width or LCD_rows if LCD is different than 16 characters by 2 rows*/
// How many rows of characters for the LCD (must be at least two)
#define LCD_ROWS 4
// How many characters across for the LCD (must be at least sixteen)
const byte LCD_width = 20;
// Calculate the middle point of the LCD display width
const byte LCD_split = LCD_width / 2;
//Calculate how many PIDs fit on a data screen (two per line)
const byte LCD_PID_count = LCD_ROWS * 2;
// Use the TinyGPS library to parse GPS data, but only if GPS is enabled
#ifdef ENABLE_GPS
#include <TinyGPS.h>
TinyGPS gps;
float gpsFLat, gpsFLon;
unsigned long gpsAge, gpsDate, gpsTime, gpsChars;
int gpsYear;
byte gpsMonth, gpsDay, gpsHour, gpsMinute, gpsSecond, gpsHundredths;
// Include the floatToString helper
#include "floatToString.h"
#endif
/* PID stuff */
unsigned long pid01to20_support; // this one always initialized at setup()
unsigned long pid21to40_support=0;
unsigned long pid41to60_support=0;
#define PID_SUPPORT00 0x00
#define MIL_CODE 0x01
#define FREEZE_DTC 0x02
#define FUEL_STATUS 0x03
#define LOAD_VALUE 0x04
#define COOLANT_TEMP 0x05
#define STFT_BANK1 0x06
#define LTFT_BANK1 0x07
#define STFT_BANK2 0x08
#define LTFT_BANK2 0x09
#define FUEL_PRESSURE 0x0A
#define MAN_PRESSURE 0x0B
#define ENGINE_RPM 0x0C
#define VEHICLE_SPEED 0x0D
#define TIMING_ADV 0x0E
#define INT_AIR_TEMP 0x0F
#define MAF_AIR_FLOW 0x10
#define THROTTLE_POS 0x11
#define SEC_AIR_STAT 0x12
#define OXY_SENSORS1 0x13
#define B1S1_O2_V 0x14
#define B1S2_O2_V 0x15
#define B1S3_O2_V 0x16
#define B1S4_O2_V 0x17
#define B2S1_O2_V 0x18
#define B2S2_O2_V 0x19
#define B2S3_O2_V 0x1A
#define B2S4_O2_V 0x1B
#define OBD_STD 0x1C
#define OXY_SENSORS2 0x1D
#define AUX_INPUT 0x1E
#define RUNTIME_START 0x1F
#define PID_SUPPORT20 0x20
#define DIST_MIL_ON 0x21
#define FUEL_RAIL_P 0x22
#define FUEL_RAIL_DIESEL 0x23
#define O2S1_WR_V 0x24
#define O2S2_WR_V 0x25
#define O2S3_WR_V 0x26
#define O2S4_WR_V 0x27
#define O2S5_WR_V 0x28
#define O2S6_WR_V 0x29
#define O2S7_WR_V 0x2A
#define O2S8_WR_V 0x2B
#define EGR 0x2C
#define EGR_ERROR 0x2D
#define EVAP_PURGE 0x2E
#define FUEL_LEVEL 0x2F
#define WARM_UPS 0x30
#define DIST_MIL_CLR 0x31
#define EVAP_PRESSURE 0x32
#define BARO_PRESSURE 0x33
#define O2S1_WR_C 0x34
#define O2S2_WR_C 0x35
#define O2S3_WR_C 0x36
#define O2S4_WR_C 0x37
#define O2S5_WR_C 0x38
#define O2S6_WR_C 0x39
#define O2S7_WR_C 0x3A
#define O2S8_WR_C 0x3B
#define CAT_TEMP_B1S1 0x3C
#define CAT_TEMP_B2S1 0x3D
#define CAT_TEMP_B1S2 0x3E
#define CAT_TEMP_B2S2 0x3F
#define PID_SUPPORT40 0x40
#define MONITOR_STAT 0x41
#define CTRL_MOD_V 0x42
#define ABS_LOAD_VAL 0x43
#define CMD_EQUIV_R 0x44
#define REL_THR_POS 0x45
#define AMBIENT_TEMP 0x46
#define ABS_THR_POS_B 0x47
#define ABS_THR_POS_C 0x48
#define ACCEL_PEDAL_D 0x49
#define ACCEL_PEDAL_E 0x4A
#define ACCEL_PEDAL_F 0x4B
#define CMD_THR_ACTU 0x4C
#define TIME_MIL_ON 0x4D
#define TIME_MIL_CLR 0x4E
#define LAST_PID 0x4E // same as the last one defined above
/* Our internal fake PIDs */
#define FIRST_FAKE_PID 0xE9 // same as the first one defined below
#define OUTING_WASTE 0xE9 // fuel wasted since car started
#define TRIP_WASTE 0xEA // fuel wasted during trip
#define TANK_WASTE 0xEB // fuel wasted for this tank
#define OUTING_COST 0xEC // the money spent since car started
#define TRIP_COST 0xED // money spent since on trip
#define TANK_COST 0xEE // money spent of current tank
#define ENGINE_ON 0xEF // The length of time car has been running.
#define NO_DISPLAY 0xF0
#define FUEL_CONS 0xF1 // instant cons
#define TANK_CONS 0xF2 // average cons of tank
#define TANK_FUEL 0xF3 // fuel used in tank
#define TANK_DIST 0xF4 // distance for tank
#define REMAIN_DIST 0xF5 // remaining distance of tank
#define TRIP_CONS 0xF6 // average cons of trip
#define TRIP_FUEL 0xF7 // fuel used in trip
#define TRIP_DIST 0xF8 // distance of trip
#define BATT_VOLTAGE 0xF9
#define OUTING_CONS 0xFA // cons since the engine turned on
#define OUTING_FUEL 0xFB // fuel used since engine turned on
#define OUTING_DIST 0xFC // distance since engine turned on
#define CAN_STATUS 0xFD
#define PID_SEC 0xFE
#ifdef DEBUG //why waste a valueable PID space!!
#define FREE_MEM 0xFF
#else
#define ECO_VISUAL 0xFF // Visually dispay relative economy with text (at end of program)
#endif
//The Textual Description of each PID
prog_char *PID_Desc[] PROGMEM=
{
"PID00-21", // 0x00 PIDs supported
"Stat DTC", // 0x01 Monitor status since DTCs cleared.
"Frz DTC", // 0x02 Freeze DTC
"Fuel SS", // 0x03 Fuel system status
"Eng Load", // 0x04 Calculated engine load value
"CoolantT", // 0x05 Engine coolant temperature
"ST F%T 1", // 0x06 Short term fuel % trim�Bank 1
"LT F%T 1", // 0x07 Long term fuel % trim�Bank 1
"ST F%T 2", // 0x08 Short term fuel % trim�Bank 2
"LT F%T 2", // 0x09 Long term fuel % trim�Bank 2
"Fuel Prs", // 0x0A Fuel pressure
" MAP ", // 0x0B Intake manifold absolute pressure
" RPM ", // 0x0C Engine RPM
" Speed ", // 0x0D Vehicle speed
"Timing A", // 0x0E Timing advance
"Intake T", // 0x0F Intake air temperature
"MAF rate", // 0x10 MAF air flow rate
"Throttle", // 0x11 Throttle position
"Cmd SAS", // 0x12 Commanded secondary air status
"Oxy Sens", // 0x13 Oxygen sensors present
"Oxy B1S1", // 0x14 Oxygen Sensor Bank 1, Sensor 1
"Oxy B1S2", // 0x15 Oxygen Sensor Bank 1, Sensor 2
"Oxy B1S3", // 0x16 Oxygen Sensor Bank 1, Sensor 3
"Oxy B1S4", // 0x17 Oxygen Sensor Bank 1, Sensor 4
"Oxy B2S1", // 0x18 Oxygen Sensor Bank 2, Sensor 1
"Oxy B2S2", // 0x19 Oxygen Sensor Bank 2, Sensor 2
"Oxy B2S3", // 0x1A Oxygen Sensor Bank 2, Sensor 3
"Oxy B2S4", // 0x1B Oxygen Sensor Bank 2, Sensor 4
"OBD Std", // 0x1C OBD standards this vehicle conforms to
"Oxy Sens", // 0x1D Oxygen sensors present
"AuxInpt", // 0x1E Auxiliary input status
"Run Time", // 0x1F Run time since engine start
"PID21-40", // 0x20 PIDs supported 21-40
"Dist MIL", // 0x21 Distance traveled with malfunction indicator lamp (MIL) on
"FRP RMF", // 0x22 Fuel Rail Pressure (relative to manifold vacuum)
"FRP Dies", // 0x23 Fuel Rail Pressure (diesel)
"OxyS1 V", // 0x24 O2S1_WR_lambda(1): ER Voltage
"OxyS2 V", // 0x25 O2S2_WR_lambda(1): ER Voltage
"OxyS3 V", // 0x26 O2S3_WR_lambda(1): ER Voltage
"OxyS4 V", // 0x27 O2S4_WR_lambda(1): ER Voltage
"OxyS5 V", // 0x28 O2S5_WR_lambda(1): ER Voltage
"OxyS6 V", // 0x29 O2S6_WR_lambda(1): ER Voltage
"OxyS7 V", // 0x2A O2S7_WR_lambda(1): ER Voltage
"OxyS8 V", // 0x2B O2S8_WR_lambda(1): ER Voltage
"Cmd EGR", // 0x2C Commanded EGR
"EGR Err", // 0x2D EGR Error
"Cmd EP", // 0x2E Commanded evaporative purge
"Fuel LI", // 0x2F Fuel Level Input
"WarmupCC", // 0x30 # of warm-ups since codes cleared
"Dist CC", // 0x31 Distance traveled since codes cleared
"Evap SVP", // 0x32 Evap. System Vapor Pressure
"Barometr", // 0x33 Barometric pressure
"OxyS1 C", // 0x34 O2S1_WR_lambda(1): ER Current
"OxyS2 C", // 0x35 O2S2_WR_lambda(1): ER Current
"OxyS3 C", // 0x36 O2S3_WR_lambda(1): ER Current
"OxyS4 C", // 0x37 O2S4_WR_lambda(1): ER Current
"OxyS5 C", // 0x38 O2S5_WR_lambda(1): ER Current
"OxyS6 C", // 0x39 O2S6_WR_lambda(1): ER Current
"OxyS7 C", // 0x3A O2S7_WR_lambda(1): ER Current
"OxyS8 C", // 0x3B O2S8_WR_lambda(1): ER Current
"C T B1S1", // 0x3C Catalyst Temperature Bank 1 Sensor 1
"C T B1S2", // 0x3D Catalyst Temperature Bank 1 Sensor 2
"C T B2S1", // 0x3E Catalyst Temperature Bank 2 Sensor 1
"C T B2S2", // 0x3F Catalyst Temperature Bank 2 Sensor 2
"PID41-60", // 0x40 PIDs supported 41-60
" MStDC", // 0x41 Monitor status this drive cycle
"Ctrl M V", // 0x42 Control module voltage
"Abs L V", // 0x43 Absolute load value
"Cmd E R", // 0x44 Command equivalence ratio
"R ThrotP", // 0x45 Relative throttle position
"Amb Temp", // 0x46 Ambient air temperature
"Acc PP B", // 0x47 Absolute throttle position B
"Acc PP C", // 0x48 Absolute throttle position C
"Acc PP D", // 0x49 Accelerator pedal position D
"Acc PP E", // 0x4A Accelerator pedal position E
"Acc PP F", // 0x4B Accelerator pedal position F
"Cmd T A", // 0x4C Commanded throttle actuator
"T MIL On", // 0x4D Time run with MIL on
"T TC Crl", // 0x4E Time since trouble codes cleared
" 0x4F", // 0x4F Unknown
" 0x50", // 0x50 Unknown
"Fuel Typ", // 0x51 Fuel Type
"Ethyl F%", // 0x52 Ethanol fuel %
"", // 0x53
"", // 0x54
"", // 0x55
"", // 0x56
"", // 0x57
"", // 0x58
"", // 0x59
"", // 0x5A
"", // 0x5B
"", // 0x5C
"", // 0x5D
"", // 0x5E
"", // 0x5F
"", // 0x60
"", // 0x61
"", // 0x62
"", // 0x63
"", // 0x64
"", // 0x65
"", // 0x66
"", // 0x67
"", // 0x68
"", // 0x69
"", // 0x6A
"", // 0x6B
"", // 0x6C
"", // 0x6D
"", // 0x6E
"", // 0x6F
"", // 0x70
"", // 0x71
"", // 0x72
"", // 0x73
"", // 0x74
"", // 0x75
"", // 0x76
"", // 0x77
"", // 0x78
"", // 0x79
"", // 0x7A
"", // 0x7B
"", // 0x7C
"", // 0x7D
"", // 0x7E
"", // 0x7F
"", // 0x80
"", // 0x81
"", // 0x82
"", // 0x83
"", // 0x84
"", // 0x85
"", // 0x86
"", // 0x87
"", // 0x88
"", // 0x89
"", // 0x8A
"", // 0x8B
"", // 0x8C
"", // 0x8D
"", // 0x8E
"", // 0x8F
"", // 0x90
"", // 0x91
"", // 0x92
"", // 0x93
"", // 0x94
"", // 0x95
"", // 0x96
"", // 0x97
"", // 0x98
"", // 0x99
"", // 0x9A
"", // 0x9B
"", // 0x9C
"", // 0x9D
"", // 0x9E
"", // 0x9F
"", // 0xA0
"", // 0xA1
"", // 0xA2
"", // 0xA3
"", // 0xA4
"", // 0xA5
"", // 0xA6
"", // 0xA7
"", // 0xA8
"", // 0xA9
"", // 0xAA
"", // 0xAB
"", // 0xAC
"", // 0xAD
"", // 0xAE
"", // 0xAF
"", // 0xB0
"", // 0xB1
"", // 0xB2
"", // 0xB3
"", // 0xB4
"", // 0xB5
"", // 0xB6
"", // 0xB7
"", // 0xB8
"", // 0xB9
"", // 0xBA
"", // 0xBB
"", // 0xBC
"", // 0xBD
"", // 0xBE
"", // 0xBF
"", // 0xC0
"", // 0xC1
"", // 0xC2
"", // 0xC3 Unknown
"", // 0xC4 Unknown
"", // 0xC5
"", // 0xC6
"", // 0xC7
"", // 0xC8
"", // 0xC9
"", // 0xCA
"", // 0xCB
"", // 0xCC
"", // 0xCD
"", // 0xCE
"", // 0xCF
"", // 0xD0
"", // 0xD1
"", // 0xD2
"", // 0xD3
"", // 0xD4
"", // 0xD5
"", // 0xD6
"", // 0xD7
"", // 0xD8
"", // 0xD9
"", // 0xDA
"", // 0xDB
"", // 0xDC
"", // 0xDD
"", // 0xDE
"", // 0xDF
"", // 0xE0
"", // 0xE1
"", // 0xE2
"", // 0xE3
"", // 0xE4
"", // 0xE5
"", // 0xE6
"", // 0xE7
"", // 0xE8
"OutWaste", // 0xE9 outing waste
"TrpWaste", // 0xEA trip waste
"TnkWaste", // 0xEB tank waste
"Out Cost", // 0xEC outing cost
"Trp Cost", // 0xED trip cost
"Tnk Cost", // 0xEE tank cost
"Out Time", // 0xEF The length of time car has been running
"No Disp", // 0xF0 No display
"InstCons", // 0xF1 instant cons
"Tnk Cons", // 0xF2 average cons of tank
"Tnk Fuel", // 0xF3 fuel used in tank
"Tnk Dist", // 0xF4 distance for tank
"Dist2MT", // 0xF5 remaining distance of tank
"Trp Cons", // 0xF6 average cons of trip
"Trp Fuel", // 0xF7 fuel used in trip
"Trp Dist", // 0xF8 distance of trip
"Batt Vlt", // 0xF9 Battery Voltage
"Out Cons", // 0xFA cons since the engine turned on
"Out Fuel", // 0xFB fuel used since engine turned on
"Out Dist", // 0xFC distance since engine turned on
"Can Stat", // 0xFD Can Status
"PID_SEC", // 0xFE
"Eco Vis", // 0xFF Visually dispay relative economy with text
};
// returned length of the PID response.
// constants so put in flash
prog_uchar pid_reslen[] PROGMEM=
{
// pid 0x00 to 0x1F
4,4,2,2,1,1,1,1,1,1,1,1,2,1,1,1,
2,1,1,1,2,2,2,2,2,2,2,2,1,1,1,4,
// pid 0x20 to 0x3F
4,2,2,2,4,4,4,4,4,4,4,4,1,1,1,1,
1,2,2,1,4,4,4,4,4,4,4,4,2,2,2,2,
// pid 0x40 to 0x4E
4,8,2,2,2,1,1,1,1,1,1,1,1,2,2
};
// Number of screens of PIDs
#define NBSCREEN 3 // 12 PIDs should be enough for everyone
byte active_screen=0; // 0,1,2,... selected by left button
prog_char pctd[] PROGMEM="- %d + "; // used in a couple of place
prog_char pctdpctpct[] PROGMEM="- %d%% + "; // used in a couple of place
prog_char pctspcts[] PROGMEM="%s %s"; // used in a couple of place
prog_char pctldpcts[] PROGMEM="%ld %s"; // used in a couple of place
prog_char select_no[] PROGMEM="(NO) YES "; // for config menu
prog_char select_yes[] PROGMEM=" NO (YES)"; // for config menu
prog_char gasPrice[][10] PROGMEM={"- %s\354 + ", "- $%s + "}; // dual string for fuel price
// menu items used by menu_selection.
prog_char *topMenu[] PROGMEM = {"Configure menu", "Exit", "Display", "Adjust", "PIDs"};
prog_char *displayMenu[] PROGMEM = {"Display menu", "Exit", "Contrast", "Metric", "Fuel/Hour"};
prog_char *adjustMenu[] PROGMEM = {"Adjust menu", "Exit", "Tank Size", "Fuel Cost", "Fuel %", "Speed %", "Out Wait", "Trip Wait", "Eng Disp"};
prog_char *PIDMenu[] PROGMEM = {"PID Screen menu", "Exit", "Scr 1", "Scr 2", "Scr 3"};
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
// Time information
#define MILLIS_PER_HOUR 3600000L
#define MILLIS_PER_MINUTE 60000L
#define MILLIS_PER_SECOND 1000L
// to differentiate trips
#define TANK 0
#define TRIP 1
#define OUTING 2 //Tracks your current outing
#define NBTRIP 3
prog_char * tripNames[NBTRIP] PROGMEM =
{
"Tank",
"Trip",
"Outing"
};
// parameters
// each trip contains fuel used and distance done
typedef struct
{
unsigned long dist; // in cm
unsigned long fuel; // in �L
unsigned long waste; // in �L
}
trip_t;
// each screen contains n PIDs (two per line)
typedef struct
{
byte PID[LCD_PID_count];
}
screen_t;
#define MINUTES_GRANULARITY 10
typedef struct
{
byte contrast; // we only use 0-100 value in step 20
byte use_metric; // 0=rods and hogshead, 1=SI
boolean use_comma; // When using metric, also use the comma decimal separator
byte per_hour_speed; // speed from which we toggle to fuel/hour (km/h or mph)
byte fuel_adjust; // because of variation from car to car, temperature, etc
byte speed_adjust; // because of variation from car to car, tire size, etc
byte eng_dis; // engine displacement in dL
unsigned int gas_price; // price per unit of fuel in 10th of cents. 905 = $0.905
unsigned int tank_size; // tank size in dL or dgal depending of unit
byte OutingStopOver; // Allowable stop over time (in tens of minutes). Exceeding time starts a new outing.
byte TripStopOver; // Allowable stop over time (in hours). Exceeding time starts a new outing.
trip_t trip[NBTRIP]; // trip0=tank, trip1=a trip
screen_t screen[NBSCREEN]; // screen
}
params_t;
// parameters default values
params_t params=
{
40,
1,
true,
20,
100,
100,
16,
905,
450,
6, // 60 minutes (6 X 10) stop or less will not cause outing reset
12, // 12 hour stop or less will not cause trip reset
{
{ 0,0,0 }, // tank: dist, fuel, waste
{ 0,0,0 }, // trip: dist, fuel, waste
{ 0,0,0 } // outing:dist, fuel, waste
},
{
{ {FUEL_CONS,LOAD_VALUE,TANK_CONS,OUTING_FUEL
#if LCD_ROWS == 4
,OUTING_WASTE,OUTING_COST,ENGINE_ON,LOAD_VALUE
#endif
} },
{ {TRIP_CONS,TRIP_DIST,TRIP_FUEL,COOLANT_TEMP
#if LCD_ROWS == 4
,TRIP_WASTE,TRIP_COST,INT_AIR_TEMP,THROTTLE_POS
#endif
} },
{ {TANK_CONS,TANK_DIST,TANK_FUEL,REMAIN_DIST
#if LCD_ROWS == 4
,TANK_WASTE,TANK_COST,ENGINE_RPM,VEHICLE_SPEED
#endif
} }
}
};
prog_char * econ_Visual[] PROGMEM=
{
"Yuck!!8{",
"Awful :(",
"Poor :[",
"OK :|",
"Good :]",
"Great :)",
"Adroit:D",
"HyprM 8D"
};
#define STRLEN 40
#ifdef ELM
#define NUL '\0'
#define CR '\r' // carriage return = 0x0d = 13
#define PROMPT '>'
#define DATA 1 // data with no cr/prompt
#else
/*
* for ISO9141-2 Protocol
*/
#define K_IN 0
#define K_OUT 1
#ifdef useL_Line
#define L_OUT 2
#endif
#endif
long tempLong; // Useful for transitory values while getting PID information.
// some globals, for trip calculation and others
unsigned long old_time;
byte has_rpm=0;
long vss=0; // speed
long maf=0; // MAF
unsigned long engine_on, engine_off; //used to track time of trip.
unsigned long getpid_time;
byte nbpid_per_second=0;
// flag used to save distance/average consumption in eeprom only if required
byte engine_started=0;
byte param_saved=0;
#ifdef ELM
#if defined do_ISO_Reinit
#error do_ISO_Reinit is ONLY ISO 9141 It is not to be used with ELM!
#endif
#endif
#ifndef useECUState
#if defined do_ISO_Reinit
#error do_ISO_Reinit must have useECUState also defined
#endif
#endif
#ifdef useECUState
boolean oldECUconnection; // Used to test for change in ECU connection state
#endif
#ifdef carAlarmScreen
boolean refreshAlarmScreen; // Used to cause non-repeating screen data to display
#endif
#ifndef ELM
// ISO 9141 communication variables
byte ISO_InitStep = 0; // Init is multistage, this is the counter
boolean ECUconnection; // Have we connected to the ECU or not
#endif
#ifdef ENABLE_VDIP
// Vinculum setup
#define VDIP_RESET 12 // Pin for reset of VDIP module (active low)
#define VDIP_STATUS_LED 11 // LED to show whether a file is open
#define VDIP_WRITE_LED 10 // LED to show when write is in progress
#define VDIP_RTS_PIN 9 // Check if the VDIP is ready to receive. Active low
#define LOG_LED 4 // Pin connected to the "log" status LED (active high)
#define LOG_BUTTON 3
#define LOG_BUTTON_INT 1
#define POWER_SENSE_PIN 2
#define POWER_SENSE_INT 0
byte logPid[] = {
LOAD_VALUE,
COOLANT_TEMP,
ENGINE_RPM,
VEHICLE_SPEED,
TIMING_ADV,
INT_AIR_TEMP,
MAF_AIR_FLOW,
THROTTLE_POS,
FUEL_RAIL_P,
FUEL_LEVEL,
BARO_PRESSURE,
AMBIENT_TEMP,
FUEL_CONS,
BATT_VOLTAGE
};
byte logPidCount = sizeof(logPid) / sizeof(logPid[0]);
unsigned long lastLogWrite = 0; // Milliseconds since boot that the last entry was written
#define LOG_INTERVAL 1000 // Milliseconds between log entries on the memory stick
// We need the PString library to create a log buffer
#include <PString.h>
volatile unsigned long logButtonTimestamp = 0;
#endif
// the buttons interrupt
// this is the interrupt handler for button presses
ISR(PCINT2_vect)
{
#if 0
static unsigned long last_millis = 0;
unsigned long m = millis();
if (m - last_millis > 20)
{ // do pushbutton stuff
#ifdef MEGA
buttonState |= ~PINK;
#else
buttonState |= ~PINC;
#endif
}
// else ignore interrupt: probably a bounce problem
last_millis = m;
#else
#ifdef MEGA
buttonState |= ~PINK;
#else
buttonState |= ~PINC;
#endif
#endif
}
#ifdef ELM
/**
* elm_read
* each ELM response ends with '\r' followed at the end by the prompt
* so read com port until we find a prompt
*/
byte elm_read(char *str, byte size)
{
int b;
byte i=0;
// wait for something on com port
while((b=OBD2.read())!=PROMPT && i<size)
{
if(/*b!=-1 &&*/ b>=' ')
str[i++]=b;
}
if(i!=size) // we got a prompt
{
str[i]=NUL; // replace CR by NUL
return PROMPT;
}
else
return DATA;
}
/**
* elm_write
* buf must be ASCIIZ
*/
void elm_write(char *str)
{
while(*str!=NUL)
OBD2.print(*str++);
}
/**
* elm_check_response
* check header byte
*/
byte elm_check_response(const char *cmd, char *str)
{
// cmd is something like "010D"
// str should be "41 0D blabla"
if(cmd[0]+4 != str[0]
|| cmd[1]!=str[1]
|| cmd[2]!=str[3]
|| cmd[3]!=str[4])
return 1;
return 0; // no error
}
/**
* elm_compact_response
*/
byte elm_compact_response(byte *buf, char *str)
{
byte i=0;
// start at 6 which is the first hex byte after header
// ex: "41 0C 1A F8"
// return buf: 0x1AF8
str+=6;
while(*str!=NUL)
buf[i++]=strtoul(str, &str, 16); // 16 = hex
return i;
}
/**
* elm_command
* Write simple string to ELM and return read result
* cmd is a PSTR!!
*/
byte elm_command(char *str, char *cmd)
{
sprintf_P(str, cmd);
elm_write(str);
return elm_read(str, STRLEN);
}
/**
* elm_init
*/
void elm_init()
{
char str[STRLEN];
OBD2.begin(OBD2_BAUD_RATE);
OBD2.flush();
#ifndef DEBUG
// reset, wait for something and display it
elm_command(str, PSTR("ATWS\r"));
lcd_gotoXY(0,1);
if(str[0]=='A') // we have read back the ATWS
lcd_print(str+4);
else
lcd_print(str);
lcd_print_P(PSTR(" Init"));
// turn echo off
elm_command(str, PSTR("ATE0\r"));
// send 01 00 until we are connected
do
{
elm_command(str, PSTR("0100\r"));
delay(1000);