1

As the answers to this question and this one state, setup() and loop() are identical in the way they execute code (apart from the obvious looping function of loop()).

However.

I get different results with following two pieces of code:

Code run once, in setup()

/*
 * light_ws2812 library test
 */ 

#include <WS2812.h>

WS2812 LED(1); // 1 LED

cRGB value;

void setup() {
    LED.setOutput(13); // Digital Pin 13

    value.b = 0; value.g = 0; value.r = 255; // RGB Value -> Yellow?
    LED.set_crgb_at(0, value); // Set value at LED found at index 0
    LED.sync(); // Sends the value to the LED
}

void loop() {
}

Code run once, in loop()

/*
 * light_ws2812 library test
 */ 

#include <WS2812.h>

WS2812 LED(1); // 1 LED

cRGB value;

bool hasBeenSet = false;

void setup() {
    LED.setOutput(13); // Digital Pin 13
}

void loop() {
  if (hasBeenSet == false){
    value.b = 0; value.g = 0; value.r = 255; // RGB Value -> Red
    LED.set_crgb_at(0, value); // Set value at LED found at index 0
    LED.sync(); // Sends the value to the LED
    hasBeenSet = true;
  }
}

The difference:

The code run in setup() makes the LED flash once with the desired color.
The code run in loop() makes the LED stay lit with the desired color.

With the data being transmitted on pin 13, I can tell (because of the LED on there) in both cases data is being sent only once. With the loop() version I can even disconnect the data line after the color has been set, and it will stay lit.

I can only conclude the same code is executed differently in both cases.

Is there some sort of (soft) power reset after setup()? That could be a potential cause, as the color is stored in volatile memory on the WS2812B (if I'm not mistaken).


Link to the library used: http://github.com/cpldcpu/light_ws2812

1

2 Answers 2

2

After some discussion it turned out to be a hardware problem. For the sake of completeness I'll outline the suggestions I made.

  • There was some initial confusion (see the edits) where the hasBeenSet flag was initialized the wrong way around.
  • I could not reproduce the problem on my Uno and my WS2812 chip, so the issue was: what was different between his setup and mine?
  • Possible wiring issue. Make sure +5V, Gnd and Din (data in) are wired correctly.
  • Possibly faulty WS2812 chip - try with another one.
  • Possibly faulty Arduino - try with another one.
  • Possibly Arduino running at the wrong clock speed which would throw the timings out.
  • Possible extra components (eg. capacitors) added to the circuit which were throwing timing out.
  • Possible bug in the library. We eliminated that by trying with my library for Neopixels.

In the end DaJF reported that the problem was solved by using another (or no) breadboard. It seems the breadboard was introducing issues, maybe noise or bad connections.

We never really worked out why doing it in loop rather than setup made such a difference. I can only conclude that the slight timing difference compensated for the bad connections (or capacitance) on the breadboard.

I'm going to stick my neck out a bit and suggest that the capacitance in the breadboard was affecting the "shape" of the signal (we are talking about timings of around 350 ns here). Possibly if you measured with an oscilloscope you would see the problem.

5
  • The hasBeenSet thing was a copy-pasting error. I was trying other stuff in the loop() and I didn't want the hasBeenSet thing to run, so I disabled it. I removed the irrelevant bits of code when I pasted it here, but forgot to make the hasBeenSet thing work again. So technically the cause of the difference wasn't a programming error on my part. I would like you to update that in your answer. If not, that's fine too, it'll make future readers consider their code too :) Otherwise, great answer!
    – KJdev
    Commented Nov 21, 2016 at 11:00
  • Maybe you could add a link to your page about the NeoPixels/WS2812B as well? As in a "More info about that {here}." at the end of the last paragraph?
    – KJdev
    Commented Nov 21, 2016 at 11:06
  • Well, the link is mentioned in the last bullet point. Did you want it mentioned again?
    – Nick Gammon
    Commented Nov 21, 2016 at 22:47
  • 1
    I reworded the part about it being a bug to "confusion".
    – Nick Gammon
    Commented Nov 21, 2016 at 22:48
  • I should've checked, but I figured the link was the GitHub repo. My bad. I think it's perfect now, thanks!
    – KJdev
    Commented Nov 22, 2016 at 0:43
1

As you can see in the source code there is really nothing going on between the setup call and the first loop iteration.

If I'm not mistaken, this type of LED needs a frequent "update" on which color to display, at a precisely timed interval (I suppose this gets more important the more LEDs you have, since they are "addressed" bases on this signal timing.)

I think you really should keep calling sync() in the loop even if you are not actually changing the desired color, to keep "refreshing" the LED. This is just based of a quick analysis of the library code and examples though.

Why you get different results in the samples below could simply be due to the LED randomly "settling" in two different states when no longer getting data. The chst conversation seems to indicate there may have been other reasons as well.

1
  • 1
    No, the LED doesn't need updating. Once the signal is latched you can disconnect the data pin. I have a page about NeoPixels which shows the timings. There are other useful pages about them elsewhere. The latching is done by a gap of about 9 µs with no data (no 1-bits). Once latched they stay latched until more 1-bits arrive.
    – Nick Gammon
    Commented Nov 21, 2016 at 4:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.