mattjlewis / diozero

Java Device I/O library that is portable across Single Board Computers and microcontrollers. Tested with Raspberry Pi, Odroid C2, BeagleBone Black, Next Thing CHIP, Asus Tinker Board and Arduinos / Pico. Supports GPIO, I2C, SPI as well as Serial communication. Also known to work with Udoo Quad.
https://www.diozero.com
MIT License
261 stars 59 forks source link

WS2812B on Raspberry Pi 3B #100

Closed mkpazon closed 2 years ago

mkpazon commented 2 years ago

I am getting the following error when running the sample code I got from https://github.com/mattjlewis/diozero/blob/main/diozero-ws281x-java/src/main/java/com/diozero/ws281xj/sampleapps/WS281xTest.java

Using GPIO 10

Cannot open /dev/spidev0.0. spi_bcm2835 module not loaded?
ws2811_init failed: Unable to initialize SPI

Error: java.lang.RuntimeException: Error initialising the WS281x strip

java.lang.RuntimeException: Error initialising the WS281x strip
    at com.diozero.ws281xj.rpiws281x.WS281x.<init>(WS281x.java:154)
    at com.diozero.ws281xj.rpiws281x.WS281x.<init>(WS281x.java:121)
    at com.diozero.ws281xj.sampleapps.WS281xTest.main(WS281xTest.java:49)
    at MainKt.main(Main.kt:20)

munmap error
: Invalid argument
ioctl_set_msg failed
: Inappropriate ioctl for device
ioctl_set_msg failed
: Inappropriate ioctl for device

Here is the code I have

build.gradle.kts

dependencies {
    ...
    implementation("com.diozero:diozero-core:1.3.3")
    implementation("com.diozero:diozero-ws281x-java:1.3.3")
}

WS281xTest.java

public class WS281xTest {
    public static void run() {
        //int gpio_num = 18;
        int gpio_num = 10;
        int brightness = 64;    // 0..255
        //int num_pixels = 12;
        int num_pixels = 60;

        System.out.println("Using GPIO " + gpio_num);

        try (LedDriverInterface led_driver = new WS281x(gpio_num, brightness, num_pixels)) {
            rainbowColours(led_driver);
            test2(led_driver);
            hsbTest(led_driver);
            hslTest(led_driver);

            PixelAnimations.demo(led_driver);
        } catch (Throwable t) {
            System.out.println("Error: " + t);
            t.printStackTrace();
        }
    }

    private static void rainbowColours(LedDriverInterface ledDriver) {
        System.out.println("rainbowColours()");

        int[] colours = PixelColour.RAINBOW;

        for (int i = 0; i < 250; i++) {
            for (int pixel = 0; pixel < ledDriver.getNumPixels(); pixel++) {
                ledDriver.setPixelColour(pixel, colours[(i + pixel) % colours.length]);
            }

            ledDriver.render();
            PixelAnimations.delay(50);
        }
    }

    private static void test2(LedDriverInterface ledDriver) {
        System.out.println("test2()");

        // Set all off
        ledDriver.allOff();

        int delay = 20;

        // Gradually add red
        System.out.println("Adding red...");
        for (int i = 0; i < 256; i += 2) {
            for (int pixel = 0; pixel < ledDriver.getNumPixels(); pixel++) {
                ledDriver.setRedComponent(pixel, i);
            }

            ledDriver.render();
            PixelAnimations.delay(delay);
        }

        // Gradually add green
        System.out.println("Adding green...");
        for (int i = 0; i < 256; i += 2) {
            for (int pixel = 0; pixel < ledDriver.getNumPixels(); pixel++) {
                ledDriver.setGreenComponent(pixel, i);
            }

            ledDriver.render();
            PixelAnimations.delay(delay);
        }

        // Gradually add blue
        System.out.println("Adding blue...");
        for (int i = 0; i < 256; i += 2) {
            for (int pixel = 0; pixel < ledDriver.getNumPixels(); pixel++) {
                ledDriver.setBlueComponent(pixel, i);
            }

            ledDriver.render();
            PixelAnimations.delay(delay);
        }

        // Set all off
        ledDriver.allOff();
    }

    private static void hsbTest(LedDriverInterface ledDriver) {
        System.out.println("hsbTest()");
        float brightness = 0.5f;

        for (float hue = 0; hue < 1; hue += 0.05f) {
            for (float saturation = 0; saturation <= 1; saturation += 0.05f) {
                for (int pixel = 0; pixel < ledDriver.getNumPixels(); pixel++) {
                    ledDriver.setPixelColourHSB(pixel, hue, saturation, brightness);
                }
                ledDriver.render();
                PixelAnimations.delay(20);
            }
        }
    }

    private static void hslTest(LedDriverInterface ledDriver) {
        System.out.println("hslTest()");
        float luminance = 0.5f;

        for (float hue = 0; hue < 360; hue += (360 / 20)) {
            for (float saturation = 0; saturation <= 1; saturation += 0.05f) {
                for (int pixel = 0; pixel < ledDriver.getNumPixels(); pixel++) {
                    ledDriver.setPixelColourHSL(pixel, hue, saturation, luminance);
                }
                ledDriver.render();
                PixelAnimations.delay(20);
            }
        }
    }
}

Main.kt

fun main(args: Array<String>) {
    println("APP STARTED")
    WS281xTest.run()
    println("APP FINISHED")
}

I also tried replacing the driver to new WS281xSpi(0, 8, StripType.WS2812, 64, 1) but got a different error:

APP STARTED
Using GPIO 10

09:48:02.643 [main] WARN com.diozero.internal.spi.SpiDeviceFactoryInterface.getSpiBufferSize - Unable to read kernel SPI buffer size, using default: java.nio.file.NoSuchFileException: /sys/module/spidev/parameters/bufsiz

rainbowColours()
Error: com.diozero.api.RuntimeIOException: Error in spiTransfer(), response: -1

com.diozero.api.RuntimeIOException: Error in spiTransfer(), response: -1
    at com.diozero.internal.provider.builtin.spi.NativeSpiDevice.write(NativeSpiDevice.java:96)
    at com.diozero.internal.provider.builtin.spi.NativeSpiDevice.write(NativeSpiDevice.java:90)
    at com.diozero.internal.provider.builtin.DefaultNativeSpiDevice.write(DefaultNativeSpiDevice.java:76)
    at com.diozero.api.SpiDevice.write(SpiDevice.java:201)
    at com.diozero.ws281xj.spi.WS281xSpi.render(WS281xSpi.java:188)
    at com.diozero.WS281xTest.rainbowColours(WS281xTest.java:43)
    at com.diozero.WS281xTest.run(WS281xTest.java:21)
    at MainKt.main(Main.kt:20)
    Suppressed: com.diozero.api.RuntimeIOException: Error in spiTransfer(), response: -1
        at com.diozero.internal.provider.builtin.spi.NativeSpiDevice.write(NativeSpiDevice.java:96)
        at com.diozero.internal.provider.builtin.spi.NativeSpiDevice.write(NativeSpiDevice.java:90)
        at com.diozero.internal.provider.builtin.DefaultNativeSpiDevice.write(DefaultNativeSpiDevice.java:76)
        at com.diozero.api.SpiDevice.write(SpiDevice.java:201)
        at com.diozero.ws281xj.spi.WS281xSpi.render(WS281xSpi.java:188)
        at com.diozero.ws281xj.spi.WS281xSpi.allOff(WS281xSpi.java:195)
        at com.diozero.ws281xj.spi.WS281xSpi.close(WS281xSpi.java:109)
        at com.diozero.WS281xTest.run(WS281xTest.java:20)
        ... 1 more

APP FINISHED
open failed: No such file or directorySPI message transfer failed: Bad file descriptorSPI message transfer failed: Bad file descriptor
mkpazon commented 2 years ago

Update: Managed to remove the error by

  1. Enable SPI through raspi-config
  2. Run sudo chmod 666 /dev/spidev*

The program is running but the led strip isn't working. I could be making the wrong connections. I'll start debugging hardware.

mkpazon commented 2 years ago

Got the leds to open up BUT all it does is render white color.

GPIO PIN = 10

mkpazon commented 2 years ago

Managed to make it work. Read through https://github.com/jgarff/rpi_ws281x and learned that for Raspberry Pi 3 I had to add a couple of configurations: