Is there a charlieplexed random LED twinkler?

Thought I'd try to make a lighted up picture frame by adding LED. I tried searching for similar project but my Google-fu is failing me. I wanted to try and make it so that about half of the LEDs are light and roughly every second one LED turns on or off like a slow twinkle. Something like this: http://www.kurtadler.com/product/BO-3L-Led-Xmas-Canvas-Frame-Orns but with a $2 Goodwill picture and about $5 worth of parts on my workbench.

I'd be easy with individual LED per IO using digitalWrite(randomPin, !digitalRead(randomPin)); then waiting for a bit. But it's more inefficient if I want to use around 30 LED. OTOH if I can use charlieplexing and change the state of a single LED every so often, I could use something like ATTiny85 with just 6 pins.

Is there an existing project around like that, that I could copy or a guide on random charlieplexing LED? Or is there a better way? All the LEDs I would be using are 3mm for small picture and 5mm for large picture. I've looked at WS2812 but they only come in flat SMD package and wouldn't quite look right.

Edit: twinkles like this: Twinkle lights - YouTube but slower rate

Multiplexed and Charlieplexed leds have to share ON time. However many are to appear lit at once, more = dimmer. Figure for more than 6 leds you will need low background lighting.

Using led driver(s) lets you have all the leds zero to full all the time.

Point is, get a MAX7219 - requires three pins to drive.

Just buy two or three of these kits:

Or these ones

which used to be more expensive but are now actually cheaper and more useful if you wish to stack matrix arrays.

The point is that you do not install the matrix arrays from the kits themselves - or their socket pins, but just solder to the positions on the PCB and you have a durable and reliable assembly to drive your own matrix-wired arrays.

Why did I say two or three? Well, you can fully assemble the first one as the matrix with which it comes and practice programming it. Then the second one for your current project and the third one - for the next! :grinning:

I've looked at WS2812 but they only come in flat SMD package and wouldn't quite look right.

You can get apa106 LEDs. These are compatible with ws2812 but come in 5mm or 8mm conventional round led shape. Never seen 3mm version unfortunately.

I have seen individual 10mm WS2811 (or 2812) leds on the dealextreme site a few years ago.

These are smaller but individual:

Also smaller (5050) but individual and $16/100:

These are 12mm but in a string (no strip) which I bet I can cut like a strip:

wilykat:
I'd be easy with individual LED per IO using digitalWrite(randomPin, !digitalRead(randomPin)); then waiting for a bit. But it's more inefficient if I want to use around 30 LED. OTOH if I can use charlieplexing and change the state of a single LED every so often, I could use something like ATTiny85 with just 6 pins.

make a hand sketch of 30 LEDs and charlie-plexing to get a pin count.

don't forget that your power supply needs to be able to handle the load of all the LED's at full ON.

It occurs to me that nobody is going to watch your picture long enough to determine that 1/3rd of the LEDs are not actually twinkling. I would use a bare-bones ATmega328p and hook each of the 20 pins to one LED. Wire the other 10 LEDs to constant power. Then the sketch to twinkle a random selection of the 20 LEDs would be simple.

As an experiment, connect your LED to a PWM output pin and use analogWrite(pin, 9); to get an idea of how bright the LED will be when it is only on 1/30th of the time. I suspect it will be very dim, even if you draw the full 40ma available from the pins.

johnwasser:
I would use a bare-bones ATmega328p and hook each of the 20 pins to one LED. Wire the other 10 LEDs to constant power. Then the sketch to twinkle a random selection of the 20 LEDs would be simple.

It is considered always wise with "newbies", to reiterate the need for a resistor in series with every LED. :astonished:

johnwasser:
I suspect it will be very dim, even if you draw the full 40ma available from the pins.

"full 40ma available"? Are you kidding?

dave-in-nj:
don't forget that your power supply needs to be able to handle the load of all the LED's at full ON.

Which means using the USB or "5V" connections, not "Vin" or the "barrel jack". :roll_eyes:

wilykat:
Edit: twinkles like this: Twinkle lights - YouTube but slower rate

Wow! Seriously ancient technology!

PaulRB:
You can get apa106 LEDs. These are compatible with ws2812 but come in 5mm or 8mm conventional round led shape. Never seen 3mm version unfortunately.

There is an extremely simple reason (or two) for this, isn't there? :sunglasses:


... Waiting for the OP.

Paul__B:

You can get apa106 LEDs. These are compatible with ws2812 but come in 5mm or 8mm conventional round led shape. Never seen 3mm version unfortunately.

There is an extremely simple reason (or two) for this, isn’t there? :sunglasses:


… Waiting for the OP.

3mm would require 2x2 pin spacing, or maybe a much closer pin spacing.

johnwasser:
It occurs to me that nobody is going to watch your picture long enough to determine that 1/3rd of the LEDs are not actually twinkling. I would use a bare-bones ATmega328p and hook each of the 20 pins to one LED. Wire the other 10 LEDs to constant power. Then the sketch to twinkle a random selection of the 20 LEDs would be simple.

I'll have to look in those. Assume I wired them with resistor to keep to about 20mA per LED, with a dumb random code I risk having all 20 on at once, 400mA total through the chip. It's the original reason I wanted to go with charlieplexing, only 1 LED is on at a time so no more than about 20mA being used.

Paul__B:

PaulRB:
You can get apa106 LEDs. These are compatible with ws2812 but come in 5mm or 8mm conventional round led shape. Never seen 3mm version unfortunately.


... Waiting for the OP.

That is possible, I didn't realize those type of LED came in dome package. I guess it's not common since it'd require more wiring than SMD on ribbon strip.

I also will look into Max7219 and see how easy it'd be.

Thanks for the info!

Update: think I’ll go with Max7219. I can store an array of 8x8 value, and at interval pull a single bit random, XOR it into one random row array, push the updated array value out, then wait a bit.

I’ll post the updated code in a few days when I get Max chip and a working prototype.

PS it seems like with plain dumb random and 8 byte array per Max7219 I could use ATTiny85 and still have memory room to control total of 8 Max chips for 512 blinky LED

EDIT: untested but passes verify in IDE:

#include "LedControl.h"                  //  need the library for Max72xx support
LedControl lc = LedControl(12, 11, 10, 1); // "1" as we only have 1 MAX 7219 atatched, maximum 8 is possible without additional pin
                                         // pin 12 is connected to the MAX7219 pin 1 labelled DIN
                                         // pin 11 is connected to the CLK pin 13 labelled CLK
                                         // pin 10 is connected to LOAD pin 12 labelled as CS
byte randNumber;                          // random digit bit storge for XORing to current stored row array
byte randRow;                             // random row 1-8
byte array[8] = {1, 2, 4, 8, 16, 32, 64, 128}; // setting array initially, value will change in setup

void setup()
{
                                         // the zero refers to the MAX7219 number, only 1 is used, max 8 can be used
  lc.shutdown(0, false);                 // turn off power saving
  lc.setIntensity(0, 8);                 // sets brightness (0~15 possible values)
  lc.clearDisplay(0);                    // clear screen
                                         // if analog input pin 0 is unconnected, random analog
                                         // noise will cause the call to randomSeed() to generate
  randomSeed(analogRead(0));
  for (byte i = 0; i <= 7; i++) {         // Need to set up all 8 rows
    array[i] = random(0, 255);           // making initial random display 1 row at a time
    lc.setRow(0, i, array[i]);           // pusing random data on current row out
  }
}
// Kilroy was here
void loop()
{
  randRow = random(0, 7);                 // picking a random row array to change
  randNumber = random(1, 8);              // getting random binary bit to XOR
  randNumber = pow(2, randNumber);        // converts from random number 1-8 to single binary digit 1, 2, 4, ... 128
                                          // or B00000001, B00000010, ... to B10000000 
  array[randRow] = array[randRow] ^ randNumber; // XORing the current stored row variable to change one bit
  lc.setRow(0, randRow, array[randRow]);  // writing the revised value to Max7219.
  delay(random(250,1500));                // do nothing for anywhere from 1/4 sec to 1.5 sec.
}
  for (byte i = 0; i <= 7; i++) {         // Need to set up all 8 rows
    array[i] = random(0, 255);           // making initial random display 1 row at a time
    lc.setRow(0, i, array[i]);           // pusing random data on current row out
  }

Doesn’t a starry sky have all of the stars visible most of the time? I’d set them all on (255) and twinkle them off briefly.

randRow = random(0, 7);  // picking a random row array to change

The lower limit is inclusive but the upper limit is exclusive. This will give you a number from 0 to 6. You probably want a number from 0 to 7.

randNumber = random(1, 8);              // getting random binary bit to XOR

Similar, but this gives you bits 1 through 7. You probably want 0 through 7

randNumber = pow(2, randNumber);

Since pow() is a floating-point function this is a bad way of creating a bit mask. Try:

randNumber = 1 << random(0, 8);

Bits 2 to 9 of micros() ( >> 2 then mask 0xFF ) makes a nice fast pseudo-random or seed if not called regularly.

Thanks for info, adjusted random and fixed range. Still waiting for the Max chip to test the code.

Update:

code works as is. The last part of the video is with delay removed, it looks like old school static.

Now I just need to wire up a bunch of random colored LEDs