2

I create for a firma a java game using LibGDX. It will run on a Raspberry Pi 3. It is a clone of a famous arcade cabinet. The game is ready. The joystick control using a port of the evdev library works well. The application will use Pi4j library for interaction with external devices like a coin acceptor, a serial LED-chain based on a chip WS2812 and a 7-segments LED display. But the control of the serial LED-chain has troubles. The LED-chain needs to have a high frequency serial impulses. The control impulses must be between 500 and 1500 nanoseconds long to transfer the data. I have launched a simple test for pin GPIO26 to know the typical frequency of the GPIO-outputs:

long end;
long start = System.nanoTime();
for (int i =0; i++; i<10000){
     ledPin.high();
     ledPin.low();
}
end = System.nanoTime();
double statementChangingTime = (double)(end - start)/(10000*2);

I have got that the time between the statement changings is between 3500 - 9000 nanoseconds. It is too long.

I want to know, is it possible to increase the frequency (make the statementChangingTime smaller) using Pi4J? Maybe I need to select an another pin? Maybe I need change something in the raspi-config? Maybe I can use an another library? I don't know C/C++ and can not write myself a low-level code and a Java-wrapper for it.

  • Why don't you use the code from the [LED Strip example](https://pi4j.com/examples/components/ledstrip/)? – Thomas Kläger Mar 19 '23 at 14:50
  • @ThomasKläger Thanks, I thought I could not find any examples for the LED-chains in this library. I had loosed too many time to launch only the simple example. If I right understood, MOSI-pin is faster than another GPIO-pins. Is it true? – Alexander Gorodilov Mar 19 '23 at 15:10
  • 1
    The MOSI pin is faster because the SPI module generates the timing - with more precision and less CPU overhead than any software based solution can achieve. – Thomas Kläger Mar 19 '23 at 17:06
  • @ThomasKläger, the SPI can only gives you up to 32-bit packet, while GPIO can (theoretically) give you any length of the bit series. If it's not a problem for the HW in question, then I agree the SPI is the best choice here and looking at https://www.elektormagazine.com/news/spi-to-ws2812b-converter-more-leds-more-power it seems the case. – 0andriy Mar 20 '23 at 13:40
  • @ThomasKläger, this example doesnot work properly with my LED. I think this example have another parameters for communication: frequency, signal duration and so on. My LED-strip looks like: https://www.youtube.com/watch?v=FeFuEqwTlGk – Alexander Gorodilov Apr 05 '23 at 07:48

1 Answers1

0

The pi4j library has different code examples. One of them (LED Strip example) seems like the perfect match for your problem.

Generating the required timing for the WS2812 chips with switching a GPIO pin to high / low at the required rate is difficult even when working in C and probably almost impossible when working in Java.

The example from pi4j uses the SPI interface to accurately generate the required timing. (Note that the approach taken is different from the one in the elektormagazine that you linked in a comment.)

The bit timing for the SPI is set to a basic rate of around 156ns per bit and the data for the WS28xx is produced as follows:

  • a 0 bit for the WS2812 (350ns high followed by 900ns low) is written as 0b1100_0000 (2 bits high -> 312ns, 6 bits low -> 936ns)
  • a 1 bit for the WS2812 (900ns high followed by 350ns low) is written as 0xb1111_1000 (5 bits high -> 780ns, 3 bits low -> 468ns low)

The timing this produces is well within the specified limits of the WS28xx chips.

The example takes the RGB codes for all configured chips and creates a byte array where each byte corresponds to one output bit. These bytes are then sent out through the MOSI pin, thereby creating the required waveform.

Note that the driver sends these bytes back-to-back by using the integrated FIFO of the SPI (it keeps that FIFO full for as long as there is some data available for sending).


You are correct in noticing that using a GPIO directly and using the CPU to create the required waveform would allow you to basically send an unlimited length bit stream.

However doing so can prove tricky if you want to

  • produce the data on the fly (using loops and if/else)
  • produce an accurate waveform without to much jitter

And if your CPU / runtime is to slow then you simply cannot use that approach at all.

Thomas Kläger
  • 17,754
  • 3
  • 23
  • 34
  • Thanks, this example works for me but with some errors. Can you please also see that question https://stackoverflow.com/questions/75917421/addressable-led-strip-control-using-raspberry-pi-3b-and-pi4j-library ? I have appended a video of my experiments. – Alexander Gorodilov Apr 03 '23 at 18:35