15 blinds driver at Mega2560 - Domoticz synchronisation problem



  • Hi,

    I made a blinds driver (30 relays, 15 buttons) to go with Domoticz. I am using Mega2560 as MySensors board to communicate with Domoticz at RaspberryPi 4. Code below:

    // Enable debug prints to serial monitor
    #define MY_DEBUG 
    
    
    // Enable and select radio type attached
    //#define MY_RADIO_NRF24
    //#define MY_RADIO_RFM69
    
    // Set LOW transmit power level as default, if you have an amplified NRF-module and
    // power your radio separately with a good regulator you can turn up PA level. 
    //#define MY_RF24_PA_LEVEL RF24_PA_LOW
    
    // Enable serial gateway
    #define MY_GATEWAY_SERIAL
    
    // Define a lower baud rate for Arduino's running on 8 MHz (Arduino Pro Mini 3.3V & SenseBender)
    #if F_CPU == 8000000L
    #define MY_BAUD_RATE 38400
    #endif
    
    // Flash leds on rx/tx/err
    // #define MY_LEDS_BLINKING_FEATURE
    // Set blinking period
    // #define MY_DEFAULT_LED_BLINK_PERIOD 300
    
    // Inverses the behavior of leds
    // #define MY_WITH_LEDS_BLINKING_INVERSE
    
    // Enable inclusion mode
    #define MY_INCLUSION_MODE_FEATURE
    // Enable Inclusion mode button on gateway
    #define MY_INCLUSION_BUTTON_FEATURE
    
    // Inverses behavior of inclusion button (if using external pullup)
    //#define MY_INCLUSION_BUTTON_EXTERNAL_PULLUP
    
    // Set inclusion mode duration (in seconds)
    #define MY_INCLUSION_MODE_DURATION 60 
    // Digital pin used for inclusion mode button
    #define MY_INCLUSION_MODE_BUTTON_PIN  3 
    
    // Uncomment to override default HW configurations
    //#define MY_DEFAULT_ERR_LED_PIN 4  // Error led pin
    //#define MY_DEFAULT_RX_LED_PIN  6  // Receive led pin
    //#define MY_DEFAULT_TX_LED_PIN  5  // the PCB, on board LED
    
    #include <SPI.h>
    #include <MySensors.h>  
    #include <Bounce2.h>
    
    // Enable repeater functionality for this node
    #define MY_REPEATER_FEATURE
    
    
    #define RELAY_1  4  // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
    #define RELAY_2  5
    #define RELAY_3  6
    #define RELAY_4  7
    #define RELAY_5  8
    #define RELAY_6  9
    #define RELAY_7  10
    #define RELAY_8  11
    #define RELAY_9  22
    #define RELAY_10  23
    #define RELAY_11  24
    #define RELAY_12  25
    #define RELAY_13  26
    #define RELAY_14  27
    #define RELAY_15  28
    #define RELAY_16  29
    #define RELAY_17  30
    #define RELAY_18  31
    #define RELAY_19  32
    #define RELAY_20  33
    #define RELAY_21  34
    #define RELAY_22  35
    #define RELAY_23  36
    #define RELAY_24  37
    #define RELAY_25  38
    #define RELAY_26  39
    #define RELAY_27  40
    #define RELAY_28  41
    #define RELAY_29  42
    #define RELAY_30  43
    
    #define NUMBER_OF_RELAYS 30 // Total number of attached relays
    #define RELAY_ON 0  // GPIO value to write to turn on attached relay
    #define RELAY_OFF 1 // GPIO value to write to turn off attached relay
    
    #define BUTTON_PIN A1 
    #define BUTTON2_PIN A2
    #define BUTTON3_PIN A3
    #define BUTTON4_PIN A4
    #define BUTTON5_PIN A5
    #define BUTTON6_PIN A6
    #define BUTTON7_PIN A7
    #define BUTTON8_PIN A8
    #define BUTTON9_PIN A9
    #define BUTTON10_PIN A10
    #define BUTTON11_PIN A11
    #define BUTTON12_PIN A12
    #define BUTTON13_PIN A13
    #define BUTTON14_PIN A14
    #define BUTTON15_PIN A15
    
    
    
    
    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);
        
        
        
    
     
      }
        
    }
    Bounce debouncer = Bounce();
    Bounce debouncer3 = Bounce();
    Bounce debouncer5 = Bounce();
    Bounce debouncer7 = Bounce();
    Bounce debouncer9 = Bounce();
    Bounce debouncer11 = Bounce();
    Bounce debouncer13 = Bounce();
    Bounce debouncer15 = Bounce();
    Bounce debouncer17 = Bounce();
    Bounce debouncer19 = Bounce();
    Bounce debouncer21 = Bounce();
    Bounce debouncer23 = Bounce();
    Bounce debouncer25 = Bounce();
    Bounce debouncer27 = Bounce();
    Bounce debouncer29 = Bounce();
    
    
    void setup() { 
      // Setup locally attached sensors
      delay(10000);
      
       // Setup the button.
      pinMode(BUTTON_PIN, INPUT_PULLUP);
      pinMode(BUTTON2_PIN, INPUT_PULLUP);
      pinMode(BUTTON3_PIN, INPUT_PULLUP);
      pinMode(BUTTON4_PIN, INPUT_PULLUP);
      pinMode(BUTTON5_PIN, INPUT_PULLUP);
      pinMode(BUTTON6_PIN, INPUT_PULLUP);
      pinMode(BUTTON7_PIN, INPUT_PULLUP);
      pinMode(BUTTON8_PIN, INPUT_PULLUP);
      pinMode(BUTTON9_PIN, INPUT_PULLUP);
      pinMode(BUTTON10_PIN, INPUT_PULLUP);
      pinMode(BUTTON11_PIN, INPUT_PULLUP);
      pinMode(BUTTON12_PIN, INPUT_PULLUP);
      pinMode(BUTTON13_PIN, INPUT_PULLUP);
      pinMode(BUTTON14_PIN, INPUT_PULLUP);
      pinMode(BUTTON15_PIN, INPUT_PULLUP);
    
      // After setting up the button, setup debouncer.
      
      debouncer.attach(BUTTON_PIN);
      debouncer.interval(5);
      debouncer3.attach(BUTTON2_PIN);
      debouncer3.interval(5);
      debouncer5.attach(BUTTON3_PIN);
      debouncer5.interval(5);
      debouncer7.attach(BUTTON4_PIN);
      debouncer7.interval(5);
      debouncer9.attach(BUTTON5_PIN);
      debouncer9.interval(5);
      debouncer11.attach(BUTTON6_PIN);
      debouncer11.interval(5);
      debouncer13.attach(BUTTON7_PIN);
      debouncer13.interval(5);
      debouncer15.attach(BUTTON8_PIN);
      debouncer15.interval(5);
      debouncer17.attach(BUTTON9_PIN);
      debouncer17.interval(5);
      debouncer19.attach(BUTTON10_PIN);
      debouncer19.interval(5);
      debouncer21.attach(BUTTON11_PIN);
      debouncer21.interval(5);
      debouncer23.attach(BUTTON12_PIN);
      debouncer23.interval(5);
      debouncer25.attach(BUTTON13_PIN);
      debouncer25.interval(5);
      debouncer27.attach(BUTTON14_PIN);
      debouncer27.interval(5);
      debouncer29.attach(BUTTON15_PIN);
      debouncer29.interval(5);
      
      //presentation();
    }
    void presentation()  
    {   
      // Send the sketch version information to the gateway and Controller
      
      sendSketchInfo("Relay", "1.0");
    
      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_LIGHT);
      }
    }
    
    MyMessage msg(1, V_LIGHT);
    MyMessage msg2(2, V_LIGHT);
    MyMessage msg3(3, V_LIGHT);
    MyMessage msg4(4, V_LIGHT);
    MyMessage msg5(5, V_LIGHT);
    MyMessage msg6(6, V_LIGHT);
    MyMessage msg7(7, V_LIGHT);
    MyMessage msg8(8, V_LIGHT);
    MyMessage msg9(9, V_LIGHT);
    MyMessage msg10(10, V_LIGHT);
    MyMessage msg11(11, V_LIGHT);
    MyMessage msg12(12, V_LIGHT);
    MyMessage msg13(13, V_LIGHT);
    MyMessage msg14(14, V_LIGHT);
    MyMessage msg15(15, V_LIGHT);
    MyMessage msg16(16, V_LIGHT);
    MyMessage msg17(17, V_LIGHT);
    MyMessage msg18(18, V_LIGHT);
    MyMessage msg19(19, V_LIGHT);
    MyMessage msg20(20, V_LIGHT);
    MyMessage msg21(21, V_LIGHT);
    MyMessage msg22(22, V_LIGHT);
    MyMessage msg23(23, V_LIGHT);
    MyMessage msg24(24, V_LIGHT);
    MyMessage msg25(25, V_LIGHT);
    MyMessage msg26(26, V_LIGHT);
    MyMessage msg27(27, V_LIGHT);
    MyMessage msg28(28, V_LIGHT);
    MyMessage msg29(29, V_LIGHT);
    MyMessage msg30(30, V_LIGHT);
    
    
    void loop() { 
    
      // Send locally attached sensor data here 
      if (debouncer.update()) {
        // Get the update value.
        int value = debouncer.read();
        // Send in the new value.
        if(value == LOW){
             saveState(1, !loadState(1));
             digitalWrite(RELAY_1, loadState(1)?RELAY_ON:RELAY_OFF);
             send(msg.set(loadState(1)));
             }
      }
      if (debouncer3.update()) {
          int value3 = debouncer3.read();
        if(value3 == LOW){
             saveState(3, !loadState(3));
             digitalWrite(RELAY_3, loadState(3)?RELAY_ON:RELAY_OFF);
             send(msg3.set(loadState(3)));
             }
      }
       if (debouncer5.update()) {
          int value5 = debouncer5.read();
        if(value5 == LOW){
             saveState(5, !loadState(5));
             digitalWrite(RELAY_5, loadState(5)?RELAY_ON:RELAY_OFF);
             send(msg5.set(loadState(5)));
             }
      }
      if (debouncer7.update()) {
          int value7 = debouncer7.read();
        if(value7 == LOW){
             saveState(7, !loadState(7));
             digitalWrite(RELAY_7, loadState(7)?RELAY_ON:RELAY_OFF);
             send(msg7.set(loadState(7)));
             }
      }
      if (debouncer9.update()) {
          int value9 = debouncer9.read();
        if(value9 == LOW){
             saveState(9, !loadState(9));
             digitalWrite(RELAY_9, loadState(9)?RELAY_ON:RELAY_OFF);
             send(msg9.set(loadState(9)));
             }
      }
      if (debouncer11.update()) {
          int value11 = debouncer11.read();
        if(value11 == LOW){
             saveState(11, !loadState(11));
             digitalWrite(RELAY_11, loadState(11)?RELAY_ON:RELAY_OFF);
             send(msg11.set(loadState(11)));
             }
      }
      if (debouncer13.update()) {
          int value13 = debouncer13.read();
        if(value13 == LOW){
             saveState(13, !loadState(13));
             digitalWrite(RELAY_13, loadState(13)?RELAY_ON:RELAY_OFF);
             send(msg13.set(loadState(13)));
             }
      }
      if (debouncer15.update()) {
          int value15 = debouncer15.read();
        if(value15 == LOW){
             saveState(15, !loadState(15));
             digitalWrite(RELAY_15, loadState(15)?RELAY_ON:RELAY_OFF);
             send(msg15.set(loadState(15)));
             }
      }
      if (debouncer17.update()) {
          int value17 = debouncer17.read();
        if(value17 == LOW){
             saveState(17, !loadState(17));
             digitalWrite(RELAY_17, loadState(17)?RELAY_ON:RELAY_OFF);
             send(msg17.set(loadState(17)));
             }
      }
      if (debouncer19.update()) {
          int value19 = debouncer19.read();
        if(value19 == LOW){
             saveState(19, !loadState(19));
             digitalWrite(RELAY_19, loadState(19)?RELAY_ON:RELAY_OFF);
             send(msg19.set(loadState(19)));
             Serial.println("19 zmiana");
             }
      }
      if (debouncer21.update()) {
          int value21 = debouncer21.read();
        if(value21 == LOW){
             saveState(21, !loadState(21));
             digitalWrite(RELAY_21, loadState(21)?RELAY_ON:RELAY_OFF);
             send(msg21.set(loadState(21)));
             }
      }
       if (debouncer23.update()) {
          int value23 = debouncer23.read();
        if(value23 == LOW){
             saveState(23, !loadState(23));
             digitalWrite(RELAY_23, loadState(23)?RELAY_ON:RELAY_OFF);
             send(msg23.set(loadState(23)));
             }
      }
       if (debouncer25.update()) {
          int value25 = debouncer25.read();
        if(value25 == LOW){
             saveState(25, !loadState(25));
             digitalWrite(RELAY_25, loadState(25)?RELAY_ON:RELAY_OFF);
             send(msg25.set(loadState(25)));
             }
      }
       if (debouncer27.update()) {
          int value27 = debouncer27.read();
        if(value27 == LOW){
             saveState(27, !loadState(27));
             digitalWrite(RELAY_27, loadState(27)?RELAY_ON:RELAY_OFF);
             send(msg27.set(loadState(27)));
             }
      }
       if (debouncer29.update()) {
          int value29 = debouncer29.read();
        if(value29 == LOW){
             saveState(29, !loadState(29));
             digitalWrite(RELAY_29, loadState(29)?RELAY_ON:RELAY_OFF);
             send(msg29.set(loadState(29)));
             }
      }
        
    }
    
    
    void receive(const MyMessage &message) {
      // We only expect one type of message from controller. But we better check anyway.
      if (message.type==V_LIGHT) {
         // Change relay state
         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());
       } 
    }
    

    It works fine, however I have a synchronisation problem. When there is a power loss, Arduino restores relay states form EEPROM, using this line:

    digitalWrite(pin, loadState(sensor)?RELAY_ON:RELAY_OFF);
    

    Domoticz seems to have its own way to remeber what relays were on. When power is restored there is a mismatch between arduino EEPROM data and domoticz. Is there any way to fix this? I was thinking 2 ways: either resend all relay statuses right after restoring them from arduino EEPROM or download on/off status from domoticz? I would actually prefer the first method. How can it be done?


  • Contest Winner

    You could send the blinds statess to Domoticz in the presentation method. My experience is that my setup doesn't like it when I send a lot messages to the gateway. So I use some small delays between each message I send from the node to the gateway, I didn't have time to look at your sketch. But here's some pseudo code:

    void presentation() {
         ... // the presentation code goes here.
          for ( int = 0; i < BLINDS_COUNT; i++ ) {
                send( message for blinds i, state of blinds i );
                delay( 50 ); // or do less it's a bit of trial and error.
          }
    }
    

    In your case using random delays might be better, because you send 15 states with a delay of 50ms. So it takes at least 750ms to send all values. Adding the delay will also give other nodes time to interact with Domoticz.


Log in to reply
 

Suggested Topics

0
Online

11.2k
Users

11.1k
Topics

112.5k
Posts