Project

General

Profile

Revision 048ed7e1

ID048ed7e1dbde71a25f5c2a6633de8ea027828dd5

Added by Thomas Mullins about 12 years ago

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.

View differences:

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