Relay Actuator with momentary (pulse) action



  • What do I need to edit in the relay actuator sketch in order to turn the relay on for about .5 seconds then turn it immediately back off?

    /**
     * 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-2015 Sensnology AB
     * Full contributor list: https://github.com/mysensors/Arduino/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_NRF24
    //#define MY_RADIO_RFM69
    
    // Enable repeater functionality for this node
    #define MY_REPEATER_FEATURE
    
    #include <MySensors.h>
    
    #define RELAY_1  3  // 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_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", "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_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(message.sensor-1+RELAY_1, message.getBool()?RELAY_ON:RELAY_OFF);
            // Store state in eeprom
            saveState(message.sensor, message.getBool());
            // Write some debug info
            Serial.print("Incoming change for sensor:");
            Serial.print(message.sensor);
            Serial.print(", New status: ");
            Serial.println(message.getBool());
        }
    }
    

  • Mod

    @drradkin change

            digitalWrite(message.sensor-1+RELAY_1, message.getBool()?RELAY_ON:RELAY_OFF);
    

    to

    if (message.getBool() == RELAY_ON) {
    digitalWrite(message.sensor-1+RELAY_1, RELAY_ON);
    wait(500);
    digitalWrite(message.sensor-1+RELAY_1, RELAY_OFF);
    }
    

    and

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

    to

    if (loadState(sensor) == RELAY_ON) {
    digitalWrite(pin, RELAY_ON);
    wait(500);
    digitalWrite(pin, RELAY_OFF);
    }
    


  • @mfalkvidd Hello, today I used your suggestion, but in the meanwhile the code of RelayActuator.ino has changed a little bit.
    So this is what has changed and how I adjusted. This could be useful to another beginner like me.

    Change:

    digitalWrite(message.getSensor()-1+RELAY_PIN, message.getBool()?RELAY_ON:RELAY_OFF);
    

    to:

    if (message.getBool() == RELAY_ON) {
        digitalWrite(message.getSensor()-1+RELAY_PIN, RELAY_ON);
        wait(500);
        digitalWrite(message.getSensor()-1+RELAY_PIN, RELAY_OFF);
        }
    

  • Plugin Developer

    Here is my code, which I used to hack my dishwasher so I can turn it on via my smart home system. The code is designed to work well with the Mozilla WebThings gateway and the Candle project, which is based on MySensors. But it but should work just fine with any smart home controller that supports MySensors.

    /**
     * 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-2015 Sensnology AB
     * Full contributor list: https://github.com/mysensors/Arduino/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
     * 
     * 
     * 
     * Only sends a quick pulse via a relay. Useful to hack other devices with push 
     * buttons. In my case, a cheap IKEA dishwasher that didn't have a timer functionality.
     */
    
    // Enable debug prints to serial monitor
    #define DEBUG
    #define MY_DEBUG
    
    #define LOOP_DURATION 1000                          // The main loop runs every x milliseconds. This main loop starts the modem, and from then on periodically requests the password.
    #define SECONDS_BETWEEN_HEARTBEAT_TRANSMISSION 120  // The smart lock might not send any data for a very long time if it isn't used. Sending a heartbeat tells the controller: I'm still there.
    
    //#define RF_NANO                                     // RF-Nano. Check this box if you are using the RF-Nano Arduino, which has a built in radio. The Candle project uses the RF-Nano.
    
    
    
    
    #ifdef RF_NANO
    // If you are using an RF-Nano, you have to switch CE and CS pins.
    #define MY_RF24_CS_PIN 9                            // Used by the MySensors library.
    #define MY_RF24_CE_PIN 10                           // Used by the MySensors library.
    #endif
    
    // Enable and select radio type attached
    #define MY_RADIO_RF24
    #define MY_RF24_PA_LEVEL RF24_PA_MAX  
    //#define MY_RADIO_RFM69
    
    // Mysensors advanced settings
    #define MY_TRANSPORT_WAIT_READY_MS 10000            // Try connecting for 10 seconds. Otherwise just continue.
    //#define MY_RF24_CHANNEL 100                       // In EU the default channel 76 overlaps with wifi, so you could try using channel 100. But you will have to set this up on every device, and also on the controller.
    //#define MY_RF24_DATARATE RF24_1MBPS                 // Slower datarate makes the network more stable
    //#define MY_RF24_DATARATE RF24_250KBPS             // Slower datarate increases wireless range
    //#define MY_NODE_ID 10                             // Giving a node a manual ID can in rare cases fix connection issues.
    //#define MY_PARENT_NODE_ID 0                       // Fixating the ID of the gatewaynode can in rare cases fix connection issues.
    //#define MY_PARENT_NODE_IS_STATIC                  // Used together with setting the parent node ID. Daking the controller ID static can in rare cases fix connection issues.
    #define MY_SPLASH_SCREEN_DISABLED                   // Saves a little memory.
    //#define MY_DISABLE_RAM_ROUTING_TABLE_FEATURE      // Saves a little memory.
    
    // Mysensors security
    //#define DEBUG_SIGNING
    //#define MY_ENCRYPTION_SIMPLE_PASSWD "changeme"      // Be aware, the length of the password has an effect on memory use.
    //#define MY_SECURITY_SIMPLE_PASSWD "changeme"      // Be aware, the length of the password has an effect on memory use.
    //#define MY_SIGNING_SOFT_RANDOMSEED_PIN A7         // Setting a pin to pickup random electromagnetic noise helps make encryption more secure.
    
    
    // Enable repeater functionality for this node
    //#define MY_REPEATER_FEATURE
    
    #include <MySensors.h>
    
    #define RELAY_1  3  // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
    #define NUMBER_OF_RELAYS 1 // Total number of attached relays
    #define RELAY_ON 1  // GPIO value to write to turn on attached relay
    #define RELAY_OFF 0 // GPIO value to write to turn off attached relay
    #define PULSELENGTH 500 // How long the pulse should last (how long the button should be pressed).
    #define RADIO_DELAY 100                             // Milliseconds delay betweeen radio signals. This gives the radio some breathing room.
    
    MyMessage relay_message(RELAY_1, V_STATUS); // A generic boolean state message.
    
    
    boolean desiredState = false;
    boolean send_all_values = 1;
    
    
    void before()
    {
      pinMode(RELAY_1, OUTPUT);
    	digitalWrite(RELAY_1, LOW);
    }
    
    void presentation()
    {
    	// Send the sketch version information to the gateway and Controller
    	sendSketchInfo(F("Dish washer"), F("1.0")); wait(RADIO_DELAY);
      present(RELAY_1, S_BINARY, F("Power") ); wait(RADIO_DELAY);
      
      send_all_values = true;                           // Whenever a new presentation is requested, we should also send the current values of the children.
    }
    
    void setup()
    {
      Serial.begin(115200);
      Serial.println(F("Hello world, I am a relay."));
    }
    
    void send_values()
    {
    #ifdef DEBUG
      Serial.println(F("Sending button states"));
    #endif
      send(relay_message.set(desiredState)); wait(RADIO_DELAY); // Send initial state
    }
    
    
    void loop()
    {
      if( send_all_values ){
    #ifdef DEBUG
        Serial.println(F("RESENDING VALUES"));
    #endif
        send_all_values = 0;
        send_values();
      }
    
    
    
      // Pulse the relay
      if(desiredState == 1){
        digitalWrite(RELAY_1, RELAY_ON);
        Serial.println(F("Turning on"));
        wait(PULSELENGTH);
        digitalWrite(RELAY_1, RELAY_OFF);
        Serial.println(F("Turned off"));
        
        desiredState = 0;
        send(relay_message.setSensor(RELAY_1).set(desiredState)); // Send off state
      }
    
    
    
      static unsigned long last_loop_time = 0;          // Holds the last time the main loop ran.
      static byte loop_counter = 0;                     // Count how many loops have passed (reset to 0 after at most 254 loops).
    
      if( millis() - last_loop_time > LOOP_DURATION ){ // Runs every second
        last_loop_time = millis();
    
        wdt_reset();                                  // Reset the watchdog timer. If this doesn't happen, the device must have crashed, and it will be automatically rebooted by the watchdog.
    
        if( loop_counter >= SECONDS_BETWEEN_HEARTBEAT_TRANSMISSION ){ // If a couple of minutes have passed, tell the controller we're still here
          loop_counter = 0;
          Serial.println(F("Sending heartbeat"));
          sendHeartbeat();
        }
      }
    
    }
    
    void receive(const MyMessage &message)
    {
      if( message.isAck() ){
    #ifdef DEBUG
        Serial.println(F("- Echo"));
    #endif
      }
      else if (message.type==V_STATUS) { // We only expect one type of message from controller. But we better check anyway.
    
        Serial.print("Incoming change for child:");
        Serial.print(message.sensor);
        Serial.print(", New status: ");
        Serial.println(message.getBool());
    
        // Change relay state
        desiredState = message.getBool(); //?RELAY_ON:RELAY_OFF;
        send(relay_message.setSensor(message.sensor).set(desiredState)); // Send on state
      }
    }
    


  • Morning all,

    I'm smashing together 3 types of sketches here (3 x Dimmer, 4 x Button, 2 x relay) and am struggling with this 'momentary' relay action. The relays do not fire at all.

    Everything is presented to the controller (Openhab) via an RS485 gateway, and the dimmer and buttons work and feedback their states. The log output shows that this device is receiving a 0 and 1 from Openhab on its relay nodes (7 and 😎 however, still no actuation.

    I wonder if someone was able to take a cursery glance at my code. The relay sections of code are bracketed with // 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-2015 Sensnology AB
     * Full contributor list: https://github.com/mysensors/Arduino/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 - February 15, 2014 - Bruce Lacey
     * Version 1.1 - August 13, 2014 - Converted to 1.4 (hek)
     *
     * DESCRIPTION
     * This sketch provides a Dimmable LED Light using PWM and based Henrik Ekblad
     * <henrik.ekblad@gmail.com> Vera Arduino Sensor project.
     * Developed by Bruce Lacey, inspired by Hek's MySensor's example sketches.
     *
     * The circuit uses a MOSFET for Pulse-Wave-Modulation to dim the attached LED or LED strip.
     * The MOSFET Gate pin is connected to Arduino pin 3 (LED_PIN), the MOSFET Drain pin is connected
     * to the LED negative terminal and the MOSFET Source pin is connected to ground.
     *
     */
    // Button
    // The below includes 4 buttons using code examples from here:  https://forum.mysensors.org/topic/9538/multiple-switch-inputs/8
    // Button
    
    // Relay
    // The below includes 2 relays from https://www.mysensors.org/build/relay
    // https://forum.mysensors.org/topic/5906/relay-actuator-with-momentary-pulse-action/2
    // 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 RS485 transport layer
    #define MY_RS485
    
    // Define this to enables DE-pin management on defined pin
    #define MY_RS485_DE_PIN 2
    
    // Set RS485 baud rate to use
    #define MY_RS485_BAUD_RATE 9600
    
    #define MY_NODE_ID 4 
    
    #include <SPI.h>
    #include <MySensors.h> 
    
    // Button
    #include <Bounce2.h>
    //
    
    #define SN "N004"
    #define SV "1.0"
    
    #define noLEDs 2
    const int LED_Pin[] = {5, 6}; 
    
    #define FADE_DELAY 10  // Delay in ms for each percentage fade up/down (10ms = 1s full-range dim)
    
    static int currentLevel1 = 0;  // Current dim level...
    static int currentLevel2 = 0;  // Current dim level...
    
    MyMessage dimmer1Msg(1, V_DIMMER);
    MyMessage light1Msg(1, V_LIGHT);
    MyMessage dimmer2Msg(2, V_DIMMER);
    MyMessage light2Msg(2, V_LIGHT);
    
    // Button
    #define FIRST_BUTTON_ID 3
    #define MAX_BUTTON 4 
    const uint8_t buttonPin[] = {4, 10, 11, 12};   //  switch around pins to your desire
    Bounce debouncer[MAX_BUTTON];
    MyMessage buttonMsg(0, V_TRIPPED);
    bool oldButton[MAX_BUTTON] = {false};
    // Button
    
    
    // Relay
    #define FIRST_RELAY_ID 7
    #define MAX_RELAY 2
    const uint8_t relayPin[] = {3, 7};  // Pins of relays
    
    MyMessage relayMsg(0, V_STATUS);
    
    
    #define RELAY_ON 1
    #define RELAY_OFF 0
    // Relay
    
    
    void before()
    {
      
    }
    
    /***
     * Dimmable LED initialization method
     */
    void setup()  
    { 
      // LEDS
      // Pull the gateway's current dim level - restore light level upon sendor node power-up
    for (int sensor=1; sensor<=noLEDs; sensor++){
      request( sensor, V_DIMMER );
     }
    // Button
    for (uint8_t i = 0; i < MAX_BUTTON; i++) {
        debouncer[i] = Bounce();                        // initialize debouncer
        debouncer[i].attach(buttonPin[i], INPUT_PULLUP);
        debouncer[i].interval(5);
        oldButton[i] =  debouncer[i].read();
      }
    // Button
    
    
    // Relay
    for (uint8_t i = 0; i < MAX_RELAY; i++) {
      pinMode(relayPin[i], OUTPUT);
      //digitalWrite(relayPin, loadState(i)?RELAY_ON:RELAY_OFF);
      if (loadState(i) == RELAY_ON) {
    digitalWrite(relayPin, RELAY_ON);
    wait(500);
    digitalWrite(relayPin, RELAY_OFF);
    }
    }
    // Relay
    }
    
    void presentation() {
      // Register the LED Dimmable Light with the gateway
     for (int sensor=1; sensor<=noLEDs; sensor++){
     present(sensor, S_DIMMER);
     wait(2);
     }
    
    // Button
     for (int i = 0; i < MAX_BUTTON; i++) { //i < numSensors &&
        present(FIRST_BUTTON_ID + i, S_DOOR);
      }
     // Button
    
    // Relay
    for (int i = 0; i < MAX_RELAY; i++)   {
      present(FIRST_RELAY_ID + i, S_BINARY);
    }
    // Relay
    
      sendSketchInfo(SN, SV);
    }
    
    /***
     *  Dimmable LED main processing loop 
     */
    void loop() 
    {
    
    // Button
      bool button[MAX_BUTTON];
      for (uint8_t i = 0; i < MAX_BUTTON; i++) {
        debouncer[i].update();
        button[i] = debouncer[i].read();
        if (button[i] != oldButton[i]) {
          send(buttonMsg.setSensor(FIRST_BUTTON_ID + i).set( button[i])); // Send tripped value to gw
          oldButton[i] = button[i];
        }
      } 
      // Button
    
    }
    
    
    
    void receive(const MyMessage &message) {
      if (message.type == V_LIGHT || message.type == V_DIMMER) {
    
        if (message.sensor == 1) {
    
         //  Retrieve the power or dim level from the incoming request message
        int requestedLevel1 = atoi( message.data );
        
        // Adjust incoming level if this is a V_LIGHT variable update [0 == off, 1 == on]
        requestedLevel1 *= ( message.type == V_LIGHT ? 100 : 1 );
        
        // Clip incoming level to valid range of 0 to 100
        requestedLevel1 = requestedLevel1 > 100 ? 100 : requestedLevel1;
        requestedLevel1 = requestedLevel1 < 0   ? 0   : requestedLevel1;
    
          
         fadeToLevel1( requestedLevel1, message.sensor );
        send(light1Msg.set(currentLevel1 > 0 ? 1 : 0)); 
        send(dimmer1Msg.set(currentLevel1) );}
       
        
        
         
       if (message.sensor == 2) {
       //  Retrieve the power or dim level from the incoming request message
        int requestedLevel2 = atoi( message.data );
        
        // Adjust incoming level if this is a V_LIGHT variable update [0 == off, 1 == on]
        requestedLevel2 *= ( message.type == V_LIGHT ? 100 : 1 );
        
        // Clip incoming level to valid range of 0 to 100
        requestedLevel2 = requestedLevel2 > 100 ? 100 : requestedLevel2;
        requestedLevel2 = requestedLevel2 < 0   ? 0   : requestedLevel2;
        
        fadeToLevel2( requestedLevel2, message.sensor );
        send(light2Msg.set(currentLevel2 > 0 ? 1 : 0));
        send(dimmer2Msg.set(currentLevel2) );}
         
    
        }
    
    // Relay
      if (message.type == V_STATUS) {
    
        if (message.sensor == 7)  {
          if (message.getBool() == RELAY_ON) {
            digitalWrite(message.getSensor()-1+relayPin, RELAY_ON);
            wait(500);
            digitalWrite(message.getSensor()-1+relayPin, RELAY_OFF);
          }
        saveState(message.sensor, message.getBool());
        }
        
        
        if (message.sensor == 8)  {
          if (message.getBool() == RELAY_ON) {
            digitalWrite(message.getSensor()-1+relayPin, RELAY_ON);
            wait(500);
            digitalWrite(message.getSensor()-1+relayPin, RELAY_OFF);
          }
          
        }
      }
    
    
    // Relay
        
    }
    
    /***
     *  This method provides a graceful fade up/down effect
     */
    void fadeToLevel1( int toLevel1, int ledid1 ) {
    
      int delta1 = ( toLevel1 - currentLevel1 ) < 0 ? -1 : 1;
      
      while ( currentLevel1 != toLevel1 ) {
        currentLevel1 += delta1;
        analogWrite(LED_Pin[ledid1-1], (int)(currentLevel1 / 100. * 255) );
        wait( FADE_DELAY );
      }
    }
    void fadeToLevel2( int toLevel2, int ledid2 ) {
    
      int delta2 = ( toLevel2 - currentLevel2 ) < 0 ? -1 : 1;
      
      while ( currentLevel2 != toLevel2 ) {
        currentLevel2 += delta2;
        analogWrite(LED_Pin[ledid2-1], (int)(currentLevel2 / 100. * 255) );
        wait( FADE_DELAY );
      }
    }
    


  • @adds666 In receive(), note how you use relayPin:

      if (message.type == V_STATUS) {
    
        if (message.sensor == 7)  {
          if (message.getBool() == RELAY_ON) {
            digitalWrite(message.getSensor()-1+relayPin, RELAY_ON);
    

    relayPin is an array (const uint8_t relayPin[] = {3, 7};). If you use it without specifying an index, like you do here, you get a pointer to the first element, not the value of an element.

    Something like digitalWrite(relayPin[message.getSensor()-7], RELAY_ON) should work here. getSensor() returns 7, because you already checked for that two lines above. 7 - 7 = 0, which results in relayPin[0] and toggles the relay on pin 3.

    Also, note that you load the current relay state from EEPROM positions 0 and 1 in setup():

    for (uint8_t i = 0; i < MAX_RELAY; i++) {
      pinMode(relayPin[i], OUTPUT);
      //digitalWrite(relayPin, loadState(i)?RELAY_ON:RELAY_OFF);
      if (loadState(i) == RELAY_ON) {
    

    But you save the state to byte 7 in receive():

    saveState(message.sensor, message.getBool());
    

    Hope this helps you out!



  • @BearWithBeard said in Relay Actuator with momentary (pulse) action:

    digitalWrite(relayPin[message.getSensor()-7], RELAY_ON)

    Many thanks for coming back @BearWithBeard, its a huge help.
    So my logic for correcting the State problem at the bottom would be to do the same calculation to get them in to 0 and 1.

    saveState(message.getSensor()-7, message.getBool());
    

    Compiled correctly and then uploaded and it works! Fantastic. The following sketch has 3 dimmers, 4 buttons and 2 relay outputs.

    Thank you very much - I'm learning 😉

    /**
     * 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-2015 Sensnology AB
     * Full contributor list: https://github.com/mysensors/Arduino/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 - February 15, 2014 - Bruce Lacey
     * Version 1.1 - August 13, 2014 - Converted to 1.4 (hek)
     *
     * DESCRIPTION
     * This sketch provides a Dimmable LED Light using PWM and based Henrik Ekblad
     * <henrik.ekblad@gmail.com> Vera Arduino Sensor project.
     * Developed by Bruce Lacey, inspired by Hek's MySensor's example sketches.
     *
     * The circuit uses a MOSFET for Pulse-Wave-Modulation to dim the attached LED or LED strip.
     * The MOSFET Gate pin is connected to Arduino pin 3 (LED_PIN), the MOSFET Drain pin is connected
     * to the LED negative terminal and the MOSFET Source pin is connected to ground.
     *
     */
    // Button
    // The below includes 4 buttons using code examples from here:  https://forum.mysensors.org/topic/9538/multiple-switch-inputs/8
    // Button
    
    // Relay
    // The below includes 2 relays from https://www.mysensors.org/build/relay
    // https://forum.mysensors.org/topic/5906/relay-actuator-with-momentary-pulse-action/2
    // 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 RS485 transport layer
    #define MY_RS485
    
    // Define this to enables DE-pin management on defined pin
    #define MY_RS485_DE_PIN 2
    
    // Set RS485 baud rate to use
    #define MY_RS485_BAUD_RATE 9600
    
    #define MY_NODE_ID 4 
    
    #include <SPI.h>
    #include <MySensors.h> 
    
    // Button
    #include <Bounce2.h>
    //
    
    #define SN "N004"
    #define SV "1.0"
    
    #define noLEDs 2
    const int LED_Pin[] = {5, 6}; 
    
    #define FADE_DELAY 10  // Delay in ms for each percentage fade up/down (10ms = 1s full-range dim)
    
    static int currentLevel1 = 0;  // Current dim level...
    static int currentLevel2 = 0;  // Current dim level...
    
    MyMessage dimmer1Msg(1, V_DIMMER);
    MyMessage light1Msg(1, V_LIGHT);
    MyMessage dimmer2Msg(2, V_DIMMER);
    MyMessage light2Msg(2, V_LIGHT);
    
    // Button
    #define FIRST_BUTTON_ID 3
    #define MAX_BUTTON 4 
    const uint8_t buttonPin[] = {4, 10, 11, 12};   //  switch around pins to your desire
    Bounce debouncer[MAX_BUTTON];
    MyMessage buttonMsg(0, V_TRIPPED);
    bool oldButton[MAX_BUTTON] = {false};
    // Button
    
    
    // Relay
    #define FIRST_RELAY_ID 7
    #define MAX_RELAY 2
    const uint8_t relayPin[] = {3, 7};  // Pins of relays
    
    MyMessage relayMsg(0, V_STATUS);
    
    
    #define RELAY_ON 1
    #define RELAY_OFF 0
    // Relay
    
    
    void before()
    {
      
    }
    
    /***
     * Dimmable LED initialization method
     */
    void setup()  
    { 
      // LEDS
      // Pull the gateway's current dim level - restore light level upon sendor node power-up
    for (int sensor=1; sensor<=noLEDs; sensor++){
      request( sensor, V_DIMMER );
     }
    // Button
    for (uint8_t i = 0; i < MAX_BUTTON; i++) {
        debouncer[i] = Bounce();                        // initialize debouncer
        debouncer[i].attach(buttonPin[i], INPUT_PULLUP);
        debouncer[i].interval(5);
        oldButton[i] =  debouncer[i].read();
      }
    // Button
    
    
    // Relay
    for (uint8_t i = 0; i < MAX_RELAY; i++) {
      pinMode(relayPin[i], OUTPUT);
      //digitalWrite(relayPin, loadState(i)?RELAY_ON:RELAY_OFF);
      if (loadState(i) == RELAY_ON) {
    digitalWrite(relayPin, RELAY_ON);
    wait(500);
    digitalWrite(relayPin, RELAY_OFF);
    }
    }
    // Relay
    }
    
    void presentation() {
      // Register the LED Dimmable Light with the gateway
     for (int sensor=1; sensor<=noLEDs; sensor++){
     present(sensor, S_DIMMER);
     wait(2);
     }
    
    // Button
     for (int i = 0; i < MAX_BUTTON; i++) { //i < numSensors &&
        present(FIRST_BUTTON_ID + i, S_DOOR);
      }
     // Button
    
    // Relay
    for (int i = 0; i < MAX_RELAY; i++)   {
      present(FIRST_RELAY_ID + i, S_BINARY);
    }
    // Relay
    
      sendSketchInfo(SN, SV);
    }
    
    /***
     *  Dimmable LED main processing loop 
     */
    void loop() 
    {
    
    // Button
      bool button[MAX_BUTTON];
      for (uint8_t i = 0; i < MAX_BUTTON; i++) {
        debouncer[i].update();
        button[i] = debouncer[i].read();
        if (button[i] != oldButton[i]) {
          send(buttonMsg.setSensor(FIRST_BUTTON_ID + i).set( button[i])); // Send tripped value to gw
          oldButton[i] = button[i];
        }
      } 
      // Button
    
    }
    
    
    
    void receive(const MyMessage &message) {
      if (message.type == V_LIGHT || message.type == V_DIMMER) {
    
        if (message.sensor == 1) {
    
         //  Retrieve the power or dim level from the incoming request message
        int requestedLevel1 = atoi( message.data );
        
        // Adjust incoming level if this is a V_LIGHT variable update [0 == off, 1 == on]
        requestedLevel1 *= ( message.type == V_LIGHT ? 100 : 1 );
        
        // Clip incoming level to valid range of 0 to 100
        requestedLevel1 = requestedLevel1 > 100 ? 100 : requestedLevel1;
        requestedLevel1 = requestedLevel1 < 0   ? 0   : requestedLevel1;
    
          
         fadeToLevel1( requestedLevel1, message.sensor );
        send(light1Msg.set(currentLevel1 > 0 ? 1 : 0)); 
        send(dimmer1Msg.set(currentLevel1) );}
       
        
        
         
       if (message.sensor == 2) {
       //  Retrieve the power or dim level from the incoming request message
        int requestedLevel2 = atoi( message.data );
        
        // Adjust incoming level if this is a V_LIGHT variable update [0 == off, 1 == on]
        requestedLevel2 *= ( message.type == V_LIGHT ? 100 : 1 );
        
        // Clip incoming level to valid range of 0 to 100
        requestedLevel2 = requestedLevel2 > 100 ? 100 : requestedLevel2;
        requestedLevel2 = requestedLevel2 < 0   ? 0   : requestedLevel2;
        
        fadeToLevel2( requestedLevel2, message.sensor );
        send(light2Msg.set(currentLevel2 > 0 ? 1 : 0));
        send(dimmer2Msg.set(currentLevel2) );}
         
    
        }
    
    // Relay
      if (message.type == V_STATUS) {
    
        if (message.sensor == 7)  {
          if (message.getBool() == RELAY_ON) {
            //digitalWrite(message.getSensor()-1+relayPin, RELAY_ON);
            digitalWrite(relayPin[message.getSensor()-7], RELAY_ON);
            wait(500);
            //digitalWrite(message.getSensor()-1+relayPin, RELAY_OFF);
            digitalWrite(relayPin[message.getSensor()-7], RELAY_OFF);
          }
        saveState(message.getSensor()-7, message.getBool());
        }
        
        
        if (message.sensor == 8)  {
          if (message.getBool() == RELAY_ON) {
            //digitalWrite(message.getSensor()-1+relayPin, RELAY_ON);
            digitalWrite(relayPin[message.getSensor()-7], RELAY_ON);
            wait(500);
            //digitalWrite(message.getSensor()-1+relayPin, RELAY_OFF);
            digitalWrite(relayPin[message.getSensor()-7], RELAY_OFF);
          }
        saveState(message.getSensor()-7, message.getBool());  
        }
      }
    
    
    // Relay
        
    }
    
    /***
     *  This method provides a graceful fade up/down effect
     */
    void fadeToLevel1( int toLevel1, int ledid1 ) {
    
      int delta1 = ( toLevel1 - currentLevel1 ) < 0 ? -1 : 1;
      
      while ( currentLevel1 != toLevel1 ) {
        currentLevel1 += delta1;
        analogWrite(LED_Pin[ledid1-1], (int)(currentLevel1 / 100. * 255) );
        wait( FADE_DELAY );
      }
    }
    void fadeToLevel2( int toLevel2, int ledid2 ) {
    
      int delta2 = ( toLevel2 - currentLevel2 ) < 0 ? -1 : 1;
      
      while ( currentLevel2 != toLevel2 ) {
        currentLevel2 += delta2;
        analogWrite(LED_Pin[ledid2-1], (int)(currentLevel2 / 100. * 255) );
        wait( FADE_DELAY );
      }
    }
    

Log in to reply
 

Suggested Topics

2
Online

11.4k
Users

11.1k
Topics

112.7k
Posts