Merging 2 or 3 sketches to one (relays & binary buttons)



  • Hello everybody.

    Thanks just for clarification - is the template sketch for relay correct? I mean this one:

    https://www.mysensors.org/build/relay

    /*
     * The MySensors Arduino library handles the wireless radio link and protocol
     * between your home built sensors/actuators and HA controller of choice.
     * The sensors forms a self healing radio network with optional repeaters. Each
     * repeater and gateway builds a routing tables in EEPROM which keeps track of the
     * network topology allowing messages to be routed to nodes.
     *
     * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
     * Copyright (C) 2013-2019 Sensnology AB
     * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
     *
     * Documentation: http://www.mysensors.org
     * Support Forum: http://forum.mysensors.org
     *
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * version 2 as published by the Free Software Foundation.
     *
     *******************************
     *
     * REVISION HISTORY
     * Version 1.0 - Henrik Ekblad
     *
     * DESCRIPTION
     * Example sketch showing how to control physical relays.
     * This example will remember relay state after power failure.
     * http://www.mysensors.org/build/relay
     */
    
    // Enable debug prints to serial monitor
    #define MY_DEBUG
    
    // Enable and select radio type attached
    #define MY_RADIO_RF24
    //#define MY_RADIO_NRF5_ESB
    //#define MY_RADIO_RFM69
    //#define MY_RADIO_RFM95
    
    // Enable repeater functionality for this node
    #define MY_REPEATER_FEATURE
    
    #include <MySensors.h>
    
    #define RELAY_PIN 4  // 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
    
    
    void before()
    {
        for (int sensor=1, pin=RELAY_PIN; 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);
        }
    }
    
    void setup()
    {
    
    }
    
    void presentation()
    {
        // Send the sketch version information to the gateway and Controller
        sendSketchInfo("Relay", "1.0");
    
        for (int sensor=1, pin=RELAY_PIN; sensor<=NUMBER_OF_RELAYS; sensor++, pin++) {
            // Register all sensors to gw (they will be created as child devices)
            present(sensor, S_BINARY);
        }
    }
    
    
    void loop()
    {
    
    }
    
    void receive(const MyMessage &message)
    {
        // We only expect one type of message from controller. But we better check anyway.
        if (message.getType()==V_STATUS) {
            // Change relay state
            digitalWrite(message.getSensor()-1+RELAY_PIN, message.getBool()?RELAY_ON:RELAY_OFF);
            // Store state in eeprom
            saveState(message.getSensor(), message.getBool());
            // Write some debug info
            Serial.print("Incoming change for sensor:");
            Serial.print(message.getSensor());
            Serial.print(", New status: ");
            Serial.println(message.getBool());
        }
    }
    
    
    

    I work on HA, and there is a common problem of not recognizing an entity untill first signal comes from a sensor. It is not a big problem with sensors or buttons, as after receiving first message the entity(ies) are registered and show up on the list. But the relay is something diffirent. There is no way to trigger a message from relay to manually let HA know that there are new entities. Am I right? Just wanted to know.

    What i wanted to do is to create a sketch being a hybrid of 3 sketches. My configuration is supposed to control lights with wall pushbuttons, so i need relays and pushbuttons.

    Some relays should be controlled by pushbuttons directly by the sketch (of course with the possibility of control via controller, HA). I regard this as a way to secure proper functioning of light control of the most important lights in case of the controller failure (those SD cards on Rpi, you know...). To do this I can just use the Relay with button template and multiplicate it - it works (with the exception of the need to manually activate every button-realy pair so it shows up in HA).

    Another two groups of entities would be so-called "free" relays (only presented to HA, proper control of them would be configured in HA itself), and so-called "free" pushbuttons, so buttons also only presented to HA, to be configured and eventually linked to certain relays in HA).

    I created adequate sketches - for "free" relays, "free" pushbuttons, and relays linked with pushbuttons. I try to merge the sketches in a proper way, I cannot see any double-used integers, the compilation shows no errors. But after uploading, HA only sees the sketch itself as a whole, with no real entities (buttons or relays)

    This is the sketch for "free" pushbuttons (it needs manual activation of each button to be registered properly in HA):

    // Enable debug prints to serial monitor
    #define MY_DEBUG
    
    
    // Enable and select radio type attached
    //#define MY_RADIO_RF24
    //#define MY_RADIO_NRF5_ESB
    //#define MY_RADIO_RFM69
    //#define MY_RADIO_RFM95
    
    // 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 Arduinos running on 8 MHz (Arduino Pro Mini 3.3V & SenseBender)
    #if F_CPU == 8000000L
    #define MY_BAUD_RATE 38400
    #endif
    
    // 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
    
    // Set blinking period
    #define MY_DEFAULT_LED_BLINK_PERIOD 300
    
    // Inverses the behavior of leds
    //#define MY_WITH_LEDS_BLINKING_INVERSE
    
    // Flash leds on rx/tx/err
    // 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 <MySensors.h>
    #include <Bounce2.h>
    
    #define FIRST_PIR_ID 1
    #define MAX_PIRS 16 
    const uint8_t pirPin[] = {A0,A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15};   //  switch around pins to your desire
    Bounce debouncer[MAX_PIRS];
    MyMessage pirMsg(0, V_TRIPPED);
    bool oldPir[MAX_PIRS] = {false};
    
    void before()
    {
    }
    
    void presentation() {
      // Send the sketch version information to the gateway and Controller
        sendSketchInfo("Free_pushbottons", "0.1");
      for (int i = 0; i < MAX_PIRS; i++) { //i < numSensors &&
        present(FIRST_PIR_ID + i, S_MOTION);
      }
    }
    
    void setup()
    {
      for (uint8_t i = 0; i < MAX_PIRS; i++) {
        debouncer[i] = Bounce();                        // initialize debouncer
        debouncer[i].attach(pirPin[i], INPUT_PULLUP);
        debouncer[i].interval(5);
        oldPir[i] =  debouncer[i].read();
      }
    }
    
    void loop() {
      
      bool pir[MAX_PIRS];
      for (uint8_t i = 0; i < MAX_PIRS; i++) {
        debouncer[i].update();
        pir[i] = debouncer[i].read();
        if (pir[i] != oldPir[i]) {
          send(pirMsg.setSensor(FIRST_PIR_ID + i).set( pir[i])); // Send tripped value to gw
          oldPir[i] = pir[i];
        }
      } 
    }
    

    This is the one for free relays, this one registers itself, so the problem from the template descirbed at the begining of the post is not occuring here:

    // Enable debug prints to serial monitor
    #define MY_DEBUG
    
    
    // Enable and select radio type attached
    //#define MY_RADIO_RF24
    //#define MY_RADIO_NRF5_ESB
    //#define MY_RADIO_RFM69
    //#define MY_RADIO_RFM95
    
    // 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 Arduinos running on 8 MHz (Arduino Pro Mini 3.3V & SenseBender)
    #if F_CPU == 8000000L
    #define MY_BAUD_RATE 38400
    #endif
    
    // 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
    
    // Set blinking period
    #define MY_DEFAULT_LED_BLINK_PERIOD 300
    
    // Inverses the behavior of leds
    //#define MY_WITH_LEDS_BLINKING_INVERSE
    
    // Flash leds on rx/tx/err
    // 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>
    
    #define RELAY_1  22          // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
    #define NUMBER_OF_RELAYS 16  // Total number of attached relays: 4
    
    // Opto Relay Module I was using Active Low - Low (0):ON, High (1): OFF
    #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
    
    bool initialValueSent = false;
    
    //Init MyMessage for Each Child ID
    MyMessage msg1(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);
    
    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);
      }
    }
    
    void setup() {
      
    }
    
    void presentation()  
    {   
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("Relay_pins22-37", "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);
      }
    }
    
    
    void loop() 
    {
      if (!initialValueSent) {
        Serial.println("Sending initial value");
        send(msg1.set(loadState(1)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg2.set(loadState(2)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg3.set(loadState(3)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg4.set(loadState(4)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg5.set(loadState(5)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg6.set(loadState(6)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg7.set(loadState(7)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg8.set(loadState(8)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg9.set(loadState(9)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg10.set(loadState(10)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg11.set(loadState(11)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg12.set(loadState(12)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg13.set(loadState(13)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg14.set(loadState(14)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg15.set(loadState(15)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg16.set(loadState(16)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        Serial.println("Sending initial value: Completed");
        wait(5000);
      }
    }
    
    void receive(const MyMessage &message) {
      Serial.println("=============== Receive Start =======================");
      if (message.isAck()) {
         Serial.println(">>>>> ACK <<<<<");
         Serial.println("This is an ack from gateway");
         Serial.println("<<<<<< ACK >>>>>>");
      }
      // We only expect one type of message from controller. But we better check anyway.
      if (message.type==V_LIGHT) {
        Serial.println(">>>>> V_LIGHT <<<<<");
        if (!initialValueSent) {
          Serial.println("Receiving initial value from controller");
          initialValueSent = true;
        }
         // Update relay state to HA
         digitalWrite(message.sensor-1+RELAY_1, message.getBool()?RELAY_ON:RELAY_OFF);
         switch (message.sensor) {
            case 1:
              Serial.print("Incoming change for sensor 1");
              send(msg1.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 2:
              Serial.print("Incoming change for sensor 2");
              send(msg2.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 3:
              Serial.print("Incoming change for sensor 3");
              send(msg3.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 4:
              Serial.print("Incoming change for sensor 4");
              send(msg4.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 5:
              Serial.print("Incoming change for sensor 5");
              send(msg5.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 6:
              Serial.print("Incoming change for sensor 6");
              send(msg6.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 7:
              Serial.print("Incoming change for sensor 7");
              send(msg7.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 8:
              Serial.print("Incoming change for sensor 8");
              send(msg8.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 9:
              Serial.print("Incoming change for sensor 9");
              send(msg9.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 10:
              Serial.print("Incoming change for sensor 10");
              send(msg10.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 11:
              Serial.print("Incoming change for sensor 11");
              send(msg11.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 12:
              Serial.print("Incoming change for sensor 12");
              send(msg12.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 13:
              Serial.print("Incoming change for sensor 13");
              send(msg13.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 14:
              Serial.print("Incoming change for sensor 14");
              send(msg14.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 15:
              Serial.print("Incoming change for sensor 15");
              send(msg15.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 16:
              Serial.print("Incoming change for sensor 16");
              send(msg16.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;                      
            default: 
              Serial.println("Default Case: Receiving Other Sensor Child ID");
            break;
         }
         // Store state in Arduino eeprom
         saveState(message.sensor, message.getBool());
         Serial.print("Saved State for sensor: ");
         Serial.print( message.sensor);
         Serial.print(", New status: ");
         Serial.println(message.getBool());
         Serial.println("<<<<<< V_LIGHT >>>>>>");
       } 
       Serial.println("=============== Receive END =======================");
    }
    

    Both of them works perfectly, the "free" pushbutton gives the possibility to freely configure double clicks and long-presses in HA.

    As I earlier wrote, the linked buttons and relays sketch is based on the template. But for now I tried to merge free buttons and free relays in one sketch, and after uploading, HA only sees the sketch itself as a whole, with no real entities (buttons or relays).

    This is the merged sketch:

    // Enable debug prints to serial monitor
    #define MY_DEBUG
    
    
    // Enable and select radio type attached
    //#define MY_RADIO_RF24
    //#define MY_RADIO_NRF5_ESB
    //#define MY_RADIO_RFM69
    //#define MY_RADIO_RFM95
    
    // 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 Arduinos running on 8 MHz (Arduino Pro Mini 3.3V & SenseBender)
    #if F_CPU == 8000000L
    #define MY_BAUD_RATE 38400
    #endif
    
    // 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
    
    // Set blinking period
    #define MY_DEFAULT_LED_BLINK_PERIOD 300
    
    // Inverses the behavior of leds
    //#define MY_WITH_LEDS_BLINKING_INVERSE
    
    // Flash leds on rx/tx/err
    // 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>
    
    #define RELAY_1  22          // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
    #define NUMBER_OF_RELAYS 16  // Total number of attached relays: 4
    
    // Opto Relay Module I was using Active Low - Low (0):ON, High (1): OFF
    #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 FIRST_PIR_ID 1
    #define MAX_PIRS 16 
    const uint8_t pirPin[] = {A0,A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15};   //  switch around pins to your desire
    Bounce debouncer[MAX_PIRS];
    MyMessage pirMsg(0, V_TRIPPED);
    bool oldPir[MAX_PIRS] = {false};
    
    bool initialValueSent = false;
    
    //Init MyMessage for Each Child ID
    MyMessage msg1(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);
    
    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);
      }
    }
    
    void setup()
    {
      for (uint8_t i = 0; i < MAX_PIRS; i++) {
        debouncer[i] = Bounce();                        // initialize debouncer
        debouncer[i].attach(pirPin[i], INPUT_PULLUP);
        debouncer[i].interval(5);
        oldPir[i] =  debouncer[i].read();
      }
    }
    
    void presentation()  
    {   
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("Combo_22-37_i_A0-A15", "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);
      for (int i = 0; i < MAX_PIRS; i++) { //i < numSensors &&
        present(FIRST_PIR_ID + i, S_MOTION);
      }
    }
    }
    
    void loop() {
      
      if (!initialValueSent) {
        Serial.println("Sending initial value");
        send(msg1.set(loadState(1)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg2.set(loadState(2)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg3.set(loadState(3)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg4.set(loadState(4)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg5.set(loadState(5)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg6.set(loadState(6)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg7.set(loadState(7)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg8.set(loadState(8)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg9.set(loadState(9)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg10.set(loadState(10)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg11.set(loadState(11)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg12.set(loadState(12)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg13.set(loadState(13)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg14.set(loadState(14)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg15.set(loadState(15)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg16.set(loadState(16)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        Serial.println("Sending initial value: Completed");
        wait(5000);
      }
       bool pir[MAX_PIRS];
      for (uint8_t i = 0; i < MAX_PIRS; i++) {
        debouncer[i].update();
        pir[i] = debouncer[i].read();
        if (pir[i] != oldPir[i]) {
          send(pirMsg.setSensor(FIRST_PIR_ID + i).set( pir[i])); // Send tripped value to gw
          oldPir[i] = pir[i];
        }
      } 
    }
    
    void receive(const MyMessage &message) {
      Serial.println("=============== Receive Start =======================");
      if (message.isAck()) {
         Serial.println(">>>>> ACK <<<<<");
         Serial.println("This is an ack from gateway");
         Serial.println("<<<<<< ACK >>>>>>");
      }
      // We only expect one type of message from controller. But we better check anyway.
      if (message.type==V_LIGHT) {
        Serial.println(">>>>> V_LIGHT <<<<<");
        if (!initialValueSent) {
          Serial.println("Receiving initial value from controller");
          initialValueSent = true;
        }
         // Update relay state to HA
         digitalWrite(message.sensor-1+RELAY_1, message.getBool()?RELAY_ON:RELAY_OFF);
         switch (message.sensor) {
            case 1:
              Serial.print("Incoming change for sensor 1");
              send(msg1.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 2:
              Serial.print("Incoming change for sensor 2");
              send(msg2.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 3:
              Serial.print("Incoming change for sensor 3");
              send(msg3.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 4:
              Serial.print("Incoming change for sensor 4");
              send(msg4.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 5:
              Serial.print("Incoming change for sensor 5");
              send(msg5.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 6:
              Serial.print("Incoming change for sensor 6");
              send(msg6.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 7:
              Serial.print("Incoming change for sensor 7");
              send(msg7.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 8:
              Serial.print("Incoming change for sensor 8");
              send(msg8.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 9:
              Serial.print("Incoming change for sensor 9");
              send(msg9.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 10:
              Serial.print("Incoming change for sensor 10");
              send(msg10.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 11:
              Serial.print("Incoming change for sensor 11");
              send(msg11.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 12:
              Serial.print("Incoming change for sensor 12");
              send(msg12.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 13:
              Serial.print("Incoming change for sensor 13");
              send(msg13.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 14:
              Serial.print("Incoming change for sensor 14");
              send(msg14.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 15:
              Serial.print("Incoming change for sensor 15");
              send(msg15.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 16:
              Serial.print("Incoming change for sensor 16");
              send(msg16.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;                      
            default: 
              Serial.println("Default Case: Receiving Other Sensor Child ID");
            break;
         }
         // Store state in Arduino eeprom
         saveState(message.sensor, message.getBool());
         Serial.print("Saved State for sensor: ");
         Serial.print( message.sensor);
         Serial.print(", New status: ");
         Serial.println(message.getBool());
         Serial.println("<<<<<< V_LIGHT >>>>>>");
       } 
       Serial.println("=============== Receive END =======================");
    }
    

    I need to understand what is wrong with that, before trying to merge the third part (linked relays and buttons) with it.

    Of course I am not the author of the sketches above - there are modified templates or parts of code found on the forum.

    In the end I can just divide the work by 3 arduinos, so one is solely for pushbuttons, one for relays and one for buttons linked with relays, but i would like to avoid that.



  • It looks like you're inputs and relays all have the same child IDs, they should be different to be handled correctly by home assistant



  • @Roschkovsky said in Merging 2 or 3 sketches to one (relays & binary buttons):

    if (!initialValueSent)

    This is always false as there is nothing I can see to set it true.

    Also, there is a LOT going on in the receive section - try to move the prints and logic to the main loop and just pass values from receive, it might save a lot of headaches...



  • I modified the code, so the relay status is sent to the HA only at the beginning. I also changed the child id numbers (those for relays now correspond to the pin numbers).

    The good news is the sensor part for the pushbuttons is now working, but the relays still not. They do not register to the HA in any way.

    // Enable debug prints to serial monitor
    #define MY_DEBUG
    
    
    // Enable and select radio type attached
    //#define MY_RADIO_RF24
    //#define MY_RADIO_NRF5_ESB
    //#define MY_RADIO_RFM69
    //#define MY_RADIO_RFM95
    
    // 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 Arduinos running on 8 MHz (Arduino Pro Mini 3.3V & SenseBender)
    #if F_CPU == 8000000L
    #define MY_BAUD_RATE 38400
    #endif
    
    // 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
    
    // Set blinking period
    #define MY_DEFAULT_LED_BLINK_PERIOD 300
    
    // Inverses the behavior of leds
    //#define MY_WITH_LEDS_BLINKING_INVERSE
    
    // Flash leds on rx/tx/err
    // 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>
    
    #define RELAY_22  22          // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
    #define NUMBER_OF_RELAYS 16  // Total number of attached relays: 4
    
    // Opto Relay Module I was using Active Low - Low (0):ON, High (1): OFF
    #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 FIRST_PIR_ID 1
    #define MAX_PIRS 16 
    const uint8_t pirPin[] = {A0,A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15};   //  switch around pins to your desire
    Bounce debouncer[MAX_PIRS];
    MyMessage pirMsg(0, V_TRIPPED);
    bool oldPir[MAX_PIRS] = {false};
    
    bool initialValueSent = false;
    
    //Init MyMessage for Each Child ID
    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);
    MyMessage msg31(31, V_LIGHT);
    MyMessage msg32(32, V_LIGHT);
    MyMessage msg33(33, V_LIGHT);
    MyMessage msg34(34, V_LIGHT);
    MyMessage msg35(35, V_LIGHT);
    MyMessage msg36(36, V_LIGHT);
    MyMessage msg37(37, V_LIGHT);
    
    void before() { 
      for (int sensor=22, pin=RELAY_22; 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);
      }
    
    }
    
    void setup()
    {
      for (uint8_t i = 0; i < MAX_PIRS; i++) {
        debouncer[i] = Bounce();                        // initialize debouncer
        debouncer[i].attach(pirPin[i], INPUT_PULLUP);
        debouncer[i].interval(5);
        oldPir[i] =  debouncer[i].read();
      }
    wait(5000);
        Serial.println("Sending initial value");
        send(msg22.set(loadState(22)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg23.set(loadState(23)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg24.set(loadState(24)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg25.set(loadState(25)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg26.set(loadState(26)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg27.set(loadState(27)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg28.set(loadState(28)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg29.set(loadState(29)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg30.set(loadState(30)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg31.set(loadState(31)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg32.set(loadState(32)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg33.set(loadState(33)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg34.set(loadState(34)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg35.set(loadState(35)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg36.set(loadState(36)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg37.set(loadState(37)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        Serial.println("Sending initial value: Completed");
        wait(5000);
    }
    
    void presentation()  
    {   
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("Combo_22-37_i_A0-A15", "1.0");
    
      for (int sensor=22, pin=RELAY_22; sensor<=NUMBER_OF_RELAYS;sensor++, pin++) {
        // Register all sensors to gw (they will be created as child devices)
        present(sensor, S_LIGHT);
      for (int i = 0; i < MAX_PIRS; i++) { //i < numSensors &&
        present(FIRST_PIR_ID + i, S_MOTION);
      }
    }
    }
    
    void loop() {
    
         bool pir[MAX_PIRS];
      for (uint8_t i = 0; i < MAX_PIRS; i++) {
        debouncer[i].update();
        pir[i] = debouncer[i].read();
        if (pir[i] != oldPir[i]) {
          send(pirMsg.setSensor(FIRST_PIR_ID + i).set( pir[i])); // Send tripped value to gw
          oldPir[i] = pir[i];
        }
      }
    }
    
    void receive(const MyMessage &message) {
      Serial.println("=============== Receive Start =======================");
      if (message.isAck()) {
         Serial.println(">>>>> ACK <<<<<");
         Serial.println("This is an ack from gateway");
         Serial.println("<<<<<< ACK >>>>>>");
      }
      // We only expect one type of message from controller. But we better check anyway.
      if (message.type==V_LIGHT) {
        Serial.println(">>>>> V_LIGHT <<<<<");
        if (!initialValueSent) {
          Serial.println("Receiving initial value from controller");
          initialValueSent = true;
        }
         // Update relay state to HA
         digitalWrite(message.sensor-1+RELAY_22, message.getBool()?RELAY_ON:RELAY_OFF);
         switch (message.sensor) {
            case 22:
              Serial.print("Incoming change for sensor 1");
              send(msg22.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 23:
              Serial.print("Incoming change for sensor 2");
              send(msg23.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 24:
              Serial.print("Incoming change for sensor 3");
              send(msg24.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 25:
              Serial.print("Incoming change for sensor 4");
              send(msg25.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 26:
              Serial.print("Incoming change for sensor 5");
              send(msg26.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 27:
              Serial.print("Incoming change for sensor 6");
              send(msg27.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 28:
              Serial.print("Incoming change for sensor 7");
              send(msg28.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 29:
              Serial.print("Incoming change for sensor 8");
              send(msg29.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 30:
              Serial.print("Incoming change for sensor 9");
              send(msg30.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 31:
              Serial.print("Incoming change for sensor 10");
              send(msg31.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 32:
              Serial.print("Incoming change for sensor 11");
              send(msg32.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 33:
              Serial.print("Incoming change for sensor 12");
              send(msg33.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 34:
              Serial.print("Incoming change for sensor 13");
              send(msg34.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 35:
              Serial.print("Incoming change for sensor 14");
              send(msg35.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 36:
              Serial.print("Incoming change for sensor 15");
              send(msg36.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;
            case 37:
              Serial.print("Incoming change for sensor 16");
              send(msg37.set(message.getBool()?RELAY_OFF:RELAY_ON));
              break;                      
            default: 
              Serial.println("Default Case: Receiving Other Sensor Child ID");
            break;
         }
         // Store state in Arduino eeprom
         saveState(message.sensor, message.getBool());
         Serial.print("Saved State for sensor: ");
         Serial.print( message.sensor);
         Serial.print(", New status: ");
         Serial.println(message.getBool());
         Serial.println("<<<<<< V_LIGHT >>>>>>");
       } 
       Serial.println("=============== Receive END =======================");
    }
    
    

    No error logs in HA, not a sign of relay entities in the json file.


Log in to reply
 

Suggested Topics

14
Online

11.4k
Users

11.1k
Topics

112.7k
Posts