Coder Social home page Coder Social logo

Comments (12)

andrewfstratton avatar andrewfstratton commented on May 27, 2024

Note: This isn't about resetting the leds (since they are reset on powerup) but about being able to change them immediately after power on.

from tinygo.

aykevl avatar aykevl commented on May 27, 2024

How much delay do you need here to fix the problem?
I can think of two possible reasons why this happens:

  1. If the power comes up at the same time, it may be that the LEDs need a bit of time to fully start up.
  2. It may be that the pin is not read as "low" before initialization leading to the first bit to be read incorrectly.

I'm not sure what a correct fix would be: this sounds like a problem that depends on the exact system so I'm hesitant to put in a delay without understanding the problem.

Also, usually these LEDs start up black? I've seen exceptions but most of them are black when powering on.

from tinygo.

andrewfstratton avatar andrewfstratton commented on May 27, 2024

How much delay do you need here to fix the problem?

The delay was for me to bodge it by resetting the leds after they have been switched on in error

I have a version of the code below that may help - it switches the leds on and off. I then recorded the result on resetting it several times using the Waveshare RP2040 Zero (not the keyboard):

  • Green (initial flash)
  • 5 x Green, 1 x Blue
  • 3 Green, 1 Blue
  • 7 Green, 1 Blue
  • 6 Green, 1 Off (black) CORRECT?!
package main

import (
	"image/color"
	"machine"
	"time"

	"tinygo.org/x/drivers/ws2812"
)

const GPIO_PIN = machine.GPIO16

func main() {
	var led ws2812.Device
	led = ws2812.NewWS2812(GPIO_PIN)
	led.Pin.Configure(machine.PinConfig{Mode: machine.PinOutput})
	var Off = color.RGBA{R: 0x00, G: 0x00, B: 0x00}
	var On = color.RGBA{R: 0x1f, G: 0x1f, B: 0x1f}
	var colours [1]color.RGBA
	time.Sleep(time.Millisecond * 1000)
	for {
		for id := range colours {
			colours[id] = Off
		}
		led.WriteColors(colours[:])
		time.Sleep(time.Millisecond * 500)
		for id := range colours {
			colours[id] = On
		}
		led.WriteColors(colours[:])
		time.Sleep(time.Millisecond * 500)
	}
}

I then swapped the On and Off round and recorded the resets (i.e. On first then Off):

  • 14 Green, then 1 Yellow (?!)

I then removed the first 1 second delay and ran again:

  • 4 Green, Yellow
  • 4 Green, yellow
  • Green, 2 Yellow
  • Green yellow
  • Green

And then swapped back to Off then On (with no initial delay):

  • 2 Green, 1 Black
  • 6 Green, Black,
  • 3 Green, 2Black
  • Green, Black
  1. If the power comes up at the same time, it may be that the LEDs need a bit of time to fully start up.

I tried a plain 1 second delay at the beginning of main - still incorrect led lit after startup beginning

  1. It may be that the pin is not read as "low" before initialization leading to the first bit to be read incorrectly.

I also tried a delay after configuring the Pin before write the leds - no joy - maybe the initialisation is incorrectly starting comms with the leds?

Also, usually these LEDs start up black? I've seen exceptions but most of them are black when powering on.

I know - so strange they are green/yellow/red more often than black. They are black if I don't access them?!

from tinygo.

andrewfstratton avatar andrewfstratton commented on May 27, 2024

Another experiment:

Here's the code this time there's a half second delay before setting the leds Off. The result is that many resets show Green (then go off), less often the leds are off.

package main

import (
	"image/color"
	"machine"
	"time"

	"tinygo.org/x/drivers/ws2812"
)

const GPIO_PIN = machine.GPIO16

func main() {
	var led ws2812.Device
	led = ws2812.NewWS2812(GPIO_PIN)
	led.Pin.Configure(machine.PinConfig{Mode: machine.PinOutput})
	time.Sleep(time.Millisecond * 500)
	var Off = color.RGBA{R: 0x00, G: 0x00, B: 0x00}
	var colours [1]color.RGBA
	for {
		for id := range colours {
			colours[id] = Off
		}
		led.WriteColors(colours[:])
		time.Sleep(time.Millisecond * 500)
	}
}

However, if second delay is removed, then the behaviour changes:

led.WriteColors(colours[:])
// time.Sleep(time.Millisecond * 500)

Now, resets get Green - and STAY GREEN, most of the time, sometimes they are black.

This looks to me like the led write can't cope with the traffic...

from tinygo.

deadprogram avatar deadprogram commented on May 27, 2024

At least from what I can tell, this is something related to your specific hardware @andrewfstratton not TinyGo itself. Or perhaps related to the ws2812 driver implementation in https://github.com/tinygo-org/drivers/tree/release/ws2812

from tinygo.

andrewfstratton avatar andrewfstratton commented on May 27, 2024

So I tried this with a Cytron Maker Pi RP2040 which has 2 RGB Leds - this is my last RP2040 with WS2812 Leds - so I don't have any other boards I can try...it would be good to see if other boards get this behaviour since I suspect this is not board or manufacturer specific (though I have only tried two manufacturers) and may therefore be the (WS2812) library...

There appear to be two issues here and therefore this issue may need splitting:

Issue 1 : After a reset, the first write to leds, sets led 0 to green incorrectly
Issue 2 : If the leds are set using writeColours without a delay, then requests can fail, possibly due to being continually overwritten/re-requested

Please see the code further down...

I get the following behaviour:

  1. after flash or reset : led 0 is green consistently and led 1 is pink - neither change
  2. after power off then on, both leds are off

If I uncomment the delay (b) sleep code, then:

  1. after flash or reset: at start, led 0 is green and led 1 is pink, then both toggle between off and pink. The first write to led 0 is being ignored
  2. after power on, the same behaviour is seen - i.e. led 0 is green initially
package main

import (
	"image/color"
	"machine"
	"time"

	"tinygo.org/x/drivers/ws2812"
)

const GPIO_PIN = machine.GPIO18

var Off = color.RGBA{R: 0x00, G: 0x00, B: 0x00}
var On = color.RGBA{R: 0x3f, G: 0x00, B: 0x1f}

func main() {
	led_pin := GPIO_PIN
	led_pin.Configure(machine.PinConfig{Mode: machine.PinOutput})
	// delay A
	time.Sleep(time.Millisecond * 500)
	var led ws2812.Device = ws2812.NewWS2812(led_pin)
	var colours [2]color.RGBA
	for {
		// (b) delay
		// time.Sleep(time.Millisecond * 500)
		for id := range colours {
			colours[id] = On
		}
		led.WriteColors(colours[:])
		// (b) delay
		// time.Sleep(time.Millisecond * 501)
		for id := range colours {
			colours[id] = Off
		}
		led.WriteColors(colours[:])
	}
}

from tinygo.

andrewfstratton avatar andrewfstratton commented on May 27, 2024

I've discovered that the first WS2812 write after power off or reset writes green as 0xff (or a high value - it's hard to be sure) to led 0 instead of the green value given - red and blue values are still set.

e.g. in the code below - both led 0 and led 1 should show blue after reset, but led 0 show turquoise and led 1 shows blue.

Note: I didn't use 0xff to protect my eyes

package main

import (
	"image/color"
	"machine"
	"time"

	"tinygo.org/x/drivers/ws2812"
)

const GPIO_PIN = machine.GPIO18

var Off = color.RGBA{R: 0x00, G: 0x00, B: 0x00}
var Pink = color.RGBA{R: 0x3f, G: 0x00, B: 0x1f}
var Blue = color.RGBA{R: 0x00, G: 0x00, B: 0x3f}

func main() {
	led_pin := GPIO_PIN
	led_pin.Configure(machine.PinConfig{Mode: machine.PinOutput})
	// delay A
	time.Sleep(time.Millisecond * 500)
	var led ws2812.Device = ws2812.NewWS2812(led_pin)
	var colours [2]color.RGBA
	colours[0] = Blue
	colours[1] = Blue
	led.WriteColors(colours[:])
	for {
		// (b) delay
		time.Sleep(time.Millisecond * 500)
		for id := range colours {
			colours[id] = Pink
		}
		led.WriteColors(colours[:])
		// (b) delay
		time.Sleep(time.Millisecond * 500)
		for id := range colours {
			colours[id] = Off
		}
		led.WriteColors(colours[:])
	}
}

from tinygo.

aykevl avatar aykevl commented on May 27, 2024

This sounds like you have something wrong with your wiring.
A few things to check:

  • Is the ground of the WS2812 strip connected to the ground of the RP2040 board?
  • Do the LEDs have a good enough power supply?
  • Is the data wire connected well enough? It shouldn't be too long (more than 1m or so can lead to problems).
  • Are you sure you've connected to the right pin on the board?

See https://learn.adafruit.com/adafruit-neopixel-uberguide/basic-connections for a more extensive guide.

I'm running a bunch of WS2812 LEDs every night in a project of mine, and they're powered using a rp2040. So that combination most certainly works for me.

from tinygo.

andrewfstratton avatar andrewfstratton commented on May 27, 2024

These are all onboard rgb leds - 4 different board types with two different manufacturers.

Power might be an issue but seems unlikely with one RGB led and the issue occurring on reset and power on - and the arduino C code works fine...

Please could you try my last listing and see what happens?

from tinygo.

Gustavomurta avatar Gustavomurta commented on May 27, 2024

I didn't read all the topics.
I'm sending this link, but I don't know if it has anything to do with the problem.
tinygo-org/pio#5

from tinygo.

aykevl avatar aykevl commented on May 27, 2024

Did a quick test and I can confirm that the first write results in some weird colors. Subsequent writes work fine however.

This will need a bit more investigation to see what's going on. But a workaround would be something like this for the first write:

        led.WriteColors(colours[:])
        time.Sleep(time.Millisecond * 20)
        led.WriteColors(colours[:])

from tinygo.

aykevl avatar aykevl commented on May 27, 2024

My best guess would be that the first time the code runs, not all the code has been loaded into the flash cache, slowing down the assembly and messing up the timing of the signal.

I'm not sure what the best way would be to fix that. One solution would be to place the code in RAM, thereby taking up precious RAM (though not so precious on the rp2040). Another solution would be some sort of prefetch, but unfortunately the rp2040 doesn't support that. The easiest solution would probably to send data of a single pixel (or even a single byte), sleep for ~10ms, and then send the real data. Like this:

        led.Write([]byte{0x00})
        time.Sleep(time.Millisecond * 10)
        led.WriteColors(colours[:])

(This might still result in a flash sometimes and I'm not sure we should add this to the ws2812 driver because it's chip-specific).

from tinygo.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.