Close

Got extremely close to 50Hz but still not good enough

A project log for T85 Target

A mini Attiny85 target dev board

mcunerdmcu_nerd 02/12/2017 at 17:240 Comments

This is a followup to An update on dealing with Servos post. I wanted to take another shot of getting close to 50Hz as I could in order to actually get my pesky MG90S digital servo to work.

I decided to calibrate my Attiny85's internal RC oscillator. On page 164 of the Attiny85 datasheet it mentions that Atmel calibrates them at 3V. Mine was running at 5V, so there was room for improvement. I didn't have any really fancy frequency measurement tools, but I did have my EX330 multimeter that has a frequency measurement function.

The first thing I needed to do was to get the current calibration value as a starting point. The calibration value is stored in the OSCCAL register. The second question was how to read that value from my Attiny85. I could hop into the Arduino IDE and use the software serial library, but that would also mean that I would have to dig out my usb-serial converter.

A more convenient way that requires no additional hardware is to write the value stored in the OSCCAL register to EEPROM and then use AVRDUDE to dump the EEPROM contents. The subroutine to write a value to EEPROM is very simple (yea I pretty much ripped it off from the datasheet):

void writetoeeprom(int addr,char data){
while(EECR & (1<<EEPE));
EECR = (0<<EEPM1)|(0<<EEPM0);
EEAR = addr;
EEDR = data;
EECR |= (1<<EEMPE);
EECR |= (1<<EEPE);

}

So now we just place the value from the OSCCAL register into a variable and use the above subroutine to write it to the first byte of EEPROM:

data = OSCCAL;
writetoeeprom(0,data);

After we upload the program which contains the above, we can dump the EEPROM with AVRDUDE:

avrdude -p t85 -c usbasp -U eeprom:r:text.hex:i

We then look at our dump file and look at the first byte that comes after ":20000000" and convert that hex value to base 10.

When I did the above I got a value of 137.

Next step was to generate a clock signal on a pin. I chose to use PWM to output what's supposed to be a 1Mhz signal on PB4 and ajusted the value of the OSCCAL register untill I got as close as I could get:

DDRB |=0b00010000; //set pin3 PB4  for output as first step for pwm 0c1b
TCCR1 |=0b10001011;//set up pwm prescaler
GTCCR |=0b01100000;//enable pwm 
OCR1C= 8-1;
OCR1B=4;
OSCCAL=131;

After doing all of that I set PWM frequency back to 50Hz and measured it. It was off by a few hundredths off normally but there was also some jitter. I looked up the digital servo and it failed to work correctly. The darn thing wants 50Hz period not 50.04 Hz or such. An important note that setting OSCCAL to a different value does not permanently change the factory calibration, if the OSCCAL line was removed, it would run at the fectory calibrated value instead.

In conclusion driving digital servos with the Attiny85's internal RC oscillator is a crapshoot. Having to use a crystal may be the only solution. I went against putting a crystal on my T85 board as that would have taken 2 I/O pins and the the Attiny85 only has 5 I/O pins to begin with (in some circumstances you can use pin 1, giving you six.)

Discussions