CFastLED::showColor() suddenly started showing wrong colors

So my Arduino Nano chinese clone board I used to control WS2812b 40 LEDs strip sudenly started showing wrong colors.
I tried this simple sketch:

#include "FastLED.h"

#define NUM_LEDS 40 // Max LED count
#define LED_PIN 6 // arduino output pin
#define GROUND_PIN 10
#define BRIGHTNESS 255 // maximum brightness
#define SPEED 115200 // virtual serial port speed

CRGB leds[NUM_LEDS];
uint8_t * ledsRaw = (uint8_t *)leds;

void setup()
{
	pinMode(10, OUTPUT); 
	digitalWrite(10, LOW);
	FastLED.addLeds<WS2812B, 6, RGB>(leds, NUM_LEDS);
	
	// initial RGB flash
	LEDS.showColor(CRGB(255, 0, 0));
	delay(1000);
	LEDS.showColor(CRGB(0, 255, 0));
	delay(1000);
	LEDS.showColor(CRGB(0, 0, 255));
	delay(1000);
	LEDS.showColor(CRGB(255, 255, 0));
	delay(1000);
	LEDS.showColor(CRGB(0, 255, 255));
	delay(1000);
	LEDS.showColor(CRGB(255, 0, 255));
	delay(1000);
}

void loop() {}

And instead of proper colors I got: Green Red Blue Red Red Green + last Green doesn't turn off at all.
DIN on strip was connected to D6, +5V and ground to PSU.
I double checked speed — it is set right.
I reinstalled driver from link in General Guidance and How to use the Forum — zero changes.
I tried another PC — problem remains.
I tried another board (new one) — it changed nothing.
I tried another new LED strip (10 LEDs long with changing NUM_LEDS accordingly) — same result.
Any ideas what can cause this?

Any ideas what can cause this?

Yes

my Arduino Nano chinese clone board

It sounds like the clock is not very accurate and is running too slow which would explain the fact that the last LED does not light and the colours are wrong.

However I would expect the first LED at least to be right if the clock is slightly off, but if that is wrong then the clock is way off. Does it have a crystal or a resonator? You might try replacing the crystal with a good one.

Grumpy_Mike:
It sounds like the clock is not very accurate and is running too slow which would explain the fact that the last LED does not light and the colours are wrong.

As I said I was also thinking about board problems but it worked fine for like a 1-1.5 years. And the second new board was really new (in sealed antistatic package and all).

Grumpy_Mike:
However I would expect the first LED at least to be right if the clock is slightly off

Well it isn't.
I tested different combinations of colors and found this:

  1. R and G channels are swapped somehow.
  2. Color simillar to white can be achieved not at (255,255,255) but at ~(79,30,255) (and it is less bright than any single color).
  3. If I add more to 1st channel all turns green. If after that I add more to 2nd channel all turns red.
  4. At ~(79,69,255) color becomes orange with dimming red LEDs (why are they dimming?).
  5. When I used previous script with AmbiBox I was able achieve white color on one 1st LED while turning off others. But the more LEDs I lit up — the more red was added to the color.
    So the result is not random colors when your clock is off, it is colors have wrong proportions and two of them are swapped.

Grumpy_Mike:
Does it have a crystal or a resonator? You might try replacing the crystal with a good one.

It does (layout is same as original 3.0), but there's no way on earth I could solder this tiny thing on board. I'm having hard time just soldering strips togeter (fingers are a bit shaking, some health issues).

but it worked fine for like a 1-1.5 years.

Then it looks like a part has failed, a sudden change in resonator value can happen and would be classed as a failure. A lot of the parts you get from China have come out of the reject bin from the manufacturers. Your new board could be suffering from the same problem.

It is possible it is due to the external components you have like decoupling or power supply issues it as you don’t describe your setup it is hard to see. Especially if when you swap out the board the fault persists. I am assuming you don’t swap out your external parts.

What you need to to look at the system with an oscilloscope and check out the clock frequencies. Also try using another LED strip, all be it a short one, and see if it works correctly with the strip demo code. Check all the voltages around the circuit, especially the power supply. Also check the output voltage on a scope to see there are no large oscillations on it.

So no series resistor in the data line then? Do you have a large capacitor across the strip’s power input?

Grumpy_Mike:
Then it looks like a part has failed, a sudden change in resonator value can happen and would be classed as a failure.
...
It is possible it is due to the external components you have like decoupling or power supply issues it as you don’t describe your setup it is hard to see. Especially if when you swap out the board the fault persists. I am assuming you don’t swap out your external parts.

This is the scheme that was before:

And seems like it is both PSU and old board.
I detached PSU from old board (currently set to light (79,30,255) color) and powered LED strip directly from board — got all 40 LEDs dimming in orange-red colors.
I swapped LED strip to a new shorter one — got colors closer to white but still dimming.

Next I tried new board (with sketch to control colors from AmbiBox program) and new strip still w/o PSU — got right colors! (almost; red and green channels were swapped but that can be fixed in AmbiBox settings).
Tried new board (still w/o PSU) with old long strip — still right colors.
But CH340G microscheme is burning hot trying to light all 40 LEDs w/o PSU.

So seems like old board is broken and I have to swap PSU.

Grumpy_Mike:
So no series resistor in the data line then? Do you have a large capacitor across the strip’s power input?

No, I don't as you can see on scheme.
I am not radioelectronics engineer, but I can take a guess capacitor is to smooth out power output, is it right?
Have no idea about purpose of resistor though.
Can you explain please? And what characteristic should they have?

but I can take a guess capacitor is to smooth out power output, is it right?

More or less. It lowers the impedance of the power source so that its voltage does not change with rapid switching of the load. Which you might summaries as you do but it is not accurate.

The resistor has two purposes, the first is to protect the first LED if the signal voltage level is above the supply voltage, which could happen especially without a large capacitor, if the power voltage droops. Second it acts as an impedance matching circuit to stop reflections on the signal line.

Thanks for explaining.
What about characteristics? I found on one site for simillar project that 1000μF and 470Ω should be enough, is it so?

found on one site for simillar project that 1000μF and 470Ω should be enough, is it so?

Yes normally that should be fine.

Thanks again. Appreciate your help. I'll buy them this sunday and will see how it will go this time.
Also one question: before I encountered this problem sometimes with adaptive lighting (capturing PC screen for colors instead of static one-color lighting) after couple hours LEDs can start blinking with different colors like crazy.
I was solving this by restarting AmbiBox.
But now I think could it be because of missing capacitor and resistor?

was solving this by restarting AmbiBox.

I am more likely to think it was the AmbiBox, than lack of capacitors. However, things do get hot and it could be the power supply getting hot and its internal capacitors dropping in effective value due to this heat. But then I would expect that the small respite given by resetting the AmbiBox would not allow the power supply to cool much.

It doesn't pay to run components right up to their maximum ratings. As a rule of thumb only run them at 80% of maximum ratings.

So I added resistor and capacitor.
Running +5V from PSU and GND from PSU+Ardunio = red colors.
Running +5V from PSU+Ardunio and GND from PSU+Ardunio = proper colors.
Have no idea why but whatever.
Thanks for help again.

OK glad you got it working. I can’t envisage those two different wirings as a circuit, maybe you could post a diagram of the two?

Well, I think this maybe goes beyond my actual knowledge. Do you know what resources can I see to learn or some detailed example code of a similar work?

Grumpy_Mike:
OK glad you got it working. I can’t envisage those two different wirings as a circuit, maybe you could post a diagram of the two?

Picture isn't mine (I added capacitor as you said), this one just looks better.

Case 1: Running +5V from PSU and GND from PSU+Ardunio = red colors.

Case 2: Running +5V from PSU+Ardunio and GND from PSU+Ardunio = proper colors.

This board also died (same red-orange blinking LEDs) and I decided to use PC's PSU via MOLEX with new one instead of separate +5V PSU. And make a nice case for all that.
Hope this will finally solve the problem.

james85:
Well, I think this maybe goes beyond my actual knowledge. Do you know what resources can I see to learn or some detailed example code of a similar work?

The original sketch is rather simple and very intuitive:

// Arduino interface for the use of ws2812 operated LEDs
// Uses Adalight protocol and is compatible with Boblight, Prismatik etc
// "Magic Word" for synchronisation is 'Ada' followed by LED High, Low and Checksum
//
#include <FastLED.h>

// Define the number of LEDs
#define NUM_LEDS 40
// Define SPI Pin
#define PIN 6
// Baudrate, higher rate allows faster refresh rate and more LEDs
#define serialRate 115200

// Adalight sends a "Magic Word" before sending the pixel data
uint8_t prefix[] = {'A', 'd', 'a'}, hi, lo, chk, i;

// initialise LED-array
CRGB leds[NUM_LEDS];

void setup()
{
	FastLED.addLeds<WS2812, PIN, GRB>(leds, NUM_LEDS);

	Serial.begin(serialRate);
	Serial.print("Ada\n"); // Send "Magic Word" string to host
}

void loop() { 
	// wait for first byte of Magic Word
	for(i = 0; i < sizeof prefix; ++i) {
		waitLoop: while (!Serial.available()) ;;
		// Check next byte in Magic Word
		if(prefix[i] == Serial.read()) continue;
		// otherwise, start over
		i = 0;
		goto waitLoop;
	}
	
	// Hi, Lo, Checksum
	while (!Serial.available()) ;;
	hi=Serial.read();
	while (!Serial.available()) ;;
	lo=Serial.read();
	while (!Serial.available()) ;;
	chk=Serial.read();
	
	// if checksum does not match go back to wait
	if (chk != (hi ^ lo ^ 0x55))
	{
		i=0;
		goto waitLoop;
	}
	
	memset(leds, 0, NUM_LEDS * sizeof(struct CRGB));
	// read the transmission data and set LED values
	for (uint8_t i = 0; i < NUM_LEDS; i++) {
		byte r, g, b;		
		while(!Serial.available());
		r = Serial.read();
		while(!Serial.available());
		g = Serial.read();
		while(!Serial.available());
		b = Serial.read();
		leds[i].r = r;
		leds[i].g = g;
		leds[i].b = b;
	}
	// shows new values
 FastLED.show();
}

You can read FastLED's Wiki for more information.
RN I'm using this sketch (not mine) that should work with lower latency, but I don't know what's going on with Serial in it:

// Slightly modified Adalight protocol implementation that uses FastLED
// library (http://fastled.io) for driving WS2811/WS2812 led strip
#include "FastLED.h"

#define NUM_LEDS 40 // Max LED count
#define LED_PIN 6 // arduino output pin
#define GROUND_PIN 10
#define BRIGHTNESS 255 // maximum brightness
#define SPEED 115200 // virtual serial port speed, must be the same in boblight_config 

CRGB leds[NUM_LEDS];
uint8_t * ledsRaw = (uint8_t *)leds;

// A 'magic word' (along with LED count & checksum) precedes each block
// of LED data; this assists the microcontroller in syncing up with the
// host-side software and properly issuing the latch (host I/O is
// likely buffered, making usleep() unreliable for latch).	You may see
// an initial glitchy frame or two until the two come into alignment.
// The magic word can be whatever sequence you like, but each character
// should be unique, and frequent pixel values like 0 and 255 are
// avoided -- fewer false positives.	The host software will need to
// generate a compatible header: immediately following the magic word
// are three bytes: a 16-bit count of the number of LEDs (high byte
// first) followed by a simple checksum value (high byte XOR low byte
// XOR 0x55).	LED data follows, 3 bytes per LED, in order R, G, B,
// where 0 = off and 255 = max brightness.

static const uint8_t magic[] = {
	'A','d','a'};
#define MAGICSIZE	sizeof(magic)
#define HEADERSIZE (MAGICSIZE + 3)
#define MODE_HEADER 0
#define MODE_DATA	 2

// If no serial data is received for a while, the LEDs are shut off
// automatically.	This avoids the annoying "stuck pixel" look when
// quitting LED display programs on the host computer.
static const unsigned long serialTimeout = 7200000; // 2 hours

void setup()
{
	pinMode(GROUND_PIN, OUTPUT); 
	digitalWrite(GROUND_PIN, LOW);
	FastLED.addLeds<WS2812B, LED_PIN, RGB>(leds, NUM_LEDS);

	// Dirty trick: the circular buffer for serial data is 256 bytes,
	// and the "in" and "out" indices are unsigned 8-bit types -- this
	// much simplifies the cases where in/out need to "wrap around" the
	// beginning/end of the buffer.	Otherwise there'd be a ton of bit-
	// masking and/or conditional code every time one of these indices
	// needs to change, slowing things down tremendously.
	uint8_t
		buffer[256],
		indexIn = 0,
		indexOut = 0,
		mode = MODE_HEADER,
		hi, lo, chk, i, spiFlag;
	int16_t
		bytesBuffered = 0,
		hold = 0,
		c;
	int32_t
		bytesRemaining;
	unsigned long
		startTime,
		lastByteTime,
		lastAckTime,
		t;
	int32_t
		outPos = 0;

	Serial.begin(SPEED); // Teensy/32u4 disregards baud rate; is OK!
	Serial.print("Ada\n"); // Send ACK string to host

	startTime = micros();
	lastByteTime = lastAckTime = millis();

	// loop() is avoided as even that small bit of function overhead
	// has a measurable impact on this code's overall throughput.

	for(;;) {

		// Implementation is a simple finite-state machine.
		// Regardless of mode, check for serial input each time:
		t = millis();
		if((bytesBuffered < 256) && ((c = Serial.read()) >= 0)) {
			buffer[indexIn++] = c;
			bytesBuffered++;
			lastByteTime = lastAckTime = t; // Reset timeout counters
		} 
		else {
			// No data received.	If this persists, send an ACK packet
			// to host once every second to alert it to our presence.
			if((t - lastAckTime) > 1000) {
				Serial.print("Ada\n"); // Send ACK string to host
				lastAckTime = t; // Reset counter
			}
			// If no data received for an extended time, turn off all LEDs.
			if((t - lastByteTime) > serialTimeout) {
				memset(leds, 0,	NUM_LEDS * sizeof(struct CRGB)); //filling Led array by zeroes
				FastLED.show();
				lastByteTime = t; // Reset counter
			}
		}

		switch(mode) {

			case MODE_HEADER:
	 
				// In header-seeking mode.	Is there enough data to check?
				if(bytesBuffered >= HEADERSIZE) {
					// Indeed.	Check for a 'magic word' match.
					for(i=0; (i<MAGICSIZE) && (buffer[indexOut++] == magic[i++]););
					if(i == MAGICSIZE) {
						// Magic word matches.	Now how about the checksum?
						hi	= buffer[indexOut++];
						lo	= buffer[indexOut++];
						chk = buffer[indexOut++];
						if(chk == (hi ^ lo ^ 0x55)) {
							// Checksum looks valid.	Get 16-bit LED count, add 1
							// (# LEDs is always > 0) and multiply by 3 for R,G,B.
							bytesRemaining = 3L * (256L * (long)hi + (long)lo + 1L);
							bytesBuffered -= 3;
							outPos = 0;
							memset(leds, 0, NUM_LEDS * sizeof(struct CRGB));
							mode = MODE_DATA; // Proceed to latch wait mode
						} 
						else {
							// Checksum didn't match; search resumes after magic word.
							indexOut -= 3; // Rewind
						}
					} // else no header match.	Resume at first mismatched byte.
					bytesBuffered -= i;
				}
				break;
	 
			case MODE_DATA:
	 
				if(bytesRemaining > 0) {
					if(bytesBuffered > 0) {
						if (outPos < sizeof(leds))
							ledsRaw[outPos++] = buffer[indexOut++];	 // Issue next byte
						bytesBuffered--;
						bytesRemaining--;
					}
					// If serial buffer is threatening to underrun, start
					// introducing progressively longer pauses to allow more
					// data to arrive (up to a point).
				} 
				else {
					// End of data -- issue latch:
					startTime = micros();
					mode = MODE_HEADER; // Begin next header search
					FastLED.show();
				}
		} // end switch
	} // end for(;;)
}

void loop()
{
	// Not used.	See note in setup() function.
}

If you want to see all project you can look here for example (except I would use AmbiBox software with way more options instead of Bambilight they are using).

elharkesser:
So I added resistor and capacitor.
Running +5V from PSU and GND from PSU+Ardunio = red colors.
Running +5V from PSU+Ardunio and GND from PSU+Ardunio = proper colors.
Have no idea why but whatever.

Well basically that shouldn't happen. The fact that it is, points to the fact that either the two setups were not quite the same, like there was a wring fault, like something was not quite making a connection properly.

Maybe something is wrong with the PSU and you have oscillations on it but when you plug in a USB connected to a computer and ground it stabilises it.