Openhab 2 Mysensors smart chicken coop



  • I would like to share with you my smart chicken coop project. I have started the project mid summer by building a chicken coop for my wife. The idea came up of making it smart with IOT gaining in popularity i look up the internet on ways to achieve my goals which are to make it easier to take care of our flock and be able to leave the house for few a days. A cheap and effective way to do so was to use the raspberry 3 with openhab2 has controller and mysensors with arduino parts.
    I also wanted to have access everywhere so i am using myopenhab as android app and it works very well so far.
    Mysensors binding makes it a lot easier for a guy like me that had no experience in programming before this project it is a great satisfaction when building the gateway and auto discovering my sensors in openhab. Even if mysensors binding is not ready yet it's very stable and haven't had any problems with it lately.
    HABMIN graphic rule designer is very nice way to implement rules in my project the only thing is i haven't found a way to make them work yet but get back to that has soon as i am done testing mysensors sketch and installing everything in the chicken coop. I hope you enjoy my project has much as i do and i will keep it up to date.
    Please comment if you have new ideas or ways to make it better and thanks for all the help!

    0_1488390357512_poulaller.jpg

    0_1488390402700_poulaller night.jpg

    Ford taurus window motor mechanism and switch
    0_1488391540755_rsz_dscn1139.jpg

    0_1488391888112_rsz_dscn1143.jpg

    0_1488391933990_rsz_1dscn1147.jpg

    0_1488392087210_rsz_dscn1144.jpg

    And these are the parts that are used in my project:

    • RPI3

    • Arduino MEGA2560

    • 8 Channels relay

    • PIR motion sensor (For sensing if chicken are not outside when closing the door also for predator alarm at night)

    • DHT22 (for inside temp and humidity)

    • Ds18b20 (outside temp)

    • Heat lamp (yes i live in north canada and ladies need a little heat to lay eggs)

    • 12volts ventillation (when humidity is to high)

    • LED strip (for inside light)

    • LED (for outside light)

    • Automotive window motor mechanism and switch (to close and open chicken door remotely)

    • 2x Limit switch

      Here is a fritzing diagram it needs work:
      0_1488333376994_Poulailler_bb.jpg

    Mysensors sketch is progressing and doing pretty much what it suppose to do.

    // MySensor Debug
    #define MY_DEBUG
    
    // Enables repeater functionality (relays messages from other nodes)
    //#define MY_REPEATER_FEATURE
    
    
    #define MY_NODE_ID 50
    
    #define MY_RF24_CE_PIN 40
    #define MY_RF24_CS_PIN 53
    #define MY_RF24_MOSI_PIN 51
    #define MY_RF24_MISO_PIN 50
    #define MY_RF24_SCK_PIN 52
    
    #define MY_RADIO_NRF24
    #include <MySensors.h>
    #include <SPI.h>
    #include <Bounce2.h>
    #include <DHT.h>
    #include <DallasTemperature.h>
    #include <OneWire.h>
    
    #define RELAY_PIN    22  // Arduino Digital I/O pin number for relay 
    #define RELAY_PIN_2  23
    #define RELAY_PIN_3  24
    #define RELAY_PIN_4  25
    #define RELAY_PIN_5  26
    #define RELAY_PIN_6  27
    #define BUTTON_PIN   9  // Arduino Digital I/O pin number for button 
    #define BUTTON_PIN_2 10
    #define BUTTON_PIN_3 11
    #define BUTTON_PIN_4 12
    #define BUTTON_PIN_5 17
    #define BUTTON_PIN_6 18
    #define CHILD_ID 11 // Id of the sensor child for 1st relay
    #define CHILD_ID_2 12 // Id of the sensor child for 2nd relay
    #define CHILD_ID_3 13
    #define CHILD_ID_4 14
    #define CHILD_ID_5 15
    #define CHILD_ID_6 16
    #define CHILD_ID_HUM1 7
    #define CHILD_ID_TEMP1 8
    #define ONE_WIRE_BUS 3 // Pin where dallase sensor is connected 
    #define MAX_ATTACHED_DS18B20 1
    #define MOTION_DATA_PIN 5
    #define CHILD_ID_MOTION 5
    // Relay status
    #define RELAY_ON 1
    #define RELAY_OFF 0
    
    // Source of state change (used when printing debug information)
    #define CHANGE_STATE_SOURCE_RADIO 0
    #define CHANGE_STATE_SOURCE_SWITCH 1
    // Set this to the pin you connected the DHT's data pin to
    #define DHT1_DATA_PIN 2
    
    // Set this offset if the sensor has a permanent small offset to the real temperatures
    #define SENSOR_TEMP_OFFSET 0
    
    
    // Sleep time between sensor updates (in milliseconds)
    // Must be >1000ms for DHT22 and >2000ms for DHT11
    static const uint64_t UPDATE_INTERVAL = 2100;
    
    // Force sending an update of the temperature after n sensor reads, so a controller showing the
    // timestamp of the last update doesn't show something like 3 hours in the unlikely case, that
    // the value didn't change since;
    // i.e. the sensor would force sending an update every UPDATE_INTERVAL*FORCE_UPDATE_N_READS [ms]
    static const uint8_t FORCE_UPDATE_N_READS = 10;
    
    float lastTemp1;
    float lastHum1;
    bool lastMotion = false;
    
    uint8_t nNoUpdatesTemp1;
    uint8_t nNoUpdatesHum1;
    uint8_t nNoUpdatesMotion;
    bool metric = true;
    
    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;
    
    
    Bounce debouncer = Bounce();
    int oldValue;
    bool state;
    Bounce debouncer2 = Bounce();
    int oldValue2;
    bool state2;
    Bounce debouncer3 = Bounce();
    int oldValue3;
    bool state3;
    Bounce debouncer4 = Bounce();
    int oldValue4;
    bool state4;
    Bounce debouncer5 = Bounce();
    int oldValue5;
    bool state5;
    Bounce debouncer6 = Bounce();
    int oldValue6;
    bool state6;
    
    MyMessage msgDallas(0,V_TEMP);
    MyMessage msg(CHILD_ID, V_LIGHT);
    MyMessage msg2(CHILD_ID_2, V_LIGHT);
    MyMessage msg3(CHILD_ID_3, V_LIGHT);
    MyMessage msg4(CHILD_ID_4, V_LIGHT);
    MyMessage msg5(CHILD_ID_5, V_LIGHT);
    MyMessage msg6(CHILD_ID_6, V_LIGHT);
    MyMessage msgHum1(CHILD_ID_HUM1, V_HUM);
    MyMessage msgTemp1(CHILD_ID_TEMP1, V_TEMP);
    MyMessage msgMotion(CHILD_ID_MOTION, V_TRIPPED);
    DHT dht;
    
    void before()
    {
      // Startup up the OneWire library
      sensors.begin();
    }
    
    void presentation() {
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("6xrelay-button-pir-dht22-ds-", "1.0");
      // Register all sensors to gw (they will be created as child devices)
      present(CHILD_ID, S_LIGHT);
      present(CHILD_ID_2, S_LIGHT);
      present(CHILD_ID_3, S_LIGHT);
      present(CHILD_ID_4, S_LIGHT);
      present(CHILD_ID_5, S_LIGHT);
      present(CHILD_ID_6, S_LIGHT);
      present(CHILD_ID_MOTION, S_MOTION);
      present(CHILD_ID_HUM1, S_HUM);
      present(CHILD_ID_TEMP1, S_TEMP);
      
      metric = getControllerConfig().isMetric;
    }
    
    void setup()
    {
      pinMode(MOTION_DATA_PIN, INPUT); 
       
       // Fetch the number of attached temperature sensors  
      numSensors = sensors.getDeviceCount();
    //numSensors = 1;
      // Present all sensors to controller
      for (int i =0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) {   
         present(i, S_TEMP);
    }
      
      // Setup the button
      pinMode(BUTTON_PIN, INPUT);
      // Activate internal pull-up
      digitalWrite(BUTTON_PIN, HIGH);
    
      // Setup the button
      pinMode(BUTTON_PIN_2, INPUT);
      // Activate internal pull-up
      digitalWrite(BUTTON_PIN_2, HIGH);
    
       // Setup the button
      pinMode(BUTTON_PIN_3, INPUT);
      // Activate internal pull-up
      digitalWrite(BUTTON_PIN_3, HIGH);
    
       // Setup the button
      pinMode(BUTTON_PIN_4, INPUT);
      // Activate internal pull-up
      digitalWrite(BUTTON_PIN_4, HIGH);
    
      // After setting up the button, setup debouncer
      debouncer.attach(BUTTON_PIN);
      debouncer.interval(5);
    
      debouncer2.attach(BUTTON_PIN_2);
      debouncer2.interval(5);
    
      debouncer3.attach(BUTTON_PIN_3);
      debouncer3.interval(5);
    
      debouncer4.attach(BUTTON_PIN_4);
      debouncer4.interval(5);
    
      debouncer5.attach(BUTTON_PIN_5);
      debouncer5.interval(5);
    
      debouncer6.attach(BUTTON_PIN_6);
      debouncer6.interval(5);
    
      // Set the initial values of oldValue/oldValue2 variables from status of physical switches
      //  if this is not done the loop() will detect status change and switch the relays on or off
      debouncer.update();
      debouncer2.update();
      debouncer3.update();
      debouncer4.update();
      debouncer5.update();
      debouncer6.update();
      oldValue = debouncer.read();
      oldValue2 = debouncer2.read();
      oldValue3 = debouncer3.read();
      oldValue4 = debouncer4.read();
      oldValue5 = debouncer5.read();
      oldValue6 = debouncer6.read();
    
      // Make sure relays are off when starting up
      setRelayState(RELAY_PIN, RELAY_OFF);
      // Then set relay pins in output mode
      pinMode(RELAY_PIN, OUTPUT);
    
      digitalWrite(RELAY_PIN_2, RELAY_OFF);
      // Then set relay pins in output mode
      pinMode(RELAY_PIN_2, OUTPUT);
      
       digitalWrite(RELAY_PIN_3, RELAY_OFF);
      // Then set relay pins in output mode
      pinMode(RELAY_PIN_3, OUTPUT);
    
       digitalWrite(RELAY_PIN_4, RELAY_OFF);
      // Then set relay pins in output mode
      pinMode(RELAY_PIN_4, OUTPUT);
    
      digitalWrite(RELAY_PIN_5, RELAY_OFF);
      // Then set relay pins in output mode
      pinMode(RELAY_PIN_5, OUTPUT);
    
      digitalWrite(RELAY_PIN_6, RELAY_OFF);
      // Then set relay pins in output mode
      pinMode(RELAY_PIN_6, OUTPUT);
    
      // Set relay to last known state (using eeprom storage)
      state = loadState(CHILD_ID);
      setRelayState(RELAY_PIN, state);
      state2 = loadState(CHILD_ID_2);
      setRelayState(RELAY_PIN_2, state2);
      state3 = loadState(CHILD_ID_3);
      setRelayState(RELAY_PIN_3, state3);
      state4 = loadState(CHILD_ID_4);
      setRelayState(RELAY_PIN_4, state4);
      state5 = loadState(CHILD_ID_5);
      setRelayState(RELAY_PIN_5, state5);
      state6 = loadState(CHILD_ID_6);
      setRelayState(RELAY_PIN_6, state6);
      
    }
    
    void loop()
    {
      bool tripped = digitalRead(MOTION_DATA_PIN) == HIGH;
    if (tripped || nNoUpdatesMotion == FORCE_UPDATE_N_READS) {
        lastMotion = tripped;
        Serial.println(tripped);
        send(msgMotion.set(tripped?"1":"0"));  // Send tripped value to gw
        nNoUpdatesMotion = 0;
      }
      else if (lastMotion) {
        Serial.println(tripped);
        send(msgMotion.set(tripped?"1":"0"));  // Send tripped value to gw
        nNoUpdatesMotion = 0;
      }
      else {
        nNoUpdatesMotion++;
      }
      
      // 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(msgDallas.setSensor(i).set(temperature,1));
          Serial.print("Dallas");
          Serial.println(i);
          Serial.println(" :");
        Serial.println(temperature);
          // Save new temperatures for next compare
          lastTemperature[i]=temperature;
        //}
      }
    
    // Sleep for a while to save energy
      wait(UPDATE_INTERVAL);
    
       
      dht.setup(DHT1_DATA_PIN); // set data pin of DHT1 sensor
      if (UPDATE_INTERVAL <= dht.getMinimumSamplingPeriod()) {
        Serial.println("Warning: UPDATE_INTERVAL is smaller than supported by the sensor!");
      }
      // Sleep for the time of the minimum sampling period to give the sensor time to power up
      // (otherwise, timeout errors might occure for the first reading)
      wait(dht.getMinimumSamplingPeriod());
      
      // Force reading sensor, so it works also after sleep()
      dht.readSensor(true);
      
      // Get temperature from DHT library
      float temperature1 = dht.getTemperature();
      if (isnan(temperature1)) {
        Serial.println("Failed reading temperature from DHT!");
      } else if (temperature1 != lastTemp1 || nNoUpdatesTemp1 == FORCE_UPDATE_N_READS) {
        // Only send temperature if it changed since the last measurement or if we didn't send an update for n times
        lastTemp1 = temperature1;
        if (!metric) {
          temperature1 = dht.toFahrenheit(temperature1);
        }
        // Reset no updates counter
        nNoUpdatesTemp1 = 0;
        temperature1 += SENSOR_TEMP_OFFSET;
        send(msgTemp1.set(temperature1, 1));
    
        //#ifdef MY_DEBUG
        //Serial.print("T1: ");
        //Serial.println(temperature1);
        //#endif
      } else {
        // Increase no update counter if the temperature stayed the same
        nNoUpdatesTemp1++;
      }
    
      // Get humidity from DHT library
      float humidity1 = dht.getHumidity();
      if (isnan(humidity1)) {
        Serial.println("Failed reading humidity from DHT");
      } else if (humidity1 != lastHum1 || nNoUpdatesHum1 == FORCE_UPDATE_N_READS) {
        // Only send humidity if it changed since the last measurement or if we didn't send an update for n times
        lastHum1 = humidity1;
        // Reset no updates counter
        nNoUpdatesHum1 = 0;
        send(msgHum1.set(humidity1, 1));
        
        #ifdef MY_DEBUG
        Serial.print("H1: ");
        Serial.println(humidity1);
        #endif
      } else {
        // Increase no update counter if the humidity stayed the same
        nNoUpdatesHum1++;
      }
    
      // Sleep for a while to save energy
      wait(UPDATE_INTERVAL); 
    
    
      debouncer.update();
      debouncer2.update();
      debouncer3.update();
      debouncer4.update();
      debouncer4.update();
      debouncer4.update();
      // Get the update value
      int value = debouncer.read();
      int value2 = debouncer2.read();
      int value3 = debouncer3.read();
      int value4 = debouncer4.read();
      int value5 = debouncer5.read(); 
      int value6 = debouncer6.read(); 
    
    
      if (value != oldValue && value == 0) {
        send(msg.set(state ? false : true), true); // Send new state and request ack back
        // Write some debug info
        printStateChangedDebug(CHANGE_STATE_SOURCE_SWITCH, CHILD_ID, value);
      }
      oldValue = value;
    
      if (value2 != oldValue2 && value2 == 0) {
        send(msg2.set(state2 ? false : true), true); // Send new state and request ack back
        // Write some debug info
        printStateChangedDebug(CHANGE_STATE_SOURCE_SWITCH, CHILD_ID_2, value2);
      }
      oldValue2 = value2;
    
     if (value3 != oldValue3) {
        send(msg3.set(state3 ? false : true), true); // Send new state and request ack back
        // Write some debug info
        printStateChangedDebug(CHANGE_STATE_SOURCE_SWITCH, CHILD_ID_3, value3);
      }
      oldValue3 = value3;
    
      if (value4 != oldValue4) {
        send(msg4.set(state4 ? false : true), true); // Send new state and request ack back
        // Write some debug info
        printStateChangedDebug(CHANGE_STATE_SOURCE_SWITCH, CHILD_ID_4, value4);
      }
      oldValue4 = value4;
    
      if (value5 != oldValue5) {
        send(msg5.set(state5 ? false : true), true); // Send new state and request ack back
        // Write some debug info
        printStateChangedDebug(CHANGE_STATE_SOURCE_SWITCH, CHILD_ID_5, value5);
      }
      oldValue5 = value5;
    
      if (value6 != oldValue6) {
        send(msg6.set(state6 ? false : true), true); // Send new state and request ack back
        // Write some debug info
        printStateChangedDebug(CHANGE_STATE_SOURCE_SWITCH, CHILD_ID_6, value6);
      }
      oldValue6 = value6;
    
     }
    
    void receive(const MyMessage &message) {
      if (message.type == V_STATUS) {  
        switch (message.sensor) {
            case CHILD_ID:                                                    
              state = message.getBool();    
              setRelayState(RELAY_PIN, state); // Change relay state
              saveState(CHILD_ID, state);      // Store state in eeprom
           // Write some debug info
              printStateChangedDebug(CHANGE_STATE_SOURCE_RADIO, CHILD_ID, state);
             break;
            case CHILD_ID_2:                                                     
              state2 = message.getBool();
              setRelayState(RELAY_PIN_2, state2);
              saveState(CHILD_ID_2, state2);
           // Write some debug info
              printStateChangedDebug(CHANGE_STATE_SOURCE_RADIO, CHILD_ID_2, state2);
             break;
            case CHILD_ID_3:                                                     
              state3 = message.getBool();
              setRelayState(RELAY_PIN_3, state3);
              saveState(CHILD_ID_3, state3);
           // Write some debug info
              printStateChangedDebug(CHANGE_STATE_SOURCE_RADIO, CHILD_ID_3, state3);
           break;
            case CHILD_ID_4:                                                    
              state4 = message.getBool();
              setRelayState(RELAY_PIN_4, state4);
              saveState(CHILD_ID_4, state4);
           // Write some debug info
              printStateChangedDebug(CHANGE_STATE_SOURCE_RADIO, CHILD_ID_4, state4);
             break;
            case CHILD_ID_5:                                           
              state5 = message.getBool();
              setRelayState(RELAY_PIN_5, state5);
              saveState(CHILD_ID_5, state5);
           // Write some debug info
              printStateChangedDebug(CHANGE_STATE_SOURCE_RADIO, CHILD_ID_5, state5); 
             break;
          case CHILD_ID_6:                                                    
              state6 = message.getBool();
              setRelayState(RELAY_PIN_6, state6);
              saveState(CHILD_ID_6, state6);
           // Write some debug info
              printStateChangedDebug(CHANGE_STATE_SOURCE_RADIO, CHILD_ID_6, state6);  
             break;
            
        }
      }   
    }
    
    // Set status of a relay pin
    void setRelayState(byte relayPin, bool value) {
      digitalWrite(relayPin, value ? RELAY_ON : RELAY_OFF);
    }
    
    // Print debug info, centralized in one place to minimize memory usage and have only one #ifdef MY_DEBUG for all state change messages
    void printStateChangedDebug(int source, int sensorID, bool value) {
    #ifdef MY_DEBUG
      Serial.print(F("Sensor value changed, source="));
      Serial.print(source == CHANGE_STATE_SOURCE_RADIO ? F("Radio") : F("Physical switch"));
      Serial.print(F(", Sensor="));
      Serial.print(sensorID);
      Serial.print(F(", New status: "));
      Serial.println(value);
    #endif
    } ```

  • Hardware Contributor

    @Ticupolu - Nice 🙂 Any images?
    Maybe you should enter the project in the contest 2017? (Tag the project with "Contest2017" and "MySensors" and submit it to openhardware.io.)



  • @sundberg84 Thank you i will work on my project later on today and put some images.


  • Hero Member

    That is a good looking hen house! Good luck with your project



  • Anybody had any luck using habmin rules designer in openhab2 with mysensors binding? I've lost a lot of time and just about to give up on oh2...is there a better controller more user frendly to use with mysensors?


  • Hardware Contributor

    I liked domoticz (was very easy to set up and use). Together with dzVents scripting wasn't that difficult either. But I also had some problem with it lately, so I was actually thinking about switching to openhab (2).



  • This post is deleted!


Suggested Topics

  • 16
  • 9
  • 5
  • 13
  • 7
  • 1
  • 1
  • 103

50
Online

11.4k
Users

11.1k
Topics

112.7k
Posts