• RE: ESP32 + Signing fails after xxx msg as result of memory leak

    @Technovation It take the blame 🙂
    Thanks for reporting, PR submitted.

    (The debug message is correct; msg contains the incoming nonce request => the sender is the recipient of the nonce response)

    https://github.com/mysensors/MySensors/pull/1402

    posted in Bug Reports
  • X27 stepper motor that can be controlled from the Arduino directly

    Here is some code to manage an X27 stepper motor. These are commonly found behind a gauge in car dashboards.

    Because this type of stepper motor uses very little power, an Arduino can operate the stepper motor directly (video), by pulsing the coils.

    The idea is that it can act as a dashboard for certain values in the smart home.

    /*
     * DESCRIPTION
     * 
     * This device can toggle two relays, and thus two electric locks. These relays can be controlled via the Candle Controller, but also via SMS (if you want).
     * The SMS function is password protected: you have to send a password to switch the relay. Access can also be limited to only certain mobile phone numbers, and only certain moments (by toggling the Mobile control switch).
     * 
     * If you send an SMS without the password, it will be shown as the Incoming SMS. This can be used to automate other things in your home. For example, you could create a rule that when the system receices an SMS with "purifier on" in it, the air purifier will turn on.
     * 
     * This way you can control smart devices in your home even if it/Candle is not connected to the internet.
     * 
     * If data transmission is disabled, you can change the state of the lock via SMS or the pushbutton without the new state being sent to the controller.
     * 
     * SETTINGS */ 
    
    #define CLOCKWISE                                   // Rotate clockwise. As values increase, the indicator needle will move clockwise. To make the needle move counter clockwise as values increase, uncheck this.
    
    #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.
    
    /* END OF SETTINGS
     *  
     *  
    */
    
    
    
    // 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.
    
    
    
    #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 ROTATION_CHILD_ID  3                        // Child ID for the actual rotation input
    #define LOWER_BOUNDARY_ID  4                        // Child ID for the lower boundary value. Starts as 0%
    #define UPPER_BOUNDARY_ID  5                        // Child ID for the upper boundary value. Starts as 100%
    
    
    #define RADIO_DELAY 100                             // Milliseconds delay betweeen radio signals. This gives the radio some breathing room.
    
    MyMessage percentage_message(ROTATION_CHILD_ID, V_PERCENTAGE); // A generic boolean state message.
    
    boolean send_all_values = 1;
    
    int percentage = 0;
    int previous_percentage = 0;
    int lower_boundary = 0;
    int upper_boundary = 100;
    
    
    // STEPPER
    #include <Stepper.h>
    #define  STEPS  720                                 // steps per revolution (limited to 315°)
    #define  STEPPER_1  3
    #define  STEPPER_2  4
    #define  STEPPER_3  5
    #define  STEPPER_4  6
    
    
    // create an instance of the stepper class:
    Stepper stepper(STEPS, STEPPER_1, STEPPER_2, STEPPER_3, STEPPER_4);
    
    int pos = 0;                                        //Position in steps(0-630)= (0°-315°)
    int val = 0;
    
    
    void before()
    {
      pinMode(STEPPER_1, OUTPUT);
      pinMode(STEPPER_2, OUTPUT);
      pinMode(STEPPER_3, OUTPUT);
      pinMode(STEPPER_4, OUTPUT);
    }
    
    
    void presentation()
    {
    	// Send the sketch version information to the gateway and Controller
    	sendSketchInfo(F("Gauge"), F("1.0")); wait(RADIO_DELAY);
      present(ROTATION_CHILD_ID, S_DIMMER, F("Rotation") ); wait(RADIO_DELAY);
      present(LOWER_BOUNDARY_ID, S_DIMMER, F("Lower boundary") ); wait(RADIO_DELAY);
      present(UPPER_BOUNDARY_ID, S_DIMMER, F("Upper boundary") ); 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 gauge."));
    
      stepper.setSpeed(30);    // set the motor speed to 30 RPM (360 PPS aprox.).
      stepper.step(630);       // Reset Position(630 steps counter-clockwise). 
    
    
      if( loadState(LOWER_BOUNDARY_ID) <= 100 ){
        lower_boundary = loadState(LOWER_BOUNDARY_ID);
        Serial.print(F("Loaded lower boundary from eeprom: ")); Serial.println(lower_boundary);
      }
      if( loadState(UPPER_BOUNDARY_ID) <= 100 ){
        
        upper_boundary = loadState(UPPER_BOUNDARY_ID);
        Serial.print(F("Loaded upper boundary from eeprom: ")); Serial.println(upper_boundary);
      }
    
      //percentage = loadState(ROTATION_CHILD_ID);
      //if( percentage > 100 ){ percentage = 100; }
      //if( percentage < 0 ){ percentage = 0; } // not really possible
    
      //Serial.println(F("Sending initial percentage"));
      //send(percentage_message.setSensor(ROTATION_CHILD_ID).set(percentage),1); wait(RADIO_DELAY); // Send initial state
    }
    
    void send_values()
    {
    #ifdef DEBUG
      Serial.println(F("Sending values and states"));
    #endif
      send(percentage_message.setSensor(ROTATION_CHILD_ID).set(percentage)); wait(RADIO_DELAY); // Send initial state
      send(percentage_message.setSensor(LOWER_BOUNDARY_ID).set(lower_boundary)); wait(RADIO_DELAY); // Send initial state
      send(percentage_message.setSensor(UPPER_BOUNDARY_ID).set(upper_boundary)); wait(RADIO_DELAY); // Send initial state
    
      send_all_values = 0;
    }
    
    
    void loop()
    {
      if( send_all_values ){
    #ifdef DEBUG
        Serial.println(F("RESENDING VALUES"));
    #endif
        send_values();
      }
    
    
    
      if( percentage != previous_percentage ){
        previous_percentage = percentage;
        Serial.print(F("Percentage changed to: ")); Serial.println(percentage);
        send(percentage_message.setSensor(ROTATION_CHILD_ID).set(percentage)); // Send on state
        //saveState(ROTATION_CHILD_ID, percentage);
    
    #ifdef CLOCKWISE
        val = map(percentage,lower_boundary,upper_boundary,0,630);    // map pot range in the stepper range.
    #else
        val = map(percentage,lower_boundary,upper_boundary,630,0);    // map pot range in the stepper range.
    #endif
    
        
        Serial.print(F("New val: "));
        Serial.println( val );
        //wait(500);
      }
    
    
    
      // Move the stepper needle
      if( abs(val - pos) > 2 ){         // if difference is greater than 2 steps.
          if( (val - pos) > 0 ){
              stepper.step(-1);      // move one step to the left.
              pos++;
              }
          if((val - pos) < 0){
              stepper.step(1);       // move one step to the right.
              pos--;
              }
          }
    
    
    
    
    
    
      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();
        loop_counter++;
        
        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;
    #ifdef DEBUG
          Serial.println(F("Sending heartbeat"));
    #endif
          sendHeartbeat();
        }
      }
    }
    
    
    
    void receive(const MyMessage &message)
    {
      Serial.print(F(">> Incoming message of type ")); Serial.print(message.type);
      Serial.print(F(" for child:")); Serial.println(message.sensor);
      
      if( message.isAck() ){
    #ifdef DEBUG
        Serial.println(F("- Echo"));
    #endif
      }
      else if( message.sensor==ROTATION_CHILD_ID ){
        percentage = message.getInt();
    
        //Serial.print(", type:");
        //Serial.print(message.type);    
        //Serial.print(", New value: ");
        //Serial.println( percentage );
        
      }
      else if( message.sensor==LOWER_BOUNDARY_ID ){                // We only expect one type of message from controller. But we better check anyway.
        lower_boundary = message.getInt();
        saveState(LOWER_BOUNDARY_ID, lower_boundary);
      }
      else if( message.sensor==UPPER_BOUNDARY_ID ){                // We only expect one type of message from controller. But we better check anyway.
        upper_boundary = message.getInt();
        saveState(UPPER_BOUNDARY_ID, upper_boundary);
      }
    }
    
    
    
    /**
     * 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.
     * 
     */
    

    During my testing I noticed that at a certain time the Arduino Nano's USB chip stopped working, so I suspect there is too much kickback from the stepper anyway. Turns out the USB cable broke. It still works fine.

    In theory there's a library out there that works better than using the standard stepper library. But I wasn't able to find it. There is a library for the X25 that might work, but I haven't tried it. But I haven't gotten it to work properly.

    As an alternative, you could use normal small servo's that the Arduino can also operate without requiring a motor control chip. But that's a lot more noisy. It does have a lot more power though.

    I put the code here in case someone wants to play around with it. For those interested, there is also an open source board to make these gauges more robust by adding protective diodes.

    posted in My Project
  • RE: Moisture sensing + relay. Please help with software.

    Here is some code that does exactly what was asked for:
    https://github.com/createcandle/Devices/tree/master/Plant_health

    posted in Troubleshooting
  • Receiver that creates details about data transmission errors

    Based on the example code by @mfalkvidd I created a USB serial receiver that outputs data about network errors.

    mysensors_network_errors.png
    The top line shows the good transmissions, the bottom one shows the bad ones.

    candle_receiver_issues_close_up.png
    Close-up

    I was surprised to see so many errors.

    • What could this be?
    • How could I find out what is causing this?

    Also, how can I understand these values? Does a transmission error mean that an incoming message failed? Or an outgoing message? How does MySensors determine what an error is? Does an error mean the transmissions totally failed? because in practize the network seems to be ok.

    For those interested, here's my full code:

    * 
    * The Candle receiver acts as the bridge between the Candle devices and the Candle Controller. 
    * 
    * It only allows communication with other Candle devices that use the same encryption password as it uses itself. 
    * When you install the Candle Manager, a random password is generated for you. If you ever want to change the encryption password used by your network, this can be done in the Candle Manager settings. 
    * Be warned that you will have to re-create this receiver as well as all your devices, since they will all need to have new code with the new password in it.
    * 
    * If you have already installed the MySensors add-on, please temporarily disable it before creating this receiver. Otherwise the MySensors add-on may try to connect to it during the creation process, and thus disrupt it.
    * 
    *
    * SETTINGS */ 
    
    // You can enable and disable the settings below by adding or removing double slashes ( // ) in front of a line.
    
    //#define RF_NANO                                     // RF-Nano. Enable this if you are using the RF-Nano Arduino, which has a built in radio. The Candle project uses the RF-Nano.
    
    #define SHOW_TRANSMISSION_DETAILS                   // Show transmission details. If you enable this, the receiver will show you details about how many good transmission are made, as well as any transmission errors. This is updated every 5 minutes.
    
    /* END OF SETTINGS
    *
    *
    *
    */
    
    
    // Enable MySensors debug output to the serial monitor, so you can check if the radio is working ok.
    //#define MY_DEBUG 
    
    #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                               // MySensors supports multiple radio modules. Candle uses NRF24.
    //#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_MIN
    //#define MY_RF24_PA_LEVEL RF24_PA_LOW
    //#define MY_RF24_PA_LEVEL RF24_PA_HIGH
    #define MY_RF24_PA_LEVEL RF24_PA_MAX                // Sets the radio to transmit at maximum power, for optimum range.
    
    // Mysensors advanced security
    #define MY_ENCRYPTION_SIMPLE_PASSWD "changeme"      // The Candle Manager add-on will change this into the actual password your network uses.
    //#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.
    
    // Mysensors advanced settings
    //#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. You can even try 115.
    //#define MY_RF24_DATARATE RF24_250KBPS             // Slower datarate increases the range, but the RF-Nano does not support this slow speed.
    #define MY_RF24_DATARATE RF24_1MBPS                 // This datarate is supported by pretty much all NRF24 radios, including the RF-Nano.
    #define MY_SPLASH_SCREEN_DISABLED                   // Saves a little memory.
    
    // Enable serial gateway
    #define MY_GATEWAY_SERIAL                           // This is the main function of this code. It tells the MySensors library to turn this device into a gateway/receiver for MySensors network.
    
    
    #ifdef SHOW_TRANSMISSION_DETAILS
    // Report how often there are wireless communication issues
    #define MY_INDICATION_HANDLER
    unsigned int txOK = 0;                              // Good transmissions counter
    unsigned int txERR = 0;                             // Failed transmissions counter
    #define REPORT_INTERVAL 300000                      // Report every 5 minutes
    #define CHILD_ID_TX_OK 1                            // Child id for the counter of OK transmissions
    #define CHILD_ID_TX_ERR 2                           // Child id for the counter of failed transmissions
    #endif
    
    
    #include <MySensors.h>                              // The MySensors library, which takes care of creating the wireless network.
    #include <avr/wdt.h>                                // The watchdog timer - if the device becomes unresponsive and doesn't periodically reset the timer, then it will automatically reset once the timer reaches 0.
    
    // Clock for the watchdog
    #define INTERVAL 500                                // Every second we reset the watchdog timer. If the device freezes, the watchdog will not be reset, and the device will reboot.
    #define RADIO_DELAY 100                             // Milliseconds of delay between sending transmissions, this keeps the radio module happy.
    
    
    unsigned long current_time = 0;
    
    
    
    #ifdef SHOW_TRANSMISSION_DETAILS
    
    
    MyMessage transmission_quality_message(CHILD_ID_TX_OK, V_CUSTOM);
    
    void indication(indication_t ind)
    {
      switch (ind)
      {
        case INDICATION_TX:
          txOK++;
          break;
        case INDICATION_ERR_TX:
          txERR++;
          break;
      }
    }
    #endif
    
    
    
    void presentation()
    {
    #ifdef SHOW_TRANSMISSION_DETAILS
      sendSketchInfo(F("Candle receiver"), F("1.0"));
      present(CHILD_ID_TX_OK, S_CUSTOM, F("Good transmissions")); // Tell the controller about this property
      present(CHILD_ID_TX_ERR, S_CUSTOM,F("Bad transmissions")); // Tell the controller about this property
    #endif
    }
    
    
    
    void setup()
    {
      //Serial.println(F("Hello, I am a Candle receiver"));
    
      send(transmission_quality_message.setSensor(CHILD_ID_TX_OK).set(txOK)); // Send the good transmissions value
      send(transmission_quality_message.setSensor(CHILD_ID_TX_ERR).set(txERR)); // Send the failed transmissions value
    
      wdt_enable(WDTO_2S);                              // Starts the watchdog timer. If it is not reset at least once every 2 seconds, then the entire device will automatically restart.                                 
    }
    
    
    
    void loop()
    {
      static unsigned long previous_millis = 0;         // Used to run the internal clock
      current_time = millis();
      
      if( current_time - previous_millis >= INTERVAL ){ // Main loop, runs every second.
        previous_millis = current_time;                 // Store the current time as the previous measurement start time.
        wdt_reset();                                    // Reset the watchdog timer
        sendHeartbeat();                                // Tell the controller we're still connected.
      }
    
    #ifdef SHOW_TRANSMISSION_DETAILS
      static unsigned long last_send = 0;
      if( current_time - last_send >= REPORT_INTERVAL ){
        send(transmission_quality_message.setSensor(CHILD_ID_TX_OK).set(txOK)); // Send the good transmissions value
        send(transmission_quality_message.setSensor(CHILD_ID_TX_ERR).set(txERR)); // Send the failed transmissions value
        txOK = 0;                                       // Reset the good transmissions counter back to 0
        txERR = 0;                                      // Reset the error transmissions counter back to 0
        last_send = current_time;                       // Remember the time when the transmissions was done.
      }
    #endif
    
    }
    
    
    /**
    * 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-2018 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.
    */
    
    
    posted in General Discussion
  • RE: RF Nano = Nano + NRF24, for just $3,50 on Aliexpress

    @torfinn These settings should make it work, regardless of which version you buy:

    // 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.
    
    // Enable and select radio type attached
    #define MY_RADIO_RF24
    #define MY_RF24_PA_LEVEL RF24_PA_MAX
    
    // Mysensors advanced settings
    #define MY_RF24_DATARATE RF24_1MBPS                 // This datarate is supported by pretty much all NRF24 radios, including the RF-Nano.
    
    
    posted in Hardware
  • RE: Anyone tried the stc15l204? It appears to be an inexpensive integrated mcu + NRF24L01+

    It's not a perfect pin-out match. You should definitely check out this thread:
    https://forum.mysensors.org/topic/10327/rf-nano-nano-nrf24-for-just-3-50-on-aliexpress/1

    But you're right, it's great for beginners. That's why it forms the basis of the Candle project.

    posted in Hardware
  • RE: Anyone tried the stc15l204? It appears to be an inexpensive integrated mcu + NRF24L01+

    The RF-Nano may be what you're looking for? It's an inexpensive Nano with built in NRF24.

    posted in Hardware
  • RE: !MCO:PRO:RC=1 in debug logs

    Updated log parser to include RC debug messages: https://github.com/mysensors/MySensors/pull/1396

    tekka007 created this issue in mysensors/MySensors

    closed Update Log parser #1396

    posted in Troubleshooting
  • RE: !MCO:PRO:RC=1 in debug logs

    Ah, interesting, thanks for the explanation.

    posted in Troubleshooting
  • RE: Relay Actuator with momentary (pulse) action

    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
      }
    }
    
    posted in Troubleshooting