Trouble with LEDs outputting wildly incorrect values (read from an array)

Hello everyone! My issue pertains to a persistence-of-vision LED stick project.
In it, I use a MATLAB script to turn an input image into an Arduino array, for ease of use.

My issue is that the Arduino is not selecting the correct value from my array, even with correct indexes.

The following is my code, with the red variable truncated due to posting requirements:

#include <FastLED.h>

FASTLED_USING_NAMESPACE

#define DATA_PIN    2
#define LED_TYPE    WS2812B
#define COLOR_ORDER GRB
#define NUM_LEDS    28
CRGB leds[NUM_LEDS];
#define FRAMES_PER_SECOND  3
int count=0;


void setup() {
  delay(1000); // 1 second delay for recovery
  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  float batvolt = 5.0*(analogRead(A5)/1023.0)*(57.0/10.0);
  if (batvolt > 6.4) {
    FastLED.setMaxPowerInVoltsAndMilliamps( 5, 3000);
    FastLED.setBrightness(25);
    Serial.begin(9600);
    Serial.print("battery power, voltage: ");
    Serial.println( batvolt);
  }
  else if((batvolt <=6.4) && (batvolt > 5.0))  {
    FastLED.setMaxPowerInVoltsAndMilliamps( 5, 400);
    FastLED.setBrightness(25);
    Serial.begin(115200);
    Serial.print("LOW BATTERY: ");
    Serial.println(batvolt);
    lowbatterywarning();
  }
  else{
    FastLED.setMaxPowerInVoltsAndMilliamps( 5, 400);
    FastLED.setBrightness(25);
    Serial.begin(115200);
    Serial.print("USB power, voltage: ");
    Serial.println(batvolt);
  }
}


const PROGMEM byte red[][28]={
{  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}, 
{  0,  0,  0,  0,  0,  0, 32, 67, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 67, 64, 10,  0,  0,  0,  0,  0,  0}, 
{  0,  0,  0,  0,  0,  0,124,255,255,255,255,255,255,255,255,255,255,255,255,255,250, 38,  0,  0,  0,  0,  0,  0}, 
{  0,  0,  0,  0,  0,  0,123,255,255,255,255,255,255,255,255,255,255,255,255,255,247, 37,  0,  0,  0,  0,  0,  0}, 
{  0,  0,  0,  0,  0,  0,124,255,255,255,255,255,255,255,255,255,255,255,255,255,250, 38,  0,  0,  0,  0,  0,  0}, 
{  0,  0,  0,  0,  0,  0, 32, 69, 68, 68, 68, 66,153,255,255,230, 75, 67, 68, 68, 66, 10,  0,  0,  0,  0,  0,  0}, 
{  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,113,255,255,220,  5,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0}, 
{  0,  0,  0,  0,  0,  0,100,209,208,208,208,207,229,255,255,248,209,207,208,208,200, 30,  0,  0,  0,  0,  0,  0}, 
{  0,  0,  0,  0,  0,  0,125,255,255,255,255,255,255,255,255,255,255,255,255,255,252, 38,  0,  0,  0,  0,  0,  0}};
void loop() {
  for(int o=1;o<56 ;o++){
    for(int k=1;k<NUM_LEDS ;k++){
      leds[k].r=red[o][k];
      //leds[k].g=grn[o][k];
      //leds[k].b=blu[o][k];
      leds[k].g=0;
      leds[k].b=0;
      Serial.print(o);
      Serial.print(',');
      Serial.print(k);
      Serial.print(':');
      Serial.print(red[o][k]);
      Serial.print(',');
      Serial.print(0);
      Serial.print(',');
      Serial.println(0);
      FastLED.show();
      FastLED.delay(1000/FRAMES_PER_SECOND); 
    }
    FastLED.show();
    FastLED.delay(10000/FRAMES_PER_SECOND); 
  }
  count++;
  if ( ((count % (FRAMES_PER_SECOND *60)) == 0)) {
    lowbatterycheck();
  }
}

void lowbatterycheck() {
  float batvolt = 5.0*(analogRead(A5)/1023.0)*(57.0/10.0);
  if ((batvolt <=6.4) && (batvolt > 5.0)){
    lowbatterywarning();}
}
void lowbatterywarning() {
  for(int k=0;k<5 ;k++) {
    for( int i = 0; i < NUM_LEDS; i++) {
      leds[i].setRGB(50,0,0);
    }
    FastLED.show();
    FastLED.delay(1000/FRAMES_PER_SECOND); 
    for( int i = 0; i < NUM_LEDS; i++) {
    leds[i].setRGB(0,0,0);}
    FastLED.show();
    FastLED.delay(1000/FRAMES_PER_SECOND); 
  }
  while(1){};
}

The following is my serial output, with the indexes used listed, followed by the specified index in the array. However, if you use these indexes to manually lookup the values, they are quite different (specifically lookup 1,8). Any advice on how to fix this would be greatly appreciated!

USB power, voltage: 4.43
1,1:0,0,0
1,2:0,0,0
1,3:0,0,0
1,4:0,0,0
1,5:0,0,0
1,6:0,0,0
1,7:0,0,0
1,8:181,0,0
1,9:181,0,0
1,10:181,0,0
1,11:181,0,0
1,12:181,0,0
1,13:181,0,0
1,14:181,0,0
1,15:181,0,0
1,16:181,0,0
1,17:181,0,0
1,18:181,0,0
1,19:181,0,0
1,20:181,0,0
1,21:181,0,0
1,22:181,0,0
1,23:181,0,0
1,24:181,0,0
1,25:181,0,0
1,26:181,0,0
1,27:181,0,0
2,1:181,0,0
2,2:181,0,0
2,3:181,0,0
2,4:181,0,0
2,5:181,0,0
2,6:181,0,0
2,7:181,0,0
2,8:181,0,0
2,9:181,0,0
2,10:181,0,0
2,11:181,0,0
2,12:181,0,0
2,13:181,0,0
2,14:0,0,0
2,15:181,0,0
2,16:1,0,0
2,17:4,0,0
2,18:108,0,0
2,19:0,0,0
2,20:0,0,0
2,21:181,0,0
2,22:0,0,0
2,23:181,0,0
2,24:0,0,0
2,25:248,0,0
2,26:254,0,0
2,27:255,0,0

PS. my code compiles with no compiler related errors, just this main issue.

  for (int o = 1; o < 56 ; o++)
  {
    for (int k = 1; k < NUM_LEDS ; k++)
    {
      leds[k].r = red[o][k];

The indices to a 2 dimensional array are in the order row then column but your code attempts to access 56 rows of 28 LEDs

Ah, such a simple mistake, my bad!

It turns out the solution for this is a little more complicated than I anticipated, perhaps. Ive tried to swap around o and k in the LED setting line, then in the for loops, to no avail, could you explain how to fix it specifically? thank you so much!

What order do you want the output to be in ?

Each of the values for a row followed by the values for the next row and so on, or each of the values for a column followed by the values for the next column and so on ?

Either way, do yourself a favour and have the compiler work out how many rows an columns there are and use the values in the for loops

byte ROWS = sizeof(red) / sizeof(red[0]);
byte COLS = sizeof(red[0]);

So I've done that, and it doesnt fix my issue. it turns out that I had 55 rows instead of 56. I then tried using a smaller table of values to see if that was the issue. That of course didnt help. Then I tried to turn it into a 1D array, and that didnt help either. Here is my code so far:

#include <FastLED.h>

FASTLED_USING_NAMESPACE

#define DATA_PIN    2
#define LED_TYPE    WS2812B
#define COLOR_ORDER GRB
#define NUM_LEDS    28
CRGB leds[NUM_LEDS];
#define FRAMES_PER_SECOND  1
int count=0;

const PROGMEM byte red[]=
{255,255,  0,  0,  0,  0,  0,  0,  0,  0,  0, 
 255,255,255,255,  0,  0,  0,  0,  0,  0,  0, 
 255,255,255,255,255,255, 00,  0,  0,  0,  0
};

byte rows=3;
byte cols = 11;
//byte rows=sizeof(red)/sizeof(red[0]);
//byte cols = sizeof(red[0]);

void setup() {
  delay(1000); // 1 second delay for recovery
  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  float batvolt = 5.0*(analogRead(A5)/1023.0)*(57.0/10.0);
  if (batvolt > 6.4) {
    FastLED.setMaxPowerInVoltsAndMilliamps( 5, 3000);
    FastLED.setBrightness(25);
    Serial.begin(115200);
    Serial.print("battery power, voltage: ");
    Serial.println( batvolt);
  }
  else if((batvolt <=6.4) && (batvolt > 5.0))  {
    FastLED.setMaxPowerInVoltsAndMilliamps( 5, 400);
    FastLED.setBrightness(25);
    Serial.begin(115200);
    Serial.print("LOW BATTERY: ");
    Serial.println(batvolt);
    lowbatterywarning();
  }
  else{
    FastLED.setMaxPowerInVoltsAndMilliamps( 5, 400);
    FastLED.setBrightness(25);
    Serial.begin(115200);
    Serial.print("USB power, voltage: ");
    Serial.println(batvolt);
  }
  Serial.print("Rows: ");
  Serial.print(rows);
  Serial.print(" Cols: ");
  Serial.println(cols);

}

void loop() {
  for(int o=0;o<(rows-1) ;o++){
    for(int k=0;k<(cols-1) ;k++){
      leds[k].r=int(red[o*11+ k]);
      //leds[k].g=grn[o][k];
      //leds[k].b=blu[o][k];
      leds[k].g=0;
      leds[k].b=0;
      Serial.println(leds[k].r);
    }
    FastLED.show();
    FastLED.delay(1000/FRAMES_PER_SECOND); 
  }
//  count++;
//  if ( ((count % (FRAMES_PER_SECOND *60)) == 0)) {
//    lowbatterycheck();
//  }
}

void lowbatterycheck() {
  float batvolt = 5.0*(analogRead(A5)/1023.0)*(57.0/10.0);
  if ((batvolt <=6.4) && (batvolt > 5.0)){
    lowbatterywarning();}
}
void lowbatterywarning() {
  for(int k=0;k<5 ;k++) {
    for( int i = 0; i < NUM_LEDS; i++) {
      leds[i].setRGB(50,0,0);
    }
    FastLED.show();
    FastLED.delay(1000/FRAMES_PER_SECOND); 
    for( int i = 0; i < NUM_LEDS; i++) {
    leds[i].setRGB(0,0,0);}
    FastLED.show();
    FastLED.delay(1000/FRAMES_PER_SECOND); 
  }
  while(1){};
}

The leds pattern is very simple, but its not the one that comes out.

USB power, voltage: 4.40
Rows: 3 Cols: 11
0
0
184
0
0
0
1
0
0
184

Just as a further clarification, I originally was trying to have each row be a frame for the LED array, the inner for loop was to individually set each LED to a specific value in the stored array.

The first thing that I would do is to write a simpler sketch with the array defiled and to have it simply print the values from the array. Once you can access the correct values then add in the code to display them using FastLed

Something like this

const PROGMEM byte red[][11] =
{
  {255, 255,  0,  0,  0,  0,  0,  0,  0,  0,  0},
  {255, 255, 255, 255,  0,  0,  0,  0,  0,  0,  0},
  {255, 255, 255, 255, 255, 255, 00,  0,  0,  0,  0}
};

const byte NUM_ROWS = sizeof(red) / sizeof(red[0]);
const byte NUM_COLS = sizeof(red[0]);

void setup()
{
  Serial.begin(115200);
  byte currentValue;
  for (int row = 0; row < NUM_ROWS ; row++)
  {
    for (int col = 0; col < NUM_COLS; col++)
    {
      currentValue = pgm_read_byte_near(&red[row][col]);
      Serial.print(currentValue);
      Serial.print("\t");
    }
    Serial.println();
  }
}

void loop()
{
}

EUREKA! Your post showed you using the pgm_read_byte_near() func, I forgot to use that! My LED strip is now working! Ill send a picture soon

kmagnum:
My LED strip is now working!

How well is it working? I would not think a ws2812 strip would work well as a POV display because of the relatively slow PWM frequency they use. There are other types of strip with much faster PWM frequencies that would be more suitable.