💬 Relay


  • Hero Member

    @Gizmoh ok so it seems like the voltage regulator on the arduino cannot handle the load the relays produce when activated. You need to power the relay board directly from your batteries either trough another 5V regulator or if your relay board already can handle a higher voltage you can connect it directly.



  • @korttoma Ah, okay, thank you. I'll give it a try.
    Maybe connecting a Decoupling-Capacitor could also fix this problem?



  • hello one doubt
    if a use this sketch: /mysensors/MySensorsArduinoExamples/examples/RelayWithButtonActuator/RelayWithButtonActuator.ino

    when i press the button home assistant knows if switch was turned or off? its change the stat?



  • Hi,

    First of all Merry Xmas to all of you!

    I want to use this sketch with three LEDs to present the status of the alarm at home, so with a multicolored LED I have a green status, a red and a blue status, but I just want one color at a time, is there a way to alter the code a little to make sure that is a color is activated, the other one is turned off?


  • Mod

    @riochicken yes, but I wouldn't recommend relays for controlling a led. It can be controlled directly from the Arduino pins.

    Look at the code for these:
    https://www.openhardware.io/view/21/RGBW-LED-Controller#tabs-source
    https://www.openhardware.io/view/74/OH-MySensors-RGBW-Controller#tabs-source



  • @mfalkvidd : I have directly soldered the LED's to the board, would be a waste of relays.. 🙂 Thanks I will look into the examples you just gave...



  • @mfalkvidd I have no clue how to decode the examples you gave, normally in vb or powershell I would check if a pin would be active if another color was requested so I could turn off the other color but I am a bit lost with the code....



  • Hi all
    I use this sketch for controlling 2 x relays. Can anybody change me this sketch to controliling only 1 x relay ?

    Next problem....
    Anybody know how edit sketch for relays to add itrms to send repeate update status to gateway? I want eliminate problem when node start and change status , but gateway is disabled. And after gateway will be enable show in my Domoticz old status/last memory before disable gateway. But after this node has changed status and this status is not show in Domoticz after run. I want to work it as Z-Wave. Z-wave has always actual status. Is any chance to also MySensors Gateway and not has always actual status ?

    /**
       DESCRIPTION
       Sketch for 2x relay with buttons monostable. After back power all relays set OFF and send correct status OFF to controller.  
    */
    
    // Enable debug prints to serial monitor
    #define MY_DEBUG
    
    // Enable and select radio type attached
    //#define MY_RADIO_NRF24
    #define MY_RADIO_RFM69
    #define MY_RFM69_FREQUENCY RF69_868MHZ
    #define MY_IS_RFM69HW
    
    // Enabled repeater feature for this node
    #define MY_REPEATER_FEATURE
    
    // Node id defaults to AUTO (tries to fetch id from controller)
    #define MY_NODE_ID AUTO
    
    #include <SPI.h>
    #include <MySensors.h>
    #include <Bounce2.h>
    
    // Define 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's
    #define SSR_A_ID 1   // Id of the sensor child
    #define SSR_B_ID 2   // Id of the sensor child
    
    // Define buttons and relays
    const int buttonPinA = 3;
    const int buttonPinB = 4;
    const int relayPinA = 5;
    const int relayPinB = 6;
    
    // Define Variables
    int oldValueA = 0;
    int oldValueB = 0;
    bool stateA = false;
    bool stateB = false;
    int trigger = 0;
    
    Bounce debouncerA = Bounce();
    Bounce debouncerB = Bounce();
    
    MyMessage msgA(SSR_A_ID, V_STATUS);
    MyMessage msgB(SSR_B_ID, V_STATUS);
    
    void setup()
    {
    
      pinMode(buttonPinA, INPUT_PULLUP); // Setup the button Activate internal pull-up
      pinMode(buttonPinB, INPUT_PULLUP); // Setup the button Activate internal pull-up
    
    
      // After setting up the buttons, setup debouncer
      debouncerA.attach(buttonPinA);
      debouncerA.interval(5);
      debouncerB.attach(buttonPinB);
      debouncerB.interval(5);
    
      // Make sure relays are off when starting up
      digitalWrite(relayPinA, RELAY_OFF);
      digitalWrite(relayPinB, RELAY_OFF);
      // Then set relay pins in output mode
      pinMode(relayPinA, OUTPUT);
      pinMode(relayPinB, OUTPUT);
    
    }
    
    void presentation()  {
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("2xRelay with monostable", "2.1");
    
      // Register all sensors to gw (they will be created as child devices)
      present(SSR_A_ID, S_LIGHT);
      present(SSR_B_ID, S_LIGHT);
    
    }
    
    /*
       Example on how to asynchronously check for new messages from gw
    */
    void loop()
    {
    if (trigger == 0){
      send(msgA.set(false)); // Send off state for relayA to ensure controller knows the switch is off
      send(msgB.set(false)); // Send off state for relayB to ensure controller knows the switch is off
      trigger = 1;
    }
      
      debouncerA.update();
      // Get the update value
      int valueA = debouncerA.read();
      if (valueA != oldValueA && valueA == 0) {
        send(msgA.set(stateA ? false : true), true); // Send new state and request ack back
    
      }
      oldValueA = valueA;
     
    
      debouncerB.update();
      // Get the update value
      int valueB = debouncerB.read();
      if (valueB != oldValueB && valueB == 0) {
        send(msgB.set(stateB ? false : true), true); // Send new state and request ack back
    
      }
      oldValueB = valueB;
    }
    
    void receive(const MyMessage &message) {
      // We only expect one type of message from controller. But we better check anyway.
      if (message.type == V_STATUS) {
          
        switch (message.sensor) {
          case 1:
            stateA = message.getBool();
            digitalWrite(message.sensor + 4, stateA ? RELAY_ON : RELAY_OFF);
            
            break;
          case 2:
            stateB = message.getBool();
            digitalWrite(message.sensor + 4, stateB ? RELAY_ON : RELAY_OFF);
            
            break;
          
        }
       
          // Write some debug info
        Serial.print("Incoming change for sensor:");
        Serial.println(message.sensor);
        Serial.print("from node:");
        Serial.println(message.sender);
        Serial.print(", New status: ");
        Serial.println(message.getBool());
      }
    }```


  • Hello,
    I would like to do an auto off after 2 sec directly in the sketch, however I do not understand how to write the code? I do not want to make a loop, but on pressing the ON button from my box the relay is activated is deactivated after 2 sec.

    Thank you for your help.



  • I'm trying to wrap my head around the button example and don't understand what the loop() really does. To me it only alters the "state" but how does it affect the relay?
    Is the button physically connected to the relay or should the controller send the new state back and let the receive() function handle the actual relay switching?
    Also, after presentation, shouldn't there be a send() to the controller?


  • Hero Member

    @Efflon you are right about the loop() function it seems like the part where it should change the relay state is missing. Did you try to use this example code?

    The button should be wired between PIN 3 and GND so that when you push the button PIN 3 is Grounded.

    PIN 3 is connected to a "Debouncer" in the "setup()" ( so that when you push the button the code detects only one push and not several ).

    loop() monitors the debouncer and when it detects that you have pushed the button it will send the new state to the controller. I think it should also change the state so if it does not do that you could add the following line

    digitalWrite(RELAY_PIN, state?RELAY_ON:RELAY_OFF); //write new state to relay output

    Before this line in the loop() function:
    send(msg.set(state?false:true), true); // Send new state and request ack back

    You could also add the line:
    saveState(CHILD_ID, state); // Store state in eeprom

    To the same part of the code so that the state change is written to eeprom so that the previous state can be returned after a power failure.



  • @korttoma
    Thanks for the explanation! Just as I suspected with missing relay code.


  • Hero Member

    @Efflon said:

    I'm trying to wrap my head around the button example and don't understand what the loop() really does. To me it only alters the "state" but how does it affect the relay?
    Is the button physically connected to the relay or should the controller send the new state back and let the receive() function handle the actual relay switching?

    The loop in the relay with button actuator sketch does three main things

    checks for a new button push
    changes the current state
    Sends the new state to the controller

    If you look at the message code you can see it also asks for an ACK back from the controller. That is the true at the end of the line.

    send(msg.set(state?false:true), true);                         // Send new state and request ack back
    

    It is this returned ACK that is used to switch the relay to the new state in the void receive function

    The one drawback in this code if it is used for say a light switch is that if this node looses contact with the controller then the relay cannot be changed by pressing the button.



  • @Boots33 Ok, you explanation is what was my only explanation to the "missing" code. When experimenting with this using the mqtt gateway sketch and home-assistant as controller, the ACK is just an ACK and not a "real" message with payload thus just toggling the state bool and getting things out of sync..



  • I did not get the example working properly with my 8 channel SSR. So here is my updated version of the example.

    I have changed the way the pins are assigned by using a array. The current example tries to connect relays 7 and 8 to pins 9 and 10 when you select an 8 channel relays. This won't work because those pins are used by the radio module.

    I think you can connect a relays to any pin which is not used. If so this will make it possible to connect up to 14 relays to the mini pro when also the pins A5-A7 are available.

    // Enable debug prints to serial monitor
    #define MY_DEBUG
    
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    //#define MY_RADIO_RFM69
    
    // Enable repeater functionality for this node
    #define MY_REPEATER_FEATURE
    
    #include <MySensors.h>
    
    const int PINS[] = {3, 4, 5, 6, 7, 8, 14, 15}; // I/O pins 3, 4, 5, 6, 7, 8, A0, A1 for the relays 
    #define NUMBER_OF_RELAYS 8 // 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
    
    
    void before()
    {
        for (int sensor=1; sensor<=NUMBER_OF_RELAYS; sensor++) {
            // Then set relay pins in output mode
            pinMode(PINS[sensor-1], OUTPUT);
            // Set relay to last known state (using eeprom storage)
            digitalWrite(PINS[sensor-1], 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; sensor<=NUMBER_OF_RELAYS; sensor++) {
            // 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.type==V_STATUS) {
            // Change relay state
            digitalWrite(PINS[message.sensor-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());
        }
    }
    

  • Hardware Contributor

    I'm attempting to get my double relay board containing two switch inputs. I see that the two sketches suggested on the relay page are there but one seems to be updated to the new version which allows you to use multiple relays on the board but the other isn't, as far as i can see. How do I go about making the sketch with buttons accept more relays?



  • Hi @Woeka
    I've been testing your code, but works inverse mode
    if switch in domoticz is on the relay is off and vice versa


  • Hero Member

    @ijobain Try changing

    #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
    

    To

    #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
    

    and see if that works as you expected


  • Hero Member

    @Samuel235 Have a look at this thread for some ideas.



  • @Boots33
    Thank you so much
    I am newbie


  • Hardware Contributor

    @Boots33 - Thanks dude, I have had a quick skim read just but will bookmark it when i get my gateway working. These issues right now are driving me insane, and spending the day to try and find the problem. Thank you for linking me to that post!



  • I just tried this sketch, works on latest version, but i cant seen any relais in Domoticz, only see the node relais, did i miss something






  • Hardware Contributor

    Hi to all!
    I would edit the secure relay sketch so in loop the node sends to the gateway, let's say every hours, his state (on or off).

    1. I avoid delay otherwise Arduino cannot receive the comands from gateway, so I will use the millis sketch, modified from the official Arduino website.

    My doubt is... How can I get the current state of the relay?

    Relevant part of sketch is in loop and before setup()

    /* TIME variables */
    unsigned long previousMillis = 0;        // will store last time state is sent
    // constants won't change:
    const long interval = 10000;           // interval at which to send state (milliseconds === seconds x 1000). For test we try every 10 seconds
    

    And the main loop

    void loop()
    {
    
      // check to see if it's time to send state; that is, if the difference
      // between the current time and last time you sent state is bigger than
      // the interval at which you want to send the state.
      unsigned long currentMillis = millis();
    
      if (currentMillis - previousMillis >= interval) {
        // save the last time you blinked the LED
        previousMillis = currentMillis;
    
        // send the state here!
        // test
        Serial.println("This is the moment where I need to send state");
    
        //send(?????????); // Send current state. Probabily will update also the log?
      }
    

    The base sketch is >>> https://github.com/mysensors/MySensors/blob/master/examples/SecureActuator/SecureActuator.ino

    And the millis example is >>> https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay

    Thank you to all!


  • Hardware Contributor

    @sineverba
    Edit:
    I did edit the pre-setup configuration

    int val = 0;  // the value of digital pin
    #define CHILD_ID 1   // Id of the sensor child
    MyMessage msg(CHILD_ID,V_LIGHT);
    

    And I did edit the loop:

    if (currentMillis - previousMillis >= interval) {
        // save the last time you blinked the LED
        previousMillis = currentMillis;
    
        // send the state here!
        // test
        Serial.println("This is the moment where I need to send state");
    
        val = digitalRead(LOCK_1);
    
        
        Serial.print("Il valore del relay è ");
        Serial.println(val);
    
        send(msg.set(val),true); // Send new state and request ack back. 
      }
    

    I got the update in Domoticz in Hardware > Configuration > Children of nodes

    alt text

    And I did test also every 3 seconds, all ok.

    But I don't have the refresh in "main page":

    alt text

    I did test removing current to Arduino when Relay was ON. With Arduino off, I did change the state in domoticz to OFF.

    Because Arduino save previous state in EEPROM, after full start the relay did go ON, in Domoticz got "1" in children (all right, because digitalRead was 1) but main panel shows OFF.

    I did expect a graphical change...

    Thank you (and hope that all is clear) 🙂


  • Hardware Contributor

    Hi to all!
    To achieve my goal (node that sends relay state after power failure to sync with domoticz), I'm editing the button script.

    I have added this line

    state = digitalRead(RELAY_PIN);
    send(msg.set(state?false:true), true); // Send new state and request ack back
    

    in setup, so I thought it send only one time at startup the current state after power failure.

    But..... the relay shutdown/shuton (or viceversa) twice, in fast sequence....

    Thank you very much!


  • Hardware Contributor

    @sineverba

    Bingo!

    If I did understand well, the actuator sketch DOESN'T directly acts the relay, but sends to the gateway and expect from the gw itself the "new state" (in effect, you short GND & PIN 4, arduino sends new state to the gateway and gateway resend the new state).

    So, 'cause I would to update the state on controller, I did this simple edit on setup:

    // Set relay to last known state (using eeprom storage) 
     state = loadState(CHILD_ID);
     digitalWrite(RELAY_PIN, state?RELAY_ON:RELAY_OFF);
    
     Serial.print("Lo stato ultimo era ");
     Serial.println(state);
    
     if ( state == 1) {
       state = 0;
     } else {
       state = 1;
     }
     
     send(msg.set(state?false:true), true); // Send new state and request ack back
    

    Basically, If relay was OFF on a power failure, and someone on Domoticz try to start the relay, the state in Domoticz will be "on".

    When power returns, the arduino read the state (in my example OFF == 0), convert in 1 and send to the gateway the 1. The gateway // Domoticz will be answer with 0.

    So, relay doesn't nothing and Domoticz state is update.

    But.... why I need to invert the logic? 😄


  • Hero Member

    @sineverba said in 💬 Relay:

    To achieve my goal (node that sends relay state after power failure to sync with domoticz)

    Have a look at the sketch I used for my Synchronising Light switch you may be able to use some of that code perhaps.


  • Hardware Contributor

    @Boots33

    Never seen the request function.
    You are hero-member for a reason...
    Thank you very much! 🙂 🙂


  • Hero Member

    @sineverba said in 💬 Relay:

    Never seen the request function.

    You can find request and other useful info on the API page.
    Hope you are enjoying your MySensors journey 🙂



  • Hello,

    since the relay has leds and is therefore power consuming, i was wondering if someone has written a sketch for a low power usage of the relay (as for the sensors) allowing the arduino (and the relay) to sleep all the time and wake up every 5 minutes for instance just to check if the controller has changed the desired state of the switch.

    Of course then the relay could be as late as 5minute, but this is not an issue for my application ...

    thanks for any suggestion


  • Mod

    @fhenryco can't the relay node use power from whatever it is controlling?

    For sleeping nodes, the smartsleep feature can be useful. Search for that keyword in the forum and look at https://www.mysensors.org/download/sensor_api_20#sleeping



  • thanks , indeed it's because the relay is controlling a 12V battery power to solenoid valve , that low power consumption is needed. BTW the 12V is obtained from a 4S lipo (16.5V max voltage) and a 12 regulator and i dont know if its better to feed the arduino from a 5V regulator fed by the same Lipo , or use an additional set of AA batteries ... i remember that it's better to have an as low as possible drop in voltage to save power...


  • Hero Member

    @fhenryco If you are trying to keep your power use down then you could also consider using either a Latching Relay or even a MOSFET.



  • @mfalkvidd smartsleep was not supported by domoticz at the begining of the year ... but there was a domoticz upgrade in july ... do you know if it's now supported ?


  • Mod

    @Boots33 said in 💬 Relay:

    @fhenryco If you are trying to keep your power use down then you could also consider using either a Latching Relay or even a MOSFET.

    Agreed, if you want to save power you need to use a latching relay. Also another regulator would be fine to power the arduino.



  • @gohan can you explain the benefit (for a low power app) of a relay switching on electrical pulse rather something else ?
    i mean, even the regular relay has both an open by default circuit output and close by default circuit ouput so it could remain on the desired state even when not powered up ...


  • Mod

    I am referring that when relay is on it is drawing power to stay on, while a latching relay it only draws power during the switch on and only during the switch off.



  • @gohan not sure this is going to be an easy way: need find arduino code for latch relay, dont know if domoticz is supporting this device ?, ...


  • Mod

    Domoticz will just see the same relay node, it is the code that need to be a little different as the relay is switched with a pulse and you need a pin to verify the relay status (if you get the ones that have a monitoring contact)



  • Hi Everyone,
    maybe the below will help people facing random incorrect behaviors.
    In sample from december 2016 /mysensors/MySensors/examples/RelayActuator/RelayActuator.ino, there is something which could be seen as a bug.

    In my case, I have used that sample to control a lot of relais. I noticed some rare but really annoying errors. From time to time a relay got switched incorrectly.
    Annoying and strange as coding was pretty straightforward. All relais are coded to act in pulse mode.

              digitalWrite(message.sensor-1+RELAY_1, RELAY_OFF);
              wait(1000);
              digitalWrite(message.sensor-1+RELAY_1, RELAY_ON);
    

    And this is the reason of the bug.

    Explanation.
    During that second of wait, a lot of things may occurs. Due to the 'message' declaration, it is possible that the 'message' is getting changed.
    Typically a ping may come and as result the 'message' is not anymore the same.

    For that reason I would suggest the code to be changed a little bit.

    void receive(const MyMessage &message_orig)
    {
      MyMessage message;
      message = message_orig;
    

    This way, the function works with a local copy and you are sure nothing can change during the processing.

    Anyway, thanks for the sample it was nevertheless very helpful


  • Contest Winner

    @amemo06

    void receive(const MyMessage &message)
    

    Because of the const keyword this is a const reference or said another way, a reference to a constant. The const keyword guarantees that the function may not change the object.

    So, I wonder what your real issue is....



  • @BulldogLowell No This is not the coding of the function which changes it. It is most likely the event which triggers it which may changes it.
    I can show the coding with trace and trace result.

    void receive(const MyMessage &message)
    //void receive(const MyMessage &message_orig)
    {
    //  MyMessage message;
    //  message = message_orig;
      Serial.println("receive_in:");
    Serial.print("1st read:Sensor=");Serial.print(message.sensor);Serial.print(", getBool=");Serial.println(message.getBool());
      // We only expect one type of message from controller. But we better check anyway.
      if (message.type==V_STATUS) {
        // Change relay state
        if (message.getBool() == RELAY_ON){
          digitalWrite(message.sensor-1+RELAY_1, RELAY_OFF);
    Serial.print("2nd read:Sensor=");Serial.print(message.sensor);Serial.print(", getBool=");Serial.println(message.getBool());
          wait(1000);
          digitalWrite(message.sensor-1+RELAY_1, RELAY_ON);
    Serial.print("3rd read:Sensor=");Serial.print(message.sensor);Serial.print(", getBool=");Serial.println(message.getBool());      
        }
    Serial.println("receive_out:");
    }
    

    Below is a normal trace

    0;255;3;0;9;Eth: 0;0;3;0;18;PING
    0;255;3;0;9;Eth: 0;1;1;0;2;1
    receive_in:
    1st read:Sensor=1, getBool=1
    2nd read:Sensor=1, getBool=1
    3rd read:Sensor=1, getBool=1
    receive_out
    

    So you see the ping which occured before the message I'm interested in
    Now, because of the wait in the middle of the code, it may occurs the ping arrive in that period. Then the issue occurs.
    See the trace with error.

    0;255;3;0;9;Eth: 0;1;1;0;2;1
    receive_in:
    1st read:Sensor=1, getBool=1
    2nd read:Sensor=1, getBool=1
    0;255;3;0;9;Eth: 0;0;3;0;18;PING
    3rd read:Sensor=0, getBool=0
    receive_out
    

    In the 3rd read, sensor value has changed and getBool returns also a different value.

    Removing the wait or ensuring the function modules performs faster could reduce the risk. Still it will never be reliable.
    Better is to have either a local copy of the message like I wrote in the original post. Or make immediately copies of the information from the message I'm interested in.


  • Mod

    @amemo06 said in 💬 Relay:

    wait(1000);

    where did you find that? I wasn't able to find it



  • @gohan This is not in the original coding. I needed something like a wait in order to make a relay pulse.
    The wait increases the risk or the frequency of the trouble. Removing it does not solves the issue.
    Processing of the function will always take time. And the message can still changes before reaching the end like it is show in the second trace.


  • Contest Winner

    @amemo06

    You should treat the message like an ISR... get in and out so that you don't have another message colliding while you are in the function.

    Get rid of that wait(). I couldn't find the source for that function but you could try to just use delay() to block while you hold the relay.

    otherwise just set a flag to handle the relay event in loop() or use a Timer/callback like the MsTimer2 Library

    example:

    #include <MsTimer2.h>
    
    const byte onButton = 5;
    
    void setup()
    {
      Serial.begin(9600);
      pinMode(13, OUTPUT);
      pinMode(onButton, INPUT_PULLUP);
    }
    
    void loop()
    {
      if(onButtonPressed())
      {
       flashLedThirteen(5000);
      }
    }
    
    bool onButtonPressed(void)
    {
      static unsigned long lastMillis = 0;
      static byte lastPress = HIGH;
      byte currentPress = digitalRead(onButton);
      if(currentPress != lastPress)
      {
        if(millis() - lastMillis < 200) return false;
        lastPress = currentPress;
        if(currentPress == LOW)
        {
          Serial.println(" button press detected!");
          lastMillis = millis();
          return true;
        }
      }
      return false;
    }
    
    void flashLedThirteen(int ledTime)
    {
      digitalWrite(13, HIGH);
      Serial.println("LED ON");
      // sets a new timer callback function
      MsTimer2::set(ledTime, [] {  // the square brackets define the start of the anonymous callback function which is executed after 5000 milliseconds in this example
        digitalWrite(13, LOW);
        Serial.println("Timer expired...");
        Serial.println("LED OFF");
        MsTimer2::stop();
      }); // the curly brace defines the end of the anonymous callback function
      MsTimer2::start();
    }
    


  • @BulldogLowell said in 💬 Relay:

    MsTimer2::

    Thanks for the MSTimer, I was not aware of it.
    And yes, definitively, having a wait() is probably the worst I could have written. Active wait cannot stay.
    My intention, in the stuff I develop, was to remove it asap and probably by handling the wait time in the loop with flags.

    Maybe I was not clear enough about my intention when I opened this thread. I have no issue with what I develop. I already had several ways to solves this. And now, I have a new one with MSTimer. Again thanks.

    I only wanted to raise the fact void receive(const MyMessage &message) may lead to trouble as 'message' content may change during processing of that function.
    And if, like many, you are not skilled enough to code/debug.., you will face erratic issues and real difficulty to understand what is going wrong.


  • Contest Winner

    @amemo06

    I only wanted to raise the fact void receive(const MyMessage &message) may lead to trouble as 'message' content may change during processing of that function.

    As I already explained... message cannot change during the function, because of constness.

    The message handler is being called again from within itself (i.e. from wait()). You would then processing any new messages on that call. It looks as if the function may not be designed to perform recursively as you are trying to do in your code, so that would explain your unexpected/undefined results.

    So yes, block during the relay's holding state or use another non-blocking method (i.e. flag or timer/callback) as you mentioned. Fully process each message before allowing the library to handle subsequent message calls.

    😉



  • I was looking for a solution for a low consumption relay and i was adviced in this thread to use a latching relay.
    However since i just need to switch on or off a 12V Vcc (from Li ion battery) to trigger a solenoid valve, i'm wondering whether i need a relay for that :
    looking at the schematic from post #2 in https://forum.arduino.cc/index.php?topic=436555.0 may be i coud just have my solenoid valve directly in place of the relay in the schematic. In other words , i just need a transistor and not a real relay ... just because my application is a low voltage (12V to apply directly to the Vcc in the schematic) rather than 230V one: can someone confirm ? There is a diode in the schematic : what is it needed for ?

    0_1505132986740_arduino-control-relay-schematic.png


  • Hardware Contributor

    @fhenryco

    Since an inductor (im many cases a relay coil) cannot change it's current instantly, the flyback diode provides a path for the current when the coil is switched off. Otherwise, a voltage spike will occur causing arcing on switch contacts or possibly destroying switching transistors.

    https://electronics.stackexchange.com/questions/100134/why-is-there-a-diode-connected-in-parallel-to-a-relay-coil



  • treat yor solenoid as it was a relay, the difference is that relay switches flow of current, and solenoid valve switches flow of water. so You have to use the same schematic, but put your valve where the relay is. But if You want power it from a battery, choose a latching solenoid valve instead of regular solenoid valve - and that requeires different schematic.



  • @rozpruwacz
    thanks, but do you mean that the schematic simply would not work for the regular valve or that it would work but not be low power cinsumption design anymore ?
    I have a regular solenoid valve but in my application the valve is normally closed and it will be only exceptionnally opened and for a short time when the 12V is applied, so i guess that i can live with it ...
    As for the transistor in the schematic, except it seems to be a NPN , i don't know if i need a particular one for it . probably i can just buy a 2N3904 , or is there a better choice?



  • the schematic you posted is not using latching relay/valve. it doesn't matter if it is relay or valve. both works the same and consume power when in ON state. If you plan to use it in a way that the valve will be ON for very short periods than it is not important if it is latching or not.

    when choosing a transistor for such use, You have to look at its datasheet into "absolute maximum ratings" section and check if it will handle the voltages you will apply to it. 2N3904 looks like it will handle 12V without a problem.



  • @rozpruwacz
    thanks , i will use 2N2222 because the valve needs between 200 and 400 mA.
    I'v read the 2N3904 is OK for < 100 mA



  • It works very well with the transistor and schematic posted above. I think the valve is a latching valve because it only discharges the battery when there is a transition. The only remaining problem is that the 5V arduino alone is too much power consuming. So i'm wondering if the transistor could as well work with a 3.3V arduino, that is when the signal level on the transistor Base is 3.3V rather than 5 V ... then i also could remove the arduino led but i'll need to keep the arduino regulator because my 3.7V cell voltage is too much greater than 3.3V



  • @fhenryco Actually the internal resistor of the solenoid is 27 Ohm while the resistance between C and E of the transistor in the passing state is 35 Ohm ... so it remains less than Vcc/2 for my solenoid which needs 12V ... so i need to tune my boost module at the max ==> more than 30V ... that does not seem ideal, may be i shoud choose another transistor with less internal resistor, but i have little experience with transistors : studied them a long time ago , so if someone can suggest something smart, ready to buy it ...



  • Can I suggest a change to this page?

    As it stands the wiring diagram only applies to sketch 1 (without switch). It could get confusing as the 2 sketches use different pins for the relay and there is no need for this.

    I propose that the wiring diagram be changed for the relay to be attached to pin 4.
    The first sketch needs the relay pin to change from pin 3 to pin 4.

    That's it. Then the diagram and sketches will work whichever way the builder wants to do it.


  • Mod

    Good idea @skywatch
    When doing the update, we should also rename RELAY_1 to RELAY_PIN to be consistent with sketch 2.


  • Mod


  • Mod

    https://www.mysensors.org/build/relay has been updated with new wiring instructions (picture + table)



  • That looks good, only the sketchs to go....On that note I wonder if Relay_1 might not be better choice as it gives a clue to people that if they want to add a second relay then that would be Relay_2.... Just a thought and maybe not needed.... 😉



  • @mfalkvidd when updating the example sketch you could maybe consider my version of the relay sketch which offers some nice additions: https://forum.mysensors.org/topic/6638/multiple-relays-motion-sketch-fully-customizable-optional-timer-manual-override


  • Mod

    @HenryWhite my mind is divided when it comes to that type of sketch. Yes, it has a lot of functionality. Yes, it is probably what people need anyway. But the examples are meant to be used by someone who is just getting into diy home automation. Someone new should be able to understand as much of the sketch as possible. There should be as little as possible to trubleshoot. If the sketch is complex, most people's initial reaction will be that there is something wrong with the code, when in reality almost all newbie problems are power or wiring-related. Keeping the sketch simple helps, at lest a bit.



  • @mfalkvidd You are right but may be should there be for each sensor or actuator first the most basic sketch but also at the end of the page a complete version with all functionalities and granted to work by the mysensors team.

    Of course for the complicated sketch version a big warning in red letters that this is not recommended for newbies would help...



  • After testing some functionalities of nodemanager, i was wondering if already somebody was working on making a GUI for nodemanager which would allow to build one's sketch completely from a graphical interface (at least the most common and basic functionalities) : i thing the great work that resulted in Nodemanager has so well structured the various functions needed that it has already paved the way for creating such a graphical interface.


  • Mod

    There was a user some time ago that was trying to make a web GUI



  • I would agree that more advanced sketches 'should' be included on the same page. Keep all the info in one resource place. Provided it is clearly marked as an advanced project it might help people looking for similar functionality or just interested in learning more about programming....


  • Admin



  • wow! fantastic! ... the github link readme warns that it's not yet fully ready but the interface is already impressive!
    I still have the same question i had for nodemanager though : for measuring another battery than the one that feeds Vcc obviously another pin is needed, however why not propose as well the option of measuring such pin voltage but with Vcc as the reference rather than the internal 1.1V which most of the time makes necessary a voltage divider ? Actually i did the modification in nodemanager.cpp to use DEFAULT (~3.3V) rather than INTERNAL (1.1V) reference for a 3.3 pro mini and i can get the expected battery level without any voltage divider.

    Another unrelated question i have is : could there be any way to adapt the idea of the readVcc method (which is to measure the internal 1.1V against the Vcc reference to get Vcc) but using any voltage applied to a pin as the reference to again measure the internal 1.1 against it ? This would allow the masurement of any voltage greater than 1.1 without voltage divider while the usual method would be applied for measuring any voltage lower than 1.1 ... what did i miss that makes this impossible ?


  • Mod

    We need to use the internal reference since it is the only stable voltage source and you need the voltage divider to lower the measured voltage between 0 and 1.1v. There are not many options to choose from



  • i also just realized that there is a special AREF pin intended for what i was thinking about ... but it's not available on the mini pro.

    My measurements using Vcc as Ref have been indeed very fluctuating, however what i get was highly sufficient to monitor the battery feeding a 3.3v step up regulator to the arduino and help anticipate failure



  • I just noticed another thing that should be changed in the 'relay with button' sketch....

    S_LIGHT should be S_BINARY
    V_LIGHT shoud be V_STATUS



  • I would like to clarify operation of the sketch, where more than 1 sensors input are used along with more than 1 relay actuator. in one node

    1. Does node need unique child ID for each sensor input AND relay output?
    2. If that is the case how child ID is assigned to relay actuators in the above examples?


  • This is a nice sketch and it is very universal for relays. Now m looking for a similar sketch for digital inputs such as buttons i.e.. I would like to join both. The problem: I want to use a mega for reading status of a lot of digital outputs (min.20) of another ISP. It is only High or Low. Only when the level changes, I want the mega send a message to the gateway. I tried this "for" loop, but it didnt help. There are too many informations sent to the gateway. I imagine a solution, where only a change at the pin will create an information, that is sent to the gateway.
    Here my test, which didnt run:
    void loop()
    {

    for (int sensor=16, pin=BIN_1; sensor<=NUMBER_OF_BIN; sensor++, pin++)
    {
    int BUTT;
    int BUTTOLD;
    BUTT =digitalRead(pin);
    if (BUTT != BUTTOLD && BUTT !=0){
    MyMessage msg(sensor, V_TRIPPED);
    send(msg.set(BUTT ? "1" : "0"));
    }
    BUTTOLD = BUTT;
    wait (900);
    }
    }
    Has anybody an idea or a hint for me?


  • Mod

    I believe there is a logic error in the sketch as you would need to declare global variables BUTTOLD_XX unique for each button, otherwise how can you keep track of the variable between each loop and FOR iteraction?



  • Thank You for Your quick answer.
    Do I understand You correctly: I must index the BUTTOLD?
    As BUTTOLD[pin) for example or how? Where?


  • Mod

    You need to create the single variables one by one, unless somebody else has a better way to do it



  • why i can't compile for arduino pro mini on other boards i can upload


  • Mod

    @mitja-blazinsek the error messages are usually essential to figuring out. Did you get any?



  • Arduino: 1.8.1 (Windows 7), Board: "Arduino Pro or Pro Mini, ATmega168 (5V, 16 MHz)"

    In file included from c:\users\mitja\appdata\local\arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.4-arduino2\avr\include\avr\io.h:99:0,

                 from c:\users\mitja\appdata\local\arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.4-arduino2\avr\include\avr\pgmspace.h:90,
    
                 from C:\Users\mitja\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.20\cores\arduino/Arduino.h:28,
    
                 from sketch\button_relay.ino.cpp:1:
    

    C:\Users\mitja\Documents\Arduino\libraries\MySensors/hal/architecture/AVR/MyHwAVR.cpp: In function 'bool hwUniqueID(uint8_t (*)[16])':

    C:\Users\mitja\Documents\Arduino\libraries\MySensors/hal/architecture/AVR/MyHwAVR.cpp:246:26: error: 'SIGRD' was not declared in this scope

    ((uint8_t)uniqueID) = boot_signature_byte_get(0x00);

                          ^
    

    C:\Users\mitja\Documents\Arduino\libraries\MySensors/hal/architecture/AVR/MyHwAVR.cpp:247:30: error: 'SIGRD' was not declared in this scope

    ((uint8_t)uniqueID + 1) = boot_signature_byte_get(0x02);

                              ^
    

    C:\Users\mitja\Documents\Arduino\libraries\MySensors/hal/architecture/AVR/MyHwAVR.cpp:248:30: error: 'SIGRD' was not declared in this scope

    ((uint8_t)uniqueID + 2) = boot_signature_byte_get(0x04);

                              ^
    

    C:\Users\mitja\Documents\Arduino\libraries\MySensors/hal/architecture/AVR/MyHwAVR.cpp:249:30: error: 'SIGRD' was not declared in this scope

    ((uint8_t)uniqueID + 3) = boot_signature_byte_get(0x01); //OSCCAL

                              ^
    

    Multiple libraries were found for "Bounce2.h"
    Used: C:\Users\mitja\Documents\Arduino\libraries\Bounce2
    Not used: C:\Users\mitja\Documents\Arduino\libraries\Bounce2-master
    exit status 1
    Error compiling for board Arduino Pro or Pro Mini.

    This report would have more information with
    "Show verbose output during compilation"
    option enabled in File -> Preferences.



  • OK it's probaly because ia have mini with 168 chip i have to buys 328 😞 again wait 1month to arive from china



  • hello.
    I am building a node with several kind of sensors and two relays.
    My sensors use CHILD ID from 0 to 3. I would like to start child ID of relay from 4.
    How I can't do that with this sketch?
    I guess I have to change this part of sketch :
    "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);"

    correct?

    thanks



  • @lekeb
    You may do something like this:
    In Header:

    uint8_t DS_First_Child_ID = 7; //First Child-ID to be used by Dallas Bus
    

    an then in presentation():

    for (int i = 0; i < numSensors && i < MAX_ATTACHED_DS18B20; i++) {
        present(i + DS_First_Child_ID, S_TEMP);
    }
    

    But afaik, it's not recommended to shift the ChildID's for relays but always start with 1. Imo it's better to change the ChildID's of the other attached sensors. You may also take care (in case of shifting ID's) about a consistent mapping from ID to the PINs where the relays are attached.


  • Mod

    Agreed, set you sensors to higher ID numbers like 20 or 30 and you are good to go .



  • ok thanks a lot I will try this night



  • perfect it works great. I started my temperature sensor at CHILD ID 4 and let relays from 1 to 2. I had to add also "DS_First_Child_ID" in the sent message to gateway.
    thanks



  • Hi
    Please put to this topic code your sketch....
    Thanks



  • Sur,

    my node controls two relays, one water pressure sensor and three DS18b20

    /**
     code pour controle cave a vin, temp et pression
     */
    
    // Enable debug prints to serial monitor
    //#define MY_DEBUG
    
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    
    // Enable repeater functionality for this node
    #define MY_REPEATER_FEATURE
    
    #define MY_NODE_ID 15
    #include <SPI.h>
    #include <MySensors.h>
    #include <DallasTemperature.h>
    #include <OneWire.h>
    
    #define BARO_CHILD 0 //Child ID for pressure sensor
    #define BAR_SENSOR_ANALOG_PIN 0 // pin for pressure sensor
    
    #define COMPARE_TEMP 1 // Send temperature only if changed? 1 = Yes 0 = No
    
    #define ONE_WIRE_BUS 5 // Pin where dallase sensor is connected 
    #define MAX_ATTACHED_DS18B20 16
    #define RELAY_PIN 3 //pin for first relay
    #define NUMBER_OF_RELAYS 2
    #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
    
    OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
    DallasTemperature sensors(&oneWire); // Pass the oneWire reference to Dallas Temperature. 
    float lastTemperature[MAX_ATTACHED_DS18B20];
    int numSensors=0;
    bool receivedConfig = false;
    bool metric = true;
    float lastpression;
    uint8_t DS_First_Child_ID = 4; //First Child-ID to be used by Dallas Bus
    MyMessage pressureMsg(BARO_CHILD, V_PRESSURE);
    MyMessage msg(0,V_TEMP);
    
    
    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);
        }
        
        // Startup up the OneWire library
      sensors.begin();
    }
    
    void setup()
    {
       
    // requestTemperatures() will not block current thread
      sensors.setWaitForConversion(false);
    }
    
    void presentation()
    {
        // Send the sketch version information to the gateway and Controller
        sendSketchInfo("Buanderie node", "1.0");
    
        //present pressure sensor
        present(BARO_CHILD, S_BARO);
    
        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);
        }
    
        
    // Fetch the number of attached temperature sensors  
      numSensors = sensors.getDeviceCount();
    
      // Present all sensors to controller
      for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) {   
         present(i + DS_First_Child_ID, S_TEMP);
      }
    }
    
    
    
    void loop()
    {
      //read water pressure
    int lecture_adc = analogRead(BAR_SENSOR_ANALOG_PIN);
      float pression = ((lecture_adc*5/1024.0)-0.50)/1.7;
      if(pression != lastpression) { 
          send(pressureMsg.set(pression, 2));
      lastpression = pression;
      }
      
      
      // Fetch temperatures from Dallas sensors
      sensors.requestTemperatures();
    
      // query conversion time and sleep until conversion completed
      int16_t conversionTime = sensors.millisToWaitForConversion(sensors.getResolution());
      // sleep() call can be replaced by wait() call if node need to process incoming messages (or if node is repeater)
      sleep(conversionTime);
    
      // Read temperatures and send them to controller 
      for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) {
    
        // Fetch and round temperature to one decimal
        float temperature = static_cast<float>(static_cast<int>((getControllerConfig().isMetric?sensors.getTempCByIndex(i):sensors.getTempFByIndex(i)) * 10.)) / 10.;
    
        // Only send data if temperature has changed and no error
        #if COMPARE_TEMP == 1
        if (lastTemperature[i] != temperature && temperature != -127.00 && temperature != 85.00) {
        #else
        if (temperature != -127.00 && temperature != 85.00) {
        #endif
    
          // Send in the new temperature
          send(msg.setSensor(i + DS_First_Child_ID).set(temperature,1));
          // Save new temperatures for next compare
          lastTemperature[i]=temperature;
        }
      }
    }
    
    void receive(const MyMessage &message)
    {
        // We only expect one type of message from controller. But we better check anyway.
        if (message.type==V_STATUS) {
            // Change relay state
            digitalWrite(message.sensor-1+RELAY_PIN, 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());
        }
    }
    

  • Mod

    @lekeb said in 💬 Relay:

    MyMessage pressureMsg(BARO_CHILD, V_PRESSURE);
    MyMessage msg(0,V_TEMP);

    Why are you using the same child ID (since you set #define BARO_CHILD 0)?



  • @gohan Effectively, he will never report any temp reading under ChildID 0. Within presentation() and the send() commands, the "0" is replaced by "i + DS_First_Child_ID".
    But you are partly right, to avoid any misunderstandings wrt. that the statement could also be written as follows:

    MyMessage msg(DS_First_Child_ID,V_TEMP);
    


  • correct, it makes sense. I will correct this error.
    However Domoticz reads correctly the temperature and links correctly the CHILD ID's, so...



  • Hello everybody !

    I would like to creat a sensor with two relays and two buttons to command this relay direct from the sensor (with actualisation of their stat in domoticz)
    Someone know the code to do this ? I'm a complete newbie on mysensor !

    Thank's a lot !



  • @jonathan-pucel Have a look at the code in this post.



  • Excellent ! It's perfect, thank's a lot rejoe2 !



  • This post is deleted!


  • Hi
    Using Home assistant, and Optimistic set to false in the mysensors config, the switch in homeassistant would turn the relay on, but in the view in homeassistant the flip switch jumped off straight after switching on. It was solved by adding the following line to the sketch, ensuring that hassio knows that the actuator actually have received the command. Not sure if this is a good way of doing it, but it seems to work for me.
    send(msg.set(state)); // Send new state and request ack back
    in:
    void receive(const MyMessage &message) {
    // We only expect one type of message from controller. But we better check anyway.
    if (message.isAck()) {
    Serial.println("This is an ack from gateway");
    }

    if (message.type == V_LIGHT) {
    // Change relay state
    state = message.getBool();
    digitalWrite(RELAY_PIN, state?RELAY_ON:RELAY_OFF);
    // Store state in eeprom
    saveState(CHILD_ID, state);

     // Write some debug info
     Serial.print("Incoming change for sensor:");
     Serial.print(message.sensor);
     Serial.print(", New status: ");
     Serial.println(message.getBool());
     send(msg.set(state)); // Send new state and request ack back
    

    }
    }

    Thanks



  • Hi!

    I would like to control some 230VAC equipment (for now roller shutters), based on inputs from my mysensors sensors (temperature and light). For controller I use domoticz.

    I would like a safe, robust and preferably authorized/lawful solution (I'm in EU/Denmark).

    I came across the following solutions:

    https://aeotec.com/z-wave-plug-in-switch
    https://sonoff.itead.cc/en/products/sonoff/sonoff-basic
    https://dlidirect.com/products/iot-power-relay

    I think the first one and maybe the second one will be authorized/lawful...? However, I have experience only with mysensors and neither z wave nor sonoff...

    Anyone has some experience/thoughts/suggestions to share?

    Thanks.


  • Mod

    There are also roller shutters nodes running via zwave if you are looking at a retail solution



  • Thank you @gohan! Retail solution is not the keyword here. What I am searching for is an authorized/lawful (safe) solution.

    I decided to do my own node (mysensors) with a cheap relay module for the arduino. Once I achieve the desired functionality I will change to some more robust hardware. Following your suggestion this could be a z wave roller shutter (e.g. fibaro or qubino).


Log in to reply
 

Suggested Topics

  • 3
  • 584
  • 110
  • 10
  • 2
  • 164

0
Online

11.4k
Users

11.1k
Topics

112.7k
Posts