Statistics
| Branch: | Revision:

root / 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
}