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