scoutece / forklift / code / analog.c @ 048ed7e1
History | View | Annotate | Download (1.84 KB)
1 |
#include <avr/io.h> |
---|---|
2 |
#include "analog.h" |
3 |
|
4 |
int line_read(int which); |
5 |
void line_update(int* values); |
6 |
int line_locate(int* values); |
7 |
|
8 |
void analog_init(void) |
9 |
{ |
10 |
// ADMUX register
|
11 |
// Bit 7,6 - Set voltage reference to AVcc (0b01)
|
12 |
// Bit 5 - ADLAR not set
|
13 |
// Bit 4 - X
|
14 |
// Bit 3:0 - Current channel
|
15 |
ADMUX = _BV(REFS0); |
16 |
|
17 |
// ADC Status Register A
|
18 |
// Bit 7 - ADEN analog enable set
|
19 |
// Bit 6 - ADSC start conversion bit not set
|
20 |
// Bit 5 - ADATE enable auto trigger (for free running mode) not set
|
21 |
// Bit 4 - ADIF ADC interrupt flag
|
22 |
// Bit 3 - ADIE enable ADC interrupt (required for free-running mode)
|
23 |
// Bits 2-0 - ADPS set to 8 MHz / 64 = 125 kHz (should be 50-200 kHz)
|
24 |
ADCSRA = _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1); |
25 |
|
26 |
// Set line sensor mux lines PD2, PD3, and PB3 (MOSI) to output
|
27 |
DDRD |= _BV(DDD2) | _BV(DDD3); |
28 |
DDRB |= _BV(DDB3); |
29 |
} |
30 |
|
31 |
int analog_read(int which) |
32 |
{ |
33 |
ADMUX = (ADMUX & 0xF0) | (which & 0x0F); |
34 |
|
35 |
// Start the conversion
|
36 |
ADCSRA |= _BV(ADSC); |
37 |
|
38 |
// Wait for the conversion to finish
|
39 |
while (ADCSRA & _BV(ADSC));
|
40 |
|
41 |
int adc_l = ADCL;
|
42 |
int adc_h = ADCH;
|
43 |
|
44 |
return ((adc_h << 8) | adc_l); |
45 |
} |
46 |
|
47 |
int line_read(int which) |
48 |
{ |
49 |
PORTD = (PORTD & 0xF3) | ((which & 3) << 2); |
50 |
PORTB = (PORTB & 0XF7) | ((which & 4) << 1); |
51 |
|
52 |
// For loop is used only as a delay to allow mux to settle
|
53 |
volatile int i; |
54 |
for(i=0; i < 5; i++); |
55 |
|
56 |
return analog_read(ADC_LINE);
|
57 |
} |
58 |
|
59 |
void line_update(int* values) |
60 |
{ |
61 |
int i;
|
62 |
for(i = 0; i<5; i++) |
63 |
values[i] = line_read(i) < 150 ? LWHITE : LBLACK;
|
64 |
} |
65 |
|
66 |
int line_locate(int* values) |
67 |
{ |
68 |
int i;
|
69 |
int wsum = 0; |
70 |
int count = 0; |
71 |
|
72 |
for(i = 0; i < 5; i++) |
73 |
{ |
74 |
count += values[i] / 2;
|
75 |
wsum += i * values[i]; |
76 |
} |
77 |
if (count == 0) |
78 |
return NOLINE;
|
79 |
if (count == 5) |
80 |
return FULL_LINE;
|
81 |
return (wsum/count)-4; |
82 |
} |
83 |
|
84 |
int line_read_pos(void) |
85 |
{ |
86 |
int values[5]; |
87 |
line_update(values); |
88 |
return line_locate(values);
|
89 |
} |