12-bit PWM resolution on Photon possible?

While I am still waiting to receive my Spark Photon I have been unsuccessful in finding any posts or other documentation on the PWM resolution (not frequency) and I am not sure I am ready yet to dig deep into the microcontroller literature. I’ve used Teensy 3 and Teensy LC in the past ( and will continue to do so) and these allow a PWM resolution of up to 16 bits.

What is the PWM resolution on the Photon ?

According to the docs:
https://docs.particle.io/guide/getting-started/tinker/core/#step-two-explore-the-tinker-app

analogWrite: Sets the pin to a value between 0 and 255, where 0 is the same as LOW and 255 is the same as HIGH.

So 256 means its 8-bit resolution on the PWM.

1 Like

As @johnventions already said, the PWM resolution on the core and photon is 8 bit. However, if you really really need 12-bit resolution (or more) you could write timers with interrupts, difficult though.

8bit is the resolution which analogWrite() allows on PWM pins, but that’s not really the possible resolution of the PWM pins.
PWM is accomplished via internal timers which count up from zero to their set maximum value (usually way higher than 255) at which they are reset/wrap round and at a given count the PWM pin will toggle.
This results in a pulse-pause-ratio which resolution is only limited by the max count of the timer.

The analogWrite() range will just be scaled up to/mapped into the timer resolution/range.

To get deeper insight into the topic you could have a look into the open source implementation of analogWrite() or even have a peek into the STM32F datasheets.
There are also lots of resources on the net to be found when searching for STM32 PWM

1 Like

If you look in this file for Photon and Electron:

https://github.com/spark/firmware/blob/develop/hal/src/stm32f2xx/pwm_hal.c

You will see that the hardware timers get many, many settings but I as read the code for analogWrite, it scales the 0-255 value onto the actual hardware range of 0-60000.

So I would say that if you write your own code to use the hardware timers, you could achieve 15.8 bits of resolution. If you changed the PWM frequency from 500Hz, you could do more or less depending on which way you moved it, but I am sure the hardware eventually has a limit you could find in the 32F205 processor manual.

1 Like

Thanks for the replies. Yes I need a higher resolution than the 8-bit for slow, brightness corrected RGB LED fading.

Background is that for my larger lamps I use a I2C Arduino Shield that offers 12-bit PWM. For the smaller design with fewer and lower power LEDs I am working on currently I don’t need the I2C functionality but want to drive the LED driver chips directly from the PWM pins and need 7 PWM pins. 2x RGB and 1 for overall brightness.

I had hoped not to have to get into programming interrupts and timers for such a simple thing. The reason I referenced a Teensy is because it also uses an Arm Cortex M4 core (Freescale) and with Teesnyduino I can set frequency and resolution simply like this:

analogWriteFrequency(4, 375000); //375KHz on pin 4
analogWriteResolution(12); //resolution in bits

Based on your replies it looks like I’d have to implement that functionality myself.

It is funny that you can connect to the internet within a few minutes of receiving your Photon (just got it in the mail today) but it takes days/weeks to figure out such a simple thing as changing the PWM resolution, which is limited by a odd design choice, at least for a 32-bit micro, to 8-bit. OK rant over. I’ll shut up and see if I can get this to work at some point in time.

Thanks again for the help!

As :particle: Particle is still in a fast moving development process, this might be worth mentioning as a feature request on the GitHub repo.
A lot of requests have been taken up and added relatively fast (e.g. digitalWriteFast()).

Maybe @mdma has got something to say about it, if he sees some broader use/call for such a feature it might make it onto the ToDos
I like it :+1:

But while it is convenient to have a prebuilt function, there is a relatively simple way to have high-res PWM (and even Binary Coded PWM which is nicer for light controls) done via interrupts by use of the SparkIntervalTimer library by @peekay123.
This approach is for instance used in the RGBMatrixPanel library.

1 Like

Thanks again for the quick help. I’ll see where I can get with these resources and wait before I make a feature request with my 4th post :wink:

1 Like

Very interesting article about the binary coded PWM. :smile:

Page 4 though; Note: From personal experience, if you try this experiment in reality, make sure that the batteries for your LED device are well held - It’s alarming how fast an AAA battery can travel from the end of a slingshot

1 Like

I’ve been looking around on the ST Microelectronics web site to find the processor manual. Here is a link to it for future reference. In case I have questions. Given the 1361 pages I assume I’ll have a few :wink:

At first sight the PWM generation feature with the Timers seems to be manageable. Thanks for posting a link to the code responsible for the PWM generation. That saved some time searching!

I’ll start to experiment some and hope my shabby oscilloscope does not explode in the process of testing :stuck_out_tongue_winking_eye:

2 Likes

Any luck with getting 12-bits PWM generation on the Photon? I really want to use 16-bit PWM output for dimming LEDs, but I lack the in-depth knowledge needed to write my own PWM generator.