Revision 048ed7e1
Added analog.c for line following and linear pot
Most of the line following was copy-pasted from Colony 3. Still unsure
about prescaler, which used to be 2 for some reason but is now 64.
forklift/code/Makefile | ||
---|---|---|
4 | 4 |
%.hex: %.elf |
5 | 5 |
avr-objcopy -j .text -j .data -O ihex $< $@ |
6 | 6 |
|
7 |
forklift.elf: forklift.c twi.c twi.h |
|
8 |
avr-gcc -mmcu=atmega168 -DF_CPU=8000000L forklift.c twi.c -o forklift.elf -Os |
|
7 |
forklift.elf: forklift.c analog.c analog.h twi.c twi.h
|
|
8 |
avr-gcc -mmcu=atmega168 -DF_CPU=8000000L forklift.c analog.c twi.c -o forklift.elf -Os
|
|
9 | 9 |
|
10 | 10 |
download: forklift.hex |
11 | 11 |
avrdude -c avrispmkII -p m328p forklift.hex |
forklift/code/analog.c | ||
---|---|---|
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 |
} |
forklift/code/analog.h | ||
---|---|---|
1 |
#ifndef _ANALOG_H_ |
|
2 |
#define _ANALOG_H_ |
|
3 |
|
|
4 |
#define LWHITE 0 |
|
5 |
#define LGREY 1 |
|
6 |
#define LBLACK 2 |
|
7 |
#define CENTER 3 |
|
8 |
#define NOLINE -42 |
|
9 |
#define LINELOST -1 |
|
10 |
|
|
11 |
#define NOBARCODE -2 |
|
12 |
#define INTERSECTION -25 |
|
13 |
#define FULL_LINE -26 |
|
14 |
|
|
15 |
#define ADC_HEIGHT 0 |
|
16 |
#define ADC_LINE 1 |
|
17 |
|
|
18 |
void analog_init(void); |
|
19 |
int analog_read(int which); |
|
20 |
int line_read_pos(void); |
|
21 |
|
|
22 |
#endif |
forklift/code/forklift.c | ||
---|---|---|
12 | 12 |
*/ |
13 | 13 |
|
14 | 14 |
#include "twi.h" |
15 |
#include "analog.h" |
|
15 | 16 |
|
16 | 17 |
#define TRACKING_ID 0x41 |
17 | 18 |
#define SERIAL_NUMBER 0x12 |
... | ... | |
21 | 22 |
#define FORKLIFT_SERIAL_NUMBER 1 |
22 | 23 |
#define FORKLIFT_HEIGHT 2 |
23 | 24 |
#define FORKLIFT_HEIGHT_SETPOINT 3 // only one that's r/w |
24 |
#define FORKLIFT_FORCE 4
|
|
25 |
#define FORKLIFT_LINEPOS 4
|
|
25 | 26 |
|
26 | 27 |
#define FORKLIFT_DATA_LEN 5 |
27 | 28 |
|
... | ... | |
58 | 59 |
twi_setAddress(TRACKING_ID); |
59 | 60 |
twi_attachSlaveRxEvent(slave_rx); |
60 | 61 |
twi_attachSlaveTxEvent(slave_tx); |
62 |
analog_init(); |
|
61 | 63 |
while (1) |
62 | 64 |
{ |
63 | 65 |
// do motor stuff |
66 |
internal_data[FORKLIFT_LINEPOS] = line_read_pos(); |
|
67 |
internal_data[FORKLIFT_HEIGHT] = analog_read(ADC_HEIGHT); |
|
64 | 68 |
} |
65 | 69 |
return 0; |
66 | 70 |
} |
Also available in: Unified diff