Binary sensor expanded help



  • I've tried the binary sensor with a switch and it works great. I would like to expand this to incorporate a few more switches, but I am not sure what the best approach would be. I have tried copying portions of the code and changing variable names and almost have things working okay (debouncing acts weird), but I know my method is no very effective. I have very little experience with programming on the arduino and would appreciate some advice on what to do or where to look for help.



  • I have been using this sketch for about a week now and it is working fine for my needs.

    // Simple binary switch example 
    // Connect button or door/window reed switch between 
    // digitial I/O pin 3 (ZONE_1 below) and GND.
    
    #include <Sensor.h>
    #include <SPI.h>
    #include <EEPROM.h>  
    #include <RF24.h>
    #include <Bounce2.h>
    
    #define ZONE_1  14  // Arduino Digital I/O pin for button/reed switch
    #define NUMBER_OF_ZONES 6
    
    Sensor gw;
    Bounce debouncer_1 = Bounce();
    Bounce debouncer_2 = Bounce();
    Bounce debouncer_3 = Bounce();
    Bounce debouncer_4 = Bounce();
    Bounce debouncer_5 = Bounce();
    Bounce debouncer_6 = Bounce();
    
    int oldValue_1 =-1;
    int oldValue_2 =-1;
    int oldValue_3 =-1;
    int oldValue_4 =-1;
    int oldValue_5 =-1;
    int oldValue_6 =-1;
    
    void setup()  
    {  
      gw.begin();
      for (int i=0; i<NUMBER_OF_ZONES;i++) {
       // Setup the button
    	pinMode(ZONE_1+i,INPUT);
    	// Activate internal pull-up
    	digitalWrite(ZONE_1+i,HIGH);
    	
    	// After setting up the button, setup debouncer
    	switch (1+i) {
    	  case 1:
    		debouncer_1.attach(ZONE_1);
    		debouncer_1.interval(5);
    		break;
    	  case 2:
    		debouncer_2.attach(ZONE_1+i);
    		debouncer_2.interval(5);
    		break;
    	  case 3:
    		debouncer_3.attach(ZONE_1+i);
    		debouncer_3.interval(5);
    		break;
    	  case 4:
    		debouncer_4.attach(ZONE_1+i);
    		debouncer_4.interval(5);
    		break;
    	  case 5:
    		debouncer_5.attach(ZONE_1+i);
    		debouncer_5.interval(5);
    		break;
    	}
    	
    	// Register binary input sensor to gw (they will be created as child devices)
    	// You can use S_DOOR, S_MOTION or S_LIGHT here depending on your usage. 
    	// If S_LIGHT is used, remember to update variable type you send in below.
    	gw.sendSensorPresentation(ZONE_1+i, S_DOOR);
    	delay(1000);
      }
    }
    
    
    //  Check if digital input has changed and send in new value
    void loop() 
    {
      for (int i=0; i<NUMBER_OF_ZONES;i++) {
    	int num = 1+i;
    	// Get the update value
    	switch (num) {
    	  case 1:
    		{
    		  debouncer_1.update();
    		  int value_1 = debouncer_1.read();
    		  if (value_1 != oldValue_1) {
    		   // Send in the new value
    		   gw.sendVariable(ZONE_1+i, V_TRIPPED, value_1==HIGH ? "1" : "0");  // Change to V_LIGHT if you use S_LIGHT in presentation above
    		   oldValue_1 = value_1;
    		  }
    		  break;
    		}
    	  case 2:
    		{
    		  debouncer_2.update();
    		  int value_2 = debouncer_2.read();
    		  if (value_2 != oldValue_2) {
    		   // Send in the new value
    		   gw.sendVariable(ZONE_1+i, V_TRIPPED, value_2==HIGH ? "1" : "0");  // Change to V_LIGHT if you use S_LIGHT in presentation above
    		   oldValue_2 = value_2;
    		  }
    		  break;
    		}
    	  case 3:
    		{
    		  debouncer_3.update();
    		  int value_3 = debouncer_3.read();
    		  if (value_3 != oldValue_3) {
    		   // Send in the new value
    		   gw.sendVariable(ZONE_1+i, V_TRIPPED, value_3==HIGH ? "1" : "0");  // Change to V_LIGHT if you use S_LIGHT in presentation above
    		   oldValue_3 = value_3;
    		  }
    		  break;
    		}
    	  case 4:
    		{
    		  debouncer_4.update();
    		  int value_4 = debouncer_4.read();
    		  if (value_4 != oldValue_4) {
    		   // Send in the new value
    		   gw.sendVariable(ZONE_1+i, V_TRIPPED, value_4==HIGH ? "1" : "0");  // Change to V_LIGHT if you use S_LIGHT in presentation above
    		   oldValue_4 = value_4;
    		  }
    		  break;
    		}
    	  case 5:
    		{
    		  debouncer_5.update();
    		  int value_5 = debouncer_5.read();
    		  if (value_5 != oldValue_5) {
    		   // Send in the new value
    		   gw.sendVariable(ZONE_1+i, V_TRIPPED, value_5==HIGH ? "1" : "0");  // Change to V_LIGHT if you use S_LIGHT in presentation above
    		   oldValue_5 = value_5;
    		  }
    		  break;
    		}
    	  case 6:
    		{
    		  debouncer_6.update();
    		  int value_6 = debouncer_6.read();
    		  if (value_6 != oldValue_6) {
    		   // Send in the new value
    		   gw.sendVariable(ZONE_1+i, V_TRIPPED, value_6==HIGH ? "1" : "0");  // Change to V_LIGHT if you use S_LIGHT in presentation above
    		   oldValue_6 = value_6;
    		  }
    		break;
    		}
    	}
      }
    }


  • Thanks Mikeones! I will try it out. I do have one question though. You seem to be setting all pins based on ZONE_1 variable, correct? So you would be using pins 14-19 for your input? Shouldn't ZONE_1 be set to 3 to use pins 3-8? Again, I am totally new so maybe I'm looking at it wrong. I am using a nano if that makes a difference.



  • @chuckconnors

    I have this on a nano also but the only open pins I have left are analog. That is why I started at ping 14.



  • @mikeones Oh, okay.. That makes sense. Are you using any resistors with your switches or are you using just the switches?



  • Wow. It's been two years since I've visited this. At any rate. I'm trying to update to the latest mysensors version and am running into an issue. I've used the binary sensor as a base but I'm pretty sure that I'm doing something wrong. Here's the code I'm trying to use:

    
    #include <MySensor.h>
    #include <SPI.h>
    #include <Bounce2.h>
    
    #define ZONE_1  3  // Arduino Digital I/O pin for button/reed switch
    #define NUMBER_OF_ZONES 6
    
    MySensor gw;
    
    Bounce debouncer_1 = Bounce();
    Bounce debouncer_2 = Bounce();
    Bounce debouncer_3 = Bounce();
    Bounce debouncer_4 = Bounce();
    Bounce debouncer_5 = Bounce();
    Bounce debouncer_6 = Bounce();
    
    int oldValue_1 =-1;
    int oldValue_2 =-1;
    int oldValue_3 =-1;
    int oldValue_4 =-1;
    int oldValue_5 =-1;
    int oldValue_6 =-1;
    
    void setup()  
    {  
      gw.begin();
    
    
      for (int i=0; i<NUMBER_OF_ZONES;i++) 
      {
       // Setup the button
        pinMode(ZONE_1+i,INPUT);
        // Activate internal pull-up
        digitalWrite(ZONE_1+i,HIGH);
        MyMessage msg(ZONE_1+i,V_TRIPPED);
        
      
      // After setting up the button, setup debouncer
          switch (1+i) 
          {
          case 1:
            debouncer_1.attach(ZONE_1);
            debouncer_1.interval(5);
            break;
          case 2:
            debouncer_2.attach(ZONE_1+i);
            debouncer_2.interval(5);
            break;
          case 3:
            debouncer_3.attach(ZONE_1+i);
            debouncer_3.interval(5);
            break;
          case 4:
            debouncer_4.attach(ZONE_1+i);
            debouncer_4.interval(5);
            break;
          case 5:
            debouncer_5.attach(ZONE_1+i);
            debouncer_5.interval(5);
            break;
          }
      
      // Register binary input sensor to gw (they will be created as child devices)
      // You can use S_DOOR, S_MOTION or S_LIGHT here depending on your usage. 
      // If S_LIGHT is used, remember to update variable type you send in. See "msg" above.
      
      gw.present(ZONE_1+i, S_DOOR); 
      delay(1000);
     }
    
    }
    
    
    //  Check if digital input has changed and send in new value
    void loop() 
    {
    for (int i=0; i<NUMBER_OF_ZONES;i++) 
      {
        int num = 1+i;
        // Get the update value
        switch (num) 
        {
          case 1:
            {
              debouncer_1.update();
              int value_1 = debouncer_1.read();
              if (value_1 != oldValue_1) {
               // Send in the new value       
               gw.send(msg.setSensor(ZONE_1+i).set(value_1==HIGH ? 1 : 0));
               oldValue_1 = value_1;
              }
              break;
            }
          case 2:
            {
              debouncer_2.update();
              int value_2 = debouncer_2.read();
              if (value_2 != oldValue_2) {
               // Send in the new value
               gw.send(msg.setSensor(ZONE_1+i).set(value_2==HIGH ? 1 : 0));
               oldValue_2 = value_2;
              }
              break;
            }
          case 3:
            {
              debouncer_3.update();
              int value_3 = debouncer_3.read();
              if (value_3 != oldValue_3) {
               // Send in the new value
               gw.send(msg.setSensor(ZONE_1+i).set(value_3==HIGH ? 1 : 0));
               oldValue_3 = value_3;
              }
              break;
            }
          case 4:
            {
              debouncer_4.update();
              int value_4 = debouncer_4.read();
              if (value_4 != oldValue_4) {
               // Send in the new value
              gw.send(msg.setSensor(ZONE_1+i).set(value_4==HIGH ? 1 : 0));
               oldValue_4 = value_4;
              }
              break;
            }
          case 5:
            {
              debouncer_5.update();
              int value_5 = debouncer_5.read();
              if (value_5 != oldValue_5) {
               // Send in the new value
               gw.send(msg.setSensor(ZONE_1+i).set(value_5==HIGH ? 1 : 0));
               oldValue_5 = value_5;
              }
              break;
            }
          case 6:
            {
              debouncer_6.update();
              int value_6 = debouncer_6.read();
              if (value_6 != oldValue_6) {
               // Send in the new value
               gw.send(msg.setSensor(ZONE_1+i).set(value_6==HIGH ? 1 : 0));
               oldValue_6 = value_6;
              }
            break;
            }
          }
    
    
         
      }
    } 
    

    When I try to compile I get this error:

    Arduino: 1.6.6 (Windows 7), Board: "Arduino/Genuino Uno"
    
    Warning: platform.txt from core 'MySensors AVR based boards' contains deprecated recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{build.path}/{archive_file}" "{object_file}", automatically converted to recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}". Consider upgrading this core.
    WARNING: Category '' in library UIPEthernet is not valid. Setting to 'Uncategorized'
    C:\Users\User\Documents\Arduino\alarm\alarm.ino: In function 'void loop()':
    
    alarm:118: error: 'msg' was not declared in this scope
    
                gw.send(msg.setSensor(ZONE_1+i).set(value_1==HIGH ? 1 : 0));
    
                        ^
    
    alarm:129: error: 'msg' was not declared in this scope
    
                gw.send(msg.setSensor(ZONE_1+i).set(value_2==HIGH ? 1 : 0));
    
                        ^
    
    alarm:140: error: 'msg' was not declared in this scope
    
                gw.send(msg.setSensor(ZONE_1+i).set(value_3==HIGH ? 1 : 0));
    
                        ^
    
    alarm:151: error: 'msg' was not declared in this scope
    
               gw.send(msg.setSensor(ZONE_1+i).set(value_4==HIGH ? 1 : 0));
    
                       ^
    
    alarm:162: error: 'msg' was not declared in this scope
    
                gw.send(msg.setSensor(ZONE_1+i).set(value_5==HIGH ? 1 : 0));
    
                        ^
    
    alarm:173: error: 'msg' was not declared in this scope
    
                gw.send(msg.setSensor(ZONE_1+i).set(value_6==HIGH ? 1 : 0));
    
                        ^
    
    exit status 1
    'msg' was not declared in this scope
    

    I'm guessing it's a syntax error but I'm having trouble trying to format it correctly. I'm a hacker not a programmer so any help would be most appreciated! Thanks



  • Hi,
    I think that your problem is that you are using a "variable" (msg) that you never declare.
    C++ requires that every variable used MUST have a type and be declared in advance.
    Inserting a declaration:

    MyMessage msg;

    should fix your problem. Let us know.

    Ciao



  • Thanks for the advice. I did have the variable declared as:

    MyMessage msg(ZONE_1+i,V_TRIPPED);
    

    but it's quite possible that I'm doing that wrong. I tried changing it to your version and I get the same error.

    I'm very excited to get this working but am so in the dark when it comes to actual programming. I appreciate any help you guys can give to get this thing running finally.


  • Mod

    You are declaring msg inside a for loop. It will not live outside the scope of that for loop. You need to declare it globally (=outside any function) to make it available inside the loop() and setup() functions.
    Since you are using multiple messages, an array makes sense. See line 20 in
    for an example.
    You can convert the debouncer_Ns and oldvalue_Ns to arrays in a similar manner, making your code much neater (no need for the long switch statement for example).



  • Thank you for taking the time to help. Unfortunately I'm more of hacker than a programmer. I understand what you are saying about making the message a global, but I don't know exactly how to accomplish it. I tried to just force it like this:

    MyMessage msg(1,V_TRIPPED);
    MyMessage msg(2,V_TRIPPED);
    MyMessage msg(3,V_TRIPPED);
    MyMessage msg(4,V_TRIPPED);
    MyMessage msg(5,V_TRIPPED);
    MyMessage msg(6,V_TRIPPED);
    

    but that did not work. Also, I do understand using an array would clean things up a bit but I'd like to get it working in this basic format first then work on refining it. Thanks again.



  • Thanks for the help again. I think I have something working. Could definitely use some help cleaning it up though:

    #include <SPI.h>
    #include <MySensor.h>
    #include <Bounce2.h>
    
    #define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
    
    #define SLEEP_TIME 600000 // Sleep time between reads (in milliseconds)
    #define STABILIZATION_TIME 500 // Let the sensor stabilize 0.5 seconds before reading
    
    const int SENSORS[] = {3,4,5,6,7,8}; // Remove the pins that you don't want to use
    #define N_ELEMENTS(array) (sizeof(array)/sizeof((array)[0]))
    
    MySensor gw;
    
    Bounce debouncer_1 = Bounce();
    Bounce debouncer_2 = Bounce();
    Bounce debouncer_3 = Bounce();
    Bounce debouncer_4 = Bounce();
    Bounce debouncer_5 = Bounce();
    Bounce debouncer_6 = Bounce();
    
    int oldValue_1 =-1;
    int oldValue_2 =-1;
    int oldValue_3 =-1;
    int oldValue_4 =-1;
    int oldValue_5 =-1;
    int oldValue_6 =-1;
    
    
    
    
    MyMessage button_messages[N_ELEMENTS(SENSORS)];
    
    void setup()
    {
      gw.begin();
    
      for (int sensor = 0; sensor < N_ELEMENTS(SENSORS); sensor++) {
        button_messages[sensor].sensor = sensor + 1; // Battery uses child ID 0 so sensors start at 1
        button_messages[sensor].type = V_TRIPPED;
        delay(250);
        gw.present(sensor + 1, S_DOOR);
      }
      for (int i = 0; i < N_ELEMENTS(SENSORS); i++) {
    
        pinMode(SENSORS[i], INPUT);
        digitalWrite(SENSORS[i], HIGH);
    
        switch (1+i)
        {
          case 1:
            debouncer_1.attach(SENSORS[i]);
            debouncer_1.interval(5);
            break;
          case 2:
            debouncer_2.attach(SENSORS[i]);
            debouncer_2.interval(5);
            break;
          case 3:
            debouncer_3.attach(SENSORS[i]);
            debouncer_3.interval(5);
            break;
          case 4:
            debouncer_4.attach(SENSORS[i]);
            debouncer_4.interval(5);
            break;                        
          case 5:
            debouncer_5.attach(SENSORS[i]);
            debouncer_5.interval(5);
            break;        
          case 6:
            debouncer_6.attach(SENSORS[i]);
            debouncer_6.interval(5);
            break;        
        }
      }
    }
    
    void loop()
    {
    
     for (int sensor = 0; sensor < N_ELEMENTS(SENSORS); sensor++) 
      {
            int num = 1+sensor;
        // Get the update value
        switch (num) 
        {
          case 1:
            {
              debouncer_1.update();
              int value_1 = debouncer_1.read();
              if (value_1 != oldValue_1) {
               // Send in the new value
               gw.send(button_messages[sensor].set(value_1==HIGH ? 1 : 0)); 
               Serial.print("Switch 1=");
               Serial.println(value_1);
               oldValue_1 = value_1;
              }
              break;
            }
          case 2:
            {
              debouncer_2.update();
              int value_2 = debouncer_2.read();
              if (value_2 != oldValue_2) {
               // Send in the new value
               gw.send(button_messages[sensor].set(value_2==HIGH ? 1 : 0)); 
               Serial.print("Switch 2=");
               Serial.println(value_2);
               oldValue_2 = value_2;
              }
              break;
            }
          case 3:
            {
              debouncer_3.update();
              int value_3 = debouncer_3.read();
              if (value_3 != oldValue_3) {
               // Send in the new value
               gw.send(button_messages[sensor].set(value_3==HIGH ? 1 : 0)); 
               Serial.print("Switch 3=");
               Serial.println(value_3);
               oldValue_3 = value_3;
              }
              break;
            }
          case 4:
            {
              debouncer_4.update();
              int value_4 = debouncer_4.read();
              if (value_4 != oldValue_4) {
               // Send in the new value
               gw.send(button_messages[sensor].set(value_4==HIGH ? 1 : 0)); 
               Serial.print("Switch 4=");
               Serial.println(value_4);
               oldValue_4 = value_4;
              }
              break;
            }
          case 5:
            {
              debouncer_5.update();
              int value_5 = debouncer_5.read();
              if (value_5 != oldValue_5) {
               // Send in the new value
               gw.send(button_messages[sensor].set(value_5==HIGH ? 1 : 0)); 
               Serial.print("Switch 5=");
               Serial.println(value_5);
               oldValue_5 = value_5;
              }
              break;
            }
          case 6:
            {
              debouncer_6.update();
              int value_6 = debouncer_6.read();
              if (value_6 != oldValue_6) {
               // Send in the new value
               gw.send(button_messages[sensor].set(value_6==HIGH ? 1 : 0)); 
               Serial.print("Switch 6=");
               Serial.println(value_6);
               oldValue_6 = value_6;
              }
            break;
            }
          }
      }
    
    
    
      
    }
    

  • Mod

    Great work! I'll see if I can help you with the cleanup tomorrow.



  • That would be great. Thanks for the push in the right direction.. I'm about to connect it to the alarm wires!


  • Mod

    Something like this should work. Note: I haven't tested the code, but it compiles and I think it does the same as your old code.

    #include <SPI.h>
    #include <MySensor.h>
    #include <Bounce2.h>
    
    #define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
    
    const int SENSORS[] = {3, 4, 5, 6, 7, 8}; // Remove the pins that you don't want to use
    #define N_ELEMENTS(array) (sizeof(array)/sizeof((array)[0]))
    
    MySensor gw;
    
    Bounce debouncers[N_ELEMENTS(SENSORS)];
    int oldValues[N_ELEMENTS(SENSORS)];
    
    MyMessage button_messages[N_ELEMENTS(SENSORS)];
    
    void setup()
    {
    
      gw.begin();
    
      for (int sensor = 0; sensor < N_ELEMENTS(SENSORS); sensor++) {
        debouncers[sensor] = Bounce();
        oldValues[sensor] = -1;
    
        button_messages[sensor].sensor = sensor + 1; // Battery uses child ID 0 so sensors start at 1
        button_messages[sensor].type = V_TRIPPED;
        delay(250);
        gw.present(sensor + 1, S_DOOR);
    
        pinMode(SENSORS[sensor], INPUT);
        digitalWrite(SENSORS[sensor], HIGH);
    
        debouncers[sensor].attach(SENSORS[sensor]);
        debouncers[sensor].interval(5);
      }
    }
    
    void loop()
    {
    
      for (int sensor = 0; sensor < N_ELEMENTS(SENSORS); sensor++)
      {
        int num = 1 + sensor;
        debouncers[num].update();
        int value = debouncers[num].read();
        if (value != oldValues[num]) {
          // Send in the new value
          gw.send(button_messages[sensor].set(value == HIGH ? 1 : 0));
          Serial.print("Switch ");
          Serial.print(num);
          Serial.print(" =");
          Serial.println(value);
          oldValues[num] = value;
        }
      }
    }
    


  • Much cleaner! I'll give it a go soon. Thanks for all the help!


Log in to reply
 

Looks like your connection to MySensors Forum was lost, please wait while we try to reconnect.