Controlling a servo with Attiny85 OCR1B

attinypwmservotimer

I currently have a project where I need to control a servo using OCR1B. I already figured out how to use one with Timer0, but I can't use that for this project though.

So, my questions are:
– How do I set the PWM frequency to 50Hz(for the servo)?
– How do I change the Duty Cycle to set the servo position?

Also my system clock is 1MHz.

Thanks for answering!

Best Answer

50Hz is once every 20 milliseconds, and you can have an almost arbitrary resolution of pulse width by using very simple logic to service a GPIO pin to go logic HIGH or logic LOW to send the pulse. You can even do a whole bunch of other tasks before the pin finally needs to change state.

You are trying to get a hardware timer to run as low as 50Hz, when usually people want those timers and PWM pulses to be hundreds of hertz, even tens of kilohertz.

Just use the pin as a digital logic pin, and use some simple timing and logic to set the pin high and low as required to send the pulses.

Lets say you want the pulse to be 1 millisecond in length (1000 microseconds), during a 20 millisecond interval. Lets say you set up a timer (doesn't matter which) to overflow and increment a global static variable called something like "TICK_COUNT" and has a known frequency. From this you can estimate the elapsed time during operation, and definitely during short intervals like in the order of 20ms. You could even reset this count variable at the end of each 20ms cycle.

in your program's main control loop, you will just check the current count value (and convert to microseconds if you can) against the intended pulse length (call this the "setPoint", and convert from microseconds to however many TICK_COUNT this needs to be).

Start with the pin set to HIGH. Once currentCount >= setPoint, let the pin LOW. Have another piece of logic which does nothing now until currentCount >= CYCLE_END which is however many ticks are needed to be ~= 20 milliseconds. Then you restart all the logic states, and begin this whole cycle again.

Whatever program logic you have that needs to change the servo's setpoint, just write to the setPoint global variable, and the servo control logic will handle it.

I think I may have gone into too much detail, but I hope all this helps.