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. 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.
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;
}
}
}