Black Lives Matter - Action and Equality. ... Adafruit is open and shipping.

Help needed! REALLY basic!)

Hey guys!

I'm embarrassed to post this actually...but:

I'm trying to get a Gemma M0 to make a strip of neopixels flash at definable rates, with various colours.

I have tried several examples off the net in an effort to learn the basics of the code.

I understand the logic, and can see where I have to define things, load lib's etc....

My examples do some nice things: all the things I'm trying to do, in fact, but I need to essentially patch little bits of several together to get the final result, iyswim?

They all run: when I start copying and pasting, however, things go wrong!

I KNOW it's just a case of getting the right things in the right order, and not missing anything out.

That's my trouble: I simply don't know what I'm getting wrong! Very frustrating.

It's going to be something really simple, hence my embarrassment! :-)

Just as a starting point to develop things from, I'd like to do this:

When powered up, the strip starts flashing at a definable rate, in a definable colour. Thats it! (to start with!)

My first exercise was to get the onboard neopixel to flash once every second (the guide example code on the CircuitPython tuition page)

Then I copied / looked at a project that drives a neopixel strip with varying colours.
I figured that if I could use the code from the first one, with the lib, output pin, etc, from the second one, it would work? Not so, it seems?!

I reckon I've been messing around with this on and off for weeks now! lol!

Here's the code I currently have:

Code: Select all | TOGGLE FULL SIZE
`import timeimport boardimport neopixel pixel_pin = board.D1num_pixels = 8 pixels = neopixel.NeoPixel(pixel_pin, num_pixels, brightness=0.3)RED = (255, 0, 0)YELLOW = (255, 150, 0)GREEN = (0, 255, 0)CYAN = (0, 255, 255)BLUE = (0, 0, 255)PURPLE = (180, 0, 255)while True:    pixels.fill(CYAN)    pixels.show()    # Increase or decrease to change the speed of the solid color change.    time.sleep(1)`

I'm thinking a couple of lines will sort this?

I'm not sure what the relevance of the "time,sleep" is, either?

I know that somewhere I need to tell the pixels how long to stay on for, then how long to go off for...in a loop...? Am I right?

Any help much appreciated...

GregNouveau

Posts: 12
Joined: Sun Jul 05, 2020 6:02 am

Re: Help needed! REALLY basic!)

btw, I'm using CP 2.x, and MU as my editor. Had no issues with that, nor with Gemma...all works fine with the correct code!

One thing I am wondering:
We're told to always use the latest Python?

I tried to update to 5.xx, and also downloaded the respective library zip.
However, after flashing Gemma and copying neopixel.mpy into my Lib folder, the code that worked before no longer worked.

I'm assuming that "board" is included in the python package, and "time" also? (they're not in the zip package)

I ended up reverting to my original 2.x.x, (copied straight from another Gemma) and everything worked again.

I'm still playing around with this (and have broken the code again..lol!)
Could I maybe achieve this using PWM...but not on output D1, as it seems Gemma has no PWM on this pin..?

GregNouveau

Posts: 12
Joined: Sun Jul 05, 2020 6:02 am

Re: Help needed! REALLY basic!)

I tried to edit my first post, but it wouldn't let me...but I've made a few mods, and made some progress!

Here's the code:

Code: Select all | TOGGLE FULL SIZE
`# CircuitPython demo - NeoPixelimport timeimport boardimport neopixelpixel_pin = board.D1num_pixels = 8pixels = neopixel.NeoPixel(pixel_pin, num_pixels, brightness=0.02, auto_write=False)OFF = (0, 0, 0)RED = (255, 0, 0)YELLOW = (255, 150, 0)GREEN = (0, 255, 0)CYAN = (0, 255, 255)BLUE = (0, 0, 255)PURPLE = (180, 0, 255)while True:    pixels.fill(GREEN)    pixels.show()    # Increase or decrease to change the speed of the solid color change.    time.sleep(0.5)    pixels.fill(OFF)    pixels.show()    time.sleep(0.5)`

This is successfully flashing 8 pixel quickly: I can define the colour, no probs there.

However, I'm a little concerned about the rate / PWM?
It is being told how long to "sleep" for (half a second): does this mean that when it has lit the pixel, then it kind of "suspends", which is the "time.sleep" part.

As I have told it in the 2nd section to switch all of the pixels off (also for half a second), then I have a 50% cycle...this I can adjust by varying the durations relative to each other.

My question is how fast can I get this to go.....is there a better way to do this using the boards proper PWM feature on a different pin?

I'm after a flash rate that I can very between 40Hz and 100Hz, ideally: my aim is to use this to drive transistors to switch a large number of LED's, ultimately, for a video shoot, perhaps...?

But I'm just experimenting with a few pixels at the moment! :-)

GregNouveau

Posts: 12
Joined: Sun Jul 05, 2020 6:02 am

Re: Help needed! REALLY basic!)

I started with a Gemma M0 too.

time.sleep(N) will pause for N seconds, the documentation for time library can be found on https://circuitpython.readthedocs.io/en ... ings/time/ . In this case it's being used to leave the NeoPixels on the set colour before changing it to another.

I just tried 5.3.0. The dependencies have changed, it needs the adafruit_pypixelbuf library installed in lib directory for the "small" boards like the Gemma M0 and no longer needs adafruit_bus_device. I'll check if that's documented but I don't think it is.

There's also a bug with specifying the brightness, I'll log a ticket for this. If you remove that parameter it'll work on 5.3.0. You can scale down the numbers in the colours to achieve the same thing. Added later: GitHub: adafruit/Adafruit_CircuitPython_NeoPixel Can't set brightness in NeoPixel() #85.

There's no need to call show() as the default value for the auto_write parameter is True. Calling it here is harmless, it will slow things down a bit so this becomes more important if you are doing many independent changes to a large number of pixels rapidly.

kevinjwalters

Posts: 674
Joined: Sun Oct 01, 2017 3:15 pm

Re: Help needed! REALLY basic!)

kevinjwalters wrote:I started with a Gemma M0 too.

time.sleep(N) will pause for N seconds, the documentation for time library can be found on https://circuitpython.readthedocs.io/en ... ings/time/ . In this case it's being used to leave the NeoPixels on the set colour before changing it to another.

I just tried 5.3.0. The dependencies have changed, it needs the adafruit_pypixelbuf library installed in lib directory for the "small" boards like the Gemma M0 and no longer needs adafruit_bus_device. I'll check if that's documented but I don't think it is.

There's also a bug with specifying the brightness, I'll log a ticket for this. If you remove that parameter it'll work on 5.3.0. You can scale down the numbers in the colours to achieve the same thing. Added later: GitHub: adafruit/Adafruit_CircuitPython_NeoPixel Can't set brightness in NeoPixel() #85.

There's no need to call show() as the default value for the auto_write parameter is True. Calling it here is harmless, it will slow things down a bit so this becomes more important if you are doing many independent changes to a large number of pixels rapidly.

Ah, I see!

I'll check out the "time" doc and the brightness thing, too.
Guess I'll remove the show part, too....?

I'm thinking that all I'm trying to achieve should be fairly simple as I'm only calling on one colour at a time, across all pixels?
If I was gonna try, say, rainbow effects flowing down a long string of Neo's, I could understand there being potential timing issues at high speeds....

It's the tight control of the rate that's more important to me at this stage: It is nice to be able to specify an exact colour, though: I'll obviously end up using this feature further down the line...lol!

Any ideas what the resolution of the time parameter is? Would it work with, say, "0.00001" ?

I have tried this, but it didn't seem to be flashing any quicker that it did at "0.0001"....? :-(

GregNouveau

Posts: 12
Joined: Sun Jul 05, 2020 6:02 am

Re: Help needed! REALLY basic!)

I believe it's limited to millisecond resolution on the current hardware/implementation. Microsecond timing is more the realm of C/C++ programming where there's faster and more predictable execution. Oddly, MakeCode can be quicker than CircuitPython in some cases because it's compiled.

The 5.x neopixel library changes were designed to improve performance but I've not followed the story closely. It's possible the code runs more efficiently on the slightly larger boards like CPX.

I would also experiment with different pins to check the performance on each. I had a look for details on this but couldn't find CircuitPython specific ones. There's only three choices so it's a quick test!

kevinjwalters

Posts: 674
Joined: Sun Oct 01, 2017 3:15 pm

Re: Help needed! REALLY basic!)

Yeh....that's the part I don't get, really?

If I want my pixels to flash at 100Hz, which is the fastest I'll need, that's a mere 10ms....!

So I figured that if I can get my pixels to turn on for 5ms, and turn off for 5ms, then I'm there..?

Seems really simple lol!

I know code takes time to execute: I can tweak the time to fine tune the timing, but I really need to know how long the loop takes to execute.

I've now told gemma that I'm using just one Neo, so there is no scanning delay anymore? Or is there? I DO still have 8 physical pixels connected: maybe it is still scanning them as if there were 8 active, and I'm getting a delay from THAT..?!

GregNouveau

Posts: 12
Joined: Sun Jul 05, 2020 6:02 am

Re: Help needed! REALLY basic!)

Anyone......?

Bueller?

Bueller?

:-)

GregNouveau

Posts: 12
Joined: Sun Jul 05, 2020 6:02 am

Re: Help needed! REALLY basic!)

This is where I'm at:

Code: Select all | TOGGLE FULL SIZE
`import timeimport board# import pulseioimport neopixel pixel_pin = board.D0num_pixels = 1pixels = neopixel.NeoPixel(pixel_pin, num_pixels, brightness=0.3)# led = pulseio.PWMOut(pixel_pin, frequency=2, duty_cycle=0)pixels[0] = (0, 255, 0)while True:    for i in range(100):        # PWM LED up and down        if i < 50:            led.duty_cycle = int(i * 2 * 65535 / 100)  # Up        else:            led.duty_cycle = 65535 - int((i - 50) * 2 * 65535 / 100)  # Down        time.sleep(0.01)`

I'm sure most of the required stuff is there...somewhere...but there's something not quite right, as it doesn't work for me....

With the pulseio and the led lines commented out, I have a green pixel, which I can control the colour of with the pixels line.
So far, so good!

Somehow I need to activate the duty cycle part: i'm sure the issue lies with some sort of conflict between the pixels and the led lines (when commented back in)?

Question is....what?

Anybody able to shed any light on this for me?

Many thanks.

GregNouveau

Posts: 12
Joined: Sun Jul 05, 2020 6:02 am

Re: Help needed! REALLY basic!)

I've taken the liberty of adding CODE tags around your code to format it. To do this yourself, select the code and press the [ CODE ] button you see above the editing rea.

You cannot use PWMOut on NeoPixels. They are not ordinary LED's: they take a data stream of what to turn on and turn off. Are you trying to do signalling with the NeoPixels? Try using PulseOut with ordinary LED's instead.

danhalbert

Posts: 2073
Joined: Tue Aug 08, 2017 12:37 pm

Re: Help needed! REALLY basic!)

Ahh....that would be something to do with it!!

So I could potentially just PWM a normal LED from D0, but to use a neopixel, I'd need to do it another way?

Is it not possible to set up, say, a 100Hz PWM on output D0, tell the output what colour you want, and specify a Neopixel on that output?

I thought this would be easy? lol!

GregNouveau

Posts: 12
Joined: Sun Jul 05, 2020 6:02 am

Re: Help needed! REALLY basic!)

Is it not possible to set up, say, a 100Hz PWM on output D0, tell the output what colour you want, and specify a Neopixel on that output?

Nope, sorry, NeoPixels operate by sending RGB levels in a serial data stream over the data line. And you can't PWM the power line, because that will turn the digital logic inside the NeoPixel on and off at a fast rate.

If you want to PWM an RGB-controllable LED (such as https://www.adafruit.com/product/159), that is possible.

Do you want to do this to do flickering at a certain rate, to send multi-colored pulsed data, to control the brightness, or just to see if it's possible?

danhalbert

Posts: 2073
Joined: Tue Aug 08, 2017 12:37 pm

Re: Help needed! REALLY basic!)

I'm trying to make a programmable strobe that will sync with video, or not, depending on what we wanna do....

The fastest rate would be around 120Hz, down to around 25Hz..? Nothing spectacular, but it must be stable.

I have managed to get a setup working with neo's / Gemma but it was trial and error to get the rate right: I'm assuming because of the program re-triggering each time, sending the data..? (using the code in my 3rd post above) I tweaked the 2 durations, but I couldn't get it stable at 100Hz. It was a little slow, and when I tweaked it by a ms, it was too fast! I'm guessing retriggering / resolution was to blame?

I could use a normal LED, but then I wouldn't have the luxury of playing games with colours at a later date, when I'm a bit more conversant with the code... :-)

The CA diode could be an option, too: would it be a case of sending a pwm signal to each cathode from a separate output, hence treating each RGB colour independently?

GregNouveau

Posts: 12
Joined: Sun Jul 05, 2020 6:02 am

Re: Help needed! REALLY basic!)

CircuitPython is not the best choice if you are trying to do something with tight timing requirements. It can interrupt what it's doing for garbage-collection reasons. Arduino would be better.

You could try a strobe kind of loop in Arduino and see if you can control it fast enough to get the timing rates you want.

DotStars can be run at a much faster rate than NeoPixels, and they take less overhead to run.

Using multi-cathode RGB LED's at a particular timing rate and supporting variable colors is not so easy. The usual way of varying the colors is to alter the intensity, and the usual way of doing that is to vary the PWM rate to provide the illusion of brighter and darker. Instead, you'd need to vary the current in some way, by varying the input voltage or the series resistor.

If you are trying to sync with video, you'd want some kind of sync pulse from the video camera, I'd assume. Doing it free-running will drift over time.

I did a little websearching, see here, for instance: https://forum.arduino.cc/index.php?topic=224659.0

danhalbert

Posts: 2073
Joined: Tue Aug 08, 2017 12:37 pm

Re: Help needed! REALLY basic!)

Our application does not really need to sync to the video and stay in sync: it's more the drift and out-of-sync effects we can get that we're interested in.

We can sync the flashing in post: as long as it is stable, and controllable by us, that is!

So you reckon I could use a Dotstar, then?

We don't know exactly what we're going to end up doing with this: for the time being, I'm just playing with a single Pixel / LED, and seeing if things work in principle.

If I can get it stable, then we'll probably end up using the pulses to fire a power transistor, and scale things up a bit..!

GregNouveau

Posts: 12
Joined: Sun Jul 05, 2020 6:02 am