Virtual switches that never go off and controllers



  • For a project i'm working on i have converted a old 1950's phone into a doorbell/multiple switches.

    If i dail 3, for example it does a "send(msgDail_1.set(1));" This message is set up as S_BINARY and V_STATUS.

    In my experience some home automation software like Domotics doesnt like this very much as the switch never switches off. A simple solution can be to send a off command directly after the on command. This seems to be working most of the time, but sometime it seems a bit random. Maybe because the status is only high for a very low time.

    A normal switch would always have 2 states, or be pressed for several 100ms.

    A solution can be to add a "wait" for maybe 500ms. However i found that the "wait" function actually stops the Arduino from receiving input. Most of the time that wont be a problem, but i would like to get it working the right way. Both the send and wait function are in a "switch case" if it makes ant difference.

    Do you guys recognize this problem? How have you solved this?



  • The code so far....

    Another problem i have is in the "ringtone" in the last part of the code. It stops the whole code of the arduino while running. Is wait not a suitable function for this? or does this happen because its in a while loop?
    Are there better ways to solve this?

    /**
     * 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.
     *
     *******************************
     *
     * DESCRIPTION
     *
     * Simple binary switch example 
     * Connect button or door/window reed switch between 
     * digitial I/O pin 3 (button below) and GND.
     * http://www.mysensors.org/build/binary
     */
    
    /// ##### mysensors setup ######
    #define ProjectName "OldPhone" // Name that is vissible in controller
    #define ProjectVersion "0,1"          // Version that is vissible in controller
    #define MY_DEBUG       // Enable debug prints to serial monitor
    #define MY_RADIO_NRF24 // Enable and select radio type attached
    #define childIdDoor 1         // child ID number used by mysensors foor doorbell button
    #define chuildIdDail_1 101    // child ID number used by mysensors when the number 1 is dailed
    #define chuildIdDail_2 102    // child ID number used by mysensors when the number 2 is dailed
    #define chuildIdDail_3 103    // child ID number used by mysensors when the number 3 is dailed
    #define chuildIdDail_4 104    // child ID number used by mysensors when the number 4 is dailed
    #define chuildIdDail_5 105    // child ID number used by mysensors when the number 5 is dailed
    #define chuildIdDail_6 106    // child ID number used by mysensors when the number 6 is dailed
    #define chuildIdDail_7 107    // child ID number used by mysensors when the number 7 is dailed
    #define chuildIdDail_8 108    // child ID number used by mysensors when the number 8 is dailed
    #define chuildIdDail_9 109    // child ID number used by mysensors when the number 9 is dailed
    #define chuildIdDail_10 110   // child ID number used by mysensors when the number 0 is dailed
    
    // ###### Include libraries #####
    #include <SPI.h>              // needed for NRF24
    #include <MySensors.h>        // mysensors library
    #include <Bounce2.h>          // for debouncing buttons and dail
    
    // ###### I/O pin number setup ######
    #define button 3              // input pin activated when doorbell button is pressed
    #define edail 8               // input pin activated when dail is used (Enable Dail)
    #define pdail 7               // input pin activated with each tick of the dail (Pulse Dial)
    #define lbell 4               // output pin to swing bellh hamer left
    #define rbell 5               // output Pin to swing bellh hamer right
    
    // ##### Debouncer variables #####
    Bounce debouncerButton = Bounce(); // Create button debouncer for doorbell button 
    Bounce debouncerEdail = Bounce();  // Create button debouncer for Enable Dail
    Bounce debouncerPdail = Bounce();  // Create button debouncer for Pulse Dial 
    int valueButton = 0;               // Value 
    int oldValueButton = 0;
    int valueEdail = 0;
    int oldValueEdail = 0;
    int valuePdail = 0;
    int oldValuePdail = 0;
    int dailCount = 0;
    int newDailCount = 0;  
    
    
    int ring = 0;
    int ringX = 15;
    int onPulse = 20;
    int offPulse = 10;
    int repeat = 0;
    int repeatX = 4;
    int ringPause = 2000;
    
    // ##### setup MySensors message containers #####
    MyMessage msgDoor(childIdDoor,V_STATUS);         // message container used for doorbell button
    MyMessage msgDail_1(chuildIdDail_1,V_STATUS);    // message container used when the number 1 is dailed
    MyMessage msgDail_2(chuildIdDail_2,V_STATUS);    // message container used when the number 2 is dailed
    MyMessage msgDail_3(chuildIdDail_3,V_STATUS);    // message container used when the number 3 is dailed
    MyMessage msgDail_4(chuildIdDail_4,V_STATUS);    // message container used when the number 4 is dailed
    MyMessage msgDail_5(chuildIdDail_5,V_STATUS);    // message container used when the number 5 is dailed
    MyMessage msgDail_6(chuildIdDail_6,V_STATUS);    // message container used when the number 6 is dailed
    MyMessage msgDail_7(chuildIdDail_7,V_STATUS);    // message container used when the number 7 is dailed
    MyMessage msgDail_8(chuildIdDail_8,V_STATUS);    // message container used when the number 8 is dailed
    MyMessage msgDail_9(chuildIdDail_9,V_STATUS);    // message container used when the number 9 is dailed
    MyMessage msgDail_10(chuildIdDail_10,V_STATUS);  // message container used when the number 0 is dailed
    
    void setup()  
    {  
    //##### I/O pin function setup #####
      pinMode(button,INPUT);    //set the already defined I/O pin as input
      pinMode(edail, INPUT);    //set the already defined I/O pin as input
      pinMode(pdail, INPUT);    //set the already defined I/O pin as input
      pinMode(lbell, OUTPUT);   //set the already defined I/O pin as output
      pinMode(rbell, OUTPUT);   //set the already defined I/O pin as output
     
    // ##### Debouncer setup #####
      debouncerButton.attach(button);
      debouncerButton.interval(5);
      debouncerEdail.attach(edail);
      debouncerEdail.interval(5);
      debouncerPdail.attach(pdail);
      debouncerPdail.interval(5);
    }
    
    // ##### Function of MySensors that presents all attached sensors to the controller #####
    void presentation() { 
      sendSketchInfo(ProjectName, ProjectVersion);   // Send the sketch version information to the gateway and Controller
      present(childIdDoor, S_BINARY);                // Present doorbell button as binary switch
      present(chuildIdDail_1, S_BINARY);             // Present the dailing of number 1 as binary switch
      present(chuildIdDail_2, S_BINARY);             // Present the dailing of number 2 as binary switch
      present(chuildIdDail_3, S_BINARY);             // Present the dailing of number 3 as binary switch
      present(chuildIdDail_4, S_BINARY);             // Present the dailing of number 4 as binary switch
      present(chuildIdDail_5, S_BINARY);             // Present the dailing of number 5 as binary switch
      present(chuildIdDail_6, S_BINARY);             // Present the dailing of number 6 as binary switch
      present(chuildIdDail_7, S_BINARY);             // Present the dailing of number 7 as binary switch
      present(chuildIdDail_8, S_BINARY);             // Present the dailing of number 8 as binary switch
      present(chuildIdDail_9, S_BINARY);             // Present the dailing of number 9 as binary switch
      present(chuildIdDail_10, S_BINARY);            // Present the dailing of number 0 as binary switch
    }
    
    void loop() {
    // ##### debouncer updater ##### 
      debouncerButton.update();                      // Update debouncer for doorbell button
      valueButton = debouncerButton.read();          // Set current value of doorbell button 
      debouncerEdail.update();                       // Update debouncer for enable dail
      valueEdail = debouncerEdail.read();            // Set current value of enable dail
      debouncerPdail.update();                       // Update debouncer for pulse dail 
      valuePdail = debouncerPdail.read();            // Set current value of pulse dail
    
    // ##### Mysensors code to check doorbell button and sent message ##### 
      if (valueButton != oldValueButton) {                       // Check if the value of the button has changed 
         send(msgDoor.set(valueButton==HIGH ? 1 : 0));           // Transmit the new value
         oldValueButton = valueButton;                           // Change old value so this doenst loop
      }
    
    // ##### Mysensors code to read dail counter and sent message as one individual sensor #####
      switch (newDailCount) {         // Check the current vallue of the completed counter
         case 1:                      // if value is equal to 1 
           send(msgDail_1.set(1));    // Transmit ON message for dail switch 1 
           send(msgDail_1.set(0));    // Transmit OFF message for dail switch 1. Some home automation software prefers this.
           break;                     // end of case
         case 2:                      // if value is equal to 2 
           send(msgDail_2.set(1));    // Transmit ON message for dail switch 2
           send(msgDail_2.set(0));    // Transmit OFF message for dail switch 2. Some home automation software prefers this.
           break;                     // end of case
         case 3:                      // if value is equal to 3 
           send(msgDail_3.set(1));    // Transmit ON message for dail switch 3
           send(msgDail_3.set(0));    // Transmit OFF message for dail switch 3. Some home automation software prefers this.
           break;                     // end of case
         case 4:                      // if value is equal to 4 
           send(msgDail_4.set(1));    // Transmit ON message for dail switch 4 
           send(msgDail_4.set(0));    // Transmit OFF message for dail switch 4. Some home automation software prefers this.
           break;                     // end of case
         case 5:                      // if value is equal to 5 
           send(msgDail_5.set(1));    // Transmit ON message for dail switch 5 
           send(msgDail_5.set(0));    // Transmit OFF message for dail switch 5. Some home automation software prefers this.
           break;                     // end of case
         case 6:                      // if value is equal to 6 
           send(msgDail_6.set(1));    // Transmit ON message for dail switch 6 
           send(msgDail_6.set(0));    // Transmit OFF message for dail switch 6. Some home automation software prefers this.
           break;                     // end of case       
         case 7:                      // if value is equal to 7 
           send(msgDail_7.set(1));    // Transmit ON message for dail switch 7 
           send(msgDail_7.set(0));    // Transmit OFF message for dail switch 7. Some home automation software prefers this.
           break;                     // end of case       
         case 8:                      // if value is equal to 8 
           send(msgDail_8.set(1));    // Transmit ON message for dail switch 8 
           send(msgDail_8.set(0));    // Transmit OFF message for dail switch 8. Some home automation software prefers this.
           break;                     // end of case       
         case 9:                      // if value is equal to 9 
           send(msgDail_9.set(1));    // Transmit ON message for dail switch 9 
           send(msgDail_9.set(0));    // Transmit OFF message for dail switch 9. Some home automation software prefers this.
           break;                     // end of case       
         case 10:                     // if value is equal to 10 
           send(msgDail_10.set(1));    // Transmit ON message for dail switch 10 
           send(msgDail_10.set(0));    // Transmit OFF message for dail switch 10. Some home automation software prefers this.
           break;                     // end of case       
      }
      newDailCount = 0;                // Reset the completed counter so this doesnt loop
    
      
    // ###### Code for checking enable dail and sending state trough serial  ######  
      if (valueEdail != oldValueEdail && valueEdail == HIGH) {          // Check if enable dail has changed AND if its currently its currently activated
         Serial.println("dail is activated...");                        // If so sent message 
         oldValueEdail = valueEdail;}                                   // And change old value so this doenst loop
         else if (valueEdail != oldValueEdail && valueEdail == LOW) {   // Check if enable dail has changed AND if its currently its currently deactivated
         Serial.println("dail is deactivated...");                      // If so sent message
         newDailCount = dailCount;                                       // Write the counted pulses to the New Dail Count
         dailCount = 0;                                                 // Reset the dail count for next dail 
         oldValueEdail = valueEdail;                                    // And change old value so this doenst loop
      }
    
    // ###### Code for checking pusle dail and sending state trough serial ######
      if (valuePdail != oldValuePdail && valueEdail == HIGH) {          // Check if dail pulse has changed AND if currently its currently activated
         if (valuePdail == LOW) {                                       // Only take action when the signal goes from high to low to prevent double count
           dailCount++;                                                 // If the conditions are met increase counter by 1
           Serial.print("Tick! Total ammout of pulses: ");              // Serial print a messagge saying a pulse was detected
           Serial.println (dailCount);                                  // Serial print a the current value of the counter
         }
           oldValuePdail = valuePdail;                                  // Change old value so this doenst loop  
      }
     
      if (valueButton == HIGH) {                // If the boorbell button was pressed (read from debouncer)
         while (repeat < repeatX){              // start a loop if the number of repeats isnt reached yet (a repeat is the time a bell is ringed pauesed)
            repeat++;                           // add 1 count to the "repeat" counter
            while (ring < ringX){               // start a loop if the number of rings isnt reached yet (a ring is the hammer hitting each bell once)
               ring++;                          // add 1 count to the "ring" counter
               digitalWrite(lbell, HIGH);       // power the bell coil so that the hammer hits the left bell  !!! VERY IMPORTANT: "LBELL" AND "RBELL" CAN NEVER BE HIGH AT THE SAME TIME !!!
               wait(onPulse);                   // hold for the amount of ms set for "onPulse"                !!! VERY IMPORTANT: "LBELL" AND "RBELL" CAN NEVER BE HIGH AT THE SAME TIME !!!
               digitalWrite(lbell, LOW);        // power down the bell coil                                   !!! VERY IMPORTANT: "LBELL" AND "RBELL" CAN NEVER BE HIGH AT THE SAME TIME !!!
               wait(offPulse);                  // wait for the amount of ms set for "offpulse"               !!! VERY IMPORTANT: "LBELL" AND "RBELL" CAN NEVER BE HIGH AT THE SAME TIME !!!
               digitalWrite(rbell, HIGH);       // power the bell coil so that the hammer hits the right bell !!! VERY IMPORTANT: "LBELL" AND "RBELL" CAN NEVER BE HIGH AT THE SAME TIME !!!
               wait(onPulse);                   // hold for the amount of ms set for "onPulse"                !!! VERY IMPORTANT: "LBELL" AND "RBELL" CAN NEVER BE HIGH AT THE SAME TIME !!!
               digitalWrite(rbell, LOW);        // power down the bell coil                                   !!! VERY IMPORTANT: "LBELL" AND "RBELL" CAN NEVER BE HIGH AT THE SAME TIME !!!
               wait(offPulse);                  // wait for the amount of ms set for "offpulse"               !!! VERY IMPORTANT: "LBELL" AND "RBELL" CAN NEVER BE HIGH AT THE SAME TIME !!!
            }                                   // go back to start if loop till "ring" has the same value as "ringX"
            wait (ringPause);                   // wait for the amount of ms set for "ringPause"
               if (ring == ringX){              // if the amount of "ring" is the same as the amount set in "ringX"....
                  ring = 0;                     // reset the "ring" counter
                  }
             }
         }  
                  
      if (repeat == repeatX){                   // if the amount of "repeat" is the same as the amount set in "repeatX"....
         repeat = 0;                            // reset the "repeat" counter
         } 
    }
    

  • Mod

    wait() will not mess with ability to receive radio - in fact, handling the radio is exactly what is done inside wait(). However, if a radio message needs to be handled, wait() can take more time than the specified number of milliseconds. Therefore, wait() won't be suitable for generating a precise 5ms square wave.

    As you probably already guessed, button presses will be ignored during wait(), unless you use interrupts.

    For a more flexible solution, you'll need to modify all code to work without wait. See https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay for a simple starting point, but be aware that it gets more and more complex with multiple different things happening at the same time.



  • @mfalkvidd said in Virtual switches that never go off and controllers:

    wait() will not mess with ability to receive radio - in fact, handling the radio is exactly what is done inside wait(). However, if a radio message needs to be handled, wait() can take more time than the specified number of milliseconds. Therefore, wait() won't be suitable for generating a precise 5ms square wave.

    As you probably already guessed, button presses will be ignored during wait(), unless you use interrupts.

    For a more flexible solution, you'll need to modify all code to work without wait. See https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay for a simple starting point, but be aware that it gets more and more complex with multiple different things happening at the same time.

    Thanks for the info! i was afraid that was what wait was doing. The question is how bad i want to fix this... I know about millis. I dont have to rewrite that much code for it. Maybe there is some library i can use.

    Also it doesnt really matter how good the square wave is, as long as the 2 "bell" pins are never high at the same time.

    I guess millis can be the solution for sending a off signal to, or are there better ways to handle this?


  • Mod

    @superkris there are probably other ways, but I would use millis.


 

474
Online

7.9k
Users

8.7k
Topics

93.6k
Posts