Project

General

Profile

Revision 048ed7e1

ID048ed7e1dbde71a25f5c2a6633de8ea027828dd5
Parent a675468b
Child bc628a35

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