3-pin, not 4-pin KY-009 RGB LED programming

Arduino Uno
IDE: 2.2.1
3-pin KY-009 RGB LED

I feel like an idiot. Hoping someone can help.
I have no problem coding a normal 4-pin ky-009 LED.
IMG_0449

However, when it comes to coding the 3-pin ky-009, I don’t even know where to begin. I’ve Googled ky-009 variants, emailed the vendor for wiring a wiring diagram/example code and have played around with it on my own with no luck. How can I get solid red, green or blue to light up instead of white (r, g, b combined)

My unsuccessful sketch:

const int LED = 3;   // Pwm pin

Void setup()
{
  PinMode(LED, OUTPUT);
}

Void loop()
{
  DigitalWrite(LED, 255);
  Delay(1000);
}

Looks like an addressable LED. You can use e.g. the FastLED library or AdaFruit's NeoPixel library if that is the case.

Please post a link to what you bought.

3 Likes

@sterretje here’s the the link you requested.

10pcs/lot RGB 3 Color Full Color LED SMD Module KY-009 Applicable: https://a.aliexpress.com/_mtU1mbO

An addressable LED… amazing. It never even crossed my mind that it might be an addressable LED module. Thank you! Going to research more on those two libraries now. I’ll update this post if I find a solution.

@sterretje Following your suggestion (using the “FastLED” library) I was able to get the 3-pin RGB LED’s communicating successfully. Thank you very much!
And now we know that digital LED pins are addressable and not binary (0/1, on/off)

IIUC precise timing lets them get away with having no latch pin but the details, I do not know. The things act like shift registers, can be chained.

1 Like

I found this

After all the color data is sent, the data line must be held low for a minimum of 50 microseconds for the new colors to “latch.”

but elsewhere have read that neopixels show their new colour as soon as they know it.

Meanwhile my disorganized self has lost the experiments where I concluded that neopixels update all at once after the long low on the data line.

As opposed to APA102 style, that have data and clock, where you can detect the new pixels rippling in.

I also found this

each APA102 updates its LED as soon as it has received the 32 required bits. Other LED strings update all of the LEDs at the end of transmission, thus the need for a something to mark the end of transmission.

which makes me think I didna dream the whole thing.

I did those experiments. Probably. I was curious. I hope the theory that posting bad information like I may have done will be the fastest way for someone who knows better to weigh in with a correction is valid.:expressionless:

a7

1 Like

With an implied how they know the data is for sure stopped. 50+ us LOW is how.

By latch perhaps I should say clock as in data is read when this pin is high, it goes low while data is changing then high again to read the new bit after shifting bits up the register.

What's the bit tx timing, are 0's shorter pulses and 1's longer?

The details matter in the code if you write your own. I have not but I do have WS2811 tree light strings. It'd be neat to run them off a Tiny85!

A 1 is a long high followed by a short low, 0 is a short high followed by a long low.

The specified longs are not equal to each other nor are the shorts. But both 1 and 0 add up to about the same. There is quite a bit of flexibility in the exact timing.

And we know the much longer low that follows the data is the signal to move collected RGB data to the driving circuitry, more or less all at once.

Here's what four neopixels data looks like:

And at the end, we can see that they arrive at the end of their last pulse at different times:

Pixel 1 actually beats Pixel 0. This is because, I think, each neopixel reforms and passes on the digital data. At that point, the long/shorts are no longer what the code dictated, they are what the previous pixel (re)produced. It can pass along a pulse as soon as it knows it is long or short, which can be before the input goes low.

We can also see that it takes some time for later pixels. My cheap 24 MHz logic analyser is inadequate, but we can see def latency introduced by each pixel of something like 167 ns, so with only this crude data, in a 100 pixel strip we can say the last pixel will change its output 16.7 us later than the first.

Compared to the rippling data speed driven updating of the APA102 (I think, experiments later), this is not too shabby.

What I cannot explain is the 308 us I observed from the end of the first strip.show() to the beginning of the next. The first strip.show() starts 10 us after the trigger, the trigger goes low 15 us after the last pulse of the second strip.show() so what is going on for 300 us between the two which are just two lines of code?

Here's the testing code:

// stimulate the strip for logic analyser

# include <Adafruit_NeoPixel.h>

# define PIN      7
# define NLAMPS   4
# define TRIGGER  8

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NLAMPS, PIN, NEO_GRB + NEO_KHZ800);

void setup()
{
	Serial.begin(115200);

	pinMode(TRIGGER, OUTPUT);
	
	strip.begin();
	strip.clear();
	strip.show();
	delay(100);

if (1) colors();
else strip.clear();

	Serial.println("gonna");

	for (; ; ) {
		digitalWrite(TRIGGER, HIGH);
		strip.show();
		strip.show();
		digitalWrite(TRIGGER, LOW);
		
		delayMicroseconds(100);

		Serial.println("did");

		static int counter;
		counter++;

		if (counter % 100 == 0) {
			strip.clear();
			strip.show();
			delay(500);
			colors();		// right?
		}
	}
}

void colors()
{
	strip.setPixelColor(0, 0x10001f); // blue
	strip.setPixelColor(1, 0x00220f); // green
	strip.setPixelColor(2, 0x23000f); // red
	strip.setPixelColor(3, 0x13131f); // grey
}

void loop(){}

Fun!

a7

2 function calls with how many lines each?
I don't know what they do. Do you?

Each module sends 1 bit for every bit it receives and it takes 24 bits per module to move a color into a module. The last pixel transmits first to the first module then shifts up from there. 100 modules, 2400 bits and then stop sending for 50+ us... the whole chain stops together, propagation delay in the nanosecs... Uno clock is 62.5 ns, less is not insignificant?

I've been unclear.

This is the code I mean

		digitalWrite(TRIGGER, HIGH);
		strip.show();
		strip.show();
		digitalWrite(TRIGGER, LOW);

With the logic analyser I can see that the first strip.show()'s stream finishes, and it is 308 us before the second strip.show()'s first bits appear on the data line.

Some more experminets and googling:

NeoPixels require a short quiet time (about 300 microseconds) after the last bit is received before the data 'latches' and new data can start being received.

strip.show() will therefor block if the required resting period has not elapse since the last strip.show().

Use the canShow() method to see if there is time to do some things with the (up to) 300 microseconds strip.show() would otherwise eat.

I did suspect some kind of preflight that strip.show() needed to do, but the first strip.show() after a pause came out right away.

So more a flight delay than a preflight. :expressionless:

a7

1 Like

Okay. You can save a tiny bit by changing the digitalWrites to writing a bit to the trigger pin of the PINx port register that the trigger pin is on. Write that fixed value and set bits of that value flip on the PORTx register without affecting any others takes 1 cycle..

Why run .show() twice? To make it take longer?

I gotta wonder, do the modules have a burst mode or a steady baud rate? The short-long difference digitizes small errors away, polling lows or highs in a row gets solid.

Soooo I forget, what's the rate?

I did like

   PORTB = 1; strip.show();
   PORTB = 2; strip.show();
   PORTB = 1; strip.show();
   PORTB = 2; strip.show();
   PORTB = 1; strip.show();
   PORTB = 2; strip.show();
   PORTB = 1; strip.show();
   PORTB = 2; strip.show();

   delay(1);

in a loop. So there's little time wasted. Direct port output. Function call/return overhead, the rest should all be work the function takes time doing. The first strip.show() comes right after pin 8 goes high, the second and subsequent strip.show()s come 300 us after the rising edge of pin 8 or pin 9.

The resting period strip.show() enforces by blocking until if necessary.

Why run .show() twice? To make it take longer?

I wanted to see the low period after the data is done going and figured out that immediately launching another strip.show() would give me something to measure. Which was way longer than the specified

See

Adafruit uberguide

and

WS2812B Data Sheet

and

Timing not so critical?

If any of those sources mentions the required short quiet time of 300 us between data streams (strip.show() calls) it means I didna read them very carefully ever, as this was news to me.

a7

What I wanted for now is Page 5 of the Datasheet.

The bit window is 1,250 ns +/- 600 ns. That's +/- 9.6 Uno cycles.

A 0 is HIGH 400 ns +/- 150 ns and LOW the rest of the frame. 4 to 8 cycles is good
A 1 is LOW 850 ns +/- 150 ns and LOW the rest of the frame. 11 to 16 cycles is good.

Toggling PORTx pins through the PINx register never disturbs any other pins. On the Uno fgerinstance you have 3 ports with 2 bits 'taken' when Serial is used and have to cookie-cut to set other PORT pins without affecting pins already used. Write to PINx avoids that.

I've got more to read up, maybe not need fastled any more.

I'm not up to the task of banging out the neopixel data stream, but I do use APA102 SPI LEDs without the need for any library.

Of course you loose the giant bag of tricks most smart pixels libraries provide. I like making my own.

Yes, an odd feature I never remember.

a7

Google is a wonderful thing...might be a surprise that the first to come up was this.
You should try it sometime.
In the reviews........

I ordered x10 of these 3-pin RGB LED's because I'm already familiar with the 4-pin KY-009 model. I had problems trying to figure out how to code them as there's only 3 pins and the control pin being either digital in or out. I was able to get it to light up solid white (r + g + b = white) and also solid green (sometimes) but it wasn't working as intended. I found out, that the LED's are addressable. Meaning, I could use a pre-made library in order to properly code the LED's to be the correct color I needed. There's 2 libraries that can do this: "FastLED" (GitHub.com) and "Adafruit Neo-Pixel" (GitHub.com) Anyways, using the "FastLED" library, I was able to get them working correctly.

I’m so glad you found the review that I had left on AliExpress to be helpful…?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.