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