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



  • Mod

    @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...


  • Mod


 

261
Online

8.9k
Users

9.7k
Topics

101.3k
Posts