repeater node with sensor



  • can i combine a repeater node with sensor together?
    i want to cover a large area with sensors and i need some thep/humid sensors on the way so i thought it could be nice to use the same node for the two missions.
    to avoid sleep time for the repeater, and continous sampling time from the sensor, i manged to copy a function from sparkfun flow sensor sketch to calculate milliiseconds between readings (there it was 1000 ms and i want it to be 600000 ms (every 10 min))

    is it possibe? also, what sketch to delcare on setup? humidity or repeater?


  • Mod

    Yes you can combine sensor and repeaters.

    Use the sensor sketch, but change gw.begin according to http://www.mysensors.org/download/sensor_api_15#create-repeating-nodes an change gw.sleep to gw.wait
    I think that's all that needs to be done.



  • You sure can. I made early on a MotionSensorRepeater using 1.5.0 . The gotcha is you need to implement some sort of NON_BLOCKING rate limiting so the sensor doesn't spam the repeater. If you use DELAY(), you will lose messages. A lot of them.

    Also, I'm using a junky Sparkfun PIR sensor for this, with NO potentiometers for sensitivity or triggered duration, so I had to do duration in software. That's why the extra complication.

    #define NODE_ID 3
    #define CHILD_ID 5   // Id of the sensor child
    String ROOM_ID = " ID 5, living room repeater" ;
    
    
    #include <MySensor.h>
    #include <SPI.h>
    
    unsigned long MIN_TIME_TRIGGERED = 60000 ; // Time for sensor to report "off". Normally set on the PIR itself but this is junky sparkfun.
    boolean previousTripped = LOW;
    unsigned long PREVIOUS_TRIPPED_TIME = millis();
    unsigned long MIN_RETRIGGER = 3500;
    
    
    #define DIGITAL_INPUT_SENSOR 3   // The digital input you attached your motion sensor.  (Only 2 and 3 generates interrupt!)
    #define INTERRUPT DIGITAL_INPUT_SENSOR-2 // Usually the interrupt = pin -2 (on uno/nano anyway)
    
    
    MySensor gw;
    // Initialize motion message
    MyMessage msg(CHILD_ID, V_TRIPPED);
    
    void setup()
    {
      gw.begin(NULL, NODE_ID, true);
    
      // Send the sketch version information to the gateway and Controller
      gw.sendSketchInfo("Motion Sensor", "1.0");
    
      pinMode(DIGITAL_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(CHILD_ID, S_MOTION);
    
    }
    
    void loop()
    {
      boolean tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH;
    
      // Sensor must be HIGH and not yet sent the status of the sensor
      if ((tripped == HIGH) && (tripped != previousTripped) ) { 
        Serial.print(tripped); Serial.println(ROOM_ID);
        gw.send(msg.set(tripped ? "1" : "0")); // Send tripped value to gw
        previousTripped = tripped;
        PREVIOUS_TRIPPED_TIME = millis();
      }
    
      // Is sensor HIGH, already sent to gateway, and under the minimum time to trigger? Then don't send
      if ( (PREVIOUS_TRIPPED_TIME + MIN_RETRIGGER) < millis() ) { 
        if ( (tripped == HIGH) && (tripped == previousTripped) ) { 
          Serial.println("Counter Reset"); PREVIOUS_TRIPPED_TIME = millis();
        }
      }
    
      // Is sensor low and not sent? Then send LOW to gateway
      if (tripped == LOW) {
        if ( ((PREVIOUS_TRIPPED_TIME + MIN_TIME_TRIGGERED) <= millis() ) && (tripped != previousTripped) ) {
          Serial.print(tripped); Serial.println(ROOM_ID);
          gw.send(msg.set(tripped ? "1" : "0")); // Send tripped value to gw
          previousTripped = tripped;
          PREVIOUS_TRIPPED_TIME = millis();
        }
      }
    
      gw.process(); // makes the node repeat
    }
    
    
    
    


  • Keep this in your loop otherwise it will not process messages:

    gw.process();
    

    PS @cranky beat me with an example 😉


  • Mod

    gw.wait() already calls process() so there is no need to call process if gw.wait is used
    See https://github.com/mysensors/Arduino/blob/master/libraries/MySensors/MySensor.cpp#L832



  • @cranky

    thanks a lot all of you,
    cranky - i made a similar sketch using the same method with if XXXX > millis:

    #include <SPI.h>
    #include <MySensor.h>  
    #include <DHT.h>  
    
    #define CHILD_ID_HUM 0
    #define CHILD_ID_TEMP 1
    #define HUMIDITY_SENSOR_DIGITAL_PIN 3
    
    
    MySensor gw;
    DHT dht;
    float lastTemp;
    float lastHum;
    boolean metric = true; 
    unsigned long oldTime;
    MyMessage msgHum(CHILD_ID_HUM, V_HUM);
    MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
    
    
    void setup()  
    { 
      gw.begin(NULL, AUTO, true);
      dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN); 
      oldTime = 0;
      // Send the Sketch Version Information to the Gateway
      gw.sendSketchInfo("Repeater Node", "1.0");
    
      // Register all sensors to gw (they will be created as child devices)
      gw.present(CHILD_ID_HUM, S_HUM);
      gw.present(CHILD_ID_TEMP, S_TEMP);
      
      metric = gw.getConfig().isMetric;
    }
    
    void loop()      
    {  
    
      if((millis() - oldTime) > 600000)
      {
      oldTime = millis();  
      
      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);
      }
      }
      gw.process();
    
    }
    

    its just the regular humidity sensor with gw.begin in repeater mode and gw.process in the end(with no sleep time) and the "anti-spam" is the if((millis() - oldtime) > 600000) statement so i still have reading every 10 minutes.

    is that ok or the dht22 delay can interfere with the repeater operation?
    also, the send.sketchc should be "repeater" or "humidity"?


  • Mod

    Using delay can cause the node to miss messages received during that time. Use gw.wait instead.

    I would call the sketch something like "Repeater+Humidity". The name is just for you to make you remember which node does what. It is not used by the system.

    By the way, your indentation is off. The code would be easier to read if you use Ctrl+T in the Arduino IDE (CMD+T on Mac)



  • @abrasha said:

    delay(dht.getMinimumSamplingPeriod());

    ok that ctrl+t is realy a nice tip. thanks.

    about this delay - delay(dht.getMinimumSamplingPeriod());
    it comes with the humidity sensor sketch and i thought it is crucial for the sensor to work.
    did you meant replace this line with the gw.wait?
    maybe i can delete it anyway because the whole loop doesnt perform until 10 minutes passed.



  • mfalkvidd means:

    gw.wait(dht.getMinimumSamplingPeriod());


  • Looking at the code, there's no good reason to use that delay at all. You're already waiting for 600 seconds with the

    if((millis() - oldTime) > 600000)
    

    loop. The Delay is only recommended in the main codebase so that the sensor has time to regenerate the data. Some sensors have to wait for a bit or the measurement will be off, but we're talking about milliseconds here.

    Just delete the whole line:

      delay(dht.getMinimumSamplingPeriod());
    

    and you should be perfectly fine. If you wanted to be on the safe side, you could do the following...

    if((millis() - oldTime) > (600000 +dht.getMinimumSamplingPeriod() )
    

    and that would include any delay that the sensor library might need.

    All the best,
    cranky



  • If cycle interval might become a parameter and for smaller values of this it is better to do it this way

    if((millis() - oldTime) > max(cycleInterval, dht.getMinimumSamplingPeriod() )
    


  • ... and to give the DHT sensor a chance on reading errors to retry and not to wait until next cycle which might be very long:

        for (unsigned int i = 0; i < DHT_MAX_TRIES; i ++) {
          float temperature = dht.getTemperature();
          if (isnan(temperature)) {
            Serial.println("Failed reading temperature from DHT");
            gw.wait(dht.getMinimumSamplingPeriod());
          } else if (temperature != lastTemp) {
            lastTemp = temperature;
            if (!metric) {
              temperature = dht.toFahrenheit(temperature);
            }
            gw.send(msgTemp.set(temperature, 1));
            Serial.print("T: ");
            Serial.println(temperature);
            break;
          }
        }
    

    Repeat the same for humidity of cause.


 

361
Online

7.9k
Users

8.8k
Topics

94.2k
Posts