Input Many Numbers Over Serial

I have used your script to build my program and it have worked very good so far, but now I need to extend the number of variables that I'm receiving. I need to send more than 40 unsigned long int (they come from hex color) but after 11 unsigned long I start getting errors and 4 ou 5 commas after I don't receive anything. I seems to happened after 100 chars received. I'm on Mega.

Any idea of the problem ?

Code of the transmitter:

unsigned long  var[55] = {
          L1L, L1R,
          L2L, L2R,
          L3L, L3R,
          L4L, L4R,
          L5L, L5R,
          L6L, L6R,
          L7L, L7R,
          L8L, L8R,
          L9L, L9R,
          L10L, L10R,
          BGL1L, BGL1R,
          BGL2L, BGL2R,
          BGL3L, BGL3R,
          BGL4L, BGL4R,
          BGL5L, BGL5R,
          BGL6L, BGL6R,
          BGL7L, BGL7R,
          BGL8L, BGL8R,
          BGL9L, BGL9R,
          BGL10L, BGL10R,
          Mode, Pwr, 
          Rot, RotO, 
          RotT, Rdm, 
          RdmT,Mood, 
          MoodT, MoodS, 
          IndexColorS
        };
        

Serial.println("Sending values to arduino");
Serial1.print("<");
    for(int i = 0; i < 51; i++){
        Serial1.print(var[i]);   
        Serial1.print(",");
        Serial.println(var[i]);
    } 
Serial1.print(">");    
Serial.println("Data sent");

Code of the receiver:

void recvWithStartEndMarkers() {
  static boolean recvInProgress = false;
  static byte ndx = 0;
  char startMarker = '<';
  char endMarker = '>';
  char rc;
  
        while (Serial1.available() > 0 && newData == false) {
    rc = Serial1.read();

    if (recvInProgress == true) {
      if (rc != endMarker) {
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars) {
          ndx = numChars - 1;
        }
      }
      else {
        receivedChars[ndx] = '\0'; // terminate the string
        recvInProgress = false;
        ndx = 0;
        newData = true;
      }
    }

    else if (rc == startMarker) {
      recvInProgress = true;
    }
  }
}

void parseData() {
if (newData == true) {
    // split the data into its parts
    
  char * strtokIndx; // this is used by strtok() as an index
  
  strtokIndx = strtok(receivedChars,",");      // get the first part - the string
  var[0] = atoi(strtokIndx);   // copy it to messageFromPC


  for(int i = 1; i<51; i++) {
  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  var[i] = atoi(strtokIndx);     // convert this part to an integer
  }
  for(int i = 0; i<51; i++) {
      Serial.println(var[i]);
      EEPROM.write(i, var[i]);
     }

LL[0] = var[0];
LR[0] = var[1];
LL[1] = var[2];
LR[1] = var[3];
LL[2] = var[4];
LR[2] = var[5];
LL[3] = var[6];
LR[3] = var[7];
LL[4] = var[8];
LR[4] = var[9];
LL[5] = var[10];
LR[5] = var[11];
LL[6] = var[12];
LR[6] = var[13];
LL[7] = var[14];
LR[7] = var[15];
LL[8] = var[16];
LR[8] = var[17];
LL[9] = var[18];
LR[9] = var[19];

BGLL[0] = var[20];
BGLR[0] = var[21];
BGLL[1] = var[22];
BGLR[1] = var[23];
BGLL[2] = var[24];
BGLR[2] = var[25];
BGLL[3] = var[26];
BGLR[3] = var[27];
BGLL[4] = var[28];
BGLR[4] = var[29];
BGLL[5] = var[30];
BGLR[5] = var[31];
BGLL[6] = var[32];
BGLR[6] = var[33];
BGLL[7] = var[34];
BGLR[7] = var[35];
BGLL[8] = var[36];
BGLR[8] = var[37];
BGLL[9] = var[38];
BGLR[9] = var[39];

ActiveMode =  var[40];
power = var[41];
rotation = var[42];
rotation_order = var[43];
rotation_time = var[44];
random_mode = var[45];
mode_time = var[46];
mood = var[47];
mood_type = var[48];
moodSpeed = var[49];
colorIndexSpeed = var[50];

newData = false;

}

You need to post your complete program. How big have you made the array receivedChars?

I am asking the moderator to move your question to its own Thread so as not to confuse readers of my tutorial.

...R

Okay good. I have made the char array 600. If there is a problem, I can just delete my posts once the we have found the problem.

Here is my complete code:

#include "FastLED.h"
#include <EEPROM.h>

#define NUM_LEDS 10
#define DATA_PIN 4
CRGB left[NUM_LEDS];
CRGB right[NUM_LEDS];


//Serial communication
const int numChars = 600;
char receivedChars[numChars];

boolean newData = false;


int i = 0;
int ii;
unsigned long int var[140];

unsigned long int LL[10];
unsigned long int LR[10];
unsigned long int BGLL[10];
unsigned long int BGLR[10];

//new mode
const int sensitivityPin = A2;  // Analog input pin that the potentiometer is attached to
const int audioPin = A0;        // Analog input pin that the audio channel is attached to
const int ledCount = 10;        // The number of LEDs in the bar graph
const int numReadings = 20;     // Number of samples to keep track of (for smoothing)
const int buttonPin = 13;
int counter=0;
int audioValue;                 // Analog value read from audio channel
int maxAudioValue = 0;          // Maximum analog value read from audio channel
int sensitivityValue;           // Analog value read from potentiometer
int ledLevel;// Value to map to the output LEDs
int ledLeveltot;

int readings[numReadings];      // the readings from the analog input
int index = 0;                  // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average
int power;
int ActiveMode;

int mode[5][10] = {  
 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},   // Mode 1
 {9, 8, 7, 6, 5, 4, 3, 2, 1, 0},   // Mode 2
 {9, 0, 8, 1, 7, 2, 6, 3, 5, 4},   // Mode 3
 {4, 5, 3, 6, 2, 7, 1, 8, 0, 9},   // Mode 4
 {9, 7, 5, 3, 1, 8, 6, 4, 2, 0}    // Mode 5
};

//MSGEQ7
const int ledCount1 = 8;
const int ledCount2 = 8;
const int ledCount3 = 7;
const int ledCount4 = 7;
const int ledCount5 = 7;
const int ledCount6 = 7;
const int ledCount7 = 7;

int ledLevel1;
int ledLevel2;
int ledLevel3;
int ledLevel4;
int ledLevel5;
int ledLevel6;
int ledLevel7;

int analogPin = 0; // read from multiplexer using analog input 0
int fqc[7]; // to hold a2d values

int strobePin = 2; // MSGEQ7 STROBE 4
int resetPin = 3; // MSGEQ7 RESET 7
int filterValue = 0;

//dev var
int rotation;
int rotation_time;
int rotation_order;
unsigned long int nextrotation = 0;
int PreviousRL;
int PreviousGL;
int PreviousBL;
int PreviousRR;
int PreviousGR;
int PreviousBR;

int random_mode;
unsigned long int nextmode = 0;
int mode_time;

//Mood
int mood;
int mood_type;
int v = 0;
int moodSpeed;
int colorIndexSpeed;

CRGBPalette16 currentPalette;
TBlendType    currentBlending;
extern CRGBPalette16 myRedWhiteBluePalette;
extern const TProgmemPalette16 myRedWhiteBluePalette_p PROGMEM;
uint8_t brightness = 255;
int a = 0;
unsigned long currentMillis;
unsigned long previousMillis;


void setup()
{

  FastLED.addLeds<NEOPIXEL, 4>(left, NUM_LEDS);
  FastLED.addLeds<NEOPIXEL, 5>(right, NUM_LEDS);
  Serial.begin(9600);
  Serial1.begin(9600);

   pinMode(analogPin, INPUT);
 pinMode(strobePin, OUTPUT);
 pinMode(resetPin, OUTPUT);
 analogReference(DEFAULT);

 digitalWrite(resetPin, LOW);
 digitalWrite(strobePin, HIGH);

 previousMillis = millis(); 
}

void loop()
{

  recvWithStartEndMarkers();
  parseData();


if(power == 1)
{
  
int ledPins[10];
 for(int i = 0; i < 10; i++){
  ledPins[i] = mode[ActiveMode-1][i];
  }
 

    digitalWrite(resetPin, HIGH);
    digitalWrite(resetPin, LOW);

    for (int i = 0; i < 7; i++)
    {
      digitalWrite(strobePin, LOW);
      delayMicroseconds(30); // to allow the output to settle
      fqc[i] = analogRead(analogPin);
      digitalWrite(strobePin, HIGH);
    }
 
    ledLevel1 = map(fqc[0], 30, 1023, 0, 4);
    ledLevel2 = map(fqc[1], 30, 1023, 0, 4);
    ledLevel3 = map(fqc[2], 30, 1023, 0, 3);
    ledLevel4 = map(fqc[3], 30, 1023, 0, 3);
    ledLevel5 = map(fqc[4], 30, 1023, 0, 3);
    ledLevel6 = map(fqc[5], 30, 1023, 0, 3);
    ledLevel7 = map(fqc[6], 30, 1023, 0, 3);

    if (ledLevel1 > ledCount1)
    {
      ledLevel1 = ledCount1;
    }
    if (ledLevel2 > ledCount2)
    {
      ledLevel2 = ledCount2;
    }
    if (ledLevel3 > ledCount3)
    {
      ledLevel3 = ledCount3;
    }
    if (ledLevel4 > ledCount4)
    {
      ledLevel4 = ledCount4;
    }
    if (ledLevel5 > ledCount5)
    {
      ledLevel5 = ledCount5;
    }
    if (ledLevel6 > ledCount6)
    {
      ledLevel6 = ledCount6;
    }
    if (ledLevel7 > ledCount7)
    {
      ledLevel7 = ledCount7;
    }

    ledLevel = (ledLevel1 + ledLevel2 + ledLevel3 + ledLevel4 + ledLevel5 + ledLevel6 + ledLevel7);

    

  for (int thisLed = 0; thisLed < ledCount; thisLed++)
  {
    pinMode(ledPins[thisLed], OUTPUT);
    if (thisLed < ledLevel)
    {
      //  digitalWrite(ledPins[thisLed], HIGH);
 left[ledPins[thisLed]] = LL[ledPins[thisLed]];
 right[ledPins[thisLed]] = LR[ledPins[thisLed]];
      FastLED.show();
      delay (1);
    }
    else
    {
  left[ledPins[thisLed]] = BGLL[ledPins[thisLed]];
  right[ledPins[thisLed]] = BGLR[ledPins[thisLed]];
   FastLED.show();
      //ShiftPWM.SetRGB(ledPins[thisLed],0,0,0);
    }
  }
  delay(1);        // delay in between reads for stability


}

}

void recvWithStartEndMarkers() {
  static boolean recvInProgress = false;
  static byte ndx = 0;
  char startMarker = '<';
  char endMarker = '>';
  char rc;
  
        while (Serial1.available() > 0 && newData == false) {
    rc = Serial1.read();

    if (recvInProgress == true) {
      if (rc != endMarker) {
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars) {
          ndx = numChars - 1;
        }
      }
      else {
        receivedChars[ndx] = '\0'; // terminate the string
        recvInProgress = false;
        ndx = 0;
        newData = true;
      }
    }

    else if (rc == startMarker) {
      recvInProgress = true;
    }
  }
}

void parseData() {
if (newData == true) {
    // split the data into its parts
    
  char * strtokIndx; // this is used by strtok() as an index
  
  strtokIndx = strtok(receivedChars,",");      // get the first part - the string
  var[0] = atoi(strtokIndx);   // copy it to messageFromPC


  for(int i = 1; i<51; i++) {
  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  var[i] = atoi(strtokIndx);     // convert this part to an integer
  }
  for(int i = 0; i<51; i++) {
      Serial.println(var[i]);
      EEPROM.write(i, var[i]);
     }

LL[0] = var[0];
LR[0] = var[1];
LL[1] = var[2];
LR[1] = var[3];
LL[2] = var[4];
LR[2] = var[5];
LL[3] = var[6];
LR[3] = var[7];
LL[4] = var[8];
LR[4] = var[9];
LL[5] = var[10];
LR[5] = var[11];
LL[6] = var[12];
LR[6] = var[13];
LL[7] = var[14];
LR[7] = var[15];
LL[8] = var[16];
LR[8] = var[17];
LL[9] = var[18];
LR[9] = var[19];

BGLL[0] = var[20];
BGLR[0] = var[21];
BGLL[1] = var[22];
BGLR[1] = var[23];
BGLL[2] = var[24];
BGLR[2] = var[25];
BGLL[3] = var[26];
BGLR[3] = var[27];
BGLL[4] = var[28];
BGLR[4] = var[29];
BGLL[5] = var[30];
BGLR[5] = var[31];
BGLL[6] = var[32];
BGLR[6] = var[33];
BGLL[7] = var[34];
BGLR[7] = var[35];
BGLL[8] = var[36];
BGLR[8] = var[37];
BGLL[9] = var[38];
BGLR[9] = var[39];

ActiveMode =  var[40];
power = var[41];
rotation = var[42];
rotation_order = var[43];
rotation_time = var[44];
random_mode = var[45];
mode_time = var[46];
mood = var[47];
mood_type = var[48];
moodSpeed = var[49];
colorIndexSpeed = var[50];

newData = false;

}

}

tchinou1:
Okay good. I have made the char array 600.

Does that mean it works properly now?

As a separate issue I was going to complain about the poor indentation of your code but then I realized the problem started with my example (which I have now corrected). For oyur convenience the following is the same code as in your Reply #2 but with better indentation to make it easier to read and to follow the logic.

#include "FastLED.h"
#include <EEPROM.h>

#define NUM_LEDS 10
#define DATA_PIN 4
CRGB left[NUM_LEDS];
CRGB right[NUM_LEDS];


//Serial communication
const int numChars = 600;
char receivedChars[numChars];

boolean newData = false;


int i = 0;
int ii;
unsigned long int var[140];

unsigned long int LL[10];
unsigned long int LR[10];
unsigned long int BGLL[10];
unsigned long int BGLR[10];

//new mode
const int sensitivityPin = A2;  // Analog input pin that the potentiometer is attached to
const int audioPin = A0;        // Analog input pin that the audio channel is attached to
const int ledCount = 10;        // The number of LEDs in the bar graph
const int numReadings = 20;     // Number of samples to keep track of (for smoothing)
const int buttonPin = 13;
int counter=0;
int audioValue;                 // Analog value read from audio channel
int maxAudioValue = 0;          // Maximum analog value read from audio channel
int sensitivityValue;           // Analog value read from potentiometer
int ledLevel;// Value to map to the output LEDs
int ledLeveltot;

int readings[numReadings];      // the readings from the analog input
int index = 0;                  // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average
int power;
int ActiveMode;

int mode[5][10] = { 
 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},   // Mode 1
 {9, 8, 7, 6, 5, 4, 3, 2, 1, 0},   // Mode 2
 {9, 0, 8, 1, 7, 2, 6, 3, 5, 4},   // Mode 3
 {4, 5, 3, 6, 2, 7, 1, 8, 0, 9},   // Mode 4
 {9, 7, 5, 3, 1, 8, 6, 4, 2, 0}    // Mode 5
};

//MSGEQ7
const int ledCount1 = 8;
const int ledCount2 = 8;
const int ledCount3 = 7;
const int ledCount4 = 7;
const int ledCount5 = 7;
const int ledCount6 = 7;
const int ledCount7 = 7;

int ledLevel1;
int ledLevel2;
int ledLevel3;
int ledLevel4;
int ledLevel5;
int ledLevel6;
int ledLevel7;

int analogPin = 0; // read from multiplexer using analog input 0
int fqc[7]; // to hold a2d values

int strobePin = 2; // MSGEQ7 STROBE 4
int resetPin = 3; // MSGEQ7 RESET 7
int filterValue = 0;

//dev var
int rotation;
int rotation_time;
int rotation_order;
unsigned long int nextrotation = 0;
int PreviousRL;
int PreviousGL;
int PreviousBL;
int PreviousRR;
int PreviousGR;
int PreviousBR;

int random_mode;
unsigned long int nextmode = 0;
int mode_time;

//Mood
int mood;
int mood_type;
int v = 0;
int moodSpeed;
int colorIndexSpeed;

CRGBPalette16 currentPalette;
TBlendType    currentBlending;
extern CRGBPalette16 myRedWhiteBluePalette;
extern const TProgmemPalette16 myRedWhiteBluePalette_p PROGMEM;
uint8_t brightness = 255;
int a = 0;
unsigned long currentMillis;
unsigned long previousMillis;


void setup()
{

    FastLED.addLeds<NEOPIXEL, 4>(left, NUM_LEDS);
    FastLED.addLeds<NEOPIXEL, 5>(right, NUM_LEDS);
    Serial.begin(9600);
    Serial1.begin(9600);

    pinMode(analogPin, INPUT);
    pinMode(strobePin, OUTPUT);
    pinMode(resetPin, OUTPUT);
    analogReference(DEFAULT);

    digitalWrite(resetPin, LOW);
    digitalWrite(strobePin, HIGH);

    previousMillis = millis();
}

void loop()
{

    recvWithStartEndMarkers();
    parseData();


if(power == 1)
{
 
int ledPins[10];
 for(int i = 0; i < 10; i++){
    ledPins[i] = mode[ActiveMode-1][i];
    }
 

    digitalWrite(resetPin, HIGH);
    digitalWrite(resetPin, LOW);

    for (int i = 0; i < 7; i++)
    {
        digitalWrite(strobePin, LOW);
        delayMicroseconds(30); // to allow the output to settle
        fqc[i] = analogRead(analogPin);
        digitalWrite(strobePin, HIGH);
    }
 
    ledLevel1 = map(fqc[0], 30, 1023, 0, 4);
    ledLevel2 = map(fqc[1], 30, 1023, 0, 4);
    ledLevel3 = map(fqc[2], 30, 1023, 0, 3);
    ledLevel4 = map(fqc[3], 30, 1023, 0, 3);
    ledLevel5 = map(fqc[4], 30, 1023, 0, 3);
    ledLevel6 = map(fqc[5], 30, 1023, 0, 3);
    ledLevel7 = map(fqc[6], 30, 1023, 0, 3);

    if (ledLevel1 > ledCount1)
    {
        ledLevel1 = ledCount1;
    }
    if (ledLevel2 > ledCount2)
    {
        ledLevel2 = ledCount2;
    }
    if (ledLevel3 > ledCount3)
    {
        ledLevel3 = ledCount3;
    }
    if (ledLevel4 > ledCount4)
    {
        ledLevel4 = ledCount4;
    }
    if (ledLevel5 > ledCount5)
    {
        ledLevel5 = ledCount5;
    }
    if (ledLevel6 > ledCount6)
    {
        ledLevel6 = ledCount6;
    }
    if (ledLevel7 > ledCount7)
    {
        ledLevel7 = ledCount7;
    }

    ledLevel = (ledLevel1 + ledLevel2 + ledLevel3 + ledLevel4 + ledLevel5 + ledLevel6 + ledLevel7);

    

    for (int thisLed = 0; thisLed < ledCount; thisLed++)
    {
        pinMode(ledPins[thisLed], OUTPUT);
        if (thisLed < ledLevel)
        {
                //  digitalWrite(ledPins[thisLed], HIGH);
            left[ledPins[thisLed]] = LL[ledPins[thisLed]];
            right[ledPins[thisLed]] = LR[ledPins[thisLed]];
            FastLED.show();
            delay (1);
        }
        else
        {
            left[ledPins[thisLed]] = BGLL[ledPins[thisLed]];
            right[ledPins[thisLed]] = BGLR[ledPins[thisLed]];
            FastLED.show();
            //ShiftPWM.SetRGB(ledPins[thisLed],0,0,0);
        }
    }
    delay(1);        // delay in between reads for stability


}

}

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;
 
    while (Serial1.available() > 0 && newData == false) {
        rc = Serial1.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
            receivedChars[ndx] = rc;
            ndx++;
            if (ndx >= numChars) {
                ndx = numChars - 1;
            }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

void parseData() {
    if (newData == true) {
        // split the data into its parts
        
        char * strtokIndx; // this is used by strtok() as an index
     
        strtokIndx = strtok(receivedChars,",");      // get the first part - the string
        var[0] = atoi(strtokIndx);   // copy it to messageFromPC


        for(int i = 1; i<51; i++) {
            strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
            var[i] = atoi(strtokIndx);     // convert this part to an integer
        }
        for(int i = 0; i<51; i++) {
            Serial.println(var[i]);
            EEPROM.write(i, var[i]);
         }

        LL[0] = var[0];
        LR[0] = var[1];
        LL[1] = var[2];
        LR[1] = var[3];
        LL[2] = var[4];
        LR[2] = var[5];
        LL[3] = var[6];
        LR[3] = var[7];
        LL[4] = var[8];
        LR[4] = var[9];
        LL[5] = var[10];
        LR[5] = var[11];
        LL[6] = var[12];
        LR[6] = var[13];
        LL[7] = var[14];
        LR[7] = var[15];
        LL[8] = var[16];
        LR[8] = var[17];
        LL[9] = var[18];
        LR[9] = var[19];

        BGLL[0] = var[20];
        BGLR[0] = var[21];
        BGLL[1] = var[22];
        BGLR[1] = var[23];
        BGLL[2] = var[24];
        BGLR[2] = var[25];
        BGLL[3] = var[26];
        BGLR[3] = var[27];
        BGLL[4] = var[28];
        BGLR[4] = var[29];
        BGLL[5] = var[30];
        BGLR[5] = var[31];
        BGLL[6] = var[32];
        BGLR[6] = var[33];
        BGLL[7] = var[34];
        BGLR[7] = var[35];
        BGLL[8] = var[36];
        BGLR[8] = var[37];
        BGLL[9] = var[38];
        BGLR[9] = var[39];

        ActiveMode =  var[40];
        power = var[41];
        rotation = var[42];
        rotation_order = var[43];
        rotation_time = var[44];
        random_mode = var[45];
        mode_time = var[46];
        mood = var[47];
        mood_type = var[48];
        moodSpeed = var[49];
        colorIndexSpeed = var[50];

        newData = false;

    }

}

...R

I could not get the rest of what I wanted to say into Reply #3, so here it is ...
As another aside, why are you using this sort of thing

LL[0] = var[0];
 LR[0] = var[1];
 LL[1] = var[2];
 LR[1] = var[3];

or this sort of thing

ledLevel6 = map(fqc[5], 30, 1023, 0, 3);
 ledLevel7 = map(fqc[6], 30, 1023, 0, 3);

 if (ledLevel1 > ledCount1)
 {
 ledLevel1 = ledCount1;
 }
 if (ledLevel2 > ledCount2)
 {
 ledLevel2 = ledCount2;
 }

when your code would be much shorter if you used a FOR loop (and arrays in the 2nd case). Shorter code reduces the scope for typing errors.

...R

Thanks for the your modifications !
I just realized that the description of the error that I gave you were for this little test program:

 if(Serial1.available()){
     Serial.println(Serial1.read());
 }

I was wondering if the fact that even when you print what is receive and you don't get all the data could not mean that the problem come from the transmitter (it's a Photon, arduino compatible Wifi microcontroller)

For the bunch of if statement, it was my friends that wrote (he just start in programmation (I'm not pretending to be an expert !)) but I didn't take time to change it because we will probably get rid of this part.

For the array part (var[0]), I don't understand what you mean by replacing it with an array (that's why I was not pretending to be an expert ! :wink: )

tchinou1:
For the array part (var[0]), I don't understand what you mean by replacing it with an array (that's why I was not pretending to be an expert ! :wink: )

You should train your expertise in reading. :wink:

Robin2:
your code would be much shorter if you used a FOR loop (and arrays in the 2nd case).

ahahah oups ! good point dude !

tchinou1:
Thanks for the your modifications !
I just realized that the description of the error that I gave you were for this little test program:

 if(Serial1.available()){

Serial.println(Serial1.read());
}




I was wondering if the fact that even when you print what is receive and you don't get all the data could not mean that the problem come from the transmitter (it's a Photon, arduino compatible Wifi microcontroller)

To confidently assign the problem to the transmittter you need to have reliable code in the receiver - which is what I tried to create in Serial Input Basics

An important part of reliable receiving code is taking account of the fact that, by Arduino standards, serial data arrives very slowly.

Am I correct to assume that your program is now receiving the data properly?

...R

Hi, eum no I still can't receive the data correctly, but I don't understand why you're saying that I need a reliable code to test, if I print in my monitor everything that I'm receiving, I will see if there is a problem. (I don't want to argument, I just don't understand).

sorry for the delay, it wasn't able to find the post...

tchinou1:
Hi, eum no I still can't receive the data correctly,

Post your latest code so we can keep up with you.

I don't want to argue either - have you tried any of the examples in Serial Input Basics? Did it work?

There is a big difference between you, an intelligent human, making sense of stuff and a stupid computer making "sense" of stuff.

...R

tchinou1:
I don't understand why you're saying that I need a reliable code to test, if I print in my monitor everything that I'm receiving, I will see if there is a problem.

And if the serial monitor output shows that everything is working properly, you're all set. But in your case, the serial monitor output is apparently not correct, or you wouldn't be posting a problem. So now, the question is where is the problem? There is a long chain of steps involved:

  • The sending code collecting the data to be output
  • The sending code formatting the data for output
  • The sending code actually transmitting the data
  • The physical medium (wires) conducting the signal between processors without noise or distortion
  • The receiving code actually receiving the data
  • The receiving code parsing and decoding the data
  • The receiving code echoing the data to the Serial Monitor
  • The physical medium between the receiver and the serial monitor
  • The Serial Monitor itself

The Serial Monitor is showing that there is a problem, but where is it? The output may let you make educated guesses (the quality of those guesses comes with experience) but you don't really know. The issue is that there are too many unknowns: you need something reliable to be able to tell you what is really happening.

That could be a known piece of test code on either end (like on the receiver end as Robin suggests) or some simple test code on the transmitter end sending fixed known test sequences. Or it could be a serial terminal replacing one of the nodes so you can see what is being sent, or simulate sending something. Or it could be a piece of test equipment monitoring the lines. The key is that whatever you use to test the communications has to be something you can trust and have faith in, or else you are just introducing another variable, one which could lead you down the wrong path.

I've used a long list of methods to debug communications:

  • Fancy serial line protocol analyzes
  • Simple receiver/transmitter test code
  • Terminal emulators on computers
  • Actual dumb video terminals (back in the day when they were prevalent)
  • Circuits to tap into the lines and allow a terminal/terminal emulator to view the data
  • But my current go-to method is to hook up a logic analyzer to the Tx/Rx lines, capture the conversation, and analyze the data content and timing.

What method you use depends on what is available to you and what works for you. But relying on print statements from the receiver code only tells you whether there is a problem, it often doesn't help you figure out where that problem might be.

Well first of all I don't think that the problem come from hardware. I'll explain which modifications I've done. In the begening, I was sending the data in int as RGB colors and I decided to double de number of color I was sending (I past from 78 to 131 int). But this was not working, beyond 100 int there was a problem (I think) in the communcation. After that I decided to pass from RGB color to HEX color (It was simplifying my code and I was hoping it might fix the problem due to the smaller number value sent)

So my first guess was a memory problem or a question of time, but I can't find anything about this.

I haven't changed the sending method or the receiception method.

I still have the RGB code for testing.

Thanks ! :slight_smile:

tchinou1:
Well first of all I don't think that the problem come from hardware.

In this case, you're right, it's probably not hardware. But it does happen, and you shouldn't have your mind closed to the possibility.

But this was not working, beyond 100 int there was a problem (I think) in the communcation.

When something suddenly stops working when you increase a quantity, it's often a case of overruning a buffer that isn't big enough, or overflowing a counter that isn't big enough.

When I first read this, I took it to mean that once an integer had a value of 100, things stopped working. That's suspicious as it points to a buffer not being big enough and having trouble once you reach a third digit. But now I read that to mean the number of integers you are sending, and not the value of the integer itself.

Looking at the code you posted in reply #2, I see a couple things in parseData() that concerns me. One is that you use strtok() to break the received characters into 52 tokens, and convert those tokens into integers. But you never check the return value of strtok() to see if you really did get at least 52 tokens. If something happened in the transmission, and some commas were lost, strtok() could start returning NULL pointers, and that will likely cause atoi() to give you some strange results.

The other concern is the possibility of a timing problem: every time you get new data, you store 51 values in EEPROM, and then echo them out at 9600 bps. There are two concerns with using the EEPROM library in this manner, as mentioned in the EEPROM.write() reference page:

Note

An EEPROM write takes 3.3 ms to complete. The EEPROM memory has a specified life of 100,000 write/erase cycles, so you may need to be careful about how often you write to it.

Besides the very real potential of wearing out the EEPROM memory, storing 51 bytes takes 168 ms. Then, printing out the data could take up to 204 characters (three digits plus newline) and that will take another 212 ms. That's 380 ms right there, not counting all of the other processing. That doesn't sound like much, but how fast is the data coming in? That delay equates to 365 characters worth of incoming data if the next update is sent right after the last. During that time, you can easily overrun a serial input buffer and drop characters.

And don't discount the life of the EEPROM: while 100,000 write cycles sounds like a lot, it really isn't. Say you're receiving a string of numbers once per second: you will wear out the EEPROM in less than 28 hours.

If you really need to store those values in EEPROM (I notice your code never reads EEPROM) then you should be comparing the new value with the last stored value, and only write it to EEPROM if the value has actually changed.

I also have a minor issue with recvWithStartEndMarkers(): you check for the startMarker character only when a receive is not in progress. What's it going to do if an endMarker character happens to get garbled or lost? For example, if "<1,2,3>\n<4,5,6>" dropped a character, and you ended up with "<1, 2, 3\n<4, 5, 6>"? You would end up with the string "1,2,3\n4,5,6" in your received characters buffer, and the code could get confused by it. Personally, I think you should be checking for the startMarker on every character, and if found, set ndx to zero in addition to setting recvInProgress to true. This will reset things, throw out the incomplete data, and start over again.

tchinou1:

 if(Serial1.available()){

Serial.println(Serial1.read());
}

This is not a reliable way to validate that things are received correctly. If both ports are running at the same speed, you are sending twice as much data out of Serial than you are reading from Serial1 (each character received is sent out with an additional newline character since you are using println().) As each character is written, two more will be received. Eventually, you will run out of receiver input buffer space (I think it's 64 bytes?) and will start dropping characters.

tchinou1:
I haven't changed the sending method or the receiception method.

That is a politician's answer. It means you did change something. Please post the latest code.

...R

Ahahahah nice anwser ! Well I will get back to where it was working.

I'll do this in 2 post to be clearer (at least I'll try !)
Forget the hex, I'll get back to the RGB Int.

This is the code that is working fine. I'm sending 71 int.

Transmister:

#include "SparkJson/SparkJson.h"

#include "application.h"
#include "HttpClient.h"
HttpClient http;

const byte kIp[] = {104, 238, 136, 31};
const char kHostname[] = "luxontower.com";

const char kPath[] = "/app/data2.php?id=50ff66065067545630290587";



// Number of milliseconds to wait without receiving any data before we give up
const int kNetworkTimeout = 5*1000;
// Number of milliseconds to wait if no data is available before trying again
const int kNetworkDelay = 200;
// If Content-Length isn't given this is used for the max body length
const int fallbackContentLength = 1024;

//int Level[20];

byte red[45];
byte green[45];
byte blue[45];

int modif = 0;
unsigned long Level_last[40];
int Options_last[40];


void setup() {
     Serial.begin(9600);
    Serial1.begin(9600);
}

void loop() {
    modif = 0;
  int err = 0;
  unsigned long httpStartTime = millis();

  err = http.get(kHostname, kPath);

  if (err == 0)
  {
    Serial.println("startedRequest ok");

    err = http.responseStatusCode();
    if (err >= 0)
    {
      Serial.print("Got status code: ");
      Serial.println(err);

      err = http.skipResponseHeaders();
      if (err >= 0)
      {
        int bodyLen = http.contentLength();
        Serial.print("Content length is: ");
        Serial.println(bodyLen);
        Serial.println();

        // Now we've got to the body, so we can print it out
        unsigned long timeoutStart = millis();
        if (bodyLen <= 0)
          bodyLen = fallbackContentLength;

        char body[bodyLen+1];

        char c;
        int i = 0;
        // Whilst we haven't timed out & haven't reached the end of the body
        while ( (http.connected() || http.available()) &&
               ((millis() - timeoutStart) < kNetworkTimeout))
        {
          if (http.available())
          {
            c = http.read();
            body[i] = c;
            i++;
            // We read something, reset the timeout counter
            timeoutStart = millis();
          }
          else
          {
            if (http.endOfBodyReached()) {
              Serial.println("End of body reached according to http.endOfBodyReached()");
              http.stop();
            }
            delay(kNetworkDelay);
          }
        }
        body[i] = '\0';
        //return body;
        Serial.println();
        Serial.println("body variable ==");
        Serial.print(body);

     const int BUFFER_SIZE = JSON_OBJECT_SIZE(52);

     StaticJsonBuffer<BUFFER_SIZE> jsonBuffer;

        
        JsonObject& root = jsonBuffer.parseObject(body);
        
        if (!root.success())
{
  Serial.println("parseObject() failed");
  return;
} else {Serial.println("Succes");}
        
 
        unsigned long L1L = root["L1L"]; 
        unsigned long  L1R = root["L1R"]; 
        unsigned long  L2L = root["L2L"]; 
        unsigned long  L2R = root["L2R"]; 
        unsigned long  L3L = root["L3L"]; 
        unsigned long  L3R = root["L3R"];
        unsigned long  L4L = root["L4L"]; 
        unsigned long  L4R = root["L4R"]; 
        unsigned long  L5L = root["L5L"]; 
        unsigned long  L5R = root["L5R"];
        unsigned long  L6L = root["L6L"]; 
        unsigned long  L6R = root["L6R"]; 
        unsigned long  L7L = root["L7L"]; 
        unsigned long  L7R = root["L7R"]; 
        unsigned long  L8L = root["L8L"]; 
        unsigned long  L8R = root["L8R"]; 
        unsigned long  L9L = root["L9L"]; 
        unsigned long  L9R = root["L9R"]; 
        unsigned long  L10L = root["L10L"]; 
        unsigned long  L10R = root["L10R"]; 
        int Mode = root["Mode"]; 
        int Pwr = root["Pwr"]; 
        int Rot = root["Rot"]; 
        int RotO = root["RotO"]; 
        int RotT = root["RotT"]; 
        int Rdm = root["Rdm"]; 
        int RdmT = root["RdmT"];
        int Mood = root["Mood"]; 
        int MoodT = root["MoodT"]; 
        int Sens = root["Sens"]; 
        int MoodS = root["MoodS"]; 
        int IndexColorS = root["IndexColorS"]; 
        
        unsigned long Level[20] = {
          L1L, L1R,
          L2L, L2R,
          L3L, L3R,
          L4L, L4R,
          L5L, L5R,
          L6L, L6R,
          L7L, L7R,
          L8L, L8R,
          L9L, L9R,
          L10L, L10R
          };  
          
          int Options[20] = {
              Mode, Pwr,
              Rot, RotO,
              RotT, Rdm,
              RdmT, Mood,
              MoodT, Sens,
              MoodS, IndexColorS
          };
          
for (i=0;i<20;i++) {
if(Level[i]!=Level_last[i] || Options[i] != Options_last[i]) {
modif = 1; 
Serial.println("not equals");
}}


    if(modif == 1) {
        for(int i = 0; i < 40; i++){ 
        red[i] = Level[i] >> 16 ;
        green[i] = (Level[i] & 0x00ff00) >> 8;
        blue[i] = (Level[i] & 0x0000ff);
        delay(1);
        }


   int var[80] = {
        red[0], green[0], blue[0],
        red[1], green[1], blue[1],
        red[2], green[2], blue[2],
        red[3], green[3], blue[3],
        red[4], green[4], blue[4],
        red[5], green[5], blue[5],
        red[6], green[6], blue[6],
        red[7], green[7], blue[7],
        red[8], green[8], blue[8],
        red[9], green[9], blue[9],
        red[10], green[10], blue[10],
        red[11], green[11], blue[11],
        red[12], green[12], blue[12],
        red[13], green[13], blue[13],
        red[14], green[14], blue[14],
        red[15], green[15], blue[15],
        red[16], green[16], blue[16],
        red[17], green[17], blue[17],
        red[18], green[18], blue[18],
        red[19], green[19], blue[19],
        Mode, Pwr, Rot, 
        RotO, RotT, Rdm, 
        RdmT, Mood, MoodT, 
        MoodS, IndexColorS
        };


Serial.println("Sending values to arduino");
Serial1.print("<");
    for(int i = 0; i < 71; i++){
        Serial1.print(var[i]);   
        Serial1.print(",");
        Serial.println(var[i]);
    } 
Serial1.print(">");    
Serial.println("Data sent");
    
    
for(i=0 ;i<20;i++) {
  Level_last[i] = Level[i]; 
  Options_last[i] = Options[i];
  }  
    }
 
      }
      
      else
      {
        Serial.print("Failed to skip response headers: ");
        Serial.println(err);
      }
    }
    else
    {
      Serial.print("Getting response failed: ");
      Serial.println(err);
    }
  }
  else
  {
    Serial.print("Connect failed: ");
    Serial.println(err);
  }
  http.stop();

  Serial.println();
  Serial.print("http request took : ");
  Serial.print(millis()-httpStartTime);
  Serial.println("ms");
   
   
}

Receiver:

void recvWithStartEndMarkers() {
  static boolean recvInProgress = false;
  static byte ndx = 0;
  char startMarker = '<';
  char endMarker = '>';
  char rc;
  
    while (Serial1.available() > 0 && newData == false) {
    rc = Serial1.read();

    if (recvInProgress == true) {
      if (rc != endMarker) {
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars) {
          ndx = numChars - 1;
        }
      }
      else {
        receivedChars[ndx] = '\0'; // terminate the string
        recvInProgress = false;
        ndx = 0;
        newData = true;
      }
    }

    else if (rc == startMarker) {
      recvInProgress = true;
    }
  }
}

void parseData() {
if (newData == true) {
    // split the data into its parts
    
  char * strtokIndx; // this is used by strtok() as an index
  
  strtokIndx = strtok(receivedChars,",");      // get the first part - the string
  var[0] = atoi(strtokIndx);   // copy it to messageFromPC


  for(int i = 1; i<71; i++) {
  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  var[i] = atoi(strtokIndx);     // convert this part to an integer
  }
  for(int i = 0; i<71; i++) {
      Serial.println(var[i]);
      EEPROM.write(i, var[i]);
     }

  RL[0] = var[0];
 RL[1] = var[6];
 RL[2] = var[12];
 RL[3] = var[18];
 //ETC
 ColorIndexSpeed = var[70];

newData = false;

}

After that, I've passed from 71 int to 131 and now this is not working.

Transmitter (I have isolated a part of the code because it is too big)

 const int BUFFER_SIZE = JSON_OBJECT_SIZE(52);
     Serial.println("Buffer size:");
       Serial.println(BUFFER_SIZE);
StaticJsonBuffer<BUFFER_SIZE> jsonBuffer;

        
        JsonObject& root = jsonBuffer.parseObject(body);
        
        if (!root.success())
{
  Serial.println("parseObject() failed");
  return;
} else {Serial.println("Succes");}
        
 
        unsigned long L1L = root["L1L"]; //Level 1 Left
        unsigned long  L1R = root["L1R"]; //Level 1 Right
        unsigned long  L2L = root["L2L"]; //Level 2 Left
        unsigned long  L2R = root["L2R"]; //Level 2 Right
        unsigned long  L3L = root["L3L"]; //Level 3 Left
        unsigned long  L3R = root["L3R"]; //Level 3 Right 
        unsigned long  L4L = root["L4L"]; //Level 4 Left
        unsigned long  L4R = root["L4R"]; //Level 4 Right
        unsigned long  L5L = root["L5L"]; //Level 5 Left
        unsigned long  L5R = root["L5R"]; //Level 5 Right
        unsigned long  L6L = root["L6L"]; //Level 6 Left
        unsigned long  L6R = root["L6R"]; //Level 6 Right
        unsigned long  L7L = root["L7L"]; //Level 7 Left
        unsigned long  L7R = root["L7R"]; //Level 7 Right
        unsigned long  L8L = root["L8L"]; //Level 8 Left
        unsigned long  L8R = root["L8R"]; //Level 8 Right
        unsigned long  L9L = root["L9L"]; //Level 9 Left
        unsigned long  L9R = root["L9R"]; //Level 9 Right
        unsigned long  L10L = root["L10L"]; //Level 10 Left
        unsigned long  L10R = root["L10R"]; //Level 10 Right
        unsigned long  BGL1L = root["BGL1L"]; //Background Level 1 Left
        unsigned long  BGL1R = root["BGL1R"]; //Background Level 1 Right
        unsigned long  BGL2L = root["BGL2L"]; //Background Level 2 Left
        unsigned long  BGL2R = root["BGL2R"]; //Background Level 2 Right
        unsigned long  BGL3L = root["BGL3L"]; //Background Level 3 Left
        unsigned long  BGL3R = root["BGL3R"]; //Background Level 3 Right 
        unsigned long  BGL4L = root["BGL4L"]; //Background Level 4 Left
        unsigned long  BGL4R = root["BGL4R"]; //Background Level 4 Right
        unsigned long  BGL5L = root["BGL5L"]; //Background Level 5 Left
        unsigned long  BGL5R = root["BGL5R"]; //Background Level 5 Right
        unsigned long  BGL6L = root["BGL6L"]; //Background Level 6 Left
        unsigned long  BGL6R = root["BGL6R"]; //Background Level 6 Right
        unsigned long  BGL7L = root["BGL7L"]; //Background Level 7 Left
        unsigned long  BGL7R = root["BGL7R"]; //Background Level 7 Right
        unsigned long  BGL8L = root["BGL8L"]; //Background Level 8 Left
        unsigned long  BGL8R = root["BGL8R"]; //Background Level 8 Right
        unsigned long  BGL9L = root["BGL9L"]; //Background Level 9 Left
        unsigned long  BGL9R = root["BGL9R"]; //Background Level 9 Right
        unsigned long  BGL10L = root["BGL10L"]; //Background Level 10 Left
        unsigned long  BGL10R = root["BGL10R"]; //Background Level 10 Right
        int Mode = root["Mode"]; //Mode
        int Pwr = root["Pwr"]; //Activate the Tower (on/off)
        int Rot = root["Rot"]; //Rotation on/off
        int RotO = root["RotO"]; //Rotation order
        int RotT = root["RotT"]; //Rotation Time
        int Rdm = root["Rdm"]; //Random on/off
        int RdmT = root["RdmT"]; //Random Time
        int Mood = root["Mood"]; //Mood On/Off
        int MoodT = root["MoodT"]; //Mood type
        int Sens = root["Sens"]; //Sensitivity
        int MoodS = root["MoodS"]; //Mood Speed
        int IndexColorS = root["IndexColorS"]; //Index Color Speed
        
        unsigned long Level[40] = {
          L1L, L1R,
          L2L, L2R,
          L3L, L3R,
          L4L, L4R,
          L5L, L5R,
          L6L, L6R,
          L7L, L7R,
          L8L, L8R,
          L9L, L9R,
          L10L, L10R,
          BGL1L, BGL1R,
          BGL2L, BGL2R,
          BGL3L, BGL3R,
          BGL4L, BGL4R,
          BGL5L, BGL5R,
          BGL6L, BGL6R,
          BGL7L, BGL7R,
          BGL8L, BGL8R,
          BGL9L, BGL9R,
          BGL10L, BGL10R
          };  
          
          int Options[40] = {
              Mode, Pwr,
              Rot, RotO,
              RotT, Rdm,
              RdmT, Mood,
              MoodT, Sens,
              MoodS, IndexColorS
          };
          
for (i=0;i<40;i++) {
if(Level[i]!=Level_last[i] || Options[i] != Options_last[i]) {
modif = 1; 
Serial.println("not equals");
}}


    if(modif == 1) {
        for(int i = 0; i < 40; i++){ 
        red[i] = Level[i] >> 16 ;
        green[i] = (Level[i] & 0x00ff00) >> 8;
        blue[i] = (Level[i] & 0x0000ff);
        delay(1);
        }

    int var[150] = {
        red[0], green[0], blue[0],
        red[1], green[1], blue[1],
        red[2], green[2], blue[2],
        red[3], green[3], blue[3],
        red[4], green[4], blue[4],
        red[5], green[5], blue[5],
        red[6], green[6], blue[6],
        red[7], green[7], blue[7],
        red[8], green[8], blue[8],
        red[9], green[9], blue[9],
        red[10], green[10], blue[10],
        red[11], green[11], blue[11],
        red[12], green[12], blue[12],
        red[13], green[13], blue[13],
        red[14], green[14], blue[14],
        red[15], green[15], blue[15],
        red[16], green[16], blue[16],
        red[17], green[17], blue[17],
        red[18], green[18], blue[18],
        red[19], green[19], blue[19],
        red[20], green[20], blue[20],
        red[21], green[21], blue[21],
        red[22], green[22], blue[22],
        red[23], green[23], blue[23],
        red[24], green[24], blue[24],
        red[25], green[25], blue[25],
        red[26], green[26], blue[26],
        red[27], green[27], blue[27],
        red[28], green[28], blue[28],
        red[29], green[29], blue[29],
        red[30], green[30], blue[30],
        red[31], green[31], blue[31],
        red[32], green[32], blue[32],
        red[33], green[33], blue[33],
        red[34], green[34], blue[34],
        red[35], green[35], blue[35],
        red[36], green[36], blue[36],
        red[37], green[37], blue[37],
        red[38], green[38], blue[38],
        red[39], green[39], blue[39],
        Mode, Pwr, Rot, 
        RotO, RotT, Rdm, 
        RdmT, Mood, MoodT, 
        MoodS, IndexColorS
        };

Serial.println("Sending values to arduino");
Serial1.print("<");
    for(int i = 0; i < 131; i++){
        Serial1.print(var[i]);   
        Serial1.print(",");
        Serial.println(var[i]);
    } 
Serial1.print(">");    
Serial.println("Data sent");
    
    
for(i=0 ;i<40;i++) {
  Level_last[i] = Level[i]; 
  Options_last[i] = Options[i];
  }

Receiver:

void recvWithStartEndMarkers() {
  static boolean recvInProgress = false;
  static byte ndx = 0;
  char startMarker = '<';
  char endMarker = '>';
  char rc;
  
  // if (Serial.available() > 0) {
        while (Serial1.available() > 0 && newData == false) {
    rc = Serial1.read();
   // Serial.println(Serial1.read());

    if (recvInProgress == true) {
      if (rc != endMarker) {
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars) {
          ndx = numChars - 1;
        }
      }
      else {
        receivedChars[ndx] = '\0'; // terminate the string
        recvInProgress = false;
        ndx = 0;
        newData = true;
      }
    }

    else if (rc == startMarker) {
      recvInProgress = true;
    }
  }
}

void parseData() {
if (newData == true) {
    // split the data into its parts
    
  char * strtokIndx; // this is used by strtok() as an index
  
  strtokIndx = strtok(receivedChars,",");      // get the first part - the string
  var[0] = atoi(strtokIndx);   // copy it to messageFromPC


  for(int i = 1; i<131; i++) {
  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  var[i] = atoi(strtokIndx);     // convert this part to an integer
  }
  for(int i = 0; i<131; i++) {
      Serial.println(var[i]);
    //  EEPROM.write(i, var[i]);
     }

  RL[0] = var[0];
 RL[1] = var[6];
 RL[2] = var[12];
 //... ETC
 colorIndexSpeed = var[130];

newData = false;

}

tchinou1:
After that, I've passed from 71 int to 131 and now this is not working.

Can you be more specific as to just what is not working? Exactly what are you seeing that is wrong? Is it always the same from run to run, or does it vary? Is the location of the first error the same from run to run, or does it vary?

@tchinou1, I can't understand your thought process.

You are having a problem receiving data so you post the complete code for the transmitter but only a snippet of the receiver code.

Post the complete receiver program.

...R

The code is too long to be posted, but I forgot that I could just join the file ! I have also joined the library to compile the code. :slight_smile:

working_71.ino (15 KB)

not_working_131.ino (16.3 KB)

FastLED-master.zip (134 KB)