dotnet / iot

This repo includes .NET Core implementations for various IoT boards, chips, displays and PCBs.
MIT License
2.15k stars 581 forks source link

Support for WS2812 via PWM #2132

Open qiuyoo opened 12 months ago

qiuyoo commented 12 months ago

Problem: Currently, there is a method to support WS2812 LEDs through SPI, which is great. However, I would like to suggest the addition of support for WS2812 LEDs via PWM as well.

Description: The current implementation provides support for WS2812 LEDs using the SPI interface, which works well in many cases. However, there are scenarios where PWM-based control for WS2812 LEDs can be more advantageous.

Use Case:

PWM (Pulse Width Modulation) is widely used for controlling LEDs and offers precise control over the LED's brightness. Some hardware configurations may not have access to SPI, making PWM a more accessible option. Supporting PWM for WS2812 LEDs would make the library more versatile and compatible with a wider range of hardware setups. Proposed Solution: I propose adding support for WS2812 LEDs via PWM to complement the existing SPI support. This would provide users with more flexibility in choosing the appropriate control method based on their hardware and application requirements.

Additional Information:

It's important to maintain backward compatibility and ensure that users can easily switch between SPI and PWM control methods. Detailed documentation and examples for using WS2812 LEDs via PWM would be valuable for users. Thank you for considering this feature request. Please let me know if you need any further information or if there are any questions regarding this proposal.

raffaeler commented 12 months ago

I'm not sure to understand the request correctly. The LEDs controlled via WS2812 use a 1-wire protocol on the data line to set the value of the RGB(W) internal leds, including the brightness. By using PWM on the power line, you compromise exchanging data on the data wire.

Am I missing something?

qiuyoo commented 12 months ago

In certain scenarios, this requirement arises. Currently, I am controlling 700 LEDs using a single PWM pin, with independent power supplies. However, the existing code is in Python, and I would like to transition to a .NET Core version for this project.

qiuyoo commented 12 months ago

I have an idea: I'm using PCA9685 to extend 16 PWM channels, all of which are meant to drive WS2812 LEDs. However, since there is no PWM support, I'm unable to implement it.

pgrawehr commented 12 months ago

Can you point us at a data sheet or the python implementation that you're using? Like Raffaele I'm quite confused as to how that should work.

qiuyoo commented 12 months ago

Can you point us at a data sheet or the python implementation that you're using? Like Raffaele I'm quite confused as to how that should work.

https://github.com/rpi-ws281x/rpi-ws281x-python

raffaeler commented 12 months ago

I'm still confused. According to the link you posted:

Both PWM and PCM use DMA transfer to output the control signal for the LEDs.

This means that PWM is used to send the bits as you would do with the SPI. This also means that PWM is not used to dim the brightness of the led power as you would do with any traditional led.

All the WS2812 leds have an internal IC taking care to indipendently drive the R, G, B and (if present) W from any brightness from 0 to 255. For example you if send over the data line the RGB data to 128,0,0 you will have a mid-brightness red, while the full brightness led could be obtained, of course, with 255,0,0.

That said, using PWM as data line is doable but I am not sure it would be a popular request as it would not add any additional feature to use the SPI.

If I misunderstood what you mean, please clarify.

qiuyoo commented 12 months ago

Yes, using PWM is feasible, and functionally equivalent to SPI. The main consideration here is the scalability of PWM, which offers a lot of possibilities in terms of quantity. If you look at open-source projects in other languages, you'll likely understand that this feature is necessary.

raffaeler commented 12 months ago

Please bring some examples here.

Once you drive with PWM, the number of leds on the data line (they are connected in serial) does not change anything. SPI is the fastest possible communication line, therefore if you want the highest possible data rate to program a huge number of leds, SPI is the way to go (faster than PWM for this purpose).

qiuyoo commented 12 months ago

Currently, my projects concern is the ability to expand the number of PWM channels, but I haven't found a way to expand the quantity for SPI yet. I have tried using the SoftwarePwmChannel in System.Device.Pwm, and it can also illuminate WS2812 LEDs. However, I didn't fully understand the calculation method used inside it. In the development of my project, I've searched for a lot of information, and it seems that .NET support is quite limited. I would like to provide as much support as possible, at least to offer an additional option.

raffaeler commented 12 months ago

You can have a decent speed when you use dedicated hardware and not by emulating in software. This is true for any peripheral, including SPI and PWM.

If you need multiple channels, you can use the FT4232H series of boards which have multiple HW SPI on board. You can find these modules (or similars) using these ICs via popular distributors or on AliExpress: https://ftdichip.com/product-category/products/modules/

Similarly, there are boards offering multiple HW PWMs (usually used to drive motors, but they are general purpose). I use this kind of board: https://www.aliexpress.com/item/1005004626900806.html

I didn't fully understand the calculation method used inside it.

I never wrote the code to drive the WS2812 but the best way is to use the oscilloscope to verify that what you write is what you expect. Once you write byes over the pwm in the expected serial order, you are done.

I would like to provide as much support as possible, at least to offer an additional option.

We gladly accept PRs of course :-) If you want to contribute adding support for this WS2812 using PWM, you are more than welcome. Anyway, I don't think that this could solve your problem.

qiuyoo commented 12 months ago

Okay, thank you. I will try some other solutions.

raffaeler commented 12 months ago

You are welcome. Let us know how it goes. Should PWM become important to solve the problem, I would be curious to understand the use-case.

qiuyoo commented 12 months ago

We are currently using a Raspberry Pi 3B along with a PCB expansion board developed by the supplier. The PCB expansion board is already in use and cannot be adjusted. The PCB is connected to 700 WS2812 LED lights, with PWM0 (Pin 18) and PWM1 (Pin 13) respectively. The original program is written in Python and is based on this project: https://github.com/rpi-ws281x/rpi-ws281x-python. However, we now want to modify it so that every 100 LEDs form a PWM channel, ensuring that a malfunctioning LED in the middle does not affect the ones behind it. The current solution we are considering is to connect a PCA9685 device externally to the Raspberry Pi. The PCA9685 can expand to provide 16 PWM data interfaces. That's the idea.

raffaeler commented 12 months ago

You should make some test before proceeding. Let me explain the reason. Those PWM ICs are meant to be programmed once and then they produce the constant PWM duty cycle (on/off timings). Instead, you want to 'hack' the PWM by creating train of bits that makes up the bytes to transmit on the data lines. Basically, you want to emulate the SPI behavior on a PWM.

I am not sure that you could do with the PCA9685 (which I also linked before) because this IC just get the parameters for the duty cycle while you should continuosly reprogram the 16 channels for each bit. For this reason I am not sure the timings are compatible with the RPi. Make a test to validate your solution first.

If instead you use multiple SPI ports, it's easier because the SPI is meant to get bytes and serialize them to the SPI channel, which is exactly how the WS2812 data line expects the bit train.

qiuyoo commented 12 months ago

I need to conduct some tests, theoretically, it should be feasible.

raffaeler commented 12 months ago

I need to conduct some tests, theoretically, it should be feasible.

In theory yes, but you will need to use a lot of CPU from the RPi because you have to change the PWM duty cycle for each bit on all the 16 channels.

For your info, the mega-screens that use huge amount of WS2812 leds, do not use boards like the Raspberry PI. They use a dedicated FPGA which can provide syncrhonous and instantaneous flow of data. Using a FPGA you don't even need SPI or PWM, but just 'bitbang' the I/O in hardware. I have played with a Verilog code sample to manage the WS2812 leds.

ghost commented 11 months ago

This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment.