1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
// doesn't work. why isn't pwm taking assignment when I do
// pwm = 650+(5*adc_result);
// in the main loop?
#define F_CPU 8000000
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
static int pwm = 1500;
int sevsegnum[10] = { 0b11000000, 0b11111001, 0b10100100, 0b10110000, 0b10011001,
0b10010010, 0b10000010, 0b11111000, 0b10000000, 0b10011000 };
void InitADC(void)
{
ADMUX=(1<<REFS0)|(1<<ADLAR); // For Aref=AVcc;
ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); //Rrescalar div factor =128
}
uint16_t ReadADC(uint8_t ch)
{
//Select ADC Channel ch must be 0-7
ch=ch&0b00000111;
ADMUX|=ch;
//Start Single conversion
ADCSRA|=(1<<ADSC);
//Wait for conversion to complete
while(!(ADCSRA & (1<<ADIF)));
//Clear ADIF by writing one to it
//Note you may be wondering why we have write one to clear it
//This is standard way of clearing bits in io as said in datasheets.
//The code writes '1' but it result in setting bit to '0' !!!
ADCSRA|=(1<<ADIF);
return(ADCH);
}
void init_servos(void)
{
TIMSK = _BV(OCIE1A);
TCCR1B = _BV(CS11) // sysclk/8 prescale: convenient @ sysclk 8MHZ
// because it means 1 tick/us
// with a 16 bit timer MAXOCR1A is 65536 or 65ms
// while our max cycle time should be 20ms... it fits!
| _BV(WGM12); // CTC mode, TOP = OCR1A
OCR1A = 1500; // count up to TOP
}
int pwm_mode = 0;
ISR (SIG_OUTPUT_COMPARE1A)
{
// pulse duration
if (pwm_mode == 0){
PORTD = 0xFF;
pwm_mode=1;
OCR1A = pwm;
}
//off duration
else
{
PORTD = 0x00;
pwm_mode=0;
OCR1A = 15000;
}
}
int main(void)
{
DDRB = 0xFF;
DDRD = 0xFF;
int adc_result;
PORTD = 0xff;
//Initialize ADC
InitADC();
init_servos();
sei();
while(1)
{
adc_result=ReadADC(7); // Read Analog value from channel-7
pwm = 650+(5*adc_result);
PORTB = sevsegnum[(adc_result/21)-2];
// _delay_ms(64);
}
}
|