Don't ad-block us - support your favorite websites. We have safe, unobstrusive, robotics related ads that you actually want to see - see here for more.
0 Members and 1 Guest are viewing this topic.
int main(void){ TCCR1A |= 1 << COM1A1; // Set OC1A on Compare Match when up counting, clear - when down counting TCCR1A |= 1 << WGM11; // PWM, phase and frequency correct TCCR1B |= 1 << WGM13; // PWM, phase and frequency correct TCCR1B |= 1 << CS10; // No prescaling ICR1 = 19999; // PWM top value OCR1A = 9999; // PWM compare value; DDRB |= 1 << DDB1; // Set PB1 (OSC1A) as output for(;;){}}
Most likely the hardware PWM module is not a good choice for producing pulses to control a servo. This is due to the very small duty cycle of a pulse width, 1 to 2 ms, to the pulse period, 20ms.It works much better to produce the servo pulses with software using either a software timing loops or hardware timers.Do some google searches on "RC servo controller", "atmega servo controller" to find code samples.
I've been away from robots for over a year and I just recently found the time to get back into it. I have the $50 robot built with a atmega328 MCU. I left this at the point where I need to superglue the pot head in place. WHERE IM HAVING TROUBLE IS, I cannot seem to program the servo to go to the '90*' midpoint. I remember having the impression that PWM was used to send the correct pulse length at the correct frequency, but I've been looking at documentation and tutorials for several hours now, and I'm not even sure if the output setup for the $50 robot MCU uses pins capable of PWM. I have a ridiculous attempt from when I was last trying to do this that uses waiting between bringing the signal high and low. It almost works, but seems completely impractical as interrupts and such can change the pulse width or frequency, and no other code is being executed during the waiting. Should I be persuing PWM, or is there a better way to control the servos? Thanks everyone!
//Zero Servos Using Timer1 and Delay//This is useful if you built a robot that uses servos or other square wave//devices on pins that cannot use built in PWM.#include <avr/io.h>#include <avr/interrupt.h>//Change the below value to your MCU Frequency. //It is required for _delay_us() #define F_CPU 1000000UL // 1 MHz#include <util/delay.h>//This is used to count milliseconds by 2. I counted by 2 because of the compare value I ended up usingvolatile unsigned int clock_2millisecond=0;int main() { //Set PinD as Output DDRD = 0xFF; //Set up the timer1 //Set Prescaler to 8 and mode to CTC TCCR1B=(1<<WGM12)|(1<<CS10); //The below compare value was found empirically with the debugger //and will differ with other frequencies. OCR1A=2149; //Enable the Output Compare A interrupt TIMSK1|=(1<<OCIE1A); //For some MCUs this is TIMSK (there is not 1) //Enable interrupts globally sei(); //infinite loop while(1); return 0;}//ISR called every 2msISR(TIMER1_COMPA_vect) { clock_2millisecond++; if(clock_2millisecond==10) { clock_2millisecond=0; //Toggle PORTD for 1.5 ms every 20ms //This could also be a series of individual pins being brought high //for different lengths of time PORTD=0xFF; _delay_us(1500); //Using a delay function within an interupt makes me irksome, but it works here. Also, nested interupts are turned off within the interupt by default, so the delay is accurate. PORTD=0x00; }}