Multiple servo control with ATmega 328p

Go To Last Post
10 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

 

Hello friends, I am doing a control of multiple servos in port B of the ATmega328p, but it is with potentiometers.

 

The code below works fine without potentiometers, my duty cyle is 0.5 to 2.5 ms (1000-5000)

 

 

This topic has a solution.
Last Edited: Wed. Apr 15, 2020 - 04:24 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

will98cf wrote:

 1<<ADPS2 | 1<<ADPS1| 0<<ADPS0 ;  // AVCC with external capacitor at AREF pin,  64 prescaler

At 16MHz, you will need /128 prescaler to run the ADC in spec

 

OCR1n sets the duty cycle for PWM, no need to touch TCNT1, read your pot and set the OCR1n register to change duty cycle, some thing similar to this:

pot_value = ADC_read_ch(0);    //read ADC(0) voltage from poteniometer
OCR1A = pot_value;             //set PWM value (Dim an LED! or servo)

You still need to scale your pot_value to limit OCR1x to the correct range (1-2ms pulse every 20ms)

 

Jim

 

 

 

 

 

 

 

Last Edited: Tue. Apr 7, 2020 - 08:14 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

 

Last Edited: Wed. Apr 15, 2020 - 04:24 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Here is some code I had that drives two servos, this uses fixed positions, but all you have to do is call the function to read your ADC channels in place of using the fixed values shown.

// 2_servos.c
// Controling two servos, connected to PB1, PB2
// Atmega8,88,168,328 F_CPU = 8 MHz

#include <avr/io.h>
#include <util/delay.h>         

//---------------------------------------------------------------------

int main (void)
{
// fast pwm, mode 14 , TOP=ICR1
   TCCR1A  = (1<<WGM11);
   TCCR1B  = (1<<WGM12)|(1<<WGM13);
   TCCR1B |= (1<<CS11);                 // prescaler=8, one counter step = 1 us             

// clear OC1A, OC1B on compare, set on TOP
   TCCR1A |= (1<<COM1A1) | (1<<COM1B1);                 

// periode = 20 ms (50 Hz)
// pwm_freq = F_CPU/prescaler/ICR1
   ICR1 = 20000;                           

   OCR1A=1500; // servo1 - 1500 microsec (center position)
   OCR1B=1500; // servo2 - 1500 microsec (center position)

   DDRB   |= (1<<PB1) | (1<<PB2); // pins OC1A, OC1B output (servo1, servo2)

     while(1)  // test
     {
         OCR1A = 1000;                   // pulse_width = 1 ms,servo1 goes to the left position
         OCR1B = 1000;                   // servo2 the same

         // now servos stay in the position "left" until values OCR1A,OCR1B are changed
         _delay_ms(1500);          

         OCR1A = 1500;                   // pulse_width = 1.5 ms,servo1 goes to center
         OCR1B = 1500;                   // servo2 the same
         _delay_ms(1500);          

         OCR1A = 2000;                   // pulse_width = 2 ms,servo1 goes to the right position
         OCR1B = 2000;                   // servo2 the same
         _delay_ms(1500);          

      }//while
}//main
//---------------------------------------------------------------------

Notice how it uses OCR1n to change the position of the servos.

 

Jim

 

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

 

Thank you, although what I am looking for is to control more than 2 servos. My program only reads the value of the potentiometer when I disconnect and reconnect the mic, only in that way its value is updated

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

will98cf wrote:
My program only reads the value of the potentiometer when I disconnect and reconnect the mic

By "mic" do you mean "microcontroller" ?

 

"MCU" would be a more usual abbreviation. Or just say, "AVR".

 

Sounds like you need to just focus on getting the pot reading working properly - independent of any servos.

 

Post a full schematic. Some good, clear, in-focus photos of the setup would also help.

 

See Tip #1 in my signature (below) for how to post pictures.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2
	uint16_t servo1=( 1000 + (ADC_Read(0)/0.25575));
	uint16_t servo2=( 1000 + (ADC_Read(1)/0.25575));
	while (1)

Silly question but why are the ADC reads outside the while(1)? Is this suggesting that you just read the pot positions as you start up and then any subsequent change is intentionally ignored?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well that explains:

In #5, will98cf wrote:
My program only reads the value of the potentiometer when I disconnect and reconnect the mic

 

laugh

 

EDIT

 

So, in fact, it would also read the pot if you were to just reset the AVR - without disconnecting it ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Thu. Apr 9, 2020 - 08:50 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

If I was referring to the microcontroller, sorry.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

It worked, that was my mistake and I'm a novice when it comes to programming in C, it only gives me some noise in the servos, thank you very much