How fast can an output pin be toggled?
How fast can an output pin be toggled?
Just got my board a couple of days ago, awesome!
I'm now trying to find a way to use it to control a strip of WS2812 serial LEDs http://www.mikrocontroller.net/attachme ... minary.pdf
These need a stream of digital pulses to control the intensity of each of the RGB LEDs. With a pulse width varying from 0.4us for a 0, and 0.85us for a 1, and a period of 1.25us.
This is a struggle on most uC. I was wondering what is the best that the uPy board can do.
If I toggle the output in Python using
while 1:
pyb.Pin('X1').value(1)
pyb.Pin('X1').value(0)
I get a period of 25us. Is this the best that can be done in straight python?
Is it likely to improve in future releases?
I guess I should get down and dirty with the assembly code for any substantial speedup.
cheers
-mike
I'm now trying to find a way to use it to control a strip of WS2812 serial LEDs http://www.mikrocontroller.net/attachme ... minary.pdf
These need a stream of digital pulses to control the intensity of each of the RGB LEDs. With a pulse width varying from 0.4us for a 0, and 0.85us for a 1, and a period of 1.25us.
This is a struggle on most uC. I was wondering what is the best that the uPy board can do.
If I toggle the output in Python using
while 1:
pyb.Pin('X1').value(1)
pyb.Pin('X1').value(0)
I get a period of 25us. Is this the best that can be done in straight python?
Is it likely to improve in future releases?
I guess I should get down and dirty with the assembly code for any substantial speedup.
cheers
-mike
Re: How fast can an output pin be toggled?
I would try rewriting it as:mpymike wrote:while 1:
pyb.Pin('X1').value(1)
pyb.Pin('X1').value(0)
Code: Select all
pin = pyb.Pin('X1')
while 1:
pin.value(1)
pin.value(0)
I would be inclined to try and figure out how I could use the hardware to generate the pulses for me, rather than trying to "bit bang" them directly.
Re: How fast can an output pin be toggled?
I would also love to control such leds! Here is the answers I got here for such project:
https://groups.google.com/forum/#!topic ... wVhsdV5vdU
To improve the speed, you could try the different code emitters:
https://www.kickstarter.com/projects/21 ... sts/664832
https://groups.google.com/forum/#!topic ... wVhsdV5vdU
To improve the speed, you could try the different code emitters:
https://www.kickstarter.com/projects/21 ... sts/664832
Frédéric
Re: How fast can an output pin be toggled?
Looking at the datasheet, you could think of the data going to the LEDs as a serial data stream, where you send one of 2 possible bit sequences.
The total of the sequences needs to be 1.25 usecs. If we were to divide this into 8, then we would have "bit times" which are 0.15625 usecs long.
3 bit times = 0.46 usec and 5 bit times = 0.78. The spec says that the pulse widths are all +/- 150 nsecs or 0.15 usecs.
So you could setup the SPI to have a clock of 6.4 MHz, which gives a bit time of 0.15625 usecs.
You could then populate memory with an 8-bit value of 0b11100000 = 0xE0 for a zero or 0b11111000 = 0xF8 for a one, and use DMA to feed the values to the SPI.
This would give you a nice clean output (on the MOSI pin) with no jitter, and you wouldn't have delays caused by interrupts or garbage collection or anything else.
The total of the sequences needs to be 1.25 usecs. If we were to divide this into 8, then we would have "bit times" which are 0.15625 usecs long.
3 bit times = 0.46 usec and 5 bit times = 0.78. The spec says that the pulse widths are all +/- 150 nsecs or 0.15 usecs.
So you could setup the SPI to have a clock of 6.4 MHz, which gives a bit time of 0.15625 usecs.
You could then populate memory with an 8-bit value of 0b11100000 = 0xE0 for a zero or 0b11111000 = 0xF8 for a one, and use DMA to feed the values to the SPI.
This would give you a nice clean output (on the MOSI pin) with no jitter, and you wouldn't have delays caused by interrupts or garbage collection or anything else.
Re: How fast can an output pin be toggled?
Thanks for the replies. It looks like the best solution is to use the SPI peripheral.
I agree bit banging is not very efficient. I was looking for an easier solution.
I didn't know about the 3 different code emitters. I tried the @micropython.native and @micropython.viper
decorators but did they did not work.
-mike
I agree bit banging is not very efficient. I was looking for an easier solution.
I didn't know about the 3 different code emitters. I tried the @micropython.native and @micropython.viper
decorators but did they did not work.
-mike
Re: How fast can an output pin be toggled?
There is an approach with DMA on the STM32 here, maybe this could lead to a native micropython library for the ws2812 ?
https://github.com/Torrentula/STM32F1-w ... ect/WS2812
https://github.com/Torrentula/STM32F1-w ... ect/WS2812
Re: How fast can an output pin be toggled?
Neat - that's basically using PWM (generated by a timer) and using DMA to change the duty cycle.
Re: How fast can an output pin be toggled?
With this design the DMA feeds the timer with a stream of pulse width values.
The size of the buffer holding these values is given by:
This is a bit wasteful imo.
Using a bit banging assembler solution it can be done with only LEDs * 3 bytes.
This matters when you want to drive large numbers of LEDs
such as a billboard.
The other issue with this DMA solution is that it is blocking.
Once the DMA is started it waits until it completes before returning from
the WS2812_send function.
-mike
The size of the buffer holding these values is given by:
Code: Select all
* The buffer size can be calculated as follows:
* number of LEDs * 24 bytes + 42 bytes
Using a bit banging assembler solution it can be done with only LEDs * 3 bytes.
This matters when you want to drive large numbers of LEDs
such as a billboard.
The other issue with this DMA solution is that it is blocking.
Once the DMA is started it waits until it completes before returning from
the WS2812_send function.
-mike
Re: How fast can an output pin be toggled?
Is it a DMA limitation, or only on the current implementation?
Frédéric