1 | /*****************************************************
|
2 | Project : SPEEDOMETER
|
3 | Version : 1.0
|
4 | Author: Peter Reinisch
|
5 | Chip type : ATmega8515
|
6 | Program type : Application
|
7 | Clock frequency : 8.000000 MHz 64MS
|
8 | Memory model : Small
|
9 | External SRAM size : 0
|
10 | Data Stack size : 196
|
11 |
|
12 | Compiled with CodeVisionAVR C cross-compiler.
|
13 | *****************************************************/
|
14 | #include <mega8515.h>
|
15 |
|
16 | // Alphanumeric LCD Module functions
|
17 | #include <alcd.h>
|
18 |
|
19 | // Standard library functions (itoa, ftoa etc.)
|
20 | #include <stdlib.h>
|
21 | #include <stdio.h>
|
22 |
|
23 | // Delay functions
|
24 | #include <delay.h>
|
25 |
|
26 | // Nicknames for port pins
|
27 | #define PLUS_KEY PINC.0
|
28 | #define MINUS_KEY PINC.1
|
29 | #define ENTER_KEY PINC.2
|
30 | #define DIA_KEY PINC.3
|
31 | //#define SPEED_PORT PORTC.7
|
32 |
|
33 | // Nicknames for delays, Etc.
|
34 | #define DEBOUNCE_DELAY 80
|
35 | #define SPEED_MULTIPLIER 4553
|
36 | #define PULSE_TURN 12
|
37 |
|
38 | // Global variables
|
39 | unsigned int dispint=0; // Zähler zur verzögerten Display aktualisierung
|
40 | unsigned char circ=0; // Circumference
|
41 | float dcm=0; // Distance covered in cm (modul 100m)
|
42 | float wheel=0; // Calculated Circ/Pulse
|
43 | float speed=0; // Calculated speed
|
44 | unsigned int trip=0; // Trip distance (0.1 Km)
|
45 | unsigned long distance=0; // Total distance (0.1 Km)
|
46 | unsigned char overflow=0; // Timer1 overflow; for long delays
|
47 | unsigned long count=0; // Current Timer1 count
|
48 | unsigned long timer=0; //Calculated Time
|
49 | unsigned char g_temp[8]; //Buffer for formated Outputs
|
50 |
|
51 | // Some messages
|
52 | flash char msg_saving[]="Saving Data...";
|
53 | flash char msg_circ[]="Circumference:";
|
54 | flash char msg_dia[]="Enter Circum";
|
55 | flash char msg_cm[]=" cm";
|
56 |
|
57 | // Temporary variables
|
58 | char tempstr[10];
|
59 | //float tempfloat=0;
|
60 |
|
61 | // EEPROM saved variables
|
62 | // Note that these variables are not written periodically.
|
63 | // The diameter is written only when the diameter is changed from the menu.
|
64 | // The odometer reading is saved only when the main power to the system is cut-off.
|
65 | eeprom unsigned long int save_odometer=0;
|
66 | eeprom unsigned long int save_trip=0;
|
67 | eeprom unsigned char save_circ=0;
|
68 | eeprom unsigned long int save_dcm=0;
|
69 |
|
70 | // Timer 0 overflow interrupt service routine
|
71 | interrupt [TIM0_OVF] void timer0_ovf_isr(void)
|
72 | {
|
73 | }
|
74 |
|
75 | // Timer 1 overflow interrupt service routine
|
76 | interrupt [TIM1_OVF] void timer1_ovf_isr(void)
|
77 | {
|
78 | overflow++;
|
79 | }
|
80 |
|
81 | // External Interrupt 0 service routine
|
82 | // A pulse is recieved & this function gets called..
|
83 | interrupt [EXT_INT0] void ext_int0_isr(void)
|
84 | {
|
85 | dcm=dcm+wheel; // Increment dcm modul 10000 (0.1 Km)
|
86 | count=TCNT1;
|
87 | // Reset the timer
|
88 | TCNT1=0;
|
89 | overflow=0;
|
90 | }
|
91 |
|
92 | // External Interrupt 1 service routine
|
93 | // This interrupt is triggered automatically by the external circuit
|
94 | // when the main power to the circuit is removed (turning off the vehicle).
|
95 | interrupt [EXT_INT1] void ext_int1_isr(void)
|
96 | {
|
97 | // RPM in Future
|
98 | }
|
99 |
|
100 | // External Interrupt 2 service routine
|
101 | interrupt [EXT_INT2] void ext_int2_isr(void)
|
102 | {
|
103 | // Save odometer reading in EEPROM
|
104 | save_odometer=distance;
|
105 | save_trip=trip;
|
106 | save_dcm=dcm;
|
107 | lcd_clear();
|
108 | lcd_putsf(msg_saving); // "Saving Data..."
|
109 | delay_ms(1000);
|
110 | lcd_clear();
|
111 | }
|
112 |
|
113 | void main(void)
|
114 | {
|
115 |
|
116 | // Input/Output Ports initialization
|
117 | // Port A initialization
|
118 | PORTA=0x00;
|
119 | DDRA=0x00;
|
120 |
|
121 | // Port B initialization
|
122 | PORTB=0x00;
|
123 | DDRB=0x00;
|
124 |
|
125 | // Port C initialization
|
126 | PORTC=0x00;
|
127 | DDRC=0x80;
|
128 |
|
129 | // Port D initialization
|
130 | PORTD=0x00;
|
131 | DDRD=0x00;
|
132 |
|
133 | // Port E initialization
|
134 | PORTE=0x00;
|
135 | DDRE=0x00;
|
136 |
|
137 | // Timer/Counter 0 initialization
|
138 | // Clock source: System Clock
|
139 | // Clock value: 7.813 kHz
|
140 | // Mode: Normal top=FFh
|
141 | // OC0 output: Disconnected
|
142 | TCCR0=0x05;
|
143 | TCNT0=0x00;
|
144 | OCR0=0x00;
|
145 |
|
146 | // Timer/Counter 1 initialization
|
147 | // Clock source: System Clock
|
148 | // Clock value: 125,000 kHz
|
149 | // Mode: Normal top=0xFFFF
|
150 | // OC1A output: Discon.
|
151 | // OC1B output: Discon.
|
152 | // Noise Canceler: Off
|
153 | // Input Capture on Falling Edge
|
154 | // Timer1 Overflow Interrupt: On
|
155 | // Input Capture Interrupt: Off
|
156 | // Compare A Match Interrupt: Off
|
157 | // Compare B Match Interrupt: Off
|
158 | TCCR1A=0x00;
|
159 | TCCR1B=0x03;
|
160 | TCNT1H=0x00;
|
161 | TCNT1L=0x00;
|
162 | ICR1H=0x00;
|
163 | ICR1L=0x00;
|
164 | OCR1AH=0x00;
|
165 | OCR1AL=0x00;
|
166 | OCR1BH=0x00;
|
167 | OCR1BL=0x00;
|
168 |
|
169 | // External Interrupt(s) initialization
|
170 | // INT0: On ; Input Pulses
|
171 | // INT0 Mode: Falling Edge
|
172 | // INT1: On ; Save the current odometer reading
|
173 | // INT1 Mode: Falling Edge
|
174 | // INT2: Off ; Not used
|
175 | //GICR|=0xC0;
|
176 | //MCUCR=0x0A;
|
177 | //EMCUCR=0x00;
|
178 | //GIFR=0xC0;
|
179 |
|
180 |
|
181 | // External Interrupt(s) initialization
|
182 | // INT0: On
|
183 | // INT0 Mode: Falling Edge
|
184 | // INT1: On
|
185 | // INT1 Mode: Falling Edge
|
186 | // INT2: On
|
187 | // INT2 Mode: Falling edge
|
188 | GICR|=0xE0;
|
189 | MCUCR=0x0A;
|
190 | EMCUCR=0x00;
|
191 | GIFR=0xE0;
|
192 |
|
193 |
|
194 |
|
195 | // Timer(s)/Counter(s) Interrupt(s) initialization
|
196 | TIMSK=0x82;
|
197 |
|
198 | // Analog Comparator initialization
|
199 | // Analog Comparator: Off
|
200 | // Analog Comparator Input Capture by Timer/Counter 1: Off
|
201 | ACSR=0x80;
|
202 |
|
203 | // LCD module initialization
|
204 | // Connections are specified in the
|
205 | // Project|Configure|C Compiler|Libraries|Alphanumeric LCD menu:
|
206 | // RS - PORTA Bit 0
|
207 | // RD - PORTA Bit 2
|
208 | // EN - PORTA Bit 1
|
209 | // D4 - PORTA Bit 4
|
210 | // D5 - PORTA Bit 5
|
211 | // D6 - PORTA Bit 6
|
212 | // D7 - PORTA Bit 7
|
213 | // Characters/line: 16/2
|
214 | lcd_init(16);
|
215 |
|
216 | //Read saved odometer reading
|
217 | distance=save_odometer;
|
218 | trip=save_trip;
|
219 | dcm=save_dcm;
|
220 |
|
221 | //Read saved diameter and Calculate Wheel
|
222 | circ=save_circ;
|
223 | lcd_putsf(msg_circ); // "Circumference:"
|
224 | itoa(circ, tempstr);
|
225 | lcd_gotoxy(3,1);
|
226 | lcd_puts(tempstr);
|
227 | lcd_putsf(msg_cm); // " cm"
|
228 | wheel=(float)circ/PULSE_TURN;
|
229 | delay_ms(1000);
|
230 | lcd_clear();
|
231 |
|
232 | // Global enable interrupts
|
233 | #asm("sei")
|
234 |
|
235 | while(1)
|
236 | {
|
237 | {
|
238 | timer=overflow*65536+count;
|
239 | }
|
240 | speed=(wheel*SPEED_MULTIPLIER)/timer;
|
241 | if(dcm>10000)
|
242 | {
|
243 | dcm=dcm-10000;
|
244 | // For every 10000 cm, trip and distance are incremented by 1 (0.1 Km)
|
245 | trip++;
|
246 | distance++;
|
247 | }
|
248 | dispint++; // Do not Refresh Display to fast
|
249 |
|
250 | if(dispint>2000)
|
251 | {
|
252 | if(speed<1)
|
253 | speed=0;
|
254 | //lcd_clear();
|
255 | // Convert speed to string
|
256 | ftoa(speed, 0, tempstr);
|
257 | lcd_gotoxy(0,0);
|
258 | sprintf((g_temp)," %3s", tempstr);
|
259 | lcd_puts(g_temp);
|
260 | //lcd_puts(tempstr);
|
261 | lcd_gotoxy(4,0);
|
262 | lcd_putsf("Km/h");
|
263 |
|
264 | //RPM Output
|
265 | //sprintf((g_temp)," %3s", tempstr);
|
266 | //lcd_puts(g_temp);
|
267 | lcd_gotoxy(13,0);
|
268 | lcd_putsf("RPM");
|
269 |
|
270 |
|
271 | // Convert trip distance (in Km) to string
|
272 | ftoa((float)trip/10, 1, tempstr);
|
273 | lcd_gotoxy(0,1);
|
274 | sprintf((g_temp)," %5s", tempstr);
|
275 | lcd_puts(g_temp);
|
276 | //lcd_puts(tempstr);
|
277 |
|
278 | // Convert total distance (in Km) to string
|
279 | ftoa((float)distance/10, 1, tempstr);
|
280 | lcd_gotoxy(8,1);
|
281 | sprintf((g_temp)," %7s", tempstr);
|
282 | lcd_puts(g_temp);
|
283 | //lcd_puts(tempstr);
|
284 | dispint=0;
|
285 | }
|
286 |
|
287 | // If the Trip Rest switch is pressed for more than 0.5s, clear the trip meter
|
288 | if(ENTER_KEY==0)
|
289 | {
|
290 | delay_ms(500);
|
291 | if(ENTER_KEY==0)
|
292 | {
|
293 | trip=0;
|
294 | }
|
295 | }
|
296 | // If the Change Diamter key is pressed for more than a second,
|
297 | if(DIA_KEY==0)
|
298 | {
|
299 | delay_ms(1000);
|
300 | if(DIA_KEY==0)
|
301 | {
|
302 | while (1)
|
303 | {
|
304 | lcd_clear();
|
305 | lcd_putsf(msg_dia);
|
306 | itoa(circ,tempstr);
|
307 | lcd_gotoxy(3,1);
|
308 | lcd_puts(tempstr);
|
309 | lcd_putsf(msg_cm);
|
310 |
|
311 | if(PLUS_KEY==0 && circ<250)
|
312 | {
|
313 | delay_ms(DEBOUNCE_DELAY);
|
314 | if(PLUS_KEY==0)
|
315 | circ=circ+1;
|
316 | } else
|
317 | if(MINUS_KEY==0 && circ>1)
|
318 | {
|
319 | delay_ms(DEBOUNCE_DELAY);
|
320 | if(MINUS_KEY==0)
|
321 | circ=circ-1;
|
322 | } else
|
323 | if(ENTER_KEY==0)
|
324 | {
|
325 | delay_ms(DEBOUNCE_DELAY);
|
326 | if(ENTER_KEY==0)
|
327 | {
|
328 | // circ=3.14*(float)dia;
|
329 | lcd_clear();
|
330 | lcd_putsf(msg_circ); // "Circumference:"
|
331 | itoa(circ, tempstr);
|
332 | lcd_gotoxy(3,1);
|
333 | lcd_puts(tempstr);
|
334 | lcd_putsf(msg_cm); // " cm"
|
335 | // Save in EEPROM
|
336 | save_circ=circ;
|
337 | delay_ms(1000);
|
338 | break;
|
339 | }
|
340 | }
|
341 | else
|
342 | delay_ms(DEBOUNCE_DELAY);
|
343 | };
|
344 | lcd_clear();
|
345 | }
|
346 | }
|
347 |
|
348 | };
|
349 |
|
350 | }
|