bicycle_odometer

view odometer.c @ 3:c0c68988bcdf

changed the wheel perimeter
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 25 Aug 2011 08:22:19 +0300
parents f74f4561e71c
children f883847a0591
line source
1 /* PORT USAGE
2 *
3 * D0-D3: data bus, connected to the D0-D3 pins of all the 4511 chips
4 * C0-C5,D4,D5: directly driving the 8 speed graph LEDs
5 * B0-B2: connected to the decoder controlling the 4511 latches as such:
6 * 000 - speed most significant
7 * 001 - speed least significant
8 * 010 - dist most significant
9 * 011 - dist middle
10 * 100 - dist least significant
11 * 101 - all latches are off (high)
12 * B3-B5: ISP. B4 also acts as generic pushbutton input
13 * B6,B7: XTAL
14 * D6,D7: comparator, hall effect sensor input and threshold trimpot.
15 */
17 /* 16mhz resonator */
18 #define F_CPU 16000000
20 #include <avr/io.h>
21 #include <avr/interrupt.h>
22 #include <avr/power.h>
23 #include <util/delay.h>
26 #define SEC_TICKS (F_CPU / 256 / 256)
28 #define PRESCL_1 1
29 #define PRESCL_8 2
30 #define PRESCL_64 3
31 #define PRESCL_256 4
32 #define PRESCL_1024 5
35 #define PB_CSEL_MASK 0x7
36 #define PD_DATA_MASK 0xf
37 #define PD_LEDS_MASK 0xc0
39 #define RPS_TO_KMH(x) ((36 * WHEEL_PERIMETER * (x)) / 1000)
41 #define DEBOUNCE_TICKS 1
44 /* wheel perimeter in centimeters */
45 #define WHEEL_PERIMETER 194
47 #define nop() asm volatile("nop")
50 void init_timer(void);
51 void latch(int n);
52 void update_display(void);
53 void disp_speed(int n);
54 void disp_dist(int n);
55 void disp_leds(int n);
57 int state;
58 int debug_mode = 0;
60 volatile long ticks;
62 unsigned long nrot;
63 unsigned long speed_rps;
65 int main(void)
66 {
67 int i;
69 DDRB = 0xf; /* only first four bits are outputs */
70 DDRC = 0xff; /* speed leds 6 bits */
71 DDRD = 0x3f; /* 4bits data bus, 2 bits speed leds, 2 bits comparator (input) */
73 /* zero-out the displays and disable all pullups except for the reset pin */
74 PORTB = 0;
75 PORTC = 0x40; /* 6th bit set, C6 is reset */
76 PORTD = 0;
78 for(i=0; i<5; i++) {
79 latch(i);
80 }
82 /* if the button at B4 is pressed during startup, enter debug mode */
83 if((PINB >> 4) & 1) {
84 debug_mode = 1;
85 PORTC |= 3 << 4;
86 }
88 init_timer();
90 /* disable digital input buffer for the AINn pins */
91 DIDR1 = 0;
93 /* read initial comparator state */
94 state = (ACSR >> ACO) & 1;
96 /* in debug mode we want an interrupt both on rising and falling edge
97 * to be able to blink leds when the wheel goes past. otherwise we only need
98 * a rising edge interrupt to increment the rotation counter.
99 */
100 /* rising edge interrupt */
101 /*ACSR |= (2 << ACIS0);*/
103 /* comparator interrupt enable */
104 ACSR |= (1 << ACIE);
106 sei();
108 for(;;) {
109 }
110 return 0;
111 }
113 void init_timer(void)
114 {
115 power_timer0_enable();
117 TCCR0A = 0;
118 TCCR0B = PRESCL_256;
120 /* enable timer overflow interrupt */
121 TIMSK0 = 1;
122 }
124 void latch(int n)
125 {
126 unsigned char upper = PORTB & ~PB_CSEL_MASK;
127 /* pull latch low */
128 PORTB = upper | n;
129 asm volatile("nop");
130 /* pull all latches high again */
131 PORTB = upper | 5;
132 }
134 ISR(ANALOG_COMP_vect)
135 {
136 volatile static long prev_time;
137 unsigned char aco;
139 nop();
140 nop();
141 nop();
143 aco = (ACSR >> ACO) & 1;
145 if(aco != state && (ticks - prev_time) > DEBOUNCE_TICKS) {
146 state = aco;
148 if(state) {
149 nrot++;
151 update_display();
152 }
153 }
155 prev_time = ticks;
156 }
158 ISR(TIMER0_OVF_vect)
159 {
160 volatile static int sec_ticks;
161 volatile static unsigned long last_rot;
163 ticks++;
164 sec_ticks++;
166 if(sec_ticks >= SEC_TICKS) {
167 speed_rps = nrot - last_rot;
169 update_display();
171 sec_ticks = 0;
172 last_rot = nrot;
173 }
176 if(debug_mode) {
177 unsigned char state = (ACSR >> ACO) & 1;
178 if(state) {
179 PORTD |= (1 << 5);
180 } else {
181 PORTD &= ~(1 << 5);
182 }
183 }
184 }
186 void update_display(void)
187 {
188 if(debug_mode) {
189 disp_dist(nrot);
190 disp_speed(speed_rps);
192 if(state) {
193 PORTD |= (1 << 5);
194 } else {
195 PORTD &= ~(1 << 5);
196 }
197 } else {
198 unsigned long dist_cm = (nrot * WHEEL_PERIMETER);
199 int speed_kmh = RPS_TO_KMH(speed_rps);
201 disp_dist(dist_cm / 10000);
202 disp_speed(speed_kmh);
203 disp_leds(speed_kmh * 8);
204 }
205 }
207 void disp_speed(int n)
208 {
209 PORTD = (PORTD & ~PD_DATA_MASK) | (n % 10);
210 latch(1);
211 n /= 10;
212 PORTD = (PORTD & ~PD_DATA_MASK) | (n % 10);
213 latch(0);
214 }
216 void disp_dist(int n)
217 {
218 PORTD = (PORTD & ~PD_DATA_MASK) | (n % 10);
219 latch(4);
220 n /= 10;
221 PORTD = (PORTD & ~PD_DATA_MASK) | (n % 10);
222 latch(3);
223 n /= 10;
224 PORTD = (PORTD & ~PD_DATA_MASK) | (n % 10);
225 latch(2);
226 }
228 void disp_leds(int n)
229 {
230 int i, count, bits;
232 count = (n + 4) >> 5;
233 bits = 0;
235 for(i=0; i<count; i++) {
236 bits |= (1 << i);
237 }
239 PORTC = bits;
240 PORTD = (PORTD & PD_DATA_MASK) | ((bits & PD_LEDS_MASK) >> 2);
241 }