scoutece / forklift / code / analog.c @ 0bd4bb32
History | View | Annotate | Download (2.13 KB)
1 | 048ed7e1 | Tom Mullins | #include <avr/io.h> |
---|---|---|---|
2 | 0bd4bb32 | Tom Mullins | #include "analog.h" |
3 | |||
4 | int line_threshold = 150; |
||
5 | 048ed7e1 | Tom Mullins | |
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 | 0bd4bb32 | Tom Mullins | values[i] = line_read(i) < line_threshold ? LWHITE : LBLACK; |
66 | 048ed7e1 | Tom Mullins | } |
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 | 0bd4bb32 | Tom Mullins | |
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 | } |