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