Simple for-loop let sketch hang

Hi all,

After hours of searching online for potential caveats and suggestions that could solve my problem I thought it might be useful to post my problem here.

The problem: I've build a sketch which drives a led-strip and a temperature sensor. Communication will mainly go through the I2C-bus. Now, everything in the sketch is working except for one simple for-loop that seems to hang my sketch. The for-loop I'm talking about is within the switch-case (33) statement (see code below). When I remove the for-loop in that 'case' it keeps on running the program. First I tried to make the sketch smaller (removing unneeded code), then I optimized my code to save SRAM (changing ints to bytes and even removing the complete temperature structure and logging). But again without any promissing results. :frowning: I can't seem to find where I make a mistake or that I am running against the limits (which I doubt).

Any advice or help would be really appreciated. :slight_smile:

Thanks in advance.

Marcel (PiDome)

/*************** INCLUDES ***************/
#include <Wire.h>
#include <Adafruit_NeoPixel.h>

/*************** DEFINE CONSTANTS ***************/
#define  AREF_VOLTAGE       5.0
#define  I2C_ADDR           0x40
#define  REG_MAP_SIZE       45
#define  MAX_SENT_BYTES     1
#define  IDENTIFICATION     0x46

#define  LEDPIN             3
#define  TEMPPIN            0
#define  MPPIN              1

/*************** GLOBAL  VARIABLES  ***************/
byte registerMap[REG_MAP_SIZE];
byte registerMapTemp[REG_MAP_SIZE];
byte receivedCommands[MAX_SENT_BYTES];
byte newDataAvailable = 0;
float TEMP_collector = 0;
int TEMP_counter = 0;
int readDelay = 20;
boolean stringComplete = false;
String inputString = "";
int charcounter = 0;
byte numLEDS = 60;
byte fadetime = 2;
byte ticktime = 20;
byte R, G, B;

Adafruit_NeoPixel strip = Adafruit_NeoPixel(numLEDS, LEDPIN, NEO_GRB + NEO_KHZ800);

void setup() {
  Serial.begin(115200);
  Wire.begin(I2C_ADDR);
  Wire.onRequest(requestEvent);                     // Set interrupt - master requesting data from slave
  Wire.onReceive(receiveEvent);                     // Set interrupt - master sending data to slave
  registerMap[REG_MAP_SIZE - 1] = IDENTIFICATION;   // Set ID register
  strip.begin();                                    // Initialize ledstrip
  strip.show();                                     // Set all pixels to 'off'
  Serial.println(F("Ready"));
}

void loop() {
  TEMPreadSignal();
  newDataAvailable = 0;
  storeData();
  newDataAvailable = 1;
  readSerial();
  serialEvent();
}

void storeData() {
  byte * bytePointer;                              // We declare a pointer as type byte
  byte arrayIndex = 1;                             // We need to keep track of where we are storing data in the array
  registerMapTemp[0] = 0;                          // No need to use a pointer for Status
  float TEMP = TEMP_collector / TEMP_counter;
  bytePointer = (byte*)&TEMP;                      // Temperature is 4 bytes
  for (int i = 3; i > -1; i--) {
    registerMapTemp[arrayIndex] = bytePointer[i];  // Increment pointer to store each byte but MSB first
    arrayIndex++;
  }
}

void requestEvent() {  // The master requests data, so lets send it
  byte sendBytes = 0;
  if(newDataAvailable) {
    switch(receivedCommands[0]) {
      case 1:  // (0x01) Store temperature in memory spots
        registerMap[0] = registerMapTemp[0];
        registerMap[1] = registerMapTemp[1];
        registerMap[2] = registerMapTemp[2];
        registerMap[3] = registerMapTemp[3];
        sendBytes = 4;
      break;
      case 49:  // (0x31) Store current RGB color in memory spots
        registerMap[0] = R;
        registerMap[1] = G;
        registerMap[2] = B; 
        Serial.println(R);
        Serial.println(G);
        Serial.println(B);
        sendBytes = 3;
      break;
    }
  }
  newDataAvailable = 0;
  Wire.write(registerMap + receivedCommands[0], sendBytes);
}

void receiveEvent(int bytesReceived) {  //The master sends data, lets handle it
  for (byte a = 0; a < bytesReceived; a++) {
    receivedCommands[a] = Wire.read();
  }

  byte Rend = receivedCommands[1];
  byte Gend = receivedCommands[2];
  byte Bend = receivedCommands[3];
  byte smoothing = 50;

  switch(receivedCommands[0]) {

    case 5:  // (0x05) (n) Set color directly
      for(byte i=0; i <= numLEDS; i++) {
        strip.setPixelColor(i, strip.Color(receivedCommands[1], receivedCommands[2], receivedCommands[3]));
      }
      strip.show();
      R = receivedCommands[1];
      G = receivedCommands[2];
      B = receivedCommands[3];
      Serial.println(F("0x05 OK"));
    break;
    
    case 9:  // (0x09) (c) Fade to color
      Serial.println(F("Fading"));
      for(byte i = 0; i <= smoothing; i++) {
        byte Rnew = R + (Rend - R) * i / smoothing;
        byte Gnew = G + (Gend - G) * i / smoothing;
        byte Bnew = B + (Bend - B) * i / smoothing;
        for (byte l = 0; l <= numLEDS; l++) {
          strip.setPixelColor(l, strip.Color(Rnew, Gnew, Bnew));
        }
        strip.show();
        delayTime(0);
      }
      R = receivedCommands[1];
      G = receivedCommands[2];
      B = receivedCommands[3];
      Serial.println(F("0x09 OK"));
    break;
    
    case 19:  // (0x13) (l) Fade from left to right
      Serial.println(F("Fading"));
      for (byte l = 0; l <= numLEDS; l++) {
        for(byte i = 0; i <= smoothing; i++) {
          byte Rnew = R + (Rend - R) * i / smoothing;
          byte Gnew = G + (Gend - G) * i / smoothing;
          byte Bnew = B + (Bend - B) * i / smoothing;
          strip.setPixelColor(l, strip.Color(Rnew, Gnew, Bnew));
          strip.show();
        }
        delayTime(40);
      }
      R = receivedCommands[1];
      G = receivedCommands[2];
      B = receivedCommands[3];
      Serial.println(F("0x13 OK"));
    break;
    
    case 23:  // (0x17) (r) Fade from right to left
      Serial.println(F("Fading"));
      for (byte l = numLEDS; l >= 0; l--) {
        for(byte i = 0; i <= smoothing; i++) {
          byte Rnew = R + (Rend - R) * i / smoothing;
          byte Gnew = G + (Gend - G) * i / smoothing;
          byte Bnew = B + (Bend - B) * i / smoothing;
          strip.setPixelColor(l, strip.Color(Rnew, Gnew, Bnew));
          strip.show();
        }
        delayTime(40);
      }
      R = receivedCommands[1];
      G = receivedCommands[2];
      B = receivedCommands[3]; 
      Serial.println(F("0x17 OK"));
    break;

    case 33:  // (0x21) (x) Set randomly the new color
      for (int x = 0; x < 60; x++) {
        Serial.println(x);
      }
      Serial.println(F("0x21 OK"));
    break;
    
    case 37:  // (0x25) (f) Set fade time
      Serial.println(F("0x25 OK"));
    break;
    
    case 39:  // (0x27) (t) Set tick time
      Serial.println(F("0x27 OK"));
    break;
    
    case 41:  // (0x29) (a) Set the amount of leds in strip
      Serial.println(F("0x29 OK"));
    break;
    
    case 53:  // (0x35) (y) Turn entire LED-strip on to last known color
      for(byte i = 0; i <= smoothing; i++) {
        byte Rnew = (R - 0) * i / smoothing;
        byte Gnew = (G - 0) * i / smoothing;
        byte Bnew = (B - 0) * i / smoothing;
        for (byte l = 0; l <= numLEDS; l++) {
          strip.setPixelColor(l, strip.Color(Rnew, Gnew, Bnew));
        }
        strip.show();
        delayTime(0);
      }
      Serial.println(F("0x35 OK"));
    break;
    
    case 55:  // (0x37) (z) Turn entire LED-strip off
      for(byte i = 0; i <= smoothing; i++) {
        byte Rnew = R + (0 - R) * i / smoothing;
        byte Gnew = G + (0 - G) * i / smoothing;
        byte Bnew = B + (0 - B) * i / smoothing;
        for (byte l = 0; l <= numLEDS; l++) {
          strip.setPixelColor(l, strip.Color(Rnew, Gnew, Bnew));
        }
        strip.show();
        delayTime(0);
      }
      Serial.println(F("0x37 OK"));
    break;
    
    case 66:  // (0x42) (s) Store volatile data in EEPROM
      Serial.println(F("0x42 OK"));
    break; 
  }
}
void delayTime(byte substract) {
  if (substract != (ticktime * fadetime)) {
    if ((ticktime * fadetime) > 0 ) {
      delay((ticktime * fadetime) - substract);
    }
  }
}

void TEMPreadSignal() {
    int TEMP_signal = analogRead(TEMPPIN);
    delay(readDelay);
    TEMP_collector += (((TEMP_signal * AREF_VOLTAGE)/1024) - 0.5) * 100;
    TEMP_counter++;
    if (TEMP_counter >= 1000) {
      TEMP_collector = TEMP_collector / TEMP_counter;
      TEMP_counter = 1;
    }
}

void readSerial() {
  if(stringComplete==true) {
    if(inputString == "T") {  // Get the current temperature
      Serial.println(TEMP_collector / TEMP_counter);
    } else if (inputString == "G") {  // Get the current RGB value
      
      Serial.print(R);Serial.print(F(":"));Serial.print(G);Serial.print(F(":"));Serial.println(B);
    }
    charcounter=0;
    inputString="";
    stringComplete = false;
  }  
}

void serialEvent() {
  while (Serial.available()) {
    char inChar = (char)Serial.read();
    if (inChar == '\n') {
      stringComplete = true;
    } else {
      inputString += inChar;
    }
  }
}

It isn't the for loop, it's the Serial print in interrupt context that is your problem.