I want to use 16-Bit PWM output on the Photon in my project to drive some LEDs, but I can’t find any resources about how to output 16-Bit PWM on the Photon. I know that it was possible on the Core (something along the lines of this post: Custom PWM Frequency Example).
Anybody have any luck changing the PWM resolution (and frequency) on the Photon? The only other similar thread is kind of dead (12-bit PWM resolution on Photon possible?)
To make it work you should first run initTimers(). This initialises all PWM pins on the Photon (D0, D1, D2, D3, WKP, TX, RX) to run on the same speed as the system clock (120MHz) and accept a maximum resolution of 16-Bits. This results in a maximum PWM frequency of 120MHz / 65536 = 1831 Hz. I have not verified this frequency yet, but it is subjectively very high, almost no stroboscope effect is visible when waving your hand over the LED light. After running initTimers(), you can run analogWrite16(pin, value), in which ‘value’ can be 0-65535, it should output that value on that pin. I tested it and it works on all PWM pins of the Photon.
I have no experience with driving LCD displays, but my code does adjust the timers of all the PWM pins, which will likely mess up your display timing signals. I might rewrite the code so that you can choose to enable 16-Bit output on certain timers/pins. The timers it adjusts are: TIM1, TIM3, TIM4 and TIM5. In this image you can see which timer and timer channel drive which pins: https://docs.particle.io/datasheets/photon-datasheet/#pin-out-diagrams
Actually I already called initTimers() in the setup().
I looked closer and I was wrong about D3 being on TIM1 (I was misleaded by the commented debug line that shoud say “modifying TIM_channel_[X]” instead of “modifying TIM[X]”).
I noticed a possible error, although it doesn’t seem related to my problem: On line 80, shouldn’t it read TIM_OC2PreloadConfig instead of TIM_OC3PreloadConfig ?
I also tried to deactivate hi-res PWM on TX/RX with no success.
It would be nice to be able to select on wich timer/pin you want hi-res PWM. Do you think it could be possible to leave TX/RX untouched while changing D0-D4 ?
The latest firmware 0.4.9 (available now on the Particle Build web IDE) has variable PWM frequency by using analogWrite(pin, dutyCycle, frequencyInHertz) but the duty cycle is still from from 0 to 255. See the docs for more details
Are you more interested in changing the frequency or increasing the resolution of the duty cycle?
You are right, on line 80 there was an error. I have updated the file on GitHub, thanks for pointing it out. Also, my code is based partially on someone else’s, so the debugging printlines etc. might not be correct at some places. But I thought I’d share my answer as soon as possible.
As for your question, I think it is possible to leave TX/RX untouched, since they share one timer which is not used by other pins. But I’ll have to dive into my code and set it up properly so you can choose which pins will get hi-res PWM.
As for your code, I see that you call initTimers() and then immediately call pinMode(PWM_PIN, OUTPUT);. All the pins are already set to OUTPUT in the initTimers(), and I think that might be messing with your results. I only got the hi-res PWM to work when I called pinMode(pin, OUTPUT); on each pin before changing all the timer settings.
So I’d comment all pinModes out and check if that works.
@jvanier, thanks for sharing that information. Good to hear the Particle team is working on integrating this into the firmware.
I believe that if you change “TIM_TimeBaseStructure.TIM_Period = 65535;” to a different value then that will be the max resolution of your PWM. So if you change that to the resolution you need (say 4096) then the frequency of your PWM will go up. Don’t know for sure though , I’m rather new to this low-level stuff.
Hi Guys,
I am trying to use the new exciting analogueWriteResolution function but it does not seem to be recognised “particle build” where am i going wrong?
Thanks
Andy