Skip to content
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. My Project
  3. My generic room-senser (Sensebender with Motion and Light)
  • Getting Started
  • Controller
  • Build
  • Hardware
  • Download/API
  • Forum
  • Store

My generic room-senser (Sensebender with Motion and Light)

Scheduled Pinned Locked Moved My Project
16 Posts 5 Posters 15.6k Views 7 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • DwaltD Offline
    DwaltD Offline
    Dwalt
    wrote on last edited by
    #1

    I have been trying to make a generic sensor to deploy throughout my house to provide variables which my home automation can work from. The primary data streams I was looking for are temp, motion sensing and light level. From these three, a lot of automation can be created. The Sensebender is the perfect platform to build from - small and designed for battery power. I added a ambient light phototransistor and a low power panasonic PIR and used these cheap housings from ALIExpress. I drove the phototransistor from a digital pin (D7) so it could be powered on and off every time thru the loop and powered the whole thing from a CR123 battery.

    The sketch was based upon the Sensebender Micro sketch with minor additions for the PIR and light level sensor. The PIR is setup on the interrupt on D3 and the light sensor follows the same timer schedule as the Si7021.

    // Default sensor sketch for Sensebender Micro module
    // Act as a temperature / humidity sensor by default.
    //
    // If A0 is held low while powering on, it will enter testmode, which verifies all on-board peripherals
    // 
    // Battery voltage is repported as child sensorId 199, as well as battery percentage (Internal message)
    
    
    #include <MySensor.h>
    #include <Wire.h>
    #include <SI7021.h>
    #include <SPI.h>
    #include <SPIFlash.h>
    #include <EEPROM.h>  
    #include <sha204_lib_return_codes.h>
    #include <sha204_library.h>
    
    // Define a static node address, remove if you want auto address assignment
    //#define NODE_ADDRESS   3
    
    #define RELEASE "1.0"
    
    // Child sensor ID's
    #define CHILD_ID_TEMP  1
    #define CHILD_ID_HUM   2
    #define CHILD_ID_PIR   3
    #define CHILD_ID_LIGHT  4
    #define CHILD_ID_BATT  199
    
    // How many milli seconds between each measurement
    #define MEASURE_INTERVAL 60000
    
    // FORCE_TRANSMIT_INTERVAL, this number of times of wakeup, the sensor is forced to report all values to the controller
    #define FORCE_TRANSMIT_INTERVAL 30 
    
    // When MEASURE_INTERVAL is 60000 and FORCE_TRANSMIT_INTERVAL is 30, we force a transmission every 30 minutes.
    // Between the forced transmissions a tranmission will only occur if the measured value differs from the previous measurement
    
    //Pin definitions
    #define TEST_PIN       A0
    #define LED_PIN        A2
    #define PIR_SENSOR_DIGITAL 3
    #define LIGHT_PIN A1
    #define ATSHA204_PIN   17 // A3
    
    const int sha204Pin = ATSHA204_PIN;
    atsha204Class sha204(sha204Pin);
    
    SI7021 humiditySensor;
    SPIFlash flash(8, 0x1F65);
    
    MySensor gw;
    
    // Sensor messages
    MyMessage msgHum(CHILD_ID_HUM, V_HUM);
    MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
    MyMessage msgPir(CHILD_ID_PIR, V_TRIPPED);
    MyMessage msgLight(CHILD_ID_LIGHT, V_LIGHT_LEVEL);
    MyMessage msgBattery(CHILD_ID_BATT, V_VOLTAGE);
    
    // Global settings
    int measureCount = 0;
    boolean isMetric = true;
    
    
    // Storage of old measurements
    float lastTemperature = -100;
    int lastHumidity = -100;
    int lastLightLevel = -1;
    long lastBattery = -100;
    boolean lastTrippedState;
    
    bool highfreq = true;
    
    void setup() {
    
      pinMode(LED_PIN, OUTPUT);
      digitalWrite(LED_PIN, LOW);
    
      pinMode(PIR_SENSOR_DIGITAL, INPUT);
      digitalWrite(PIR_SENSOR_DIGITAL, HIGH);
    
      pinMode(7, OUTPUT);  // “power pin” for Light Sensor
      digitalWrite(7, LOW);  // switch power off
    
      Serial.begin(115200);
      Serial.print(F("Sensebender Micro FW "));
      Serial.print(RELEASE);
      Serial.flush();
    
      // First check if we should boot into test mode
    
      pinMode(TEST_PIN,INPUT);
      digitalWrite(TEST_PIN, HIGH); // Enable pullup
      if (!digitalRead(TEST_PIN)) testMode();
    
      digitalWrite(TEST_PIN,LOW);
      digitalWrite(LED_PIN, HIGH); 
    
    #ifdef NODE_ADDRESS
      gw.begin(NULL, NODE_ADDRESS, false);
    #else
      gw.begin(NULL,AUTO,false);
    #endif
    
      digitalWrite(LED_PIN, LOW);
    
      humiditySensor.begin();
      Serial.flush();
      Serial.println(F(" - Online!"));
      gw.sendSketchInfo("Sensebender 4-Way", RELEASE);
      
      gw.present(CHILD_ID_TEMP,S_TEMP);
      gw.present(CHILD_ID_HUM,S_HUM);
      gw.present(CHILD_ID_PIR, S_MOTION);
      gw.present(CHILD_ID_LIGHT, S_LIGHT_LEVEL);
      
      isMetric = gw.getConfig().isMetric;
      Serial.print("isMetric: "); Serial.println(isMetric);
    
    }
    
    
    // Main loop function
    void loop() {
      measureCount ++;
      bool forceTransmit = false;
    
      // When we wake up the 5th time after power on, switch to 1Mhz clock
      // This allows us to print debug messages on startup (as serial port is dependend on oscilator settings).
      if ((measureCount == 5) && highfreq) switchClock(1<<CLKPS2); // Switch to 1Mhz for the reminder of the sketch, save power.
      
      if (measureCount > FORCE_TRANSMIT_INTERVAL) { // force a transmission
        forceTransmit = true; 
        measureCount = 0;
      }
    
      gw.process();
      sendBattLevel(forceTransmit);
      digitalWrite(7, HIGH); // switch power on to LDR
      sendTempHumidityMeasurements(forceTransmit);
      sendLight(forceTransmit);
      digitalWrite(7, LOW); // switch power off to LDR
      sendPir();
      
      gw.sleep(PIR_SENSOR_DIGITAL - 2, CHANGE, MEASURE_INTERVAL);  
    }
    
    /*
     * Sends temperature and humidity from Si7021 sensor
     *
     * Parameters
     * - force : Forces transmission of a value (even if it's the same as previous measurement)
     */
    void sendTempHumidityMeasurements(bool force)
    {
      if (force) {
        lastHumidity = -100;
        lastTemperature = -100;
      }
      
      si7021_env data = humiditySensor.getHumidityAndTemperature();
      
      float temperature = (isMetric ? data.celsiusHundredths : data.fahrenheitHundredths) / 100.0;
        
      int humidity = data.humidityPercent;
    
      if ((lastTemperature != temperature) | (lastHumidity != humidity)) {
        Serial.print("T: ");Serial.println(temperature);
        Serial.print("H: ");Serial.println(humidity);
        
        gw.send(msgTemp.set(temperature,1));
        gw.send(msgHum.set(humidity));
        lastTemperature = temperature;
        lastHumidity = humidity;
      }
    }
    
    /*   
     *  Sends Motion alert on interupt
     */
    
    void sendPir() // Get value of PIR
    {
      boolean tripped = digitalRead(PIR_SENSOR_DIGITAL) == HIGH; // Get value of PIR
      if (tripped != lastTrippedState)
      {  
        Serial.println(tripped? "tripped" : "not tripped");
        gw.send(msgPir.set(tripped?"1":"0"));  // Send tripped value to gw//
      }
      lastTrippedState = tripped;
      
      
        
      }
      
    
    /*
     * Sends Ambient Light Sensor information
     * 
     * Parameters
     * - force : Forces transmission of a value
     */
    
    void sendLight(bool force) // Get light level
    {
      if (force) lastLightLevel = -1;
      int lightLevel =  (analogRead(LIGHT_PIN)) / 10.23;
      if (lightLevel != lastLightLevel) {
       gw.send(msgLight.set(lightLevel));
        lastLightLevel = lightLevel;
      }
      Serial.print("Light: ");
      Serial.println(lightLevel);
    }
    
    /*
     * Sends battery information (both voltage, and battery percentage)
     *
     * Parameters
     * - force : Forces transmission of a value
     */
    void sendBattLevel(bool force)
    {
      if (force) lastBattery = -1;
      long vcc = readVcc();
      if (vcc != lastBattery) {
        lastBattery = vcc;
        // Calculate percentage
    
        vcc = vcc - 1900; // subtract 1.9V from vcc, as this is the lowest voltage we will operate at
        
        long percent = vcc / 14.0;
        gw.sendBatteryLevel(percent);
      }
    }
    
    long readVcc() {
      // Read 1.1V reference against AVcc
      // set the reference to Vcc and the measurement to the internal 1.1V reference
      #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
        ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
      #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
        ADMUX = _BV(MUX5) | _BV(MUX0);
      #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
        ADcdMUX = _BV(MUX3) | _BV(MUX2);
      #else
        ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
      #endif  
     
      delay(2); // Wait for Vref to settle
      ADCSRA |= _BV(ADSC); // Start conversion
      while (bit_is_set(ADCSRA,ADSC)); // measuring
     
      uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH  
      uint8_t high = ADCH; // unlocks both
     
      long result = (high<<8) | low;
     
      result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
      return result; // Vcc in millivolts
    }
    
    void switchClock(unsigned char clk)
    {
      cli();
      
      CLKPR = 1<<CLKPCE; // Set CLKPCE to enable clk switching
      CLKPR = clk;  
      sei();
      highfreq = false;
    }
    
    
    // Verify all peripherals, and signal via the LED if any problems.
    void testMode()
    {
      uint8_t rx_buffer[SHA204_RSP_SIZE_MAX];
      uint8_t ret_code;
      byte tests = 0;
      
      digitalWrite(LED_PIN, HIGH); // Turn on LED.
      Serial.println(F(" - TestMode"));
      Serial.println(F("Testing peripherals!"));
      Serial.flush();
      Serial.print(F("-> SI7021 : ")); 
      Serial.flush();
      
      if (humiditySensor.begin()) 
      {
        Serial.println(F("ok!"));
        tests ++;
      }
      else
      {
        Serial.println(F("failed!"));
      }
      Serial.flush();
    
      Serial.print(F("-> Flash : "));
      Serial.flush();
      if (flash.initialize())
      {
        Serial.println(F("ok!"));
        tests ++;
      }
      else
      {
        Serial.println(F("failed!"));
      }
      Serial.flush();
    
      
      Serial.print(F("-> SHA204 : "));
      ret_code = sha204.sha204c_wakeup(rx_buffer);
      Serial.flush();
      if (ret_code != SHA204_SUCCESS)
      {
        Serial.print(F("Failed to wake device. Response: ")); Serial.println(ret_code, HEX);
      }
      Serial.flush();
      if (ret_code == SHA204_SUCCESS)
      {
        ret_code = sha204.getSerialNumber(rx_buffer);
        if (ret_code != SHA204_SUCCESS)
        {
          Serial.print(F("Failed to obtain device serial number. Response: ")); Serial.println(ret_code, HEX);
        }
        else
        {
          Serial.print(F("Ok (serial : "));
          for (int i=0; i<9; i++)
          {
            if (rx_buffer[i] < 0x10)
            {
              Serial.print('0'); // Because Serial.print does not 0-pad HEX
            }
            Serial.print(rx_buffer[i], HEX);
          }
          Serial.println(")");
          tests ++;
        }
    
      }
      Serial.flush();
    
      Serial.println(F("Test finished"));
      
      if (tests == 3) 
      {
        Serial.println(F("Selftest ok!"));
        while (1) // Blink OK pattern!
        {
          digitalWrite(LED_PIN, HIGH);
          delay(200);
          digitalWrite(LED_PIN, LOW);
          delay(200);
        }
      }
      else 
      {
        Serial.println(F("----> Selftest failed!"));
        while (1) // Blink FAILED pattern! Rappidly blinking..
        {
        }
      }  
    }
    
    
    

    Photos of the assembly -
    The parts:
    IMG_20150622_115335.jpg
    The board with radio, resistors and FTDI header:
    IMG_20150622_131215.jpg
    The board connected to the battery and sensors (the sensors were wire-wrapped utilizing the 'whiskers' from the resistors):
    IMG_20150622_151216.jpg
    The finished enclosures (I made a few):
    IMG_20150622_152033.jpg
    IMG_20150622_153431.jpg

    They work pretty well but after a few days I have noticed some peculiarities which I hope the forum could assist with:

    1. The Si7021 is VERY sensitive and as a result, the sensors update every minute or two and have not yet slept more than 2-3 minutes. Is there an easy way to fix this in the code so they only transmit every .3 or .5 degree temperature change?

    2. The Panasonic PIRs I am using do not have trim pots to adjust their 'standby-after-alert' time and return to detecting motion after 2.5 seconds which leads to a lot of radio traffic to the gateway when someone is in the room. I thought about 'detaching' the interrupt after alert and 'reattaching' on the next run thru the loop. The would give it up to 60 seconds of standby which would work for my needs but I do not know exactly how to go about this and if it would cause more problems than solve.

    3. I oriented the headers over the blank part of the board (over the stylish logo). They are on the opposite side of the board from the radio but are located directly in line with the antenna (see photo 2). Is this a bad idea? I have not observed any transmission problems or at least I do not think I have...

    Veralite UI5 :: IBoard Ethernet GW :: MyS 1.5

    Moshe LivneM 1 Reply Last reply
    5
    • DwaltD Dwalt

      I have been trying to make a generic sensor to deploy throughout my house to provide variables which my home automation can work from. The primary data streams I was looking for are temp, motion sensing and light level. From these three, a lot of automation can be created. The Sensebender is the perfect platform to build from - small and designed for battery power. I added a ambient light phototransistor and a low power panasonic PIR and used these cheap housings from ALIExpress. I drove the phototransistor from a digital pin (D7) so it could be powered on and off every time thru the loop and powered the whole thing from a CR123 battery.

      The sketch was based upon the Sensebender Micro sketch with minor additions for the PIR and light level sensor. The PIR is setup on the interrupt on D3 and the light sensor follows the same timer schedule as the Si7021.

      // Default sensor sketch for Sensebender Micro module
      // Act as a temperature / humidity sensor by default.
      //
      // If A0 is held low while powering on, it will enter testmode, which verifies all on-board peripherals
      // 
      // Battery voltage is repported as child sensorId 199, as well as battery percentage (Internal message)
      
      
      #include <MySensor.h>
      #include <Wire.h>
      #include <SI7021.h>
      #include <SPI.h>
      #include <SPIFlash.h>
      #include <EEPROM.h>  
      #include <sha204_lib_return_codes.h>
      #include <sha204_library.h>
      
      // Define a static node address, remove if you want auto address assignment
      //#define NODE_ADDRESS   3
      
      #define RELEASE "1.0"
      
      // Child sensor ID's
      #define CHILD_ID_TEMP  1
      #define CHILD_ID_HUM   2
      #define CHILD_ID_PIR   3
      #define CHILD_ID_LIGHT  4
      #define CHILD_ID_BATT  199
      
      // How many milli seconds between each measurement
      #define MEASURE_INTERVAL 60000
      
      // FORCE_TRANSMIT_INTERVAL, this number of times of wakeup, the sensor is forced to report all values to the controller
      #define FORCE_TRANSMIT_INTERVAL 30 
      
      // When MEASURE_INTERVAL is 60000 and FORCE_TRANSMIT_INTERVAL is 30, we force a transmission every 30 minutes.
      // Between the forced transmissions a tranmission will only occur if the measured value differs from the previous measurement
      
      //Pin definitions
      #define TEST_PIN       A0
      #define LED_PIN        A2
      #define PIR_SENSOR_DIGITAL 3
      #define LIGHT_PIN A1
      #define ATSHA204_PIN   17 // A3
      
      const int sha204Pin = ATSHA204_PIN;
      atsha204Class sha204(sha204Pin);
      
      SI7021 humiditySensor;
      SPIFlash flash(8, 0x1F65);
      
      MySensor gw;
      
      // Sensor messages
      MyMessage msgHum(CHILD_ID_HUM, V_HUM);
      MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
      MyMessage msgPir(CHILD_ID_PIR, V_TRIPPED);
      MyMessage msgLight(CHILD_ID_LIGHT, V_LIGHT_LEVEL);
      MyMessage msgBattery(CHILD_ID_BATT, V_VOLTAGE);
      
      // Global settings
      int measureCount = 0;
      boolean isMetric = true;
      
      
      // Storage of old measurements
      float lastTemperature = -100;
      int lastHumidity = -100;
      int lastLightLevel = -1;
      long lastBattery = -100;
      boolean lastTrippedState;
      
      bool highfreq = true;
      
      void setup() {
      
        pinMode(LED_PIN, OUTPUT);
        digitalWrite(LED_PIN, LOW);
      
        pinMode(PIR_SENSOR_DIGITAL, INPUT);
        digitalWrite(PIR_SENSOR_DIGITAL, HIGH);
      
        pinMode(7, OUTPUT);  // “power pin” for Light Sensor
        digitalWrite(7, LOW);  // switch power off
      
        Serial.begin(115200);
        Serial.print(F("Sensebender Micro FW "));
        Serial.print(RELEASE);
        Serial.flush();
      
        // First check if we should boot into test mode
      
        pinMode(TEST_PIN,INPUT);
        digitalWrite(TEST_PIN, HIGH); // Enable pullup
        if (!digitalRead(TEST_PIN)) testMode();
      
        digitalWrite(TEST_PIN,LOW);
        digitalWrite(LED_PIN, HIGH); 
      
      #ifdef NODE_ADDRESS
        gw.begin(NULL, NODE_ADDRESS, false);
      #else
        gw.begin(NULL,AUTO,false);
      #endif
      
        digitalWrite(LED_PIN, LOW);
      
        humiditySensor.begin();
        Serial.flush();
        Serial.println(F(" - Online!"));
        gw.sendSketchInfo("Sensebender 4-Way", RELEASE);
        
        gw.present(CHILD_ID_TEMP,S_TEMP);
        gw.present(CHILD_ID_HUM,S_HUM);
        gw.present(CHILD_ID_PIR, S_MOTION);
        gw.present(CHILD_ID_LIGHT, S_LIGHT_LEVEL);
        
        isMetric = gw.getConfig().isMetric;
        Serial.print("isMetric: "); Serial.println(isMetric);
      
      }
      
      
      // Main loop function
      void loop() {
        measureCount ++;
        bool forceTransmit = false;
      
        // When we wake up the 5th time after power on, switch to 1Mhz clock
        // This allows us to print debug messages on startup (as serial port is dependend on oscilator settings).
        if ((measureCount == 5) && highfreq) switchClock(1<<CLKPS2); // Switch to 1Mhz for the reminder of the sketch, save power.
        
        if (measureCount > FORCE_TRANSMIT_INTERVAL) { // force a transmission
          forceTransmit = true; 
          measureCount = 0;
        }
      
        gw.process();
        sendBattLevel(forceTransmit);
        digitalWrite(7, HIGH); // switch power on to LDR
        sendTempHumidityMeasurements(forceTransmit);
        sendLight(forceTransmit);
        digitalWrite(7, LOW); // switch power off to LDR
        sendPir();
        
        gw.sleep(PIR_SENSOR_DIGITAL - 2, CHANGE, MEASURE_INTERVAL);  
      }
      
      /*
       * Sends temperature and humidity from Si7021 sensor
       *
       * Parameters
       * - force : Forces transmission of a value (even if it's the same as previous measurement)
       */
      void sendTempHumidityMeasurements(bool force)
      {
        if (force) {
          lastHumidity = -100;
          lastTemperature = -100;
        }
        
        si7021_env data = humiditySensor.getHumidityAndTemperature();
        
        float temperature = (isMetric ? data.celsiusHundredths : data.fahrenheitHundredths) / 100.0;
          
        int humidity = data.humidityPercent;
      
        if ((lastTemperature != temperature) | (lastHumidity != humidity)) {
          Serial.print("T: ");Serial.println(temperature);
          Serial.print("H: ");Serial.println(humidity);
          
          gw.send(msgTemp.set(temperature,1));
          gw.send(msgHum.set(humidity));
          lastTemperature = temperature;
          lastHumidity = humidity;
        }
      }
      
      /*   
       *  Sends Motion alert on interupt
       */
      
      void sendPir() // Get value of PIR
      {
        boolean tripped = digitalRead(PIR_SENSOR_DIGITAL) == HIGH; // Get value of PIR
        if (tripped != lastTrippedState)
        {  
          Serial.println(tripped? "tripped" : "not tripped");
          gw.send(msgPir.set(tripped?"1":"0"));  // Send tripped value to gw//
        }
        lastTrippedState = tripped;
        
        
          
        }
        
      
      /*
       * Sends Ambient Light Sensor information
       * 
       * Parameters
       * - force : Forces transmission of a value
       */
      
      void sendLight(bool force) // Get light level
      {
        if (force) lastLightLevel = -1;
        int lightLevel =  (analogRead(LIGHT_PIN)) / 10.23;
        if (lightLevel != lastLightLevel) {
         gw.send(msgLight.set(lightLevel));
          lastLightLevel = lightLevel;
        }
        Serial.print("Light: ");
        Serial.println(lightLevel);
      }
      
      /*
       * Sends battery information (both voltage, and battery percentage)
       *
       * Parameters
       * - force : Forces transmission of a value
       */
      void sendBattLevel(bool force)
      {
        if (force) lastBattery = -1;
        long vcc = readVcc();
        if (vcc != lastBattery) {
          lastBattery = vcc;
          // Calculate percentage
      
          vcc = vcc - 1900; // subtract 1.9V from vcc, as this is the lowest voltage we will operate at
          
          long percent = vcc / 14.0;
          gw.sendBatteryLevel(percent);
        }
      }
      
      long readVcc() {
        // Read 1.1V reference against AVcc
        // set the reference to Vcc and the measurement to the internal 1.1V reference
        #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
          ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
        #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
          ADMUX = _BV(MUX5) | _BV(MUX0);
        #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
          ADcdMUX = _BV(MUX3) | _BV(MUX2);
        #else
          ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
        #endif  
       
        delay(2); // Wait for Vref to settle
        ADCSRA |= _BV(ADSC); // Start conversion
        while (bit_is_set(ADCSRA,ADSC)); // measuring
       
        uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH  
        uint8_t high = ADCH; // unlocks both
       
        long result = (high<<8) | low;
       
        result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
        return result; // Vcc in millivolts
      }
      
      void switchClock(unsigned char clk)
      {
        cli();
        
        CLKPR = 1<<CLKPCE; // Set CLKPCE to enable clk switching
        CLKPR = clk;  
        sei();
        highfreq = false;
      }
      
      
      // Verify all peripherals, and signal via the LED if any problems.
      void testMode()
      {
        uint8_t rx_buffer[SHA204_RSP_SIZE_MAX];
        uint8_t ret_code;
        byte tests = 0;
        
        digitalWrite(LED_PIN, HIGH); // Turn on LED.
        Serial.println(F(" - TestMode"));
        Serial.println(F("Testing peripherals!"));
        Serial.flush();
        Serial.print(F("-> SI7021 : ")); 
        Serial.flush();
        
        if (humiditySensor.begin()) 
        {
          Serial.println(F("ok!"));
          tests ++;
        }
        else
        {
          Serial.println(F("failed!"));
        }
        Serial.flush();
      
        Serial.print(F("-> Flash : "));
        Serial.flush();
        if (flash.initialize())
        {
          Serial.println(F("ok!"));
          tests ++;
        }
        else
        {
          Serial.println(F("failed!"));
        }
        Serial.flush();
      
        
        Serial.print(F("-> SHA204 : "));
        ret_code = sha204.sha204c_wakeup(rx_buffer);
        Serial.flush();
        if (ret_code != SHA204_SUCCESS)
        {
          Serial.print(F("Failed to wake device. Response: ")); Serial.println(ret_code, HEX);
        }
        Serial.flush();
        if (ret_code == SHA204_SUCCESS)
        {
          ret_code = sha204.getSerialNumber(rx_buffer);
          if (ret_code != SHA204_SUCCESS)
          {
            Serial.print(F("Failed to obtain device serial number. Response: ")); Serial.println(ret_code, HEX);
          }
          else
          {
            Serial.print(F("Ok (serial : "));
            for (int i=0; i<9; i++)
            {
              if (rx_buffer[i] < 0x10)
              {
                Serial.print('0'); // Because Serial.print does not 0-pad HEX
              }
              Serial.print(rx_buffer[i], HEX);
            }
            Serial.println(")");
            tests ++;
          }
      
        }
        Serial.flush();
      
        Serial.println(F("Test finished"));
        
        if (tests == 3) 
        {
          Serial.println(F("Selftest ok!"));
          while (1) // Blink OK pattern!
          {
            digitalWrite(LED_PIN, HIGH);
            delay(200);
            digitalWrite(LED_PIN, LOW);
            delay(200);
          }
        }
        else 
        {
          Serial.println(F("----> Selftest failed!"));
          while (1) // Blink FAILED pattern! Rappidly blinking..
          {
          }
        }  
      }
      
      
      

      Photos of the assembly -
      The parts:
      IMG_20150622_115335.jpg
      The board with radio, resistors and FTDI header:
      IMG_20150622_131215.jpg
      The board connected to the battery and sensors (the sensors were wire-wrapped utilizing the 'whiskers' from the resistors):
      IMG_20150622_151216.jpg
      The finished enclosures (I made a few):
      IMG_20150622_152033.jpg
      IMG_20150622_153431.jpg

      They work pretty well but after a few days I have noticed some peculiarities which I hope the forum could assist with:

      1. The Si7021 is VERY sensitive and as a result, the sensors update every minute or two and have not yet slept more than 2-3 minutes. Is there an easy way to fix this in the code so they only transmit every .3 or .5 degree temperature change?

      2. The Panasonic PIRs I am using do not have trim pots to adjust their 'standby-after-alert' time and return to detecting motion after 2.5 seconds which leads to a lot of radio traffic to the gateway when someone is in the room. I thought about 'detaching' the interrupt after alert and 'reattaching' on the next run thru the loop. The would give it up to 60 seconds of standby which would work for my needs but I do not know exactly how to go about this and if it would cause more problems than solve.

      3. I oriented the headers over the blank part of the board (over the stylish logo). They are on the opposite side of the board from the radio but are located directly in line with the antenna (see photo 2). Is this a bad idea? I have not observed any transmission problems or at least I do not think I have...

      Moshe LivneM Offline
      Moshe LivneM Offline
      Moshe Livne
      Hero Member
      wrote on last edited by
      #2

      @Dwalt as for (1), replace
      if ((lastTemperature != temperature) | (lastHumidity != humidity)) {

      with:

      if (abs(lastTemperature - temperature) < TEMPERATURE_THRESHOLD....

      define the threshold to be how much change you want to be reported. make sure you keep the "lastTempreture=tempreture" inside the if otherwise nothing will ever be reported...

      this is dry run, so please check it before implementing throughout your house. can be implemented same way for humidity

      1 Reply Last reply
      0
      • Moshe LivneM Offline
        Moshe LivneM Offline
        Moshe Livne
        Hero Member
        wrote on last edited by
        #3

        Oh, forgot to say, great project and wonderful housings! i think i'll get some as well. what are the soldered resistors?

        1 Reply Last reply
        0
        • DwaltD Offline
          DwaltD Offline
          Dwalt
          wrote on last edited by
          #4

          Thanks, I will try your suggestion.

          I have a 22k on the PIR to ground and a 2k on the LDR. I need to try differing resistors on the light sensor to adjust to the 3V ( I am used to 5V on my other LDRs).

          Veralite UI5 :: IBoard Ethernet GW :: MyS 1.5

          1 Reply Last reply
          0
          • tbowmoT Offline
            tbowmoT Offline
            tbowmo
            Admin
            wrote on last edited by
            #5

            @Dwalt

            The preprogrammed sketch is a bit outdated, compared to the one on github where I had been working on minimizing transmissions with a moving average.

            Been running the github version for some weeks in my two prototype nodes, but still need some adjustments to the temperature part, as it still seems to trigger a transmit with a little temperature deviation

            1 Reply Last reply
            0
            • tbowmoT Offline
              tbowmoT Offline
              tbowmo
              Admin
              wrote on last edited by
              #6

              Hmm.. seems like some expensive sensors.. 16.75$ from mouser.

              DwaltD 1 Reply Last reply
              0
              • tbowmoT tbowmo

                Hmm.. seems like some expensive sensors.. 16.75$ from mouser.

                DwaltD Offline
                DwaltD Offline
                Dwalt
                wrote on last edited by
                #7

                @tbowmo I think they have been discontinued and that makes them hard to find, I picked them up from a government surplus sale for cheap. I like them because they are very compact and are low power.

                Veralite UI5 :: IBoard Ethernet GW :: MyS 1.5

                tbowmoT 1 Reply Last reply
                0
                • DwaltD Dwalt

                  @tbowmo I think they have been discontinued and that makes them hard to find, I picked them up from a government surplus sale for cheap. I like them because they are very compact and are low power.

                  tbowmoT Offline
                  tbowmoT Offline
                  tbowmo
                  Admin
                  wrote on last edited by
                  #8

                  @Dwalt

                  Mouse has ekmb variants on stock, but as said before they are relatively expensive (19€ a piece for the 2uA version, while 6uA is a bit cheaper). Are thinking that I need a couple of samples next time I order from them.

                  1 Reply Last reply
                  0
                  • M Offline
                    M Offline
                    mvader
                    wrote on last edited by
                    #9

                    @Dwalt - I really like this project and i'm looking to tag along building my own.
                    a few questions if you don't mind.

                    1. what were the resistors for? the battery?
                    2. can i just get the light sensor and run it off d7? i don't need a "light sensor board"?
                    3. i like your choice of case. do you think a double A battery holder will fit inside that? everything else would end up being the same, except i'd be using AA instead of CR123

                    4)how is your battery life?

                    Thanks!

                    DwaltD 1 Reply Last reply
                    0
                    • M mvader

                      @Dwalt - I really like this project and i'm looking to tag along building my own.
                      a few questions if you don't mind.

                      1. what were the resistors for? the battery?
                      2. can i just get the light sensor and run it off d7? i don't need a "light sensor board"?
                      3. i like your choice of case. do you think a double A battery holder will fit inside that? everything else would end up being the same, except i'd be using AA instead of CR123

                      4)how is your battery life?

                      Thanks!

                      DwaltD Offline
                      DwaltD Offline
                      Dwalt
                      wrote on last edited by
                      #10

                      @mvader 1. The resistors are for the LDR and PIR.
                      2. I use LDRs (and occasionally photo transistors) for light measurement. They do not return lux readings but simple voltage readings which can be converted in your sketch to an unscientific % value of light level which is good enough for most HA purposes.
                      3. The case is too small for my 2-AA battery holders.

                      Veralite UI5 :: IBoard Ethernet GW :: MyS 1.5

                      Moshe LivneM 1 Reply Last reply
                      0
                      • DwaltD Dwalt

                        @mvader 1. The resistors are for the LDR and PIR.
                        2. I use LDRs (and occasionally photo transistors) for light measurement. They do not return lux readings but simple voltage readings which can be converted in your sketch to an unscientific % value of light level which is good enough for most HA purposes.
                        3. The case is too small for my 2-AA battery holders.

                        Moshe LivneM Offline
                        Moshe LivneM Offline
                        Moshe Livne
                        Hero Member
                        wrote on last edited by
                        #11

                        @Dwalt how is the battery holding? I have a need for very similar sensors but with hall effect or reed to sense the opening and closing of the air conditioning flaps to sense if they are on or off. The case is too small for 2xaa or 2xaaa so looking at other ideas. I remember something being said about using a li-io battery is not a great idea? or was it only rechargeable?

                        DwaltD 1 Reply Last reply
                        0
                        • Moshe LivneM Moshe Livne

                          @Dwalt how is the battery holding? I have a need for very similar sensors but with hall effect or reed to sense the opening and closing of the air conditioning flaps to sense if they are on or off. The case is too small for 2xaa or 2xaaa so looking at other ideas. I remember something being said about using a li-io battery is not a great idea? or was it only rechargeable?

                          DwaltD Offline
                          DwaltD Offline
                          Dwalt
                          wrote on last edited by
                          #12

                          @Moshe-Livne The batteries have not dropped in the last two weeks although they all read around 80% during the first battery report. One of three actually has dropped 1%, the other two are steady. The 80% initial reading comes from the sketch which I believe is calibrated for 3.3V as 100%. I tested my CR123s before using them and they all read exactly 3V. They are Lithium (Li-MNO2) but not rechargeable (Lithium Ion). Typically they run around $1-$1.5. I picked up around 50 when RadioShack went belly-up this winter for 5 for $1. They have a very small self discharge rate and 10 year shelf life. Below is a picture of my case lid with a 2-AA holder inserted. Technically it fits, but no room for anything else and the case is hard to close. Also shown is the lid of one of my recently built sensors with the CR123 holder.
                          IMG_20150705_215645.jpg

                          Veralite UI5 :: IBoard Ethernet GW :: MyS 1.5

                          Moshe LivneM 1 Reply Last reply
                          0
                          • DwaltD Dwalt

                            @Moshe-Livne The batteries have not dropped in the last two weeks although they all read around 80% during the first battery report. One of three actually has dropped 1%, the other two are steady. The 80% initial reading comes from the sketch which I believe is calibrated for 3.3V as 100%. I tested my CR123s before using them and they all read exactly 3V. They are Lithium (Li-MNO2) but not rechargeable (Lithium Ion). Typically they run around $1-$1.5. I picked up around 50 when RadioShack went belly-up this winter for 5 for $1. They have a very small self discharge rate and 10 year shelf life. Below is a picture of my case lid with a 2-AA holder inserted. Technically it fits, but no room for anything else and the case is hard to close. Also shown is the lid of one of my recently built sensors with the CR123 holder.
                            IMG_20150705_215645.jpg

                            Moshe LivneM Offline
                            Moshe LivneM Offline
                            Moshe Livne
                            Hero Member
                            wrote on last edited by
                            #13

                            @Dwalt Thanks! I think i'll go that way as well.

                            1 Reply Last reply
                            0
                            • M Offline
                              M Offline
                              mvader
                              wrote on last edited by
                              #14

                              @Dwalt Thanks for the pics.
                              but as I've already invested in over 20 AA battery holders, I'll need to find a new case solution.
                              I have decided to use a LDR as well. I was planning to use rechargeable AA batteries.
                              but they are 2.6v total instead of 3v so i guess i'm going to stick with alkaline.

                              Moshe LivneM 1 Reply Last reply
                              0
                              • M mvader

                                @Dwalt Thanks for the pics.
                                but as I've already invested in over 20 AA battery holders, I'll need to find a new case solution.
                                I have decided to use a LDR as well. I was planning to use rechargeable AA batteries.
                                but they are 2.6v total instead of 3v so i guess i'm going to stick with alkaline.

                                Moshe LivneM Offline
                                Moshe LivneM Offline
                                Moshe Livne
                                Hero Member
                                wrote on last edited by
                                #15

                                @mvader These are perfect for 2aa powered sensors although slightly ominous http://www.aliexpress.com/item/Dummy-Security-Camera-CCTV-Home-Dome-Camera-With-Red-Flashing-Light-Woshida/32317143038.html?spm=2114.32010308.4.11.8z1AAX

                                they are basically empty. for 2.5$ you get a case, a battery holder and a clear dome.... Even a switch!!!! Best deal in the world.

                                1 Reply Last reply
                                0
                                • T Offline
                                  T Offline
                                  tomkxy
                                  wrote on last edited by
                                  #16
                                  This post is deleted!
                                  1 Reply Last reply
                                  0
                                  Reply
                                  • Reply as topic
                                  Log in to reply
                                  • Oldest to Newest
                                  • Newest to Oldest
                                  • Most Votes


                                  18

                                  Online

                                  11.7k

                                  Users

                                  11.2k

                                  Topics

                                  113.0k

                                  Posts


                                  Copyright 2019 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
                                  • Login

                                  • Don't have an account? Register

                                  • Login or register to search.
                                  • First post
                                    Last post
                                  0
                                  • OpenHardware.io
                                  • Categories
                                  • Recent
                                  • Tags
                                  • Popular