Hi... I thought I'd make another thread because I am severely confused!
I'm trying to increase the frequency of a PWM pin's output (let's say this pin uses Timer1), and increase the resolution to 10-bit. I've spent the last couple of hours trying to make sense of the datasheet, and lots of old threads and blog entries about how to go about this, and I've seen so many slightly different methods that I don't know what to do any more!
void analogWrite(uint8_t pin, int val)
{
// We need to make sure the PWM output is enabled for those pins
// that support it, as we turn it off when digitally reading or
// writing with them. Also, make sure the pin is in output mode
// for consistenty with Wiring, which doesn't require a pinMode
// call for the analog output pins.
pinMode(pin, OUTPUT);
if (val == 0)
{
digitalWrite(pin, LOW);
}
else if (val == 255)
{
digitalWrite(pin, HIGH);
}
else
{
First, analogWrite takes a 16-bit value. So far so good. But it has a specific test for 255. That's not so good. My testing confirms that if you try something like this:
At the moment when we have sent out 257, we get a pulse width of 2.0545 out of 8.1819 which gives:
2.0545 / 8.1819 * 1023 = 256.88
So, close enough to a duty cycle of 257 / 1023. That seems to work then.
You will note that the frequency has dropped down to 122 Hz. This would be because of the longer overall cycle time (counting up to 1023 rather than 255). You could bump that back up by changing the prescaler.
The extra two lines change the prescaler from 64 to 8, multiplying the frequency by 8. Now I measure a frequency of 978 Hz which is roughly 122 Hz * 8.
liudr:
Sorry for lingering here beyond the [Solved] word but I thought this library provides a way to manipulate timer1 for PWM (arbitrary period and 10bit):
I am myself just starting with this so don't know too much about it.
Hi!
I came across this library yesterday, and at the time of reading, I just couldn't make sense of the example, so I decided not to use it. But it makes sense to me now, and seems to be a slightly nicer way of what Mr. Gammon did.
However, in the last hour I've realised something awful... with 10-bit PWM, and with the timer frequency set to 31250 Hz (but with the PWM frequency being a quarter of this), if I wrote a value of 1 (out of 1024, approximately 0.1% duty cycle), the pulse has a duration of 0.000128s, if my calculations are correct, and my low-pass filter does not have a settling time anywhere near that. I don't think it's very likely that a value of 1 would ever need to be written, but I'm considering going back to 8-bit, or trying 9-bit, because of this! =(
edit: duh, I should reduce the frequency, shouldn't I?
liudr:
Sorry for lingering here beyond the [Solved] word but I thought this library provides a way to manipulate timer1 for PWM (arbitrary period and 10bit):
That library looks nice. I must admit that the question was asked in terms of register manipulation, and that's how I answered. Plus I like to understand what all those registers do.
edit: duh, I should reduce the frequency, shouldn't I?
Not sure I understand that question, but 10 bit PWM sounds pretty precise. And you are right, if you write a 1 there is a long gap before the next 1. I suppose it depends on what you need.
I'll need to read the library doc once more. I think I am not understanding how it works entirely. Will report back with more understanding once I have some
I came across a document about PWM filters: http://www.proaxis.com/~wagnerj/PWMfil/PWM%20Filters.pdf and on page 12 there's a graph of what happens to the filter output when there is a narrow pulse. I was concerned that because a single pulse of 10-bit PWM is narrower than that of 8-bit PWM, and with a high frequency, that the filter would not work correctly. But having thought about it some more, I think it will still work.