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 } }
-
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?
-
@superkris there are probably other ways, but I would use millis.