spedo.c


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