Hello all,
I was getting a lot of jitter on a servo that was going into a pan and tilt system and I posted thread a few months ago Resolution question - 12 bit servo, 8 bit Arduino Ethernet - Project Guidance - Arduino Forum and learned that pin 5 has a higher than expected duty cycle and faster freq than the other PWM pins. The servo that was giving me problems was on pin 5 and I moved it to pin 9 and I got rid of the jitter. I let the project go and came back to it recently and I noticed that the jitter is still there. In the old thread, andsetinn posted a link in which someone else had servo jitter problems and showed how they fixed the problem.
andsetinn:
Apparently the Arduino Servo library has limitations that can cause servo jitter. This guy has written a workaround. http://www.karlssonrobotics.com/tutorials/arduino/workaround-for-servo-jitter-on-arduino/ It may not fix your problem but is worth a try.
I had no clue what this code was telling me. I then started reading the ATmega328P data sheet to understand the PWM better and figure out how I can use that code as a basis for my code. I have an okay grasp on what everything is doing inside the code from Karlsson Robotics now. From my understanding, the code creates the variables, sets them up, then initializes the registers for PWM and commands the WGM and CS to be in CTC mode. From there he makes a main loop and an interrupt for the PWM. Inside that interrupt loop is where I am lost. So every time TCNT0 (Time/Counter 0) = OCR0A (Output compare register), it goes into the Interrupt loop and TCNT0 resets to 0x00 - correct? Pin 8 is the pin used for PWM and is oringally set high and then a counter (motorcount) is used to tell the motor to turn on and off. Once motor count hits 999, it resets. So that means that every time TCNT0 = OCR0A, 999 and then restart - correct? In that case, the PWM signal will be based on motorcount setting pin 8 to high/low - correct?
Now here are my problems with this. I read that if I wanted to use motors, I should use Phase PWM because it gives better frequency resolution. I've also read that changing timer0 will cause things like millis() to be off - which I use in my main code. Therefore, wouldn't I want to use a TCNT2? If so, what pins are those exactly? I forget how I found which pins go to which timers a few months back, but I know they do - I'm 99% sure 5 and 6 go to timer0.
EDIT:
I found pin 3,11 timer 2 and pin 9,10 timer1 in my notes. I am using an Arduino Ethernet set up as a server, sooo... what exactly will changing timer2 do to my Ethernet communications?
What are your thoughts? I haven't started writing code yet. I am still not 100% sure what I'm supposed to do. From my understanding though, I'd want to set up the timer in the void steup() area and then have an ISR which does my PWM.
ALSO:
I am currently using a custom servo library, VarServoSpeed. It allows me to move the servos slower than the standard motion - when using the normal library, the servos went to places too fast and I was afraid something may get loose mechanically and get flung to somewhere.
Thanks for reading, Hopefully I explained myself well enough
Matt
For those that can't see the code, it is posted here.
Initialize timers
//set timer0 interrupt at 2kHz
TCCR0A = 0;// set entire TCCR2A register to 0
TCCR0B = 0;// same for TCCR2B
TCNT0 = 0;//initialize counter value to 0
// set compare match register for 50khz increments
OCR0A = 4;// = (16*10^6) / (50000*64) - 1 (must be <256)
// turn on CTC mode
TCCR0A |= (1 << WGM01);
// Set CS11 and CS10 bits for 64 prescaler
TCCR0B |= (1 << CS11) | (1 << CS10);
// enable timer compare interrupt
TIMSK0 |= (1 << OCIE0A);
Interrupt Loop
ISR(TIMER0_COMPA_vect){
//timer0 interrupt 50kHz to drive servo motor connect to pin 8
// pulse width is 1 ms in motor state '0' and 2 ms in motor state '1'
switch(motorenabled){
case 1:
motorcount++;
switch(motorstate){
case 0:
if(motorcount>motorstate0){
digitalWrite(8,LOW);
}
if(motorcount>motormax){
motorcount=0;
digitalWrite(8,HIGH);
}
break;
case 1:
if(motorcount>motorstate1){
digitalWrite(8,LOW);
}
if(motorcount>motormax){
motorcount=0;
digitalWrite(8,HIGH);
}
break;
}
break;
case 0:
ledcount--;
if(ledcount==0){
switch(ledstate){
case 0:
ledstate=1;
digitalWrite(ledPin, HIGH);
ledcount=ledontime;
break;
case 1:
ledstate=0;
digitalWrite(ledPin, LOW);
ledcount=ledofftime;
break;
}
}
}
}