bicycle_odometer
changeset 2:f74f4561e71c
first version almost done
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 24 Aug 2011 07:51:12 +0300 |
parents | 5cbd47000b50 |
children | c0c68988bcdf |
files | Makefile odometer.c |
diffstat | 2 files changed, 156 insertions(+), 50 deletions(-) [+] |
line diff
1.1 --- a/Makefile Tue Aug 23 19:01:38 2011 +0300 1.2 +++ b/Makefile Wed Aug 24 07:51:12 2011 +0300 1.3 @@ -27,7 +27,7 @@ 1.4 1.5 .PHONY: fuses 1.6 fuses: 1.7 - avrdude -c usbtiny -p $(mcu_dude) -U lfuse:w:0x66:m 1.8 + avrdude -c usbtiny -p $(mcu_dude) -U lfuse:w:0xe6:m 1.9 1.10 .PHONY: program 1.11 program: $(hex)
2.1 --- a/odometer.c Tue Aug 23 19:01:38 2011 +0300 2.2 +++ b/odometer.c Wed Aug 24 07:51:12 2011 +0300 2.3 @@ -15,22 +15,49 @@ 2.4 */ 2.5 2.6 /* 16mhz resonator */ 2.7 -#define F_CPU 2000000 2.8 +#define F_CPU 16000000 2.9 2.10 #include <avr/io.h> 2.11 #include <avr/interrupt.h> 2.12 +#include <avr/power.h> 2.13 #include <util/delay.h> 2.14 2.15 +#define SEC_TICKS (F_CPU / 256 / 256) 2.16 + 2.17 +#define PRESCL_1 1 2.18 +#define PRESCL_8 2 2.19 +#define PRESCL_64 3 2.20 +#define PRESCL_256 4 2.21 +#define PRESCL_1024 5 2.22 + 2.23 + 2.24 +#define PB_CSEL_MASK 0x7 2.25 +#define PD_DATA_MASK 0xf 2.26 +#define PD_LEDS_MASK 0xc0 2.27 + 2.28 +#define RPS_TO_KMH(x) ((36 * WHEEL_PERIMETER * (x)) / 1000) 2.29 + 2.30 +#define DEBOUNCE_TICKS 1 2.31 + 2.32 +#define nop() asm volatile("nop") 2.33 + 2.34 +void init_timer(void); 2.35 void latch(int n); 2.36 void update_display(void); 2.37 +void disp_speed(int n); 2.38 +void disp_dist(int n); 2.39 +void disp_leds(int n); 2.40 2.41 int state; 2.42 -int debug_mode = 1; 2.43 +int debug_mode = 0; 2.44 + 2.45 +volatile long ticks; 2.46 2.47 unsigned long nrot; 2.48 +unsigned long speed_rps; 2.49 2.50 /* wheel perimeter in centimeters */ 2.51 -#define WHEEL_PERIMETER 100 2.52 +#define WHEEL_PERIMETER 220 2.53 2.54 int main(void) 2.55 { 2.56 @@ -38,7 +65,7 @@ 2.57 2.58 DDRB = 0xf; /* only first four bits are outputs */ 2.59 DDRC = 0xff; /* speed leds 6 bits */ 2.60 - DDRD = 0xff; /* 4bits data bus, 2 bits speed leds, 2 bits comparator (don't care) */ 2.61 + DDRD = 0x3f; /* 4bits data bus, 2 bits speed leds, 2 bits comparator (input) */ 2.62 2.63 /* zero-out the displays and disable all pullups except for the reset pin */ 2.64 PORTB = 0; 2.65 @@ -49,56 +76,51 @@ 2.66 latch(i); 2.67 } 2.68 2.69 + /* if the button at B4 is pressed during startup, enter debug mode */ 2.70 + if((PINB >> 4) & 1) { 2.71 + debug_mode = 1; 2.72 + PORTC |= 3 << 4; 2.73 + } 2.74 + 2.75 + init_timer(); 2.76 + 2.77 + /* disable digital input buffer for the AINn pins */ 2.78 + DIDR1 = 0; 2.79 + 2.80 /* read initial comparator state */ 2.81 state = (ACSR >> ACO) & 1; 2.82 2.83 - if(debug_mode) { 2.84 - int i, j, leds, leds_val; 2.85 - 2.86 - for(i=0; ; i++) { 2.87 - for(j=0; j<5; j++) { 2.88 - /* set bits */ 2.89 - PORTD = (PORTD & 0xf0) | (((i + j) % 10) & 0xf); 2.90 - /* latch */ 2.91 - latch(j); 2.92 - } 2.93 - 2.94 - leds_val = 0; 2.95 - leds = i % 8; 2.96 - for(j=0; j<8; j++) { 2.97 - if(j <= leds) { 2.98 - leds_val |= (1 << j); 2.99 - } 2.100 - } 2.101 - PORTC = leds_val; 2.102 - PORTD = (PORTD & 0xf) | ((leds_val >> 2) & (3 << 4)); 2.103 - 2.104 - _delay_ms(1000); 2.105 - } 2.106 - } 2.107 - 2.108 - /* disable digital input buffer for the AINn pins */ 2.109 - /*DIDR1 = 0;*/ 2.110 - 2.111 - ACSR = (1 << ACIE); 2.112 /* in debug mode we want an interrupt both on rising and falling edge 2.113 * to be able to blink leds when the wheel goes past. otherwise we only need 2.114 * a rising edge interrupt to increment the rotation counter. 2.115 */ 2.116 - if(!debug_mode) { 2.117 - /* rising edge interrupt */ 2.118 - ACSR |= (3 << ACIS0); 2.119 - } 2.120 + /* rising edge interrupt */ 2.121 + /*ACSR |= (2 << ACIS0);*/ 2.122 + 2.123 + /* comparator interrupt enable */ 2.124 + ACSR |= (1 << ACIE); 2.125 2.126 sei(); 2.127 2.128 - for(;;); 2.129 + for(;;) { 2.130 + } 2.131 return 0; 2.132 } 2.133 2.134 +void init_timer(void) 2.135 +{ 2.136 + power_timer0_enable(); 2.137 + 2.138 + TCCR0A = 0; 2.139 + TCCR0B = PRESCL_256; 2.140 + 2.141 + /* enable timer overflow interrupt */ 2.142 + TIMSK0 = 1; 2.143 +} 2.144 + 2.145 void latch(int n) 2.146 { 2.147 - unsigned char upper = PORTB & 0xf0; 2.148 + unsigned char upper = PORTB & ~PB_CSEL_MASK; 2.149 /* pull latch low */ 2.150 PORTB = upper | n; 2.151 asm volatile("nop"); 2.152 @@ -108,25 +130,109 @@ 2.153 2.154 ISR(ANALOG_COMP_vect) 2.155 { 2.156 - if(debug_mode) { 2.157 - int state = (ACSR >> ACO) & 1; 2.158 + volatile static long prev_time; 2.159 + unsigned char aco; 2.160 + 2.161 + nop(); 2.162 + nop(); 2.163 + nop(); 2.164 + 2.165 + aco = (ACSR >> ACO) & 1; 2.166 + 2.167 + if(aco != state && (ticks - prev_time) > DEBOUNCE_TICKS) { 2.168 + state = aco; 2.169 2.170 if(state) { 2.171 - PORTB |= 1; 2.172 nrot++; 2.173 - } else { 2.174 - PORTB &= ~1; 2.175 + 2.176 + update_display(); 2.177 } 2.178 - } else { 2.179 - nrot++; 2.180 } 2.181 2.182 - update_display(); 2.183 + prev_time = ticks; 2.184 +} 2.185 + 2.186 +ISR(TIMER0_OVF_vect) 2.187 +{ 2.188 + volatile static int sec_ticks; 2.189 + volatile static unsigned long last_rot; 2.190 + 2.191 + ticks++; 2.192 + sec_ticks++; 2.193 + 2.194 + if(sec_ticks >= SEC_TICKS) { 2.195 + speed_rps = nrot - last_rot; 2.196 + 2.197 + update_display(); 2.198 + 2.199 + sec_ticks = 0; 2.200 + last_rot = nrot; 2.201 + } 2.202 + 2.203 + 2.204 + if(debug_mode) { 2.205 + unsigned char state = (ACSR >> ACO) & 1; 2.206 + if(state) { 2.207 + PORTD |= (1 << 5); 2.208 + } else { 2.209 + PORTD &= ~(1 << 5); 2.210 + } 2.211 + } 2.212 } 2.213 2.214 void update_display(void) 2.215 { 2.216 - unsigned long dist_cm = (nrot * WHEEL_PERIMETER); 2.217 + if(debug_mode) { 2.218 + disp_dist(nrot); 2.219 + disp_speed(speed_rps); 2.220 2.221 - /* TODO */ 2.222 + if(state) { 2.223 + PORTD |= (1 << 5); 2.224 + } else { 2.225 + PORTD &= ~(1 << 5); 2.226 + } 2.227 + } else { 2.228 + unsigned long dist_cm = (nrot * WHEEL_PERIMETER); 2.229 + int speed_kmh = RPS_TO_KMH(speed_rps); 2.230 + 2.231 + disp_dist(dist_cm / 10000); 2.232 + disp_speed(speed_kmh); 2.233 + disp_leds(speed_kmh * 8); 2.234 + } 2.235 } 2.236 + 2.237 +void disp_speed(int n) 2.238 +{ 2.239 + PORTD = (PORTD & ~PD_DATA_MASK) | (n % 10); 2.240 + latch(1); 2.241 + n /= 10; 2.242 + PORTD = (PORTD & ~PD_DATA_MASK) | (n % 10); 2.243 + latch(0); 2.244 +} 2.245 + 2.246 +void disp_dist(int n) 2.247 +{ 2.248 + PORTD = (PORTD & ~PD_DATA_MASK) | (n % 10); 2.249 + latch(4); 2.250 + n /= 10; 2.251 + PORTD = (PORTD & ~PD_DATA_MASK) | (n % 10); 2.252 + latch(3); 2.253 + n /= 10; 2.254 + PORTD = (PORTD & ~PD_DATA_MASK) | (n % 10); 2.255 + latch(2); 2.256 +} 2.257 + 2.258 +void disp_leds(int n) 2.259 +{ 2.260 + int i, count, bits; 2.261 + 2.262 + count = (n + 4) >> 5; 2.263 + bits = 0; 2.264 + 2.265 + for(i=0; i<count; i++) { 2.266 + bits |= (1 << i); 2.267 + } 2.268 + 2.269 + PORTC = bits; 2.270 + PORTD = (PORTD & PD_DATA_MASK) | ((bits & PD_LEDS_MASK) >> 2); 2.271 +}