Programming Help Needed For Neopixel Matrix

Hello all,
I am not very good at programming. Sometimes I can figure out what to do if there is some code that comes close to what I want my project to do. However, if there isn't then I have no clue where to start.
I built a bedside table with Arduino+neopixels. Inside the table is a 7x7 matrix. Yep, another LED matrix table. The pixels are arranged in the ZIGZAG configuration. I got it all hooked up & got it working. No big deal...with ready-to-use code. (Don't get me wrong. I know lots of people worked hard on all of the coding/libraries/sketches, & I appreciate that & respect them for being able to do it!) I worked with those sketches for hours, days, & now going on weeks. I can usually change the basics, such as, the pin(s) being used, rate at which pixels change state, etc. I have very limited time to learn all about programming. I have tried over the past couple of years & have learned enough to make me think I know what I'm doing only to, in reality, learn enough to frustrate the H**L out of myself!! I have had limited success with regular ol' 8x8 LED matrices (MAX7219 modules) showing patterns & scrolling text (frustrated with the MD_Parola but getting there!) & have had fun with the online matrix code generators. But, how the heck can I generate code for my neopixel matrix?!?! I want to be able to get this kind of pattern:

Can someone please tell me how to go about it. Keep in mind that I have literally about 2-4 hrs per week at best for my hobby. That's long enough to search for what I'm looking for on the internet. Set up a circuit, Mess with the code for a while & (if I got it working) modify the code until I am once again frustrated! I don't know how to come up with more time to learn. It's to fun to give up on & forget electronics. But, I don't know anyone personally within a hundred mile radius of me that knows what an Arduino Uno is. Half the time when I post questions all I seem to get is, "why don't you just learn how to do it yourself & stop expecting someone else to do all the work for you." I don't expect that, but that is why this post sounds much like a rant. Sorry for that.
Here is a picture of my table.

As you can see, I'm not totally incompetent. But, is there a "pattern generator" for a NEOPIXEL matrix like those for the MAX modules? Or, does it have to involve mapping (read about mapping, experimented a little. Got the gist of it, maybe)? I have installed the Adafruit libraries and FastLED. Maybe another one or two. I don't remember off hand. Can someone point me in the right direction without pointing to a spot on the distant horizon?

Thanks,
Jeff - AKA, AptPupil (maybe it's time to change my nickname! :frowning: )

BTW, the current setup is an Uno, 49 (7x7) WS2811 neopixel strip, breadboard with a button and pot (I think I can get it to change patterns with button presses, speed with the pot if I can figure out how to do patterns), and Adafruit EZ-Link Bluetooth module. Planning to use a Pro Mini with wall wart/battery option. Just FYI.

There are basically two ways of creating a pattern, one by steps a program takes, this is known as an algorithm and the other is by having the pattern stored in the memory and moving that pattern into the LEDs, this is called a look up table.

The look up table technique is the simplest because it is the same no matter what the pattern, but some algorithms can occupy less space because you don't have to define the state of every LED for every state in the pattern.

You can quickly run out of SRAM memory to put patterns in therefore it is best if you put them in program memory where there is much more room. I have not got any neopixels with me at the moment so what I have written here is totally untested but it should give you an idea of what is needed. Also note that it only produces a single fixed colour pattern but that is the way you must work, that is get one thing working at a time. Once you have the hand of making patterns then defining the colours is just another step away.

You need to draw your grid and put the LED number in each one. Then for each stage of the pattern you write down what LED number you want lit. Then transfer those numbers into an array and tag a 255 value on the end. That 255 signals the end of one step of a pattern. You then repeat this for as many steps as you want.

Then to play the pattern you take a point in that array and read the value, if it is less than 255 then treat it as an LED number and set that LED to come on. When 255 is read, display those LEDs, pause for a time, and then clear out all the LEDs and start with the next stage in the pattern. The pattern I have put here are just random numbers at the moment, you change these to make them look nice.

// Neopixel pattern generator
// By Mike Cook August 2015

#include <Adafruit_NeoPixel.h>
#define PIN   6 // pin connected to the NeoPixels
#define NUMPIXELS      49 // number of LEDs in a 7 by 7 array

// pattern is LED numbers followed by a 255 to indicate the pattern end
// this is put into porgram memory and can be as long as you like
const PROGMEM uint8_t pattern[] = { 23,22,17,255, 1,5,7,12,42,13,255,
                                       18,14,10,11,255, 14,22,18,19,12,255,
                                       16,47,23,35,1,42,16,8,0,255};
                                       
int patternLength = sizeof(pattern);
int patternSpeed = 1000; // change every second
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

void setup() {
   pixels.begin(); // This initializes the NeoPixel library.
   wipe();
   pixels.show();
}

void loop() {
  int point = 0; // point in the pattern array
  int led = 0;
  while(point <= patternLength) { // read out the pattern
   led = pgm_read_byte_near(&pattern[point]);
   point ++; // increment next point in pattern
   if(led != 255) {
      pixels.setPixelColor(led, pixels.Color(0,128,0)); // note green fixed colour
   }
   else {
     pixels.show();
     delay(patternSpeed); // pause
     wipe(); // clear out pixels
     }
  }
}

void wipe(){
    for(int i=0;i<NUMPIXELS;i++){
       pixels.setPixelColor(i, pixels.Color(0,0,0)); 
       }
}

Mike,
Thank you sooo much! That seemed easy. I understand some of the things in the code, but a lot are beyond me. I know that it's a language & that it has to be put together in a precise manner. I only seem to know enough of the language to hail a cab, so to speak. I have bought Jeremy Blum's book from the Google Play Store, just no time to read it AND get hands practice before it slips away.
Anyway, here's another GIF of my table:

So, how do I get different colors? Or, how do I integrate buttons to change to a different pattern or a different mode that can switch from custom patterns to a modified Strand Test (or other example from FastLED or Adafruit library)?

Thanks again Mike,
Jeff

Well done.

I understand some of the things in the code, but a lot are beyond me.

I would urge you to learn to read the code. That is take each line and understand what it does, just in the same way as you would take a foreign language and look up each word. However when you have done that you need to be able to put it all together to make a sentence so to speak. I know it is not glamorous but it is rather like a musician practicing scales when all he want's to do is play a tune.

So, how do I get different colors?

It depends on what sort of control you want with the colours. The simplest and most complete is to define the colour for each LED, however this also takes up the most memory.
You know how your pattern was stored in an array:-

const PROGMEM uint8_t pattern[] = { 23,22,17,255, // step 1
         1,5,7,12,42,13,255, // step 2
         18,14,10,11,255, // step 3
         14,22,18,19,12,255,// step 4
         16,47,23,35,1,42,16,8,0,255}; // step 5

Well you need an array for each element of the colour. The position of the colours should match the array of lit LED numbers you have originally. Again it should be placed in program memory.

const PROGMEM uint8_t red[] = { 255,255,128,0, // step 1
                                                             128,64,32,16,8,4,0, // step 2
                                                              8,16,32,64,0   // step 3
                                                             255,190,130,64,32,0,  // step 4
                                                             16,47,23,35,1,42,16,8,0,0}; // step 5
const PROGMEM uint8_t green[] = { 128,255,128,0, // step 1
                                                             128,64,32,16,8,4,0, // step 2
                                                              8,16,32,64,0   // step 3
                                                             255,190,130,64,32,0,  // step 4
                                                             16,47,23,35,1,42,16,8,0,0}; // step 5
const PROGMEM uint8_t blue[] = { 0,255,128,0, // step 1
                                                             128,64,32,16,8,4,0, // step 2
                                                              8,16,32,64,0   // step 3
                                                             255,190,130,64,32,0,  // step 4
                                                             16,47,23,35,1,42,16,8,0,0}; // step 5

Again these are just made up numbers, but the first LED of the first pattern will have a colour of red = 255 (full on ), green = 128, blue = 0. As I have used the same numbers in each colour array then all the other colours will be shades of white / grey. Note that the end colour in each step is not used and can be anything but a number needs to be present to keep the numbers in the right places in the arrays.

So now you need to read the colours as well as the lit LED number. So you modify the code to read:-

void loop() {
  int point = 0; // point in the pattern array
  int led = 0;
  int r, g, b;
  while(point <= patternLength) { // read out the pattern
   led = pgm_read_byte_near(&pattern[point]);

 // read the colours 
  r = pgm_read_byte_near(&pattern[red]);
  g = pgm_read_byte_near(&pattern[green]);
  b = pgm_read_byte_near(&pattern[blue]);

   point ++; // increment next point in pattern
   if(led != 255) {
// set the colours according to the array
      pixels.setPixelColor(led, pixels.Color(r,g,b));
   }
   else {
     pixels.show();
     delay(patternSpeed); // pause
     wipe(); // clear out pixels
     }
  }
}

how do I integrate buttons to change to a different pattern or a different mode .....

Let's leave that for another time, one step at a time. :slight_smile:

Well, I'm back & have been playing with the code. I think I changed things the way you explained, but now it gives me an error:

'pattern' was not declared in this scope

I'll just post the whole thing:

// Neopixel pattern generator
// By Mike Cook August 2015

#include <Adafruit_NeoPixel.h>
#define PIN   12 // pin connected to the NeoPixels
#define NUMPIXELS      49 // number of LEDs in a 7 by 7 array

// pattern is LED numbers followed by a 255 to indicate the pattern end
// this is put into porgram memory and can be as long as you like
const PROGMEM uint8_t red[] = { 255,255,128,0, // step 1
                                                             128,64,32,16,8,4,0, // step 2
                                                              8,16,32,64,0,   // step 3
                                                             255,190,130,64,32,0,  // step 4
                                                             16,47,23,35,1,42,16,8,0,0}; // step 5
const PROGMEM uint8_t green[] = { 128,255,128,0, // step 1
                                                             128,64,32,16,8,4,0, // step 2
                                                              8,16,32,64,0,   // step 3
                                                             255,190,130,64,32,0,  // step 4
                                                             16,47,23,35,1,42,16,8,0,0}; // step 5
const PROGMEM uint8_t blue[] = { 0,255,128,0, // step 1
                                                             128,64,32,16,8,4,0, // step 2
                                                              8,16,32,64,0,   // step 3
                                                             255,190,130,64,32,0,  // step 4
                                                             16,47,23,35,1,42,16,8,0,0}; // step 5
                                       
int patternLength = sizeof(pattern);
int patternSpeed = 1000; // change every second
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_RGB + NEO_KHZ800);

void setup() {
   pixels.begin(); // This initializes the NeoPixel library.
   wipe();
   pixels.show();
}


void loop() {
  int point = 0; // point in the pattern array
  int led = 0;
  int r, g, b;
  while(point <= patternLength) { // read out the pattern
   led = pgm_read_byte_near(&pattern[point]);

 // read the colours 
  r = pgm_read_byte_near(&pattern[red]);
  g = pgm_read_byte_near(&pattern[green]);
  b = pgm_read_byte_near(&pattern[blue]);

   point ++; // increment next point in pattern
   if(led != 255) {
// set the colours according to the array
      pixels.setPixelColor(led, pixels.Color(r,g,b));
   }
   else {
     pixels.show();
     delay(patternSpeed); // pause
     wipe(); // clear out pixels
     }
  }
}
void wipe(){
    for(int i=0;i<NUMPIXELS;i++){
       pixels.setPixelColor(i, pixels.Color(0,0,0)); 
       }
}

I added a comma to the end of "step three" of the colors:

const PROGMEM uint8_t red[] = { 255,255,128,0, // step 1
                                                             128,64,32,16,8,4,0, // step 2
                                                              8,16,32,64,0   // step 3
                                                             255,190,130,64,32,0,  // step 4
                                                             16,47,23,35,1,42,16,8,0,0}; // step 5

That took care of:

expected '}' before numeric constant

But, no clue on the pattern error.

Jeff

You have not declared the array called pattern hence the error message.
If you have moved the information given by the pattern array into red array you must replace references to the pattern array to the red array. But because is is now twice as long as the original pattern the number of steps must be half of what you originally had. Also you need two pointers, one for the red array and another for the green and blue array. These need to move at different rates.
In short you have messed up the linkage between data and positions in the arrays.

Do not remove that } on the end of the statement, that is wrong. All you have done is introduce a new error that temporarily cancels out the previous one. So now you have two things wrong so while it might compile without errors it will not do what you want.

Grumpy_Mike:
Do not remove that } on the end of the statement, that is wrong. All you have done is introduce a new error that temporarily cancels out the previous one. So now you have two things wrong so while it might compile without errors it will not do what you want.

I think you misunderstood. I did not remove "}". The first error I got was, "expected '}' before numeric constant", apparently because in, " 8,16,32,64,0 // step 3" there was no "," after the 0.

As for,

You have not declared the array called pattern hence the error message.
If you have moved the information given by the pattern array into red array you must replace references to the pattern array to the red array. But because is is now twice as long as the original pattern the number of steps must be half of what you originally had. Also you need two pointers, one for the red array and another for the green and blue array. These need to move at different rates.
In short you have messed up the linkage between data and positions in the arrays.

What you say makes complete since to me, but, even after reading pages of references on Arduino.cc, I don't understand how to

replace references to the pattern array to the red array

I know I need to learn the language, but I haven't found a Rosetta Stone for Arduino. :confused:

Jeff

I don't understand how to
Quote

"replace references to the pattern array to the red array"

Old code:-

int patternLength = sizeof(pattern);
// .............

led = pgm_read_byte_near(&pattern[point]);

Replace by:-

int patternLength = sizeof(red);
// .............

led = pgm_read_byte_near(&red[point]);

So where you did anything with "pattern" you replace it with "red"

However as I said that alone is not going to fix things because:-

you have messed up the linkage between data and positions in the arrays.

That means the red array now contains a mixture of LED data and colour data. So for every two entries in the red array there is only one entry in the green and the blue array.

Basically by doing the changes you did you broke it to a point where it is not worth fixing because the fix is very messy and it will loose any elegance the program had.

I know you might not think it was "elegant" but it was.