Multiple Sensors on Gateway



  • Hello,
    I Want to use multiple sensors (motion sensor, temperature, rain sensor etc) on one Arduino MEGA.

    For the moment I use a module with 4 relays, 2 Dallas temperature sensors, 1 motion sensor(I would like to change the sketch to use multiple motion sensor as the temperature example) and the problem is that I have to prioritize the sensors, for example I need update for the temperature sensors every 20-30 seconds but the motion sensor should update instantly.

    Here is my code based on the MySensors examples.

    // Debug
    #define MY_DEBUG
    // Partea cu Conexiunea la net 
    #define MY_GATEWAY_ENC28J60
    #define MY_IP_ADDRESS 192,168,1,66  
    #define MY_PORT 5003   
    #define MY_MAC_ADDRESS 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
    #include <UIPEthernet.h>
    // Sfarsit parte
    
    
    
    #include <SPI.h>
    #include <MySensors.h>  
    #include <DallasTemperature.h>
    #include <OneWire.h>
    
    //==TEMP==
    #define COMPARE_TEMP 1 // Send temperature only if changed? 1 = Yes 0 = No
    #define ONE_WIRE_BUS 2 // Pin where dallase sensor is connected 
    unsigned long SLEEP_TIME = 20000; // Sleep time between reads (in milliseconds)
    #define MAX_ATTACHED_DS18B20 1
    OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
    DallasTemperature sensors(&oneWire); // Pass the oneWire reference to Dallas Temperature. 
    float lastTemperature[MAX_ATTACHED_DS18B20];
    int numSensors=0;
    bool receivedConfig = false;
    bool metric = true;
    // Initialize temperature message
    MyMessage msgtemp(0,V_TEMP);
    //==TEMP==
    
    //==RELAY==
    #define RELAY_1  8  // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
    #define NUMBER_OF_RELAYS 4 // 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
    //==RELAY==
    
    //==MOTION==
    
    #define DIGITAL_INPUT_SENSOR 3   // The digital input you attached your motion sensor.  (Only 2 and 3 generates interrupt!)
    #define CHILD_ID_MISCARE 15   // Id of the sensor child
    unsigned long SEND_FREQUENCY = 10;              // Minimum time between send (in seconds). We don't want to spam the gateway.
    long lastDebounce = 0;
    long debounceDelay = 500;
    unsigned long lastSend;
    unsigned long currentTime;
    unsigned int isTripped =0;
    
    // Initialize motion message
    MyMessage msgmiscare(CHILD_ID_MISCARE, V_TRIPPED);
    
    void before()
    {
      // Startup up the OneWire library
      sensors.begin();
    
      for (int sensor=1, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS; sensor++, pin++) {
        // Then set relay pins in output mode
        pinMode(pin, OUTPUT);
        // Set relay to last known state (using eeprom storage)
        digitalWrite(pin, loadState(sensor)?RELAY_ON:RELAY_OFF);
      }
    }
    
    void setup()  
    { 
      // requestTemperatures() will not block current thread
      sensors.setWaitForConversion(false);
        pinMode(DIGITAL_INPUT_SENSOR, INPUT);      // sets the motion sensor digital pin as input
      lastSend = -1;
    }
    
    void presentation() {
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("Arduino SmartHub", "1.1");
      present(CHILD_ID_MISCARE, S_MOTION);
    
      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)
        present(sensor, S_BINARY);
      }
      // Fetch the number of attached temperature sensors  
      numSensors = sensors.getDeviceCount();
    
      // Present all sensors to controller
      for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) {   
         present(i, S_TEMP);
      }
    }
    
    void loop()     
    {     
    //==MOTION==
     
      currentTime = millis();
    // Read digital motion value
      boolean tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH; 
      Serial.println(tripped);
      Serial.println(currentTime-lastSend);
    if ((isTripped==0) &&(tripped==1)) {
        Serial.println("tripped");
        send(msgmiscare.set(tripped?"1":"0"));  // Send tripped value to gw
        lastSend=currentTime;
        isTripped=1;
      }
    if ((tripped==0) && (isTripped==1) && (currentTime - lastSend > 1000*SEND_FREQUENCY)){
        Serial.println("un-tripped");
        send(msgmiscare.set(tripped?"1":"0"));  // Send tripped value to gw
        lastSend=currentTime;
        isTripped=0;
      }
    
      // Fetch temperatures from Dallas sensors
      sensors.requestTemperatures();
    
      // query conversion time and sleep until conversion completed
      int16_t conversionTime = sensors.millisToWaitForConversion(sensors.getResolution());
      // sleep() call can be replaced by wait() call if node need to process incoming messages (or if node is repeater)
      //wait(conversionTime);
    
      // Read temperatures and send them to controller 
      for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) {
    
        // Fetch and round temperature to one decimal
        float temperature = static_cast<float>(static_cast<int>((getControllerConfig().isMetric?sensors.getTempCByIndex(i):sensors.getTempFByIndex(i)) * 10.)) / 10.;
    
        // Only send data if temperature has changed and no error
        #if COMPARE_TEMP == 1
        if (lastTemperature[i] != temperature && temperature != -127.00 && temperature != 85.00) {
        #else
        if (temperature != -127.00 && temperature != 85.00) {
        #endif
    
          // Send in the new temperature
          send(msgtemp.setSensor(i).set(temperature,1));
          // Save new temperatures for next compare
          lastTemperature[i]=temperature;
        }
      }
      wait(SLEEP_TIME);
     }
    
    void receive(const MyMessage &message) //Loop for receiving messages
    {
      // We only expect one type of message from controller. But we better check anyway.
      if (message.type==V_STATUS) {
        // Change relay state
        digitalWrite(message.sensor-1+RELAY_1, message.getBool()?RELAY_ON:RELAY_OFF);
        // Store state in eeprom
        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());
      }
    }
    

  • Mod

    How about using interrupts? You connect the pir sensors on the pins supporting interrupts.



  • Thank you for your reply!
    The motion sensor part from the sketch works perfectly, the problem is with the temperature part.

    If I am using wait or sleep for temperature, arduino won't listen the motion sensor until the time elapses.

    If I am commenting the wait the sensor will spam the controller until the controller stop receiving data from arduino.


  • Mod

    That's my point, use interrupts that will "wake" the Arduino when pin changes status and process the pir signal



  • @gohan I understand what you are saying but if I am doing in that way I will spam the controller with the interrupts(flaps) right now it works like this
    if pin=0 send the state of the pin(the next update is when pin state changes), if pin=1 send the state and wait for 10 seconds for the next update.

    For the moment I have found a solution with millis[if(time%frequency==0)]:

    time=millis()/1000;
    if(time%10 ==0)
    

    Any suggestion for improving this part?


Log in to reply
 

Suggested Topics

17
Online

11.4k
Users

11.1k
Topics

112.7k
Posts