Statistics
| Branch: | Revision:

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