Revision 1924
Fixed line following readings, addded 1ms delay to fix the mux.
analog.c | ||
---|---|---|
74 | 74 |
* |
75 | 75 |
**/ |
76 | 76 |
void analog_init(int start_conversion) { |
77 |
start_conversion=0; //forces the analog loop off
|
|
78 |
for (int i = 0; i < 11; i++) {
|
|
79 |
an_val[i].adc10 = 0;
|
|
80 |
an_val[i].adc8 = 0;
|
|
81 |
}
|
|
77 |
start_conversion=0; //forces the analog loop off
|
|
78 |
for (int i = 0; i < 11; i++) {
|
|
79 |
an_val[i].adc10 = 0;
|
|
80 |
an_val[i].adc8 = 0;
|
|
81 |
}
|
|
82 | 82 |
|
83 |
// ADMUX register
|
|
84 |
// Bit 7,6 - Set voltage reference to AVcc (0b01)
|
|
85 |
// Bit 5 - ADLAR set to simplify moving from register
|
|
86 |
// Bit 4 - X
|
|
87 |
// Bit 3:0 - Sets the current channel
|
|
88 |
// Initializes to read from AN1 first (AN0 is reservered for the BOM)
|
|
89 |
ADMUX = 0;
|
|
90 |
ADMUX |= ADMUX_OPT | _BV(MUX0);
|
|
83 |
// ADMUX register
|
|
84 |
// Bit 7,6 - Set voltage reference to AVcc (0b01)
|
|
85 |
// Bit 5 - ADLAR set to simplify moving from register
|
|
86 |
// Bit 4 - X
|
|
87 |
// Bit 3:0 - Sets the current channel
|
|
88 |
// Initializes to read from AN1 first (AN0 is reservered for the BOM)
|
|
89 |
ADMUX = 0;
|
|
90 |
ADMUX |= ADMUX_OPT | _BV(MUX0);
|
|
91 | 91 |
|
92 |
// ADC Status Register A |
|
93 |
// Bit 7 - ADEN is set (enables analog) |
|
94 |
// Bit 6 - Start conversion bit is set (must be done once for free-running mode) |
|
95 |
// Bit 5 - Enable Auto Trigger (for free running mode) NOT DOING THIS RIGHT NOW |
|
96 |
// Bit 4 - ADC interrupt flag, 0 |
|
97 |
// Bit 3 - Enable ADC Interrupt (required to run free-running mode) |
|
98 |
// Bits 2-0 - Set to create a clock divisor of 2, to make ADC clock != 8,000,000/64 = 125kHz (it runs at highest frequency) |
|
99 |
ADCSRA = 0; |
|
100 |
ADCSRA |= _BV(ADEN) | /*_BV(ADPS2) | _BV(ADPS1) |*/ _BV(ADPS0); |
|
101 |
|
|
102 |
// Set external mux lines to outputs |
|
103 |
DDRG |= 0x1C; |
|
92 |
// ADC Status Register A |
|
93 |
// Bit 7 - ADEN is set (enables analog) |
|
94 |
// Bit 6 - Start conversion bit is set (must be done once for free-running mode) |
|
95 |
// Bit 5 - Enable Auto Trigger (for free running mode) NOT DOING THIS RIGHT NOW |
|
96 |
// Bit 4 - ADC interrupt flag, 0 |
|
97 |
// Bit 3 - Enable ADC Interrupt (required to run free-running mode) |
|
98 |
// Bits 2-0 - Set to create a clock divisor of 2, to make ADC clock != 8,000,000/64 = 125kHz (it runs at highest frequency) |
|
99 |
ADCSRA = 0; |
|
100 |
ADCSRA |= _BV(ADEN) | /*_BV(ADPS2) | _BV(ADPS1) |*/ _BV(ADPS0); |
|
104 | 101 |
|
105 |
// Set line sensor mux lines to output. Uses LCD/SPI header
|
|
106 |
DDRD |=0xE0;
|
|
102 |
// Set external mux lines to outputs
|
|
103 |
DDRG |= 0x1C;
|
|
107 | 104 |
|
108 |
// Set up first port for conversions |
|
109 |
set_adc_mux(0x00); |
|
110 |
adc_current_port = AN1; |
|
105 |
// Set line sensor mux lines to output. Uses LCD/SPI header |
|
106 |
DDRD |=0xE0; |
|
111 | 107 |
|
112 |
//Start the conversion loop if requested |
|
113 |
if (start_conversion) |
|
114 |
analog_start_loop(); |
|
115 |
|
|
116 |
//Conversion loop disabled by default |
|
108 |
// Set up first port for conversions |
|
109 |
set_adc_mux(0x00); |
|
110 |
adc_current_port = AN1; |
|
111 |
|
|
112 |
//Start the conversion loop if requested |
|
113 |
if (start_conversion) |
|
114 |
analog_start_loop(); |
|
115 |
|
|
116 |
//Conversion loop disabled by default |
|
117 | 117 |
} |
118 | 118 |
|
119 | 119 |
/** |
... | ... | |
136 | 136 |
* @see analog10, analog_get8, analog_get10 |
137 | 137 |
**/ |
138 | 138 |
unsigned int analog8(int which) { |
139 |
/* if (which == BOM_PORT) { |
|
140 |
return 0;
|
|
141 |
} else {
|
|
142 |
return an_val[which - 1].adc8;
|
|
143 |
}
|
|
144 |
*/ |
|
145 |
return analog_get8(which); |
|
139 |
/* if (which == BOM_PORT) {
|
|
140 |
return 0;
|
|
141 |
} else {
|
|
142 |
return an_val[which - 1].adc8;
|
|
143 |
}
|
|
144 |
*/
|
|
145 |
return analog_get8(which);
|
|
146 | 146 |
} |
147 | 147 |
|
148 | 148 |
/** |
... | ... | |
165 | 165 |
* @see analog8, analog_get8, analog_get10 |
166 | 166 |
**/ |
167 | 167 |
unsigned int analog10(int which) { |
168 |
/* if (which == BOM_PORT) { |
|
169 |
return 0;
|
|
170 |
} else {
|
|
171 |
return an_val[which - 1].adc10;
|
|
172 |
}
|
|
173 |
*/ |
|
174 |
return analog_get10(which); |
|
168 |
/* if (which == BOM_PORT) {
|
|
169 |
return 0;
|
|
170 |
} else {
|
|
171 |
return an_val[which - 1].adc10;
|
|
172 |
}
|
|
173 |
*/
|
|
174 |
return analog_get10(which);
|
|
175 | 175 |
} |
176 | 176 |
|
177 | 177 |
/** |
... | ... | |
181 | 181 |
* @see analog_stop_loop, analog_loop_status |
182 | 182 |
**/ |
183 | 183 |
void analog_start_loop(void) { |
184 |
if(adc_loop_status != ADC_LOOP_RUNNING){
|
|
185 |
//Start the conversion, enable ADC interrupt
|
|
186 |
ADCSRA |= _BV(ADIE);
|
|
187 |
ADCSRA |= _BV(ADSC);
|
|
188 |
adc_loop_status = ADC_LOOP_RUNNING;
|
|
189 |
}
|
|
184 |
if(adc_loop_status != ADC_LOOP_RUNNING){
|
|
185 |
//Start the conversion, enable ADC interrupt
|
|
186 |
ADCSRA |= _BV(ADIE);
|
|
187 |
ADCSRA |= _BV(ADSC);
|
|
188 |
adc_loop_status = ADC_LOOP_RUNNING;
|
|
189 |
}
|
|
190 | 190 |
} |
191 | 191 |
|
192 | 192 |
/** |
... | ... | |
198 | 198 |
* @see analog_start_loop, analog_loop_status |
199 | 199 |
**/ |
200 | 200 |
void analog_stop_loop() { |
201 |
//Signal to stop after the next conversion
|
|
202 |
adc_sig_stop_loop = 1;
|
|
201 |
//Signal to stop after the next conversion
|
|
202 |
adc_sig_stop_loop = 1;
|
|
203 | 203 |
} |
204 | 204 |
|
205 | 205 |
/** |
... | ... | |
209 | 209 |
* @see analog_start_loop, analog_stop_loop |
210 | 210 |
**/ |
211 | 211 |
int analog_loop_status(void) { |
212 |
return adc_loop_status;
|
|
212 |
return adc_loop_status;
|
|
213 | 213 |
} |
214 | 214 |
|
215 | 215 |
/** |
... | ... | |
230 | 230 |
* analog_start_loop |
231 | 231 |
**/ |
232 | 232 |
unsigned int analog_get8(int which) { |
233 |
// Let any previous conversion finish |
|
234 |
while (ADCSRA & _BV(ADSC)); |
|
235 |
|
|
236 |
if(which < EXT_MUX) { |
|
237 |
ADMUX = ADMUX_OPT + which; |
|
238 |
} else { |
|
239 |
ADMUX = ADMUX_OPT + EXT_MUX; |
|
240 |
set_adc_mux(which - 8); |
|
241 |
} |
|
242 |
|
|
243 |
// Start the conversion |
|
244 |
ADCSRA |= _BV(ADSC); |
|
233 |
// Let any previous conversion finish |
|
234 |
while (ADCSRA & _BV(ADSC)); |
|
245 | 235 |
|
246 |
// Wait for the conversion to finish |
|
247 |
while (ADCSRA & _BV(ADSC)); |
|
236 |
if(which < EXT_MUX) { |
|
237 |
ADMUX = ADMUX_OPT + which; |
|
238 |
} else { |
|
239 |
ADMUX = ADMUX_OPT + EXT_MUX; |
|
240 |
set_adc_mux(which - 8); |
|
241 |
} |
|
248 | 242 |
|
249 |
return ADCH; //since we left aligned the data, ADCH is the 8 MSB. |
|
243 |
// Start the conversion |
|
244 |
ADCSRA |= _BV(ADSC); |
|
245 |
|
|
246 |
// Wait for the conversion to finish |
|
247 |
while (ADCSRA & _BV(ADSC)); |
|
248 |
|
|
249 |
return ADCH; //since we left aligned the data, ADCH is the 8 MSB. |
|
250 | 250 |
} |
251 | 251 |
|
252 | 252 |
/** |
... | ... | |
268 | 268 |
* analog_start_loop |
269 | 269 |
**/ |
270 | 270 |
unsigned int analog_get10(int which) { |
271 |
int adc_h; |
|
272 |
int adc_l; |
|
273 |
|
|
274 |
// Let any previous conversion finish |
|
275 |
while (ADCSRA & _BV(ADSC)); |
|
271 |
int adc_h; |
|
272 |
int adc_l; |
|
276 | 273 |
|
277 |
if(which < EXT_MUX) { |
|
278 |
ADMUX = ADMUX_OPT + which; |
|
279 |
} else { |
|
280 |
ADMUX = ADMUX_OPT + EXT_MUX; |
|
281 |
set_adc_mux(which - 8); |
|
282 |
} |
|
283 |
|
|
284 |
// Start the conversion |
|
285 |
ADCSRA |= _BV(ADSC); |
|
274 |
// Let any previous conversion finish |
|
275 |
while (ADCSRA & _BV(ADSC)); |
|
286 | 276 |
|
287 |
// Wait for the conversion to finish |
|
288 |
while (ADCSRA & _BV(ADSC)); |
|
289 |
|
|
290 |
adc_l = ADCL; |
|
291 |
adc_h = ADCH; |
|
277 |
if(which < EXT_MUX) { |
|
278 |
ADMUX = ADMUX_OPT + which; |
|
279 |
} else { |
|
280 |
ADMUX = ADMUX_OPT + EXT_MUX; |
|
281 |
set_adc_mux(which - 8); |
|
282 |
} |
|
292 | 283 |
|
293 |
return ((adc_h << 2) | (adc_l >> 6)); |
|
284 |
// Start the conversion |
|
285 |
ADCSRA |= _BV(ADSC); |
|
286 |
|
|
287 |
// Wait for the conversion to finish |
|
288 |
while (ADCSRA & _BV(ADSC)); |
|
289 |
|
|
290 |
adc_l = ADCL; |
|
291 |
adc_h = ADCH; |
|
292 |
|
|
293 |
return ((adc_h << 2) | (adc_l >> 6)); |
|
294 | 294 |
} |
295 | 295 |
|
296 | 296 |
|
297 | 297 |
/** Returns the 10 bit value from the line sensors **/ |
298 | 298 |
unsigned int read_line(int which) { |
299 |
int adc_h; |
|
300 |
int adc_l; |
|
301 |
|
|
302 |
// Let any previous conversion finish |
|
303 |
while (ADCSRA & _BV(ADSC)); |
|
299 |
int adc_h; |
|
300 |
int adc_l; |
|
304 | 301 |
|
305 |
ADMUX = ADMUX_OPT + AN1; |
|
302 |
// Let any previous conversion finish |
|
303 |
while (ADCSRA & _BV(ADSC)); |
|
306 | 304 |
|
307 |
// which = (which&1)<<2 + (which&2) + (which&4)>>2; |
|
308 |
|
|
309 |
// mask so only proper bits are possible. |
|
310 |
PORTD = (PORTD & 0x1F) | ((which & 0x07) << 5); |
|
311 |
// Start the conversion |
|
312 |
ADCSRA |= _BV(ADSC); |
|
305 |
ADMUX = ADMUX_OPT + AN1; |
|
313 | 306 |
|
314 |
// Wait for the conversion to finish |
|
315 |
while (ADCSRA & _BV(ADSC)); |
|
316 |
|
|
317 |
adc_l = ADCL; |
|
318 |
adc_h = ADCH; |
|
307 |
which = ((which&1)<<2) + ((which&2)) + ((which&4)>>2); |
|
319 | 308 |
|
320 |
return ((adc_h << 2) | (adc_l >> 6)); |
|
309 |
// mask so only proper bits are possible. |
|
310 |
PORTD = (PORTD & 0x1F) | ((which & 0x07) << 5); |
|
321 | 311 |
|
312 |
delay_ms(1); |
|
313 |
|
|
314 |
// Start the conversion |
|
315 |
ADCSRA |= _BV(ADSC); |
|
316 |
|
|
317 |
// Wait for the conversion to finish |
|
318 |
while (ADCSRA & _BV(ADSC)); |
|
319 |
|
|
320 |
adc_l = ADCL; |
|
321 |
adc_h = ADCH; |
|
322 |
|
|
323 |
return ((adc_h << 2) | (adc_l >> 6)); |
|
324 |
|
|
322 | 325 |
} |
323 | 326 |
|
324 | 327 |
|
... | ... | |
335 | 338 |
* @see analog_init |
336 | 339 |
**/ |
337 | 340 |
int wheel(void) { |
338 |
return analog8(WHEEL_PORT);
|
|
341 |
return analog8(WHEEL_PORT);
|
|
339 | 342 |
} |
340 | 343 |
|
341 | 344 |
|
... | ... | |
354 | 357 |
* @see analog_init |
355 | 358 |
**/ |
356 | 359 |
void set_adc_mux(int which) { |
357 |
// mask so only proper bits are possible. |
|
358 |
PORTG = (PORTG & 0xE3) | ((which & 0x03) << 3) | (which & 0x04); |
|
360 |
// mask so only proper bits are possible.
|
|
361 |
PORTG = (PORTG & 0xE3) | ((which & 0x03) << 3) | (which & 0x04);
|
|
359 | 362 |
} |
360 | 363 |
|
361 | 364 |
/**@}**/ //end defgroup |
362 | 365 |
|
363 | 366 |
|
364 | 367 |
ISR(ADC_vect) { |
365 |
int adc_h = 0; |
|
366 |
int adc_l = 0; |
|
367 |
|
|
368 |
if(adc_loop_status != ADC_LOOP_RUNNING) return; |
|
368 |
int adc_h = 0; |
|
369 |
int adc_l = 0; |
|
369 | 370 |
|
370 |
//Store the value only if this read isn't for the BOM |
|
371 |
if (ADMUX != BOM_PORT) { |
|
372 |
adc_l = ADCL; |
|
373 |
adc_h = ADCH; |
|
374 |
|
|
375 |
an_val[adc_current_port - 1].adc10 = (adc_h << 2) | (adc_l >> 6); |
|
376 |
an_val[adc_current_port - 1].adc8 = adc_h; |
|
377 |
} |
|
378 |
|
|
379 |
//Skip AN7 because it is not a real port |
|
380 |
if (adc_current_port == AN6) { |
|
381 |
ADMUX = ADMUX_OPT | EXT_MUX; |
|
382 |
set_adc_mux(AN8 - 8); |
|
383 |
adc_current_port = AN8; |
|
384 |
//Wrap around |
|
385 |
} else if (adc_current_port == AN11) { |
|
386 |
adc_current_port = AN1; |
|
387 |
ADMUX = ADMUX_OPT | adc_current_port; |
|
388 |
//Normal increment |
|
389 |
} else { |
|
390 |
adc_current_port++; |
|
391 |
|
|
392 |
if(adc_current_port < EXT_MUX) { |
|
393 |
ADMUX = ADMUX_OPT | adc_current_port; |
|
394 |
} else { |
|
395 |
ADMUX = ADMUX_OPT | EXT_MUX; |
|
396 |
set_adc_mux(adc_current_port - 8); |
|
397 |
} |
|
398 |
} |
|
371 |
if(adc_loop_status != ADC_LOOP_RUNNING) return; |
|
399 | 372 |
|
400 |
//Stop loop if signal is set |
|
401 |
if(adc_sig_stop_loop) { |
|
402 |
adc_sig_stop_loop = 0; |
|
403 |
adc_loop_status = ADC_LOOP_STOPPED; |
|
404 |
return; |
|
405 |
} |
|
406 |
|
|
407 |
//Start next conversion |
|
408 |
ADCSRA |= _BV(ADSC); |
|
373 |
//Store the value only if this read isn't for the BOM |
|
374 |
if (ADMUX != BOM_PORT) { |
|
375 |
adc_l = ADCL; |
|
376 |
adc_h = ADCH; |
|
377 |
|
|
378 |
an_val[adc_current_port - 1].adc10 = (adc_h << 2) | (adc_l >> 6); |
|
379 |
an_val[adc_current_port - 1].adc8 = adc_h; |
|
380 |
} |
|
381 |
|
|
382 |
//Skip AN7 because it is not a real port |
|
383 |
if (adc_current_port == AN6) { |
|
384 |
ADMUX = ADMUX_OPT | EXT_MUX; |
|
385 |
set_adc_mux(AN8 - 8); |
|
386 |
adc_current_port = AN8; |
|
387 |
//Wrap around |
|
388 |
} else if (adc_current_port == AN11) { |
|
389 |
adc_current_port = AN1; |
|
390 |
ADMUX = ADMUX_OPT | adc_current_port; |
|
391 |
//Normal increment |
|
392 |
} else { |
|
393 |
adc_current_port++; |
|
394 |
|
|
395 |
if(adc_current_port < EXT_MUX) { |
|
396 |
ADMUX = ADMUX_OPT | adc_current_port; |
|
397 |
} else { |
|
398 |
ADMUX = ADMUX_OPT | EXT_MUX; |
|
399 |
set_adc_mux(adc_current_port - 8); |
|
400 |
} |
|
401 |
} |
|
402 |
|
|
403 |
//Stop loop if signal is set |
|
404 |
if(adc_sig_stop_loop) { |
|
405 |
adc_sig_stop_loop = 0; |
|
406 |
adc_loop_status = ADC_LOOP_STOPPED; |
|
407 |
return; |
|
408 |
} |
|
409 |
|
|
410 |
//Start next conversion |
|
411 |
ADCSRA |= _BV(ADSC); |
|
409 | 412 |
} |
410 | 413 |
|
Also available in: Unified diff