3 in 1 incl battery monitor



  • I'am trying to build some 3 in 1 ( motion / temp / hum ) incl. battery monitor .
    At the moment i try to combine these sketches , as result

    #include <SPI.h>
    #include <MySensor.h>  
    #include <DHT.h>  
    
    int BATTERY_SENSE_PIN = A0;  // select the input pin for the battery sense point
    
    #define CHILD_ID_HUM 0
    #define CHILD_ID_TEMP 1
    #define CHILD_ID_MOT 2   // Id of the sensor child
    #define HUMIDITY_SENSOR_DIGITAL_PIN 4
    
    #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)
    
    
    unsigned long SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds)
    int oldBatteryPcnt = 0;
    
    MySensor gw;
    DHT dht;
    float lastTemp;
    float lastHum;
    boolean metric = true; 
    MyMessage msgHum(CHILD_ID_HUM, V_HUM);
    MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
    MyMessage msgMot(CHILD_ID_MOT, V_TRIPPED);
    
    void setup()  
    { 
       // use the 1.1 V internal reference
    #if defined(__AVR_ATmega2560__)
       analogReference(INTERNAL1V1);
    #else
       analogReference(INTERNAL);
    #endif
      gw.begin();
      dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN); 
    
      // Send the Sketch Version Information to the Gateway
      gw.sendSketchInfo("Humidity/Motion", "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_HUM, S_HUM);
      gw.present(CHILD_ID_TEMP, S_TEMP);
      gw.present(CHILD_ID_MOT, S_MOTION);
       
      metric = gw.getConfig().isMetric;
    }
    
    void loop()      
    
    {  
      // get the battery Voltage
       int sensorValue = analogRead(BATTERY_SENSE_PIN);
       #ifdef DEBUG
       Serial.println(sensorValue);
       #endif
       
       // 1M, 470K divider across battery and using internal ADC ref of 1.1V
       // Sense point is bypassed with 0.1 uF cap to reduce noise at that point
       // ((1e6+470e3)/470e3)*1.1 = Vmax = 3.44 Volts
       // 3.44/1023 = Volts per bit = 0.003363075
       float batteryV  = sensorValue * 0.003363075;
       int batteryPcnt = sensorValue / 10;
    
       #ifdef DEBUG
       Serial.print("Battery Voltage: ");
       Serial.print(batteryV);
       Serial.println(" V");
    
       Serial.print("Battery percent: ");
       Serial.print(batteryPcnt);
       Serial.println(" %");
       #endif
    
       if (oldBatteryPcnt != batteryPcnt) {
         // Power up radio after sleep
         gw.sendBatteryLevel(batteryPcnt);
         oldBatteryPcnt = batteryPcnt;
       }
         
         
      // Read digital motion value
      boolean tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH; 
            
      Serial.println(tripped);
      gw.send(msgMot.set(tripped?"1":"0"));  // Send tripped value to gw 
      
      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);
      }
    
      
     
      // Sleep until interrupt comes in on motion sensor. Send update every two minute. 
      gw.sleep(INTERRUPT,CHANGE, SLEEP_TIME);
    }
    
    

    Would this work ? ( sketch verification is okay 🙂 )



  • I also moded the arduino pro mini 8 Mhz like : http://www.mysensors.org/build/battery
    are there more (sketch) mod's possible to make it run as long as possible on 2 x AA


  • Hardware Contributor

    Look here for more info about battery operations: http://forum.mysensors.org/topic/486/my-2aa-battery-sensor


  • Hero Member

    @the-cosmic-gate What you can do is combine the radio actions (gw.send) in one burst at the end of the sketch. That way you avoid having the radio "on" during sensor reading. The sensebender sketch can be inspiring too.



  • @AWI
    If i remove the (gw.send) action, the code would be

    #include <MySensor.h>  
    #include <DHT.h>  
    
    int BATTERY_SENSE_PIN = A0;  // select the input pin for the battery sense point
    
    #define CHILD_ID_HUM 0
    #define CHILD_ID_TEMP 1
    #define CHILD_ID_MOT 2   // Id of the sensor child
    #define HUMIDITY_SENSOR_DIGITAL_PIN 4
    
    #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)
    
    
    unsigned long SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds)
    int oldBatteryPcnt = 0;
    
    MySensor gw;
    DHT dht;
    float lastTemp;
    float lastHum;
    boolean metric = true; 
    MyMessage msgHum(CHILD_ID_HUM, V_HUM);
    MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
    MyMessage msgMot(CHILD_ID_MOT, V_TRIPPED);
    
    void setup()  
    { 
       // use the 1.1 V internal reference
    #if defined(__AVR_ATmega2560__)
       analogReference(INTERNAL1V1);
    #else
       analogReference(INTERNAL);
    #endif
      gw.begin();
      dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN); 
    
      // Send the Sketch Version Information to the Gateway
      SketchInfo("Humidity/Motion", "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_HUM, S_HUM);
      gw.present(CHILD_ID_TEMP, S_TEMP);
      gw.present(CHILD_ID_MOT, S_MOTION);
       
      metric = gw.getConfig().isMetric;
    }
    
    void loop()      
    
    {  
      // get the battery Voltage
       int sensorValue = analogRead(BATTERY_SENSE_PIN);
       #ifdef DEBUG
       Serial.println(sensorValue);
       #endif
       
       // 1M, 470K divider across battery and using internal ADC ref of 1.1V
       // Sense point is bypassed with 0.1 uF cap to reduce noise at that point
       // ((1e6+470e3)/470e3)*1.1 = Vmax = 3.44 Volts
       // 3.44/1023 = Volts per bit = 0.003363075
       float batteryV  = sensorValue * 0.003363075;
       int batteryPcnt = sensorValue / 10;
    
       #ifdef DEBUG
       Serial.print("Battery Voltage: ");
       Serial.print(batteryV);
       Serial.println(" V");
    
       Serial.print("Battery percent: ");
       Serial.print(batteryPcnt);
       Serial.println(" %");
       #endif
    
       if (oldBatteryPcnt != batteryPcnt) {
         // Power up radio after sleep
         BatteryLevel(batteryPcnt);
         oldBatteryPcnt = batteryPcnt;
       }
         
         
      // Read digital motion value
      boolean tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH; 
            
      Serial.println(tripped);
     (msgMot.set(tripped?"1":"0"));  // Send tripped value to gw 
      
      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);
        }
        (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;
          (msgHum.set(humidity, 1));
          Serial.print("H: ");
          Serial.println(humidity);
      }
    
      
     
      // Sleep until interrupt comes in on motion sensor. Send update every two minute. 
      gw.sleep(INTERRUPT,CHANGE, SLEEP_TIME);
    }
    
    

  • Hero Member

    @the-cosmic-gate That is true but you will lose the MySensors functionality 😉 which is probably not your intention.
    What I meant is that you combine the gw.send actions in one "burst" or at least don't have the radio on while waiting for a (DHT) sensor to complete.

    like this part of code from the sensebender sketch

    if (tx) {
        measureCount = 0;
        float temperature = (isMetric ? data.celsiusHundredths : data.fahrenheitHundredths) / 100.0;
         
        int humidity = data.humidityPercent;
        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;
    }
    
    


  • So the code "must" be

    #include <SPI.h>
    #include <MySensor.h>  
    #include <DHT.h>  
    
    int BATTERY_SENSE_PIN = A0;  // select the input pin for the battery sense point
    
    #define CHILD_ID_HUM 0
    #define CHILD_ID_TEMP 1
    #define CHILD_ID_MOT 2   // Id of the sensor child
    #define HUMIDITY_SENSOR_DIGITAL_PIN 4
    
    #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)
    
    
    unsigned long SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds)
    int oldBatteryPcnt = 0;
    
    MySensor gw;
    DHT dht;
    float lastTemp;
    float lastHum;
    boolean metric = true; 
    MyMessage msgHum(CHILD_ID_HUM, V_HUM);
    MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
    MyMessage msgMot(CHILD_ID_MOT, V_TRIPPED);
    
    void setup()  
    { 
       // use the 1.1 V internal reference
    #if defined(__AVR_ATmega2560__)
       analogReference(INTERNAL1V1);
    #else
       analogReference(INTERNAL);
    #endif
      gw.begin();
      dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN); 
    
    
    
     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_HUM, S_HUM);
      gw.present(CHILD_ID_TEMP, S_TEMP);
      gw.present(CHILD_ID_MOT, S_MOTION);
       
      metric = gw.getConfig().isMetric;
    }
    
    void loop()      
    
    {  
      // get the battery Voltage
       int sensorValue = analogRead(BATTERY_SENSE_PIN);
       #ifdef DEBUG
       Serial.println(sensorValue);
       #endif
       
       // 1M, 470K divider across battery and using internal ADC ref of 1.1V
       // Sense point is bypassed with 0.1 uF cap to reduce noise at that point
       // ((1e6+470e3)/470e3)*1.1 = Vmax = 3.44 Volts
       // 3.44/1023 = Volts per bit = 0.003363075
       float batteryV  = sensorValue * 0.003363075;
       int batteryPcnt = sensorValue / 10;
    
       #ifdef DEBUG
       Serial.print("Battery Voltage: ");
       Serial.print(batteryV);
       Serial.println(" V");
    
       Serial.print("Battery percent: ");
       Serial.print(batteryPcnt);
       Serial.println(" %");
       #endif
    
       if (oldBatteryPcnt != batteryPcnt) {
         
         
       }
         
         
      // Read digital motion value
      boolean tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH; 
            
      Serial.println(tripped);
     
      
      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);
        }
        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));
          gw.send(msgMot.set(tripped?"1":"0"));
          gw.sendSketchInfo("Humidity/Motion", "1.0");
          gw.sendBatteryLevel(batteryPcnt);
          oldBatteryPcnt = batteryPcnt;
          Serial.print("H: ");
          Serial.println(humidity);
          gw.send(msgTemp.set(temperature, 1));
      }
    
      
     
      // Sleep until interrupt comes in on motion sensor. Send update every two minute. 
      gw.sleep(INTERRUPT,CHANGE, SLEEP_TIME);
    }
    
    

  • Hardware Contributor

    Dont know if im answring the question (or i understand it)...
    Do you mean @AWI that if you put the gw.*** together?

    gw.begin();
      dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN); 
     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_HUM, S_HUM);
      gw.present(CHILD_ID_TEMP, S_TEMP);
      gw.present(CHILD_ID_MOT, S_MOTION);
    

    put all the gw. *** together it will not cause the radio be on during DHT setup and readings like:

    dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN); 
     pinMode(DIGITAL_INPUT_SENSOR, INPUT);      // sets the motion sensor digital pin as input
    
    gw.begin(); 
      // 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);
      gw.present(CHILD_ID_MOT, S_MOTION);
    
    


  • @sundberg84 said:

    Dont know if im answring the question (or i understand it)...
    Do you mean @AWI that if you put the gw.*** together?

    gw.begin();
      dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN); 
     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_HUM, S_HUM);
      gw.present(CHILD_ID_TEMP, S_TEMP);
      gw.present(CHILD_ID_MOT, S_MOTION);
    

    put all the gw. *** together it will not cause the radio be on during DHT setup and readings like:

    dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN); 
     pinMode(DIGITAL_INPUT_SENSOR, INPUT);      // sets the motion sensor digital pin as input
    
    gw.begin(); 
      // 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);
      gw.present(CHILD_ID_MOT, S_MOTION);
    
    

    Now I'am getting confused 🙂

    The thing i want to do is to make this 3in1 sketch , an 4 in 1 where the 4th is the battery sensors.
    When i copy and paste this sketches together, i want to arrange one sketch who can run als long as possible on 2xAA batteries.
    So if there are some tricks to make this sketch more battery friendle, so it runs longer on this 2 AA then it try to arrange is.
    So As @AWI said i'll removed all the gw.send instructions, which gives me the result that the mysensors function is gone.
    Then i tried again and put all the gw.send instructions "together".
    But when i read you're reactien @sundberg84 this is not okay, or are there even more options to combine rules to make the sketch more battery friendly ?

    Thnx for all the input


  • Hero Member

    @the-cosmic-gate The reason to group all the "gw.send" instructions together (at the end of the sketch) is that the radio can "sleep" during the temperature and humidity readings. There are many ways (other than HW) to save battery power, like: only send values when a certain threshold is exceeded, decrease update frequency etc.

    Just an example for a sensor which uses 11 uA in idle and sends updates only when needed (including a once in a hour 'heartbeat' of all sensors).

    /*
     PROJECT: MySensors / Small battery sensor low power 1 mhz
     PROGRAMMER: AWI
     DATE: november 4, 2015/ last update: december 4, 2015
     FILE: AWI small THM.ino
     LICENSE: Public domain
    
     Hardware: ATMega328p board w/ NRF24l01
    	and MySensors 1.6 (Development)
    		
    Special:
    	program with Arduino Pro 3.3V 1Mhz!!!
    	
    Summary:
    	low power (battery)
    	HTU21 Temp/Hum & Motion (interrupt)
    	voltage meter for battery (internal)
    
    Remarks:
    	Fixed node-id
    	
    Change log:
    20151204 - made it universal with respect to node id, only change   first 2 lines
    */
    
    // Enable debug prints to serial monitor
    #define MY_NODE_ID 19
    #define NODE_TXT "THM 19"							// Text to add to sensor name
    
    #define MY_DEBUG 
    #define MY_RADIO_NRF24								// Enable and select radio type attached
    
    #include <SPI.h>
    #include <MySensor.h>
    #include <Wire.h> 									// I2C
    #include <HTU21D.h>            						// temperature / humidity (i2c, HTU21D, SHT21)
    #include <Vcc.h>									// library for internal reference Vcc reading
    
    #undef MY_DEBUG										// turns of MySensors Serial debug (default on)
    
    // Reference values for ADC and Battery measurements
    const float VccMin        	= 1.0*2.5 ;    			// Minimum expected Vcc level, in Volts. Example for 1 rechargeable lithium-ion.
    const float VccMax       	= 1.0*3.0 ;    			// Maximum expected Vcc level, in Volts. 
    //const float VccMin        = 2.0*0.6 ;  			// Minimum expected Vcc level, in Volts. for 2xAA Alkaline.
    //const float VccMax        = 2.0*1.5 ;  			// Maximum expected Vcc level, in Volts.for 2xAA Alkaline.
    const float VccCorrection 	= 3.30/3.42 ;			// Measured Vcc by multimeter divided by reported Vcc
    Vcc vcc(VccCorrection); 							// instantiate internal voltage measurement lib
    
    const float tempThreshold = 0.02 ; 					// send only if change > treshold (Celcius)
    const float humThreshold = 0.05 ; 					// send only if change > treshold (% RG)
    const float voltageThreshold = 0.01 ; 				// send only if change > treshold (Volt)
    
    #define MOTION_CHILD_ID 		1
    #define TEMP_CHILD_ID 			3
    #define HUM_CHILD_ID 			4
    #define VOLTAGE_CHILD_ID 		7
    
    #define DIGITAL_INPUT_SENSOR 	3  					// motion sensor.  (Only 2 and 3 generates interrupt!)
    #define INTERRUPT DIGITAL_INPUT_SENSOR-2 			// Usually the interrupt = pin -2 
    
    HTU21D SHT21;										// Hum/Temp (SHT12)
    
    const unsigned long SLEEP_TIME = 60000UL;			// 60 sec sleep time between reads (seconds * 1000 milliseconds)
    const int heartbeat = 60 ;							// heartbeat every hour (x times SLEEP_TIME)
    unsigned long lastHeartbeat = 0 ; 
    float lastHumidity = 0 ;
    float lastTemperature = 0 ;
    float lastVoltage = 0 ;
    boolean lastTripped = false ;
    // flags to indicate if transmission is needed, heartbeat and/or changes > treshold
    boolean txHumidity = true ;							// flags to indicate if transmit is needed (time & change driven)
    boolean txTemperature = true ;
    boolean txVoltage = true ;
    boolean txTripped = true ;
    
    // standard messages
    MyMessage temperatureMsg(TEMP_CHILD_ID, V_TEMP);	// SHT temp
    MyMessage humidityMsg(HUM_CHILD_ID, V_HUM);			// SHT hum
    MyMessage voltageMsg(VOLTAGE_CHILD_ID, V_VOLTAGE);	// Node voltage
    MyMessage motionMsg(MOTION_CHILD_ID, V_TRIPPED);	// Motion/ door contact
    
    void setup()  
    {
    	analogReference(INTERNAL);						// use the 1.1 V internal reference for voltage measurement
    	//begin(NULL, nodeId);  						// fixed node 
    	Serial.begin(9600);								// reset baud rate for 1 mhz clock rate
        // Send the sketch version information to the gateway and Controller
    	sendSketchInfo("AWI small " NODE_TXT, "1.0");
    	present(TEMP_CHILD_ID, S_TEMP, "Temperature SHT " NODE_TXT);
    	present(HUM_CHILD_ID, S_HUM, "Humidity SHT " NODE_TXT);
    	present(VOLTAGE_CHILD_ID, S_MULTIMETER, "Battery " NODE_TXT);
    	present(MOTION_CHILD_ID, S_MOTION, "Motion " NODE_TXT);
    
    	pinMode(DIGITAL_INPUT_SENSOR, INPUT);      		// sets the motion sensor digital pin as input
       
    	Wire.begin();									// init I2C
    	SHT21.begin();									// initialize temp/hum
    }
    
    void loop()
    {
    	// first read all sensors before possible transmission (save battery)
        readTempHum(); 
    	// Read digital motion value
    	boolean tripped = false ;//digitalRead(DIGITAL_INPUT_SENSOR) == HIGH;     
    	if (lastTripped != tripped){
    		lastTripped = tripped ;
    		txTripped = true ;
    		}
    	// read battery Voltage
        float voltage = vcc.Read_Volts() ;
    	if ( abs(voltage - lastVoltage) >= voltageThreshold ){ // update only if threshold exceeded
    		lastVoltage = voltage ;
    		txVoltage = true ;
    		} 
    	sendSensors() ;											// send sensors (== radio) at the end 
    	sleep(INTERRUPT, CHANGE , SLEEP_TIME );					// sleep and wait for time and motion
    }
    
    void readTempHum(void)
    {
        // SHT2x sensor
    	// Temperature and Humidity
    	float humidity = SHT21.readHumidity();
    	float temperature = SHT21.readTemperature();			// save battery by sending changes only & reading SHT first (>50ms)
    	if ( abs(humidity  - lastHumidity) >= humThreshold ){	// update only if threshold exceeded
    		lastHumidity = humidity ;
    		txHumidity = true ;
    		} 
    	if ( abs(temperature - lastTemperature) >= tempThreshold ){ 
    		lastTemperature = temperature ;
    		txTemperature = true ;
    		} 
    	// Serial.print("SHT_ temp: ");
    	// Serial.print(temperatureSHT);
    	// Serial.print(" SHT_ hum: ");
    	// Serial.println(humidity);
    }
    
    // send to gateway depending on tx.. settings
    void sendSensors()
    {
    	lastHeartbeat++ ;										// update Heartbeatcount every call
    	if ( lastHeartbeat > heartbeat) {						// if heartbeat update all sensors & battery status
    		txTemperature = txHumidity = txVoltage = true ;
    	    sendBatteryLevel(vcc.Read_Perc(VccMin, VccMax, true));
    		lastHeartbeat = 0 ;
    		}
    	if (txTemperature){
    		send(temperatureMsg.set(lastTemperature, 2));		// Send in deg C
    		txTemperature = false ;
    		}
    	if (txHumidity){
    		send(humidityMsg.set(lastHumidity, 2));  			// Send in %RH
    		txHumidity = false ;
    		}
    	if (txVoltage){
    		send(voltageMsg.set(lastVoltage,2));				//send battery in Volt 
    		txVoltage = false ;
    		}
    	if (txTripped){
    		send(motionMsg.set(lastTripped?"1":"0"));  			// Send tripped value to gw 
    		txTripped = false ;
    		}
    }
    


  • I'am not getting this clear / working 😞
    Could somebody help me to complete this 3in1 incl battery monitoring sketch working? Thnx


  • Hardware Contributor

    What does your serial or error log tell you when you upload the sketch you have? And which sketch/code do you use at this point?


  • Hero Member

    @the-cosmic-gate

    I changed your original sketch a little. It now includes a conditional send for the "tripped" values and groups the conditional sends for all values.

    I was not able to test as I'm using a different library for the DHT.

    Have fun..

    #include <SPI.h>
    #include <MySensor.h>  
    #include <DHT.h>  
    
    int BATTERY_SENSE_PIN = A0;  // select the input pin for the battery sense point
    
    #define CHILD_ID_HUM 0
    #define CHILD_ID_TEMP 1
    #define CHILD_ID_MOT 2   // Id of the sensor child
    
    #define HUMIDITY_SENSOR_DIGITAL_PIN 4
    #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)
    
    unsigned long SLEEP_TIME = 30000UL; // Sleep time between reads (in milliseconds)
    int oldBatteryPcnt = 0;
    
    MySensor gw;
    DHT dht;
    float lastTemp = 0 ;
    float lastHum = 0 ;
    boolean lastTripped = false ;
    boolean metric = true; 
    MyMessage msgHum(CHILD_ID_HUM, V_HUM);
    MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
    MyMessage msgMot(CHILD_ID_MOT, V_TRIPPED);
    
    void setup()  
    { 
       // use the 1.1 V internal reference
    #if defined(__AVR_ATmega2560__)
       analogReference(INTERNAL1V1);
    #else
       analogReference(INTERNAL);
    #endif
      gw.begin();
      dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN. DHT22); 
    
      // Send the Sketch Version Information to the Gateway
      gw.sendSketchInfo("Humidity/Motion", "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_HUM, S_HUM);
      gw.present(CHILD_ID_TEMP, S_TEMP);
      gw.present(CHILD_ID_MOT, S_MOTION);
       
      metric = gw.getConfig().isMetric;
    }
    
    void loop()      
    
    {  
      // get the battery Voltage
       int sensorValue = analogRead(BATTERY_SENSE_PIN);
       #ifdef DEBUG
       Serial.println(sensorValue);
       #endif
       
       // 1M, 470K divider across battery and using internal ADC ref of 1.1V
       // Sense point is bypassed with 0.1 uF cap to reduce noise at that point
       // ((1e6+470e3)/470e3)*1.1 = Vmax = 3.44 Volts
       // 3.44/1023 = Volts per bit = 0.003363075
       float batteryV  = sensorValue * 0.003363075;
       int batteryPcnt = sensorValue / 10;
    
       #ifdef DEBUG
       Serial.print("Battery Voltage: ");
       Serial.print(batteryV);
       Serial.println(" V");
    
       Serial.print("Battery percent: ");
       Serial.print(batteryPcnt);
       Serial.println(" %");
       #endif
    
       if (oldBatteryPcnt != batteryPcnt) {
         // Power up radio after sleep
         gw.sendBatteryLevel(batteryPcnt);
         oldBatteryPcnt = batteryPcnt;
       }
         
         
      // Read digital motion value
      boolean tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH; 
      
      if (tripped != lastTripped ) {      
      	Serial.println(tripped);
      	gw.send(msgMot.set(tripped?"1":"0"));  // Send tripped value to gw 
      }
      delay(dht.getMinimumSamplingPeriod());
    
      float temperature = dht.getTemperature();
      float humidity = dht.getHumidity();
      
      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);
      }
      
      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);
      }
    
       if (oldBatteryPcnt != batteryPcnt) {
         // Power up radio after sleep
         gw.sendBatteryLevel(batteryPcnt);
         oldBatteryPcnt = batteryPcnt;
       }
      
     
      // Sleep until interrupt comes in on motion sensor. Send update every two minute. 
      gw.sleep(INTERRUPT,CHANGE, SLEEP_TIME);
    }
    


  • Thnx a lot @AWI
    there was 1 verification error,

    dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN. DHT22); 
    

    changed it, to :

    #include <SPI.h>
    #include <MySensor.h>  
    #include <DHT.h>  
    
    int BATTERY_SENSE_PIN = A0;  // select the input pin for the battery sense point
    
    #define CHILD_ID_HUM 0
    #define CHILD_ID_TEMP 1
    #define CHILD_ID_MOT 2   // Id of the sensor child
    
    #define HUMIDITY_SENSOR_DIGITAL_PIN 4
    #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)
    
    unsigned long SLEEP_TIME = 30000UL; // Sleep time between reads (in milliseconds)
    int oldBatteryPcnt = 0;
    
    MySensor gw;
    DHT dht;
    float lastTemp = 0 ;
    float lastHum = 0 ;
    boolean lastTripped = false ;
    boolean metric = true; 
    MyMessage msgHum(CHILD_ID_HUM, V_HUM);
    MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
    MyMessage msgMot(CHILD_ID_MOT, V_TRIPPED);
    
    void setup()  
    { 
       // use the 1.1 V internal reference
    #if defined(__AVR_ATmega2560__)
       analogReference(INTERNAL1V1);
    #else
       analogReference(INTERNAL);
    #endif
      gw.begin();
      dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN); 
    
      // Send the Sketch Version Information to the Gateway
      gw.sendSketchInfo("Humidity/Motion", "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_HUM, S_HUM);
      gw.present(CHILD_ID_TEMP, S_TEMP);
      gw.present(CHILD_ID_MOT, S_MOTION);
       
      metric = gw.getConfig().isMetric;
    }
    
    void loop()      
    
    {  
      // get the battery Voltage
       int sensorValue = analogRead(BATTERY_SENSE_PIN);
       #ifdef DEBUG
       Serial.println(sensorValue);
       #endif
       
       // 1M, 470K divider across battery and using internal ADC ref of 1.1V
       // Sense point is bypassed with 0.1 uF cap to reduce noise at that point
       // ((1e6+470e3)/470e3)*1.1 = Vmax = 3.44 Volts
       // 3.44/1023 = Volts per bit = 0.003363075
       float batteryV  = sensorValue * 0.003363075;
       int batteryPcnt = sensorValue / 10;
    
       #ifdef DEBUG
       Serial.print("Battery Voltage: ");
       Serial.print(batteryV);
       Serial.println(" V");
    
       Serial.print("Battery percent: ");
       Serial.print(batteryPcnt);
       Serial.println(" %");
       #endif
    
       if (oldBatteryPcnt != batteryPcnt) {
         // Power up radio after sleep
         gw.sendBatteryLevel(batteryPcnt);
         oldBatteryPcnt = batteryPcnt;
       }
         
         
      // Read digital motion value
      boolean tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH; 
      
      if (tripped != lastTripped ) {      
        Serial.println(tripped);
        gw.send(msgMot.set(tripped?"1":"0"));  // Send tripped value to gw 
      }
      delay(dht.getMinimumSamplingPeriod());
    
      float temperature = dht.getTemperature();
      float humidity = dht.getHumidity();
      
      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);
      }
      
      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);
      }
    
       if (oldBatteryPcnt != batteryPcnt) {
         // Power up radio after sleep
         gw.sendBatteryLevel(batteryPcnt);
         oldBatteryPcnt = batteryPcnt;
       }
      
     
      // Sleep until interrupt comes in on motion sensor. Send update every two minute. 
      gw.sleep(INTERRUPT,CHANGE, SLEEP_TIME);
    }
    

    uploading now



  • working nice for 2 day's now !
    Thnx a lot @AWI !!!



  • Something strange: when I look in the IDE console the battery % is displayed. But using Domoticz there's no battery % display / selectable ? What's wrong , or do I forget something ?



  • In Domoticz you can see the battery level in Setup->Devices.
    domi_batt_level.png
    If you would like to see on a chart, you have to send the battery level or voltage to the controller as a sensor value too. After it, you can see as this:
    domi_batt_chart.png



  • @icebob

    Hi, I'm a newbee just started with MySensors. I built the first temp/hum sensor, and I'm trying to plot the battery level in a graph too. In this discussion you mention that I need to send the battery level to the controller as sensor value. Can you please share with me the code which I should use? Thanks a lot.

    Marco



  • Yes, I can.

    This is the definition of message for battery level:

    // Battery sensor (A0)
    #define CHILD_ID_BATTERY 199
    #define BATTERY_SENSOR_ANALOG_PIN 0
    MyMessage msgBattery(CHILD_ID_BATTERY, V_VOLTAGE);
    

    And this is the sender function:

    // 1M, 470K divider across battery and using internal ADC ref of 1.1V
    // Sense point is bypassed with 0.1 uF cap to reduce noise at that point
    // ((1e6+470e3)/470e3)*1.1 = Vmax = 3.44 Volts
    // 3.44/1023 = Volts per bit = 0.003363075
    #define VBAT_PER_BITS 0.003363075
    #define VMIN 1.9  // Battery monitor lower level. Vmin_radio=1.9V
    #define VMAX 3.00  // Vmin<Vmax<=3.44
    #define VCC_CORRECTION (3.4 / 3.33)
    int lastBatteryLevel;
    
    bool sendBatteryLevel(bool force = false) {
      int value = analogRead(BATTERY_SENSOR_ANALOG_PIN);
    
      float batVoltage  = value * VBAT_PER_BITS / VCC_CORRECTION;
      int batLevel = static_cast<int>(((batVoltage-VMIN)/(VMAX-VMIN))*100.);
      if (batLevel != lastBatteryLevel || force) {
        gw.sendBatteryLevel(batLevel);
        gw.send(msgBattery.set(batVoltage, 2));
        
        lastBatteryLevel = batLevel;
      }
      return true;
    }```


  • Great, thanks for your quick response. Implementing now. Looks good.



  • Running the sketch for 1 Monty (+-), and the AA batteries are dead empty ?
    I did all the "possible" mods on the arduino ( cut the LED an V ) , what can i do to make this sketch run langer on this 2AA batteries ?
    Something in the sketch , some fine tuning or something else ?
    When read the arduino hardware tweaking topics on different forums they dat that running for 1 year ( and more) is possible but how ;-)?



  • Hello,

    Did you measured the current of your circuit ?
    What motion sensor are you using ? This component may consume a lot of current. Did you check this post ?

    If you wake-up the arduino every 30 seconds for measurement it's a problem. Every 5 minutes is the minimum I think. I have connected the Vcc pin of the DHT sensors and the Vcc of the LDR to a digital pin of the arduino and when a measurement is done I set the PIN to the HIGH state.

    First measurement of my sensor gives an IDLE current consumption close to 5uA which is really correct according to elements connected to the arduino (RFM69HW, DHT22 and LDR).

    David.



  • Yes as Carlierd writes, it's important that the Arduino are controlling the voltage to the external components, like DHT.
    I might have overlooked, but which component are you using for motion sensing? maybe this component is also power-hungry



  • @the-cosmic-gate Now I measured my dev circuit (Arduino Nano from China (cutted power led and desoldered regulator) + DHT22 + PIR + Battery measure resistor divider) and in gw.sleep (with 1 interrupt for PIR) the power comsumption is ~90uA.
    DSC_9591_rs.jpg
    It wakes up every minutes, measuring and sending (~100ms and 5 - 20mA).
    So 100ms with 20mA and 59900ms with 0.09mA. The average current is 120uA and with 2 AA battery it is about 2 years.
    ardu_batt.png



  • @icebob,
    whats that app you are using to do the battery calculations?



  • @icebob
    100ms for measurement and transmission seems very small ! I am at approximately 1500ms.
    Give me your secret now !! 😉



  • @ericvdb http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2680&dDocName=en545243. It's specified for PIC, but I select SLEEP mode in every cycle, so I can use for any uC.

    @carlierd: I have no extra secret. If I measure 3-4 sensor and every values is changed, the loop time is 100ms. Best case is 10-20ms (if every sensors is unchanged). I'm not using delay in the loop.



  • @icebob: It's true that as I used signing feature, transmission is longer ! and in order to increase a little bit more I send every measure even if they not changed. I will probably upgrade my sketch to add a one-hour message at minimum and do not transfer mesure without change !



  • @carlierd said:

    Hello,

    Did you measured the current of your circuit ?
    What motion sensor are you using ? This component may consume a lot of current. Did you check this post ?

    If you wake-up the arduino every 30 seconds for measurement it's a problem. Every 5 minutes is the minimum I think. I have connected the Vcc pin of the DHT sensors and the Vcc of the LDR to a digital pin of the arduino and when a measurement is done I set the PIN to the HIGH state.

    First measurement of my sensor gives an IDLE current consumption close to 5uA which is really correct according to elements connected to the arduino (RFM69HW, DHT22 and LDR).

    David.

    Hello David,
    I tried to meassure , but didn't have the right stuff to do this good enough.
    The parts i use for this "project": DHT-22 (connected to D4), HC-SR501 (connected to D3)and connected to the 3.3V pin post , the VVC is connected to the VVC of the arduino pro mini 8 Mhz /3.3 V .
    And use the sketch as above:

    #include <SPI.h>
    #include <MySensor.h>  
    #include <DHT.h>  
    
    int BATTERY_SENSE_PIN = A0;  // select the input pin for the battery sense point
    
    #define CHILD_ID_HUM 0
    #define CHILD_ID_TEMP 1
    #define CHILD_ID_MOT 2   // Id of the sensor child
    
    #define HUMIDITY_SENSOR_DIGITAL_PIN 4
    #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)
    
    unsigned long SLEEP_TIME = 30000UL; // Sleep time between reads (in milliseconds)
    int oldBatteryPcnt = 0;
    
    MySensor gw;
    DHT dht;
    float lastTemp = 0 ;
    float lastHum = 0 ;
    boolean lastTripped = false ;
    boolean metric = true; 
    MyMessage msgHum(CHILD_ID_HUM, V_HUM);
    MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
    MyMessage msgMot(CHILD_ID_MOT, V_TRIPPED);
    
    void setup()  
    { 
       // use the 1.1 V internal reference
    #if defined(__AVR_ATmega2560__)
       analogReference(INTERNAL1V1);
    #else
       analogReference(INTERNAL);
    #endif
      gw.begin();
      dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN); 
    
      // Send the Sketch Version Information to the Gateway
      gw.sendSketchInfo("Humidity/Motion", "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_HUM, S_HUM);
      gw.present(CHILD_ID_TEMP, S_TEMP);
      gw.present(CHILD_ID_MOT, S_MOTION);
       
      metric = gw.getConfig().isMetric;
    }
    
    void loop()      
    
    {  
      // get the battery Voltage
       int sensorValue = analogRead(BATTERY_SENSE_PIN);
       #ifdef DEBUG
       Serial.println(sensorValue);
       #endif
       
       // 1M, 470K divider across battery and using internal ADC ref of 1.1V
       // Sense point is bypassed with 0.1 uF cap to reduce noise at that point
       // ((1e6+470e3)/470e3)*1.1 = Vmax = 3.44 Volts
       // 3.44/1023 = Volts per bit = 0.003363075
       float batteryV  = sensorValue * 0.003363075;
       int batteryPcnt = sensorValue / 10;
    
       #ifdef DEBUG
       Serial.print("Battery Voltage: ");
       Serial.print(batteryV);
       Serial.println(" V");
    
       Serial.print("Battery percent: ");
       Serial.print(batteryPcnt);
       Serial.println(" %");
       #endif
    
       if (oldBatteryPcnt != batteryPcnt) {
         // Power up radio after sleep
         gw.sendBatteryLevel(batteryPcnt);
         oldBatteryPcnt = batteryPcnt;
       }
         
         
      // Read digital motion value
      boolean tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH; 
      
      if (tripped != lastTripped ) {      
        Serial.println(tripped);
        gw.send(msgMot.set(tripped?"1":"0"));  // Send tripped value to gw 
      }
      delay(dht.getMinimumSamplingPeriod());
    
      float temperature = dht.getTemperature();
      float humidity = dht.getHumidity();
      
      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);
      }
      
      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);
      }
    
       if (oldBatteryPcnt != batteryPcnt) {
         // Power up radio after sleep
         gw.sendBatteryLevel(batteryPcnt);
         oldBatteryPcnt = batteryPcnt;
       }
      
     
      // Sleep until interrupt comes in on motion sensor. Send update every two minute. 
      gw.sleep(INTERRUPT,CHANGE, SLEEP_TIME);
    }
    

    So how do you connect the DHT / SR501 to the digital pin, and what's the sketch you're using ?



  • Hello,

    You need to power the motion sensor all time as you want to detect any mouvement and not only every 2 minutes.

    Caution, in your sketch, the battery level is sent at the beginning and at the end.

    Did you tweak the motion sensor ?? Not tested yet but it seems that modification could (must ?) be done to reduce power consumption (LINK).

    Why do you wake-up the arduino every 30 seconds ? For temperature, every 5 or 15 minutes is enough.



  • @icebob: is you motion sensor often triggered ? I mean, is the sensor placed somewhere where there is a lot of mouvement ? I tried to do such sensor some months ago but my sensors was very often triggered on finally the time is sleep was small and my battery decreased very quickly !



  • Currently I'm developing my boards, so there is no live device/sensor in my home. But in the future I plan to make a custom controller, and it will turn on/off the PIR sensors on the nodes, depending on the house is armed or not. So if I'm at home, PIR sensor won't watching. (It's just a plan for the present)



  • I am new in this forum so may be what I will tell here is posted already somewhere else.
    Firstly I would measure the battery voltage at the end after sending some values to see the voltage after some stress. Often it is the case for a nearly empty battery that it shows a relaxed high voltage after a long sleep and the break down on some stress. I think it is better to measure the lower level.
    Secondly for a motion sensor I would implement a wakeup on a pin change interrupt. As a stand-alone sensor this would be optimal for battery life time. In combination the other components you can use a large cycle time for getting temperature humidity and so on and for the motion sensor you get an intermediate interrupt on demand. If those event are too often for your desire, you can check it against time or count of last event and go back to sleep without sending.



  • @carlierd said:

    Hello,

    You need to power the motion sensor all time as you want to detect any mouvement and not only every 2 minutes.

    Caution, in your sketch, the battery level is sent at the beginning and at the end.

    Did you tweak the motion sensor ?? Not tested yet but it seems that modification could (must ?) be done to reduce power consumption (LINK).

    Why do you wake-up the arduino every 30 seconds ? For temperature, every 5 or 15 minutes is enough.

    Sure i modded the motion sensor as shown in the hyperlink , modded it this way :
    upload-91e4fc48-511f-46de-8512-a86c74023af3.JPG
    I don't know why i wake-up this arduino every 30 seconds, the sketch was fabricated by combine 2 or 3 other sketches to this one ( with help from @AWI )
    So if there are some tweaking thing to do, do not hesitate and change the sketch as you think it must be

    @icebob what's the sketch you using /testing ?


  • Hero Member

    @the-cosmic-gate No specific reason to have a 30 second interval. You can just change the SLEEP_TIME to whatever eg. 5 minutes == 300000UL. The pin change interrupt is present in the code..

    gw.sleep(INTERRUPT,CHANGE, SLEEP_TIME);
    


  • @icebob could you share us you're code ?



  • @the-cosmic-gate sorry, I'm working a big complex sketch, I can't share my code currently.



  • @icebob said:

    @the-cosmic-gate sorry, I'm working a big complex sketch, I can't share my code currently.

    Big and complex sounds interesting 🙂
    Could you maybe share us a sneak peak 😉



  • @the-cosmic-gate Nothing special. I made a big sketch, which contains 7-8 sensors (DHT, Si7021, MQ-2/9, PIR, Door magnet, Light, battery) reading code because I would like to upload the same sketch to all nodes and configurate it on controller side, which sensors is on the node and need to read.
    But currently I reached the limit with I2C includes, so I need to think over this solution.



  • @the-cosmic-gate Did you solved your power consumption issue ?



  • @carlierd said:

    @the-cosmic-gate Did you solved your power consumption issue ?
    Not yet, this because we moved to oneother house and didn't have the time now .
    Also i had to disconnect and reconect all te sensors and domotica in this new house



  • I just finished my first motion sensor node and the power consumption in idle is about 75uA. Could be better but not too bad 😉
    The only thing is that the range is a little bit low for good detection. It's between 1 and 3 meters ...

    David.



  • @carlierd said:

    I just finished my first motion sensor node and the power consumption in idle is about 75uA. Could be better but not too bad 😉
    The only thing is that the range is a little bit low for good detection. It's between 1 and 3 meters ...

    David.

    Hello David

    Could you share what and how ? 🙂

    Thnx



  • And how is this sensor acting?

    This is what i am looking for..
    How lang can this sensor work? [ i wil try this with a 9Volt battery with a nano ]
    What battery do you use?



  • Hello,

    This is the code I use but it's not perfect especially with the battery report.

    The principle is as follow when the sensor start:

    • node in sleep mode with interrupt enable
    • if a move is detected, the detection is reported to the gateway
    • the node then go in sleep mode WITHOUT interrupt for 5 minutes
    • then the node return to sleep mode with interrupt enable

    This is to avoid having many report (and power consumption) to the gateway.

    The code (not perfect ! I have to rework on it but it's ok for the moment):

    /**
     * The MySensors Arduino library handles the wireless radio link and protocol
     * between your home built sensors/actuators and HA controller of choice.
     * The sensors forms a self healing radio network with optional repeaters. Each
     * repeater and gateway builds a routing tables in EEPROM which keeps track of the
     * network topology allowing messages to be routed to nodes.
     *
     * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
     * Copyright (C) 2013-2015 Sensnology AB
     * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
     *
     * Documentation: http://www.mysensors.org
     * Support Forum: http://forum.mysensors.org
     *
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * version 2 as published by the Free Software Foundation.
     *
     */
    
    /**************************************************************************************/
    /* Motion sensor.                                                                     */
    /*                                                                                    */
    /* Version     : 1.1.5                                                                */
    /* Date        : 30/01/2016                                                           */
    /* Modified by : David Carlier                                                        */
    /**************************************************************************************/
    /*                                ---------------                                     */
    /*                            RST |             |  A5                                 */
    /*                            RX  |             |  A4                                 */
    /*                            TX  |   ARDUINO   |  A3                                 */
    /*     RFM69 (DIO0) --------- D2  |     UNO     |  A2                                 */
    /*           Motion --------- D3  |             |  A1                                 */
    /*            Power --------- D4  | ATMEGA 328p |  A0                                 */
    /*              +3v --------- VCC |             | GND --------- GND                   */
    /*              GND --------- GND |  8MHz int.  | REF                                 */
    /*                            OSC |             | VCC --------- +3v                   */
    /*                            OSC |             | D13 --------- RFM69 (SCK)           */
    /*                            D5  |             | D12 --------- RFM69 (MISO)          */
    /*                            D6  |             | D11 --------- RFM69 (MOSI)          */
    /*                            D7  |             | D10 --------- RFM69 (NSS)           */
    /*                            D8  |             |  D9                                 */
    /*                                ---------------                                     */
    /*                                                                                    */
    /* +3v = 2*AA                                                                         */
    /*                                                                                    */
    /**************************************************************************************/
    
    #include <SPI.h>
    #include <MySensor.h>
    #include <MyTransportRFM69.h>
    #include <MySigningAtsha204Soft.h>
    
    //Constants
    #define SKETCH_NAME           "Motion Sensor"
    #define SKETCH_VERSION        "1.1.5"
    #define CHILD_ID              0
    #define CHILD_ID_VOLTAGE      1
    #define DIGITAL_INPUT_SENSOR  3
    #define BATTERY_REPORT_CYCLE  4   //Report each hour (4 * 15')
    
    //Misc. variables
    uint8_t switchState = 2;
    unsigned long SLEEP_TIME = 820000; // Sleep time between reads (in milliseconds) (close to 15')
    unsigned long SLEEP_TIME2 = 275000; // Sleep time after int. (in milliseconds) (close to 5')
    uint8_t cycleInProgress = 0;
    uint8_t firstReportDone = 0;
    uint8_t firstReportWithZeroDone = 0;
    
    //Construct MySensors library
    MySigningAtsha204Soft signer;
    MyHwATMega328 hw;
    MyTransportRFM69 transport;
    MySensor node(transport, hw, signer);
    MyMessage msgSwitch(CHILD_ID, V_TRIPPED);
    MyMessage msgVolt(CHILD_ID_VOLTAGE, V_VOLTAGE);
    
    /**************************************************************************************/
    /* Initialization                                                                     */
    /**************************************************************************************/
    void setup()  
      {
      //Get time (for setup duration)
      #ifdef DEBUG
        unsigned long startTime = millis();
      #endif
    
      //Start MySensors and send the Sketch Version Information to the Gateway
      node.begin();
      node.sendSketchInfo(SKETCH_NAME, SKETCH_VERSION);
    
      //Setup the button
      pinMode(DIGITAL_INPUT_SENSOR, INPUT);
    
      //Register all sensors
      node.present(CHILD_ID, S_MOTION);
      node.present(CHILD_ID_VOLTAGE, S_MULTIMETER);
    
      //Print setup debug
      #ifdef DEBUG
        int duration = millis() - startTime;
        Serial.print("[Setup duration: "); Serial.print(duration, DEC); Serial.println(" ms]");
      #endif
      }
    
    /**************************************************************************************/
    /* Main loop                                                                          */
    /**************************************************************************************/
    void loop()
      {
      //Get time (for a complete loop)
      #ifdef DEBUG
        unsigned long startTime = millis();
      #endif
    
      //Read digital motion value
      uint8_t value = digitalRead(DIGITAL_INPUT_SENSOR);
    
      //Get voltage for battery capacity report (add 0.1v to the read value)
      float realVoltage = (getVoltage() / 100.0) + 0.1;
      int batteryPcnt = realVoltage * 100 / 3.0;
      if (batteryPcnt > 100) {batteryPcnt = 100;}
    
      //Check is state change
      if (value != switchState)
        {
        //Report result if not first loop
        if (firstReportDone != 0)
          {
          node.send(msgSwitch.set(value==HIGH ? 1 : 0));
          }
    
        //Store result
        switchState = value;
        }
    
      //Report data to the gateway each hour
      if (cycleInProgress >= BATTERY_REPORT_CYCLE || firstReportDone == 0)
        {
        node.send(msgSwitch.set(value==HIGH ? 1 : 0));
        node.send(msgVolt.set(realVoltage, 2));
        node.sendBatteryLevel(batteryPcnt);
        cycleInProgress = 0;
        firstReportDone = 1;
        }
    
      //Change cycle number
      cycleInProgress++;
    
      //Print debug
      #ifdef DEBUG
        Serial.print("Value is ");
        Serial.print(value, 1);
        Serial.print("   ");
        Serial.print("Cycle is ");
        Serial.print(cycleInProgress, 1);
        Serial.print("   ");
        Serial.print(realVoltage);
        Serial.print(" v");
        int duration = millis() - startTime;
        Serial.print("   ");
        Serial.print("["); Serial.print(duration, DEC); Serial.println(" ms]");
        Serial.flush();
      #endif
    
      //Check if the motion was triggered and if it's not the first report
      if (switchState == 0 && firstReportWithZeroDone == 1)
        {
        //Sleep 5' without interrupt
        node.sleep(SLEEP_TIME2);
        }
    
      //Check if it's the first loop
      if (switchState == 0 && firstReportWithZeroDone == 0)
        {
        firstReportWithZeroDone = 1;
        }
    
      //Sleep until something happens with the sensor
      node.sleep(DIGITAL_INPUT_SENSOR-2, CHANGE, SLEEP_TIME);
      }
    
    /**************************************************************************************/
    /* Allows to get the real Vcc (return value * 100).                                   */
    /**************************************************************************************/
    int getVoltage()
      {
      const long InternalReferenceVoltage = 1056L;
      ADMUX = (0<<REFS1) | (1<<REFS0) | (0<<ADLAR) | (1<<MUX3) | (1<<MUX2) | (1<<MUX1) | (0<<MUX0);
      delay(50);  // Let mux settle a little to get a more stable A/D conversion
      //Start a conversion  
      ADCSRA |= _BV( ADSC );
      //Wait for it to complete
      while (((ADCSRA & (1<<ADSC)) != 0));
      //Scale the value
      int result = (((InternalReferenceVoltage * 1023L) / ADC) + 5L) / 10L;
      return result;
      }
    

    On one sensor I tweak the PIR (remove regulator and diode) but on a second one, I just plug the 3 v to the H pin (see other topic on the forum).

    Working correctly for the moment (one month) but it depends on the presence in the house.

    David.



  • @ Carlied,

    What code is better that one of you or the one from cosmi gate?

    What are the different thing? Is your code check'the battery status?

    And i get a error:
    no matching function for call to 'MySensor::MySensor(MyTransportRFM69&, MyHwATMega328&, MySigningAtsha204Soft&)'



  • The error is because I enable the signing function !
    Remove the following line:

    MySigningAtsha204Soft signer;
    

    And replace

    MySensor node(transport, hw, signer);
    

    by

    MySensor node(transport, hw);
    

    I don't know who had the best sketch.
    I measure internal battery status using the 1.1 reference.

    David.



  • When i put this sketch in to a nano..
    With a 9volt battery....
    How long do think this working?

    Or how long is this acting on your 3 volt battery's?



  • It depends on the activity close to the sensor so not possible to say but some people reach several month without problem.
    In my house it's very fresh so I have not a lot of feedback to give.

    David.



  • 5 days....👎 on a 9volt block
    The sketch on a nano
    On my toilet.... so not a very busy room

    Is there some one that live longer, with this sketch......?



  • @icebob said:

    @the-cosmic-gate Nothing special. I made a big sketch, which contains 7-8 sensors (DHT, Si7021, MQ-2/9, PIR, Door magnet, Light, battery) reading code because I would like to upload the same sketch to all nodes and configurate it on controller side, which sensors is on the node and need to read.
    But currently I reached the limit with I2C includes, so I need to think over this solution.

    Dear..
    Did you finish your big code....



  • Hello,

    9v means that you are using a voltage regulator which probably consumes a lot of power.
    Why not using AA or AAA battery directly connected to Vcc ?

    David



  • @carlierd said:

    Hello,

    9v means that you are using a voltage regulator which probably consumes a lot of power.
    Why not using AA or AAA battery directly connected to Vcc ?

    David

    Motion and DHT needed 5volt i wash thinking..?
    So 9 @ the vcc should be strong enough i was thinking.
    And i do have @ the same time 3.5 for the radio

    Are the extern step up better than the step down on a nano?



  • The motion can be adapt to run on 3v easily (connect the Vcc to the H pad if available. You can find information on the forum). The DHT could also run on 3v. I have several nodes like that. No problem.
    Can't reply for the step-up because I don't use it.

    David.



  • @carlierd said:

    The motion can be adapt to run on 3v easily (connect the Vcc to the H pad if available. You can find information on the forum). The DHT could also run on 3v. I have several nodes like that. No problem.
    Can't reply for the step-up because I don't use it.

    David.

    @ David

    How long is the 3v battery running whit this option?



  • @Dylano : My nodes are really new so difficult to say exactly but for the moment the oldest node was started one month ago (04/02) and battery still at 3.32v.

    David.



  • i'am back in business after the "big move" and going to try again to get this 4:1 sensor working for a long time uning 2 x AA batteries.
    If someone has some new input, please let me know 🙂 and feel free to change the sketch



  • @the-cosmic-gate
    Hello,
    Motion nodes are still working correctly. The oldest node started the 4 of February is still at 3,29v. My other nodes (temp / humidity / light) are also working correctly but I will replace DHT22 for another sensor.

    David.



  • Hey @carlierd Just curious if you are still using a DHT22 with your sketch? Have you modified the code much from the above? I am looking at implementing something similiar ( identical actually ) and was wondering if much has changed for you over the last few months?

    Thanks!



  • Hello,

    All nodes are still working correctly but I still want to replace DHT22. But nothing done for the moment. Not at top position on my todo list 😉

    David.


Log in to reply
 

Suggested Topics

13
Online

11.4k
Users

11.1k
Topics

112.7k
Posts