Monday, June 29, 2020

Using ADC and Timer/Counter 0 PWM of ATMega32 to rotate a DC servo motor

DC Servo Motor

A typical DC servo motor could rotate using a controlling pulse with a period of 50 Hz (20 milli seconds period). The duty cycle or high time is between 1 milli second to 2 milli seconds, with the corresponding rotating angle between -90 to +90 degree (180 degree in total).

Using ADC and Timer/Counter 0 PWM of ATMega32 to rotate a DC servo motor


Here, I use timer and counter 0 module of ATMega32 to create a PWM signal in phase correction mode. The frequency is 122 Hz regardless of the DC servo standard timing requirement. 

Using ADC and Timer/Counter 0 PWM of ATMega32 to rotate a DC servo motor
A sample of program

The clock fed to the CPU is 4 MHz. The timer/counter 0 prescaler is 1:64. The PWM frequency of phase correction mode is 4MHz/(64*510) which is 122.54 Hz. The period is 816 milli seconds.

For OCR0 step timing is (816 milli seconds)/256 is 31 micro seconds. To get a one milli second high time, OCR0 must be loaded 31. To get a two milli seconds high pulse, we must load OCR0 with 62 or 63. Hence OCR0 is varied between 31 to 63 to make the DC servo rotate at any angles.

The angle is get from the analog value from a POT fed to ADC7. The 10-bit (1024) ADC value is scaled to a decimal value of 32 as referred above.

Atmel Studio 7 C Coding

The AVR C source code is implemented as below.

#include <avr/io.h>
int main(void)
{
 unsigned int adcResult,adcOld=0;
 //PA0 or ADC0 as an analog input
 DDRA=0;
 //PWM OUT
 DDRB|=(1<<3);
 /*Turn on the ADC module
 ADC Clock divided by 128
 */
 ADCSRA|=(1<<ADEN)|0x07;
 ADMUX|=0x07;
 /*Set phase correct PWM mode with non
 inverting output
 */
 TCCR0|=(1<<COM01)|(1<<WGM00)|(1<<CS01)|(1<<CS00);
 //select 1:64 pre-scaler
 //TCCR0|=(1<<CS01)|(1<<CS00);
 while (1)
 {
  //Start the conversion
  ADCSRA|=(1<<ADSC);
  //Wait for the completion
  while((ADCSRA&(1<<ADSC))==1);
  
  adcResult=ADCL+(ADCH<<8);
  if(adcResult!=adcOld)
   OCR0=((adcResult*32)/1024)+31;
  adcOld=adcResult;
 }
}

Using ADC and Timer/Counter 0 PWM of ATMega32 to rotate a DC servo motor
Schematic diagram





Click here to download its source file.

1 comment:

  1. Hello, thank you for your explanations and your code.
    I have a few questions that I would appreciate if you could clarify:
    1- Why did you choose 1024? Shouldn't it be 1023?
    2- I would appreciate it if you could explain further about the numbers 32 and 31 and how you selected them.
    3- I ran the program, and the servo motor angle is set to 180 degrees. However, it doesn't change when I adjust the potentiometer. Why is that?

    ReplyDelete

Search This Blog

Labels

25AA010A (1) 8051 (7) 93AA46B (1) ADC (30) Analog Comparator (1) Arduino (15) ARM (6) AT89C52 (7) ATMega32 (54) AVR (57) CCS PICC (28) DAC (1) DHT11 (2) Display (105) Distance Sensor (3) DS18B20 (3) dsPIC (2) dsPIC30F1010 (2) EEPROM (5) Environment Sensor (4) esp8266 (1) I2C (29) Input/Output (67) Interrupt (19) Keil (5) Keypad (10) LCD (46) Master/Slave (1) MAX7221 (1) MCP23017 (5) MCP23S17 (4) Meter (3) MikroC (2) Motor (15) MPLABX (66) Nokia 5110 LCD (3) OLED (2) One-Wire (6) Oscillator (8) PCB (6) PCD8544 (3) PCF8574 (5) PIC (107) PIC12F (2) PIC16F628A (2) PIC16F630 (1) PIC16F716 (3) PIC16F818 (10) PIC16F818/819 (2) PIC16F84A (15) PIC16F876A (1) PIC16F877A (9) PIC16F88 (1) PIC16F887 (60) PIC18 (19) PIC18F1220 (4) PIC18F2550 (3) PIC18F4550 (12) PWM (11) RTC (8) Sensor (10) SH1106 (1) Shift Register (11) Shift Registers (2) SPI (24) STM32 (6) STM32 Blue Pill (6) STM32CubeIDE (6) STM32F103C8T6 (6) SysTick (3) temperature sensor (11) Thermometer (21) Timer/Counter (30) TM1637 (2) UART (7) Ultrasonic (4) Voltmeter (7) WDT (1) XC16 (2) XC8 (94)