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