I'm trying to develop an application in atmel studio 7.0 which will allow me to control the speed of my servo motor with my potentiometer. Now, the problem is that I don't really know how to do that? Also my servo motor spins around and around instead of going 0 -> 45 -> 90 degrees and then back the same way again. I've managed to do a successfull convertion of analog signals to use, and I've set my admux input channel to 2; also, my pwm channel is 10 for the servo motor. I use an Arduino Uno with Atmega328P processor with 16 000 000 Hz.

Might also say I'm pretty new to the use of PWM, which is why this would be an exciting thing to do.

Heres the code this far:

void initPWM();
void initADC();
uint16_t doConversion(void);

int main(void)
    DDRD = 0b11111111;
    DDRB = 0xFF;

    while (1)
      PORTB = 0b00000100;
      OCR1A=250;   //0 degree

      OCR1A=375;  //45 degree

      OCR1A=500;  //90 degree


      OCR1A = 0;


void initPWM(){
   TCCR1A|=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM11);        //NON Inverted PWM
   TCCR1B|=(1<<WGM13)|(1<<WGM12)|(1<<CS11)|(1<<CS10); //PRESCALER=64 MODE 14(FAST PWM)
    ICR1 = 4999 ; // 50 Hz 

void initADC(void) {
    // Configure the ADC module
    ADMUX = 0b11000010; //Set channel 2
    // REFS1:0 = 01 -> AVCC as reference,
    // ADLAR = 1 -> Leftadjust
    // MUX4:0 = 00000 -> ADC0 as input
    ADCSRA = 0b10000111;
    //ADEN = 1: enableADC,
    // ADSC = 0: don't start conversion yet
    // ASPS2:0 = 001: pre-scaler= 2
    // ADATE = 0: disable auto trigger,
    // ADIE = 0: disableADC interrupt

uint16_t doConversion(void){
    uint16_t result;
    // Start conversion by setting flag ADSC
    ADCSRA |= (1 << ADSC);
    // Wait until conversion is  completed
    while(ADCSRA & (1 << ADSC));
    // Read the all bits, output to PORTB
    result= ADC;
    return result;

I used 4999 as the value for ICR1 since I have a 16000000 Hz CPU and use a prescaler of 64.

My servo motors degrees are based on the following: 0 degrees = 1000 microseconds 45 degrees = 1500 microseconds 90 degrees = 2000 microseconds

PORTB is for using the pwm, and the potentiometer is connected to channel 2.

Does anyone know what I did wrong? Or can help me solve/accomplish what I'm trying to do?

  • \$\begingroup\$ Post a link to a data sheet or product page on your servo motor. If you bought a hobbyist "servo motor" then you have an RC servo that expects a PWM command. If you bought an industrial "servo motor" then you have a bare DC motor optimized for servo use, or a "smart servo motor" with a built in driver that probably takes an up/down comand and a pulse, but may take something else. RC servo motors usually have a mechanical range of around 270 degrees, and don't spin "around and around". \$\endgroup\$ – TimWescott Jun 10 at 17:57
  • \$\begingroup\$ wiki.keyestudio.com/… I'm using the one that can be seen here. Which would be identified as a hobbyist (9G servo motor). And the potentionmeter is a 10k ohm one. The servo motor also have built-in-reference circuit which gives out a reference signal , cycle of 20ms and width of 1.5ms \$\endgroup\$ – wazev Jun 10 at 18:00
  • \$\begingroup\$ Do you have an oscilloscope that you can use to verify the PWM to the servo? It should be a 1ms - 2ms pulse once every 16 to 20 ms. \$\endgroup\$ – TimWescott Jun 10 at 18:08
  • \$\begingroup\$ I get a correct analog input signal, and the servo motor rotates (around and around). And when I checked this the other day when I had an oscilloscope (which I sadly don't have on me today), I got the correct pulse/wave, yes. \$\endgroup\$ – wazev Jun 10 at 18:13
  • 1
    \$\begingroup\$ Try another servo! It's a hobby shop item (called just "servo" in all the English-speaking countries I know of). If you know what to look for it may be as close as the nearest discarded RC plane, boat or car. \$\endgroup\$ – TimWescott Jun 10 at 18:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.