post
poster: Xorm
description: borked ADC/servoPWM control
language: plain text
[download]
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);
   }

}