Combine PIR, relay, distance and gas sensors



  • Hi everyone,

    I'm trying to combine 3 relays, PIR, gas and distance sensors together for my kitchen but i have no luck already spend 3 days on but nothing works.

    Can someone help me please? Gas sensor is not necessary
    Using: mysensors 1.4
    Controller: Domoticz

    Everything separately working fine but not together.

    Here is my code with 3 relays, pir and distance sensors

    #include <SPI.h>
    #include <MySensor.h>  
    #include <NewPing.h>
    
    #define CHILD_ID 8
    #define TRIGGER_PIN  8  // Arduino pin tied to trigger pin on the ultrasonic sensor.
    #define ECHO_PIN     7  // Arduino pin tied to echo pin on the ultrasonic sensor.
    #define MAX_DISTANCE 300 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.
    unsigned long SLEEP_TIME = 5000; // Sleep time between reads (in milliseconds)
    
    #define MOTOIN_INPUT_SENSOR 3   // The digital input you attached your motion sensor.  (Only 2 and 3 generates interrupt!)
    
    #define RELAY_1  4  // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
    #define NUMBER_OF_RELAYS 3 // Total number of attached relays
    #define RELAY_ON 0  // GPIO value to write to turn on attached relay
    #define RELAY_OFF 1 // GPIO value to write to turn off attached relay
    #define MOTION_CHILD_ID 5   // Id of the sensor child
    #define RELAY_CHILD_ID 1   // Id of the sensor child 
    
    boolean lastMotion = false;
    
    MySensor gw;
    NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.
    MyMessage msgdist(MOTION_CHILD_ID, V_TRIPPED);
    MyMessage msg(CHILD_ID, V_DISTANCE);
    int lastDist;
    boolean metric = true; 
    
    void setup()  
    { 
    
    gw.begin(incomingMessage, AUTO, true);
      // Send the sketch version information to the gateway and Controller
      gw.sendSketchInfo("Zet", "1.0");
    
      // Register all sensors to gw (they will be created as child devices)
      gw.present(CHILD_ID, S_DISTANCE);
      boolean metric = gw.getConfig().isMetric;
      
      pinMode(MOTOIN_INPUT_SENSOR, INPUT);      // sets the motion sensor digital pin as input
      // Register all sensors to gw (they will be created as child devices)
      gw.present(MOTION_CHILD_ID, S_MOTION);
      // Fetch relay status
      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)
        gw.present(sensor, S_LIGHT);
        // Then set relay pins in output mode
        pinMode(pin, OUTPUT);   
        // Set relay to last known state (using eeprom storage) 
        digitalWrite(pin, gw.loadState(sensor)?RELAY_ON:RELAY_OFF);
    }
    }
    
    void loop()      
    {     
      int dist = metric?sonar.ping_cm():sonar.ping_in();
      Serial.print("Ping: ");
      Serial.print(dist); // Convert ping time to distance in cm and print result (0 = outside set distance range)
      Serial.println(metric?" cm":" in");
    
      if (dist != lastDist) {
          gw.send(msg.set(dist));
          lastDist = dist;
          
           // Alway process incoming messages whenever possible
      gw.process();
      // Read digital motion value
      boolean motion = digitalRead(MOTOIN_INPUT_SENSOR) == HIGH; 
      if (lastMotion != motion) {
        lastMotion = motion;     
        gw.send(msg.set(motion ? "1" : "0" ));  // Send motion value to gw
      }
    
      gw.sleep(SLEEP_TIME);
    }
    }
    
    void incomingMessage(const MyMessage &message) {
      // We only expect one type of message from controller. But we better check anyway.
      if (message.type==V_LIGHT) {
         // Change relay state
         digitalWrite(message.sensor-1+RELAY_1, message.getBool()?RELAY_ON:RELAY_OFF);
         // Store state in eeprom
         gw.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());
       } 
    }
    

    LOG from serial monitor:

    repeater started, id 1
    send: 1-1-0-0 s=255,c=0,t=18,pt=0,l=5,st=ok:1.4.1
    send: 1-1-0-0 s=255,c=3,t=6,pt=1,l=1,st=ok:0
    read: 0-0-1 s=255,c=3,t=6,pt=0,l=1:M
    send: 1-1-0-0 s=255,c=3,t=11,pt=0,l=3,st=ok:Zet
    send: 1-1-0-0 s=255,c=3,t=12,pt=0,l=3,st=ok:1.0
    send: 1-1-0-0 s=8,c=0,t=15,pt=0,l=5,st=ok:1.4.1
    send: 1-1-0-0 s=5,c=0,t=1,pt=0,l=5,st=ok:1.4.1
    send: 1-1-0-0 s=1,c=0,t=3,pt=0,l=5,st=ok:1.4.1
    send: 1-1-0-0 s=2,c=0,t=3,pt=0,l=5,st=ok:1.4.1
    send: 1-1-0-0 s=3,c=0,t=3,pt=0,l=5,st=ok:1.4.1
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    Ping: 0 cm
    

    Any help?



  • I would try getting rid of the sleep time and use a timer function to call the motion detection every 5 seconds. As noting else can happen during sleep.


  • Hero Member

    @miremi I think @stephenmhall is right on the money.

    Get rid of the sleep function all together, and run "full tilt boggy" to see what happens (don't try activating any of the relays).

    Did I miss the gas code??

    If PIR, and Distance works, then add in a interval to slow things down.



  • @stephenmhall How can i do that?

    @ServiceXp I don't have the knowledge of arduino programming to do that 😞 i just started 2 days ago with arduino for dummies.
    Can you help me with this one?

    I didn't include gas code yet because i was thinking let the firs three work and than gas sensor.



  • Okydoky

    here is some of my code from a combined temp/humidity sensor a relay and a button to trigger the relay locally. Hopefully you can put your code together with it.

    First I do some variable setup. the gap between checks (30 seconds) and millis() gives time in unix time.

    unsigned long SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds)
    unsigned long CHECK_TIME = millis();
    

    in the void loop I have the gw.process() and code to check for the button being pressed and also a timer that calls the function to check the sensors. It gets the current time, subtracts the old time from it and if the difference is greater than the SLEEP_TIME it calls the check function.

    void loop()      
    {
      gw.process();
      debouncer.update();
      // Get the update value
      int value = debouncer.read();
      if (value != oldValue && value==0) {
          gw.send(msgRelay.set(state?false:true), true); // Send new state and request ack back
      }
      oldValue = value;
      
      // Check Temp and Humidity sensor every set ammount of time
      unsigned long NOW_TIME = millis();
      if(NOW_TIME - CHECK_TIME >= SLEEP_TIME) {
        getTemps();
        CHECK_TIME = NOW_TIME;
      }
    }
    

    Here is the function to read the temps, this goes below the void loop. You probably have the void incommingMesage function for MySensors, it can go above or below that.

    void getTemps(){
      delay(dht.getMinimumSamplingPeriod());
    
      float temperature = dht.getTemperature();
      if (isnan(temperature)) {
          Serial.println("Failed reading temperature from DHT");
      } else if (temperature != lastTemp) {
        lastTemp = temperature;
        if (!metric) {
          temperature = dht.toFahrenheit(temperature);
        }
        gw.send(msgTemp.set(temperature, 1));
        Serial.print("T: ");
        Serial.println(temperature);
      }
      
      float humidity = dht.getHumidity();
      if (isnan(humidity)) {
          Serial.println("Failed reading humidity from DHT");
      } else if (humidity != lastHum) {
          lastHum = humidity;
          gw.send(msgHum.set(humidity, 1));
          Serial.print("H: ");
          Serial.println(humidity);
      }  
    }
    

    this does the work of checking the sensors and updating the gateway if the readings have changed.

    This way it is always checking for the button being pressed, and only checking the sensors every 30 seconds, with no sleeptime. Probably not great if on batteries but that's another problem. My Arduino kung-fu is not super strong, I suspect you can set up interrupts and stuff to allow for sleeptime but that is beyond me currently.



  • @stephenmhall thank for your help.

    Still no luck. Pir and distance sensors working but relay doesn't wont to work.


  • Hero Member

    What happens when you add the relay? Only the relay does not obey, or the pir/dist stop too? What do you get in serial monitor?


Log in to reply
 

Suggested Topics

50
Online

11.4k
Users

11.1k
Topics

112.6k
Posts