1#include <LiquidCrystal.h>
2const int rs = 7, en = 2, d4 = 13, d5 = 12, d6 = 11, d7 = 10;
3LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
4
5#define CLOCK_FREQUENCY 16000000
6volatile unsigned int secs = 0;
7
8#define magnet 3
9int count = 0;
10double t = 0;
11double distance = 0.0013048795;
12double velocity = 0;
13double lastTime = 0;
14double odometer = 0;
15volatile bool state = false;
16
17
18uint8_t empty[8] = {0b00000,0b00000,0b00000,0b00000,0b00000,0b00000,0b00000,0b00000};
19uint8_t l[8] = {0b10000,0b10000,0b10000,0b10000,0b10000,0b10000,0b10000,0b10000};
20uint8_t ml[8] = {0b11000,0b11000,0b11000,0b11000,0b11000,0b11000,0b11000,0b11000};
21uint8_t center[8] = {0b11100,0b11100,0b11100,0b11100,0b11100,0b11100,0b11100,0b11100};
22uint8_t mr[8] = {0b11110,0b11110,0b11110,0b11110,0b11110,0b11110,0b11110,0b11110};
23uint8_t r[8] = {0b11111,0b11111,0b11111,0b11111,0b11111,0b11111,0b11111,0b11111};
24
25String custChars[6] = {"\x01","\x02","\x03","\x04","\x05","\x06"};
26
27
28
29int idleCount = 0;
30int oneLoopCount = 0;
31
32
33void updateSpeed(){
34 state = true;
35}
36
37
38ISR(TIMER1_COMPA_vect) {
39 idleCount = idleCount + 1;
40}
41
42void setup() {
43 Serial.begin(9600);
44
45 lcd.begin(16, 2);
46
47
48 pinMode(magnet, INPUT_PULLUP);
49
50
51 attachInterrupt(digitalPinToInterrupt(magnet), updateSpeed, FALLING);
52
53
54 setupTimer(1.0);
55
56
57 lcd.createChar(1, empty);
58 lcd.createChar(2, l);
59 lcd.createChar(3, ml);
60 lcd.createChar(4, center);
61 lcd.createChar(5, mr);
62 lcd.createChar(6, r);
63}
64
65void loop() {
66 t = (millis() / 1000.0);
67 int h = floor(t/3600);
68 int m = floor(t/60) - (60*floor(t/3600));
69 int s = floor(t) - (60*floor(t/60));
70
71
72
73
74
75
76
77
78
79
80
81
82 lcd.setCursor(0,0);
83 lcd.print(m);
84 lcd.setCursor(2,0);
85 lcd.print("min");
86
87 if(idleCount >= 7){
88 velocity = 0.0;
89
90
91 if(oneLoopCount == 0){
92 lcd.clear();
93 oneLoopCount = 1;
94 }
95
96
97 lcd.setCursor(7, 0);
98 lcd.print(velocity);
99 lcd.setCursor(13, 0);
100 lcd.print("mph");
101
102
103 lcd.setCursor(0,1);
104 lcd.print(odometer);
105 lcd.setCursor(5, 1);
106 lcd.print("mi");
107
108
109 int bars = floor(velocity);
110 int sects = bars/5;
111 lcd.setCursor(8+sects,1);
112 bars = bars - 5*sects;
113 lcd.print(custChars[bars]);
114 for(int u = 0;u<sects;u++){
115 lcd.setCursor(8+u,1);
116 lcd.print(custChars[5]);
117 }
118 }
119
120 if(state){
121
122 count++;
123 velocity = ((distance * 3600)/((t - lastTime)));
124
125
126 if((t - lastTime) <= 0.09396){
127 velocity = 0.0;
128 }
129
130
131 lcd.clear();
132
133
134 lcd.setCursor(7, 0);
135 lcd.print(velocity);
136 lcd.setCursor(13, 0);
137 lcd.print("mph");
138
139
140
141
142
143
144
145
146
147
148
149
150 lastTime = t;
151 state = false;
152 idleCount = 0;
153 oneLoopCount = 0;
154 }
155
156
157 odometer = count * distance;
158
159
160 lcd.setCursor(0,1);
161 lcd.print(odometer);
162 lcd.setCursor(5, 1);
163 lcd.print("mi");
164
165
166 int bars = floor(velocity);
167 int sects = bars/5;
168 lcd.setCursor(8+sects,1);
169 bars = bars - 5*sects;
170 lcd.print(custChars[bars]);
171 for(int u = 0;u<sects;u++){
172 lcd.setCursor(8+u,1);
173 lcd.print(custChars[5]);
174 }
175}
176
177void setupTimer(float freq){
178
179 noInterrupts();
180
181
182 TCCR1A = 0;
183 TCCR1B = 0;
184 TCNT1 = 0;
185
186 TCCR1B |= (1 << WGM12);
187
188 TCCR1B |= (1 << CS12) | (1 << CS10);
189
190 OCR1A = CLOCK_FREQUENCY/freq/1024 - 1;
191
192 TIMSK1 |= (1 << OCIE1A);
193
194 interrupts();
195}