Arduino Mega RGBW sketch lock-ups
-
Hi everyone,
I have this current node controlling the lights and TV in my bedroom that works great, only problem is that on occasion it locks up for a period of time I cant identify, but its somewhere north of 30 minutes. If I just wait it will eventually go back to working, or I can pull the power, wait, plug it back in and it goes back to working. It doesn't happen at the same time of day, no real pattern that I can find. I can deal but it doesn't really pass the wife test as she can't reach it :) Anyone have any suggestions? (Also I'll take other optimizations if anyone has any, it's been running for 3 years on the current sketch)
/** Based on the MySensors Project: http://www.mysensors.org This sketch controls a (analog)RGBW strip by listening to new color values from a (OpenHab2) controller and then fading to the new color. Version 2.0 - Updated to MySensors 2 and changed fading Version 1.0 - Changed pins and gw definition Version 0.9 - Oliver Hilsky **/ #define SN "RGBW and TV" #define SV "v3.0 09112019" // library settings #define MY_RADIO_NRF24 #define MY_NODE_ID 22 #define MY_DEBUG // Enables debug messages in the serial log #define MY_RF24_CE_PIN 49 //atmega 2560 code #define MY_RF24_CS_PIN 53 //atmega 2560 code #define MY_RF24_PA_LEVEL RF24_PA_HIGH #include <SPI.h> #include <MySensors.h> #define RELAY_1 30 // Arduino Digital I/O pin number for first relay (second on pin+1 etc) #define NUMBER_OF_RELAYS 1 // Total number of attached relays #define RELAY_ON 1 // GPIO value to write to turn on attached relay #define RELAY_OFF 0 // GPIO value to write to turn off attached relay #define SENSOR_ID 10 //RGBW Sensor ID // Arduino pin attached to driver pins #define RED_PIN 6 #define WHITE_PIN 8 #define GREEN_PIN 5 #define BLUE_PIN 7 #define NUM_CHANNELS 4 // how many channels, RGBW=4 RGB=3... // Smooth stepping between the values #define STEP 1 #define INTERVAL 10 // Stores the current color settings byte channels[4] = {RED_PIN, GREEN_PIN, BLUE_PIN, WHITE_PIN}; byte values[4] = {0, 0, 0, 255}; byte target_values[4] = {0, 0, 0, 255}; boolean isOn = true; // tracks if the strip should be on of off // time tracking for updates unsigned long lastupdate = millis(); void before() { for (int sensor=1, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS; sensor++, pin++) { // Then set relay pins in output mode pinMode(pin, OUTPUT); // Set relay to last known state (using eeprom storage) digitalWrite(pin, loadState(sensor)?RELAY_ON:RELAY_OFF); } // Set all channels to output (pin number, type) for (int i = 0; i < NUM_CHANNELS; i++) { pinMode(channels[i], OUTPUT); } } void presentation() { // Present sketch (name, version) sendSketchInfo(SN, SV); for (int sensor=1, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS; sensor++, pin++) { // Register all sensors to gw (they will be created as child devices) present(sensor, S_BINARY); } // Register sensors (id, type, description, ack back) present(SENSOR_ID, S_RGBW_LIGHT, SN, true); } void setup() { request(SENSOR_ID, V_RGBW); // get old values if this is just a restart updateLights(); // init lights Serial.println("Waiting for messages..."); } void loop() { // and set the new light colors if (millis() > lastupdate + INTERVAL) { updateLights(); lastupdate = millis(); } } // callback function for incoming messages void receive(const MyMessage &message) { Serial.print("Got a message - "); Serial.print("Messagetype is: "); Serial.println(message.type); // acknoledgment if (message.isAck()) { Serial.println("Got ack from gateway"); } // on / off message else if (message.type == V_STATUS) { if(message.sensor == SENSOR_ID) { Serial.print("Turning light "); isOn = message.getInt(); if (isOn) { Serial.println("on"); } else { Serial.println("off"); } }else { digitalWrite(message.sensor-1+RELAY_1, message.getBool()?RELAY_ON:RELAY_OFF); // Store state in eeprom saveState(message.sensor, message.getBool()); // Write some debug info Serial.print("Incoming change for sensor:"); Serial.print(message.sensor); Serial.print(", New status: "); Serial.println(message.getBool()); } } // new color value else if (message.type == V_RGBW) { const char * rgbvalues = message.getString(); inputToRGBW(rgbvalues); // a new color also means on, no seperate signal gets send (by domoticz); needed e.g. for groups isOn = true; } } // this gets called every INTERVAL milliseconds and updates the current pwm levels for all colors void updateLights() { // for each color for (int v = 0; v < NUM_CHANNELS; v++) { if (values[v] < target_values[v]) { //Serial.print("V+: "); //Serial.print(v); //Serial.print(" value/target value: "); //Serial.print(values[v]); //Serial.println(target_values[v]); values[v] += STEP; if (values[v] > target_values[v]) { values[v] = target_values[v]; } } if (values[v] > target_values[v]) { //Serial.print("V-: "); //Serial.print(v); //Serial.print(" value/target value: "); //Serial.print(values[v]); //Serial.println(target_values[v]); values[v] -= STEP; if (values[v] < target_values[v]) { values[v] = target_values[v]; } } } // set actual pin values for (int i = 0; i < NUM_CHANNELS; i++) { if (isOn) { analogWrite(channels[i], values[i]); } else { analogWrite(channels[i], 0); } } } // converts incoming color string to actual (int) values // ATTENTION this currently does nearly no checks, so the format needs to be exactly like domoticz sends the strings void inputToRGBW(const char * input) { Serial.print("Got color value of length: "); Serial.println(strlen(input)); if (strlen(input) == 6) { Serial.println("new rgb value"); target_values[0] = fromhex (& input [0]); target_values[1] = fromhex (& input [2]); target_values[2] = fromhex (& input [4]); target_values[3] = 0; } else if (strlen(input) == 8) { Serial.println("new rgbw value"); target_values[0] = fromhex (& input [0]); // ignore # as first sign target_values[1] = fromhex (& input [2]); target_values[2] = fromhex (& input [4]); target_values[3] = fromhex (& input [6]); } else { Serial.println("Wrong length of input"); } Serial.print("New color values: "); Serial.println(input); for (int i = 0; i < NUM_CHANNELS; i++) { Serial.print(target_values[i]); Serial.print(", "); } } // converts hex char to byte byte fromhex (const char * str) { char c = str [0] - '0'; if (c > 9) c -= 7; int result = c; c = str [1] - '0'; if (c > 9) c -= 7; return (result << 4) | c; }``` -
Hi everyone,
I have this current node controlling the lights and TV in my bedroom that works great, only problem is that on occasion it locks up for a period of time I cant identify, but its somewhere north of 30 minutes. If I just wait it will eventually go back to working, or I can pull the power, wait, plug it back in and it goes back to working. It doesn't happen at the same time of day, no real pattern that I can find. I can deal but it doesn't really pass the wife test as she can't reach it :) Anyone have any suggestions? (Also I'll take other optimizations if anyone has any, it's been running for 3 years on the current sketch)
/** Based on the MySensors Project: http://www.mysensors.org This sketch controls a (analog)RGBW strip by listening to new color values from a (OpenHab2) controller and then fading to the new color. Version 2.0 - Updated to MySensors 2 and changed fading Version 1.0 - Changed pins and gw definition Version 0.9 - Oliver Hilsky **/ #define SN "RGBW and TV" #define SV "v3.0 09112019" // library settings #define MY_RADIO_NRF24 #define MY_NODE_ID 22 #define MY_DEBUG // Enables debug messages in the serial log #define MY_RF24_CE_PIN 49 //atmega 2560 code #define MY_RF24_CS_PIN 53 //atmega 2560 code #define MY_RF24_PA_LEVEL RF24_PA_HIGH #include <SPI.h> #include <MySensors.h> #define RELAY_1 30 // Arduino Digital I/O pin number for first relay (second on pin+1 etc) #define NUMBER_OF_RELAYS 1 // Total number of attached relays #define RELAY_ON 1 // GPIO value to write to turn on attached relay #define RELAY_OFF 0 // GPIO value to write to turn off attached relay #define SENSOR_ID 10 //RGBW Sensor ID // Arduino pin attached to driver pins #define RED_PIN 6 #define WHITE_PIN 8 #define GREEN_PIN 5 #define BLUE_PIN 7 #define NUM_CHANNELS 4 // how many channels, RGBW=4 RGB=3... // Smooth stepping between the values #define STEP 1 #define INTERVAL 10 // Stores the current color settings byte channels[4] = {RED_PIN, GREEN_PIN, BLUE_PIN, WHITE_PIN}; byte values[4] = {0, 0, 0, 255}; byte target_values[4] = {0, 0, 0, 255}; boolean isOn = true; // tracks if the strip should be on of off // time tracking for updates unsigned long lastupdate = millis(); void before() { for (int sensor=1, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS; sensor++, pin++) { // Then set relay pins in output mode pinMode(pin, OUTPUT); // Set relay to last known state (using eeprom storage) digitalWrite(pin, loadState(sensor)?RELAY_ON:RELAY_OFF); } // Set all channels to output (pin number, type) for (int i = 0; i < NUM_CHANNELS; i++) { pinMode(channels[i], OUTPUT); } } void presentation() { // Present sketch (name, version) sendSketchInfo(SN, SV); for (int sensor=1, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS; sensor++, pin++) { // Register all sensors to gw (they will be created as child devices) present(sensor, S_BINARY); } // Register sensors (id, type, description, ack back) present(SENSOR_ID, S_RGBW_LIGHT, SN, true); } void setup() { request(SENSOR_ID, V_RGBW); // get old values if this is just a restart updateLights(); // init lights Serial.println("Waiting for messages..."); } void loop() { // and set the new light colors if (millis() > lastupdate + INTERVAL) { updateLights(); lastupdate = millis(); } } // callback function for incoming messages void receive(const MyMessage &message) { Serial.print("Got a message - "); Serial.print("Messagetype is: "); Serial.println(message.type); // acknoledgment if (message.isAck()) { Serial.println("Got ack from gateway"); } // on / off message else if (message.type == V_STATUS) { if(message.sensor == SENSOR_ID) { Serial.print("Turning light "); isOn = message.getInt(); if (isOn) { Serial.println("on"); } else { Serial.println("off"); } }else { digitalWrite(message.sensor-1+RELAY_1, message.getBool()?RELAY_ON:RELAY_OFF); // Store state in eeprom saveState(message.sensor, message.getBool()); // Write some debug info Serial.print("Incoming change for sensor:"); Serial.print(message.sensor); Serial.print(", New status: "); Serial.println(message.getBool()); } } // new color value else if (message.type == V_RGBW) { const char * rgbvalues = message.getString(); inputToRGBW(rgbvalues); // a new color also means on, no seperate signal gets send (by domoticz); needed e.g. for groups isOn = true; } } // this gets called every INTERVAL milliseconds and updates the current pwm levels for all colors void updateLights() { // for each color for (int v = 0; v < NUM_CHANNELS; v++) { if (values[v] < target_values[v]) { //Serial.print("V+: "); //Serial.print(v); //Serial.print(" value/target value: "); //Serial.print(values[v]); //Serial.println(target_values[v]); values[v] += STEP; if (values[v] > target_values[v]) { values[v] = target_values[v]; } } if (values[v] > target_values[v]) { //Serial.print("V-: "); //Serial.print(v); //Serial.print(" value/target value: "); //Serial.print(values[v]); //Serial.println(target_values[v]); values[v] -= STEP; if (values[v] < target_values[v]) { values[v] = target_values[v]; } } } // set actual pin values for (int i = 0; i < NUM_CHANNELS; i++) { if (isOn) { analogWrite(channels[i], values[i]); } else { analogWrite(channels[i], 0); } } } // converts incoming color string to actual (int) values // ATTENTION this currently does nearly no checks, so the format needs to be exactly like domoticz sends the strings void inputToRGBW(const char * input) { Serial.print("Got color value of length: "); Serial.println(strlen(input)); if (strlen(input) == 6) { Serial.println("new rgb value"); target_values[0] = fromhex (& input [0]); target_values[1] = fromhex (& input [2]); target_values[2] = fromhex (& input [4]); target_values[3] = 0; } else if (strlen(input) == 8) { Serial.println("new rgbw value"); target_values[0] = fromhex (& input [0]); // ignore # as first sign target_values[1] = fromhex (& input [2]); target_values[2] = fromhex (& input [4]); target_values[3] = fromhex (& input [6]); } else { Serial.println("Wrong length of input"); } Serial.print("New color values: "); Serial.println(input); for (int i = 0; i < NUM_CHANNELS; i++) { Serial.print(target_values[i]); Serial.print(", "); } } // converts hex char to byte byte fromhex (const char * str) { char c = str [0] - '0'; if (c > 9) c -= 7; int result = c; c = str [1] - '0'; if (c > 9) c -= 7; return (result << 4) | c; }``` -
Hi everyone,
I have this current node controlling the lights and TV in my bedroom that works great, only problem is that on occasion it locks up for a period of time I cant identify, but its somewhere north of 30 minutes. If I just wait it will eventually go back to working, or I can pull the power, wait, plug it back in and it goes back to working. It doesn't happen at the same time of day, no real pattern that I can find. I can deal but it doesn't really pass the wife test as she can't reach it :) Anyone have any suggestions? (Also I'll take other optimizations if anyone has any, it's been running for 3 years on the current sketch)
/** Based on the MySensors Project: http://www.mysensors.org This sketch controls a (analog)RGBW strip by listening to new color values from a (OpenHab2) controller and then fading to the new color. Version 2.0 - Updated to MySensors 2 and changed fading Version 1.0 - Changed pins and gw definition Version 0.9 - Oliver Hilsky **/ #define SN "RGBW and TV" #define SV "v3.0 09112019" // library settings #define MY_RADIO_NRF24 #define MY_NODE_ID 22 #define MY_DEBUG // Enables debug messages in the serial log #define MY_RF24_CE_PIN 49 //atmega 2560 code #define MY_RF24_CS_PIN 53 //atmega 2560 code #define MY_RF24_PA_LEVEL RF24_PA_HIGH #include <SPI.h> #include <MySensors.h> #define RELAY_1 30 // Arduino Digital I/O pin number for first relay (second on pin+1 etc) #define NUMBER_OF_RELAYS 1 // Total number of attached relays #define RELAY_ON 1 // GPIO value to write to turn on attached relay #define RELAY_OFF 0 // GPIO value to write to turn off attached relay #define SENSOR_ID 10 //RGBW Sensor ID // Arduino pin attached to driver pins #define RED_PIN 6 #define WHITE_PIN 8 #define GREEN_PIN 5 #define BLUE_PIN 7 #define NUM_CHANNELS 4 // how many channels, RGBW=4 RGB=3... // Smooth stepping between the values #define STEP 1 #define INTERVAL 10 // Stores the current color settings byte channels[4] = {RED_PIN, GREEN_PIN, BLUE_PIN, WHITE_PIN}; byte values[4] = {0, 0, 0, 255}; byte target_values[4] = {0, 0, 0, 255}; boolean isOn = true; // tracks if the strip should be on of off // time tracking for updates unsigned long lastupdate = millis(); void before() { for (int sensor=1, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS; sensor++, pin++) { // Then set relay pins in output mode pinMode(pin, OUTPUT); // Set relay to last known state (using eeprom storage) digitalWrite(pin, loadState(sensor)?RELAY_ON:RELAY_OFF); } // Set all channels to output (pin number, type) for (int i = 0; i < NUM_CHANNELS; i++) { pinMode(channels[i], OUTPUT); } } void presentation() { // Present sketch (name, version) sendSketchInfo(SN, SV); for (int sensor=1, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS; sensor++, pin++) { // Register all sensors to gw (they will be created as child devices) present(sensor, S_BINARY); } // Register sensors (id, type, description, ack back) present(SENSOR_ID, S_RGBW_LIGHT, SN, true); } void setup() { request(SENSOR_ID, V_RGBW); // get old values if this is just a restart updateLights(); // init lights Serial.println("Waiting for messages..."); } void loop() { // and set the new light colors if (millis() > lastupdate + INTERVAL) { updateLights(); lastupdate = millis(); } } // callback function for incoming messages void receive(const MyMessage &message) { Serial.print("Got a message - "); Serial.print("Messagetype is: "); Serial.println(message.type); // acknoledgment if (message.isAck()) { Serial.println("Got ack from gateway"); } // on / off message else if (message.type == V_STATUS) { if(message.sensor == SENSOR_ID) { Serial.print("Turning light "); isOn = message.getInt(); if (isOn) { Serial.println("on"); } else { Serial.println("off"); } }else { digitalWrite(message.sensor-1+RELAY_1, message.getBool()?RELAY_ON:RELAY_OFF); // Store state in eeprom saveState(message.sensor, message.getBool()); // Write some debug info Serial.print("Incoming change for sensor:"); Serial.print(message.sensor); Serial.print(", New status: "); Serial.println(message.getBool()); } } // new color value else if (message.type == V_RGBW) { const char * rgbvalues = message.getString(); inputToRGBW(rgbvalues); // a new color also means on, no seperate signal gets send (by domoticz); needed e.g. for groups isOn = true; } } // this gets called every INTERVAL milliseconds and updates the current pwm levels for all colors void updateLights() { // for each color for (int v = 0; v < NUM_CHANNELS; v++) { if (values[v] < target_values[v]) { //Serial.print("V+: "); //Serial.print(v); //Serial.print(" value/target value: "); //Serial.print(values[v]); //Serial.println(target_values[v]); values[v] += STEP; if (values[v] > target_values[v]) { values[v] = target_values[v]; } } if (values[v] > target_values[v]) { //Serial.print("V-: "); //Serial.print(v); //Serial.print(" value/target value: "); //Serial.print(values[v]); //Serial.println(target_values[v]); values[v] -= STEP; if (values[v] < target_values[v]) { values[v] = target_values[v]; } } } // set actual pin values for (int i = 0; i < NUM_CHANNELS; i++) { if (isOn) { analogWrite(channels[i], values[i]); } else { analogWrite(channels[i], 0); } } } // converts incoming color string to actual (int) values // ATTENTION this currently does nearly no checks, so the format needs to be exactly like domoticz sends the strings void inputToRGBW(const char * input) { Serial.print("Got color value of length: "); Serial.println(strlen(input)); if (strlen(input) == 6) { Serial.println("new rgb value"); target_values[0] = fromhex (& input [0]); target_values[1] = fromhex (& input [2]); target_values[2] = fromhex (& input [4]); target_values[3] = 0; } else if (strlen(input) == 8) { Serial.println("new rgbw value"); target_values[0] = fromhex (& input [0]); // ignore # as first sign target_values[1] = fromhex (& input [2]); target_values[2] = fromhex (& input [4]); target_values[3] = fromhex (& input [6]); } else { Serial.println("Wrong length of input"); } Serial.print("New color values: "); Serial.println(input); for (int i = 0; i < NUM_CHANNELS; i++) { Serial.print(target_values[i]); Serial.print(", "); } } // converts hex char to byte byte fromhex (const char * str) { char c = str [0] - '0'; if (c > 9) c -= 7; int result = c; c = str [1] - '0'; if (c > 9) c -= 7; return (result << 4) | c; }``` -
@gundark2 the sketchlooks good to me.
Best way would be if you can get the debug log for the time when it locks up.
@mfalkvidd I was afraid someone would say something about this avenue of debugging. I was "smart" enough to put all of the connections up high where I can't reach... I guess a next step could be to order a longer usb cable for the mega.
@skywatch Seeing your post here makes me remember when I tried to add a watchdog timer which didn't seem to work... But I thought that the problem persisting meant the watchdog wasn't working... but maybe there is something going on with this radio causing it to misbehave for a period of time...
-
@mfalkvidd I was afraid someone would say something about this avenue of debugging. I was "smart" enough to put all of the connections up high where I can't reach... I guess a next step could be to order a longer usb cable for the mega.
@skywatch Seeing your post here makes me remember when I tried to add a watchdog timer which didn't seem to work... But I thought that the problem persisting meant the watchdog wasn't working... but maybe there is something going on with this radio causing it to misbehave for a period of time...
@gundark2 a long usb cable, or something like https://www.aliexpress.com/item/32959138610.html or https://www.openhardware.io/view/532/The-Logger-Machine-Short-and-long-term-serial-logging