Merge Help: Door+ BME280
-
Hello,
I have been struggling with this for a few days now. I have tried various permutations and combinations and the sketch does not work.
Individually both Door Sensor and BME280 work just fine but once I merge them into one sketch the node hangs.Do I need to do anything different here?
//#define MY_DEBUG #define REED_PIN 6 #define MY_NODE_ID 2 //change everytime #define MY_PASSIVE_NODE #define MY_RADIO_NRF5_ESB #define MY_PARENT_NODE_ID 0 #define MY_PARENT_NODE_IS_STATIC #define MY_TRANSPORT_WAIT_READY_MS 10000 // Try connecting for 10 seconds. Otherwise just continue. #define MY_SPLASH_SCREEN_DISABLED // Saves a little memory. #define IS_NRF51 //true iff the target is an nRF51. If an nRF52, then comment this line out! #define SKETCH_NAME "Hobby Room Door Sensor" #define SKETCH_VERSION "v1" #define DOOR_CHILD_ID 0 #define VOLT_CHILD_ID 10 #define TEMP_CHILD_ID 1 #define BARO_CHILD_ID 2 #define HUM_CHILD_ID 3 /* End NodeID definitions */ /* Sketch specific libraries*/ #include <SPI.h> // A communication backbone, the Serial Peripheral Interface. #include <Wire.h> // Enables the Wire communication protocol. #include <MySensors.h> // The MySensors library. Hurray! #include <Adafruit_BME280.h> /* door sensor variables */ volatile bool door_tripped = false; bool magnet_detected= false; float batteryVoltage = 0; bool oldValueDoor = -1; /* door sensor variables */ /* Sleep variables */ #define SHORT_WAIT 50 uint32_t SLEEP_TIME = 60000 *15; //60000 ms = 1 minute * number of minutes /* Sleep variables */ /* BME 280 */ Adafruit_BME280 bme; // use I2C interface //#define BME280_ADDRESS_ALTERNATE Adafruit_Sensor *bme_temp = bme.getTemperatureSensor(); Adafruit_Sensor *bme_pressure = bme.getPressureSensor(); Adafruit_Sensor *bme_humidity = bme.getHumiditySensor(); /* BME 280 */ MyMessage msgDoor(DOOR_CHILD_ID, V_TRIPPED); //TRIPPED --> Open, ARMED --> Closed MyMessage msgVoltage(VOLT_CHILD_ID, V_VOLTAGE); MyMessage msgTemperature(TEMP_CHILD_ID, V_TEMP); MyMessage msgHumidity(HUM_CHILD_ID, V_HUM); MyMessage msgPressure(BARO_CHILD_ID, V_PRESSURE); //void before() //{ // NRF_POWER->DCDCEN = 1; // sleep(400); //} void setup() { hwInit(); Wire.begin(); if (!bme.begin(0x76)) { while(1) delay(10); } environment(); hwPinMode(REED_PIN, INPUT_PULLUP); turnOffAdc(); disableNfc(); turnOffAdc(); activateLpComp(); mySleepPrepare(); } void presentation() { sendSketchInfo(SKETCH_NAME, SKETCH_VERSION); wait(SHORT_WAIT); present(DOOR_CHILD_ID, S_DOOR, "Door Sensor", true); wait(SHORT_WAIT); present(VOLT_CHILD_ID, S_MULTIMETER,"Battery voltage", true); wait(SHORT_WAIT); present(HUM_CHILD_ID, S_HUM); wait(SHORT_WAIT); present(BARO_CHILD_ID, S_BARO); wait(SHORT_WAIT); present(TEMP_CHILD_ID, S_TEMP); } void loop() { mySleep(SLEEP_TIME); if (door_tripped) { door(); // sleep(digitalPinToInterrupt(REED_PIN), CHANGE, SLEEP_TIME); wait(SHORT_WAIT); battery_report(); } else { environment(); wait(SHORT_WAIT); } } void door() { bool tripped = digitalRead(REED_PIN) == HIGH; if (tripped != oldValueDoor) { send(msgDoor.set(tripped ? "Open" : "Close"), true); oldValueDoor = tripped; } } void environment() { float pressure = bme.readPressure() /100.0f; bme.begin(0x76); sensors_event_t temp_event, pressure_event, humidity_event; bme_temp->getEvent(&temp_event); bme_pressure->getEvent(&pressure_event); bme_humidity->getEvent(&humidity_event); send(msgTemperature.set(temp_event.temperature, 1)); send(msgHumidity.set(bme.readHumidity(), 1)); send(msgPressure.set(pressure, 1)); // i2c_off(); } void i2c_off() // Shut i2c down, powerconsumption rises up to 450uA instead of 11 ua - https://github.com/sandeepmistry/arduino-nRF5/issues/291#issuecomment-407492282 { NRF_TWI1->ENABLE=TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos; *(volatile uint32_t *)0x40004FFC = 0; *(volatile uint32_t *)0x40004FFC; *(volatile uint32_t *)0x40004FFC = 1; } void battery_report() { batteryVoltage = ((float)hwCPUVoltage()) / 1000.0; send(msgVoltage.set(batteryVoltage, 2)); } void mySleep(uint32_t ms) { mySleepPrepare(); //Take steps to reduce drains on battery current prior to sleeping // sleep(ms); // sleep(digitalPinToInterrupt(REED_PIN), CHANGE, SLEEP_TIME); } void disableNfc() { //only applied to nRF52 #ifndef IS_NRF51 //Make pins 9 and 10 usable as GPIO pins. NRF_NFCT->TASKS_DISABLE=1; //disable NFC NRF_NVMC->CONFIG=1; // Write enable the UICR NRF_UICR->NFCPINS=0; //Make pins 9 and 10 usable as GPIO pins. NRF_NVMC->CONFIG=0; // Put the UICR back into read-only mode. #endif } void turnOffRadio() { NRF_RADIO->TASKS_DISABLE=1; while (!(NRF_RADIO->EVENTS_DISABLED)) {} //until radio is confirmed disabled } void turnOffUarte0() { #ifndef IS_NRF51 NRF_UARTE0->TASKS_STOPRX = 1; NRF_UARTE0->TASKS_STOPTX = 1; NRF_UARTE0->TASKS_SUSPEND = 1; NRF_UARTE0->ENABLE=0; //disable UART0 while (NRF_UARTE0->ENABLE!=0) {}; //wait until UART0 is confirmed disabled. #endif #ifdef IS_NRF51 NRF_UART0->TASKS_STOPRX = 1; NRF_UART0->TASKS_STOPTX = 1; NRF_UART0->TASKS_SUSPEND = 1; NRF_UART0->ENABLE=0; //disable UART0 while (NRF_UART0->ENABLE!=0) {}; //wait until UART0 is confirmed disabled. #endif } void turnOffAdc() { #ifndef IS_NRF51 if (NRF_SAADC->ENABLE) { //if enabled, then disable the SAADC NRF_SAADC->TASKS_STOP=1; while (NRF_SAADC->EVENTS_STOPPED) {} //wait until stopping of SAADC is confirmed NRF_SAADC->ENABLE=0; //disable the SAADC while (NRF_SAADC->ENABLE) {} //wait until the disable is confirmed } #endif } void turnOffHighFrequencyClock() { NRF_CLOCK->TASKS_HFCLKSTOP = 1; while ((NRF_CLOCK->HFCLKSTAT) & 0x0100) {} //wait as long as HF clock is still running. } void mySleepPrepare() { turnOffHighFrequencyClock(); turnOffRadio(); turnOffUarte0(); } void activateLpComp() { //NRF_LPCOMP->PSEL=1; // monitor AIN1 (pin P0.03 on nRF52832 test board). //while (!(NRF_LPCOMP->PSEL==1)) {} //wait until confirmed NRF_LPCOMP->PSEL=3; // monitor AIN3 (pin P0.02 on nRF51822 for coincell_multisensor_v10) while (!(NRF_LPCOMP->PSEL==3)) {} //wait until confirmed NRF_LPCOMP->REFSEL=1; // choose 1/4 VDD as the reference voltage while (!(NRF_LPCOMP->REFSEL==1)) {} //wait until confirmed NRF_LPCOMP->ANADETECT=1; //detect UP events. while (NRF_LPCOMP->ANADETECT!=1) {} //wait until confirmed NRF_LPCOMP->INTENSET=B0100; //Enable interrupt for UP event while (!(NRF_LPCOMP->INTENSET==B0100)) {} //wait until confirmed NRF_LPCOMP->ENABLE=1; //Enable LPCOMP while (!(NRF_LPCOMP->ENABLE==1)) {} //wait until confirmed NRF_LPCOMP->TASKS_START=1; //start the LPCOMP while (!(NRF_LPCOMP->EVENTS_READY)) {} //wait until ready NVIC_SetPriority(LPCOMP_IRQn, 15); NVIC_ClearPendingIRQ(LPCOMP_IRQn); NVIC_EnableIRQ(LPCOMP_IRQn); } void suspendLpComp() { //suspend getting more interrupts from LPCOMP before the first interrupt can be handled if ((NRF_LPCOMP->ENABLE) && (NRF_LPCOMP->EVENTS_READY)) { //if LPCOMP is enabled NRF_LPCOMP->INTENCLR=B0100; //disable interrupt from LPCOMP while (NRF_LPCOMP->INTENCLR==B0100) {} //wait until confirmed } } void resumeLpComp() { //suspend getting interrupts from LPCOMP NRF_LPCOMP->INTENSET=B0100; //Enable interrupt for UP event while (!(NRF_LPCOMP->INTENSET==B0100)) {} //wait until confirmed } #if __CORTEX_M == 0x04 #define NRF5_RESET_EVENT(event) \ event = 0; \ (void)event #else #define NRF5_RESET_EVENT(event) event = 0 #endif extern "C" { void LPCOMP_IRQHandler(void) {door_tripped=true; NRF5_RESET_EVENT(NRF_LPCOMP->EVENTS_UP); NRF_LPCOMP->EVENTS_UP=0; MY_HW_RTC->CC[0]=(MY_HW_RTC->COUNTER+2);}}
-
Hi,
I had some progress with the sketch - and it works fine on the bench. On the bench, I report readings every 30 seconds but in deployment, its once in 10 minutes.So this is happening:
The door sensor interrupt works fine. When the node wakes up after an interrupt, it gives BME readings and goes to sleep for 10 minutes and reports again. But after the first wake after sleep, it does not wake up any more until interrupt happens again.
Could someone please see what mistake am I doing in this sketch//#define MY_DEBUG //Debug Disabled in production #define MY_RADIO_NRF5_ESB #define MY_NODE_ID 61 #define SKETCH_NAME "Hobby Room Door Sensor" #define SKETCH_VERSION "V1" #define MY_SMART_SLEEP_WAIT_DURATION 500 //activate smart sleep #define MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS 10000 //wait for 10 seconds to reconnect in case of transport problems #define MY_TRANSPORT_WAIT_READY_MS 30000 //try connecting for 30 seconds //#define MY_PARENT_NODE_ID 0 //#define MY_PARENT_NODE_IS_STATIC #define DIGITAL_INPUT_SENSOR 2 // The digital input you attached your Door/Window sensor. #define CHILD_ID_DOOR 1 // Id of the door/window sensor child. #define CHILD_ID_BATTERY 254 #define CHILD_ID_TEMP 2 #define CHILD_ID_HUMID 3 #define CHILD_ID_BARO 4 #include <MySensors.h> #include <SPI.h> #include <Adafruit_BME280.h> #include <Wire.h> #ifdef MY_DEBUG uint32_t SLEEP_TIME = 30000; // when debugging, sleep time is 30 seconds #endif #ifndef MY_DEBUG uint32_t SLEEP_TIME = 60000 * 10 ; // when deployed, sleep time is 10 minutes #endif #define SHORT_WAIT 1000 Adafruit_BME280 bme; // use I2C interface Adafruit_Sensor *bme_temp = bme.getTemperatureSensor(); Adafruit_Sensor *bme_pressure = bme.getPressureSensor(); Adafruit_Sensor *bme_humidity = bme.getHumiditySensor(); bool oldValueDoor = -1; float batteryVoltage = 0; // Initialize door/window message MyMessage msgDoor(CHILD_ID_DOOR, V_TRIPPED); //Door/Window. MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP); MyMessage msgHumid(CHILD_ID_HUMID, V_HUM); MyMessage msgPressure(CHILD_ID_BARO, V_PRESSURE); MyMessage msgBattery(CHILD_ID_BATTERY, V_VOLTAGE); void setup() { #ifdef MY_DEBUG { Serial.println("Setup started"); } #endif pinMode(DIGITAL_INPUT_SENSOR, INPUT_PULLUP); // sets the door/window sensor digital pin as input Wire.begin(); if (!bme.begin(0x76)) { while (1) delay(100); } #ifdef MY_DEBUG { Serial.println("Setup done"); } #endif } void presentation() { #ifdef MY_DEBUG { Serial.println("Presentation started"); } #endif // Send the sketch version information to the gateway and Controller sendSketchInfo(SKETCH_NAME, SKETCH_VERSION); // Register all sensors to gw (they will be created as child devices) present(CHILD_ID_DOOR, S_DOOR, "Hobby Room Door", true); wait(SHORT_WAIT); present(CHILD_ID_TEMP, S_TEMP, "Hobby Room Temperature", true); wait(SHORT_WAIT); present(CHILD_ID_HUMID, S_HUM, "Hobby Room Humidity", true); wait(SHORT_WAIT); present(CHILD_ID_BARO, S_BARO, "Hobby Room Pressure", true); wait(SHORT_WAIT); present(CHILD_ID_BATTERY, S_MULTIMETER, "Battery Voltage", true); #ifdef MY_DEBUG { Serial.println("Presentation done"); } #endif } void loop() { //Read digital door/window value. bool tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH; #ifdef MY_DEBUG { Serial.println("Tripped value"); Serial.print(tripped); } #endif if (tripped != oldValueDoor) { #ifdef MY_DEBUG { Serial.println("Tripped value in if statement"); Serial.print(tripped); Serial.println("oldValueDoor "); Serial.print(oldValueDoor); } #endif wait(100); send(msgDoor.set(tripped ? "1" : "0"), true); // Send door/window tripped value to gw wait(100); #ifdef MY_DEBUG { Serial.println(" Messgae sent and now tripped value is "); Serial.print(tripped); Serial.println(" Messgae sent and now oldValueDoor value is "); Serial.print(oldValueDoor); } #endif oldValueDoor = tripped; #ifdef MY_DEBUG { Serial.println("oldValue is now equal to tripped, check it - tripped is "); Serial.print(tripped); Serial.println("oldValue is now equal to tripped, check it - oldValueDoor is "); Serial.print(oldValueDoor); } #endif wait(100); #ifdef MY_DEBUG { Serial.println("Door message sent, exiting if"); wait(100); } #endif batteryVoltage = ((float)hwCPUVoltage()) / 1000.0; wait(100); send(msgBattery.set(batteryVoltage, 2)); wait(100); bool sendBatteryLevel(uint8_t level, bool echo); #ifdef MY_DEBUG { Serial.println("Battery reported"); } #endif wait(100); float pressure = bme.readPressure() / 100.0F; #ifdef MY_DEBUG { Serial.println("Starting BME readings"); } #endif bme.begin(0x76); sensors_event_t temp_event, pressure_event, humidity_event; bme_temp->getEvent(&temp_event); bme_pressure->getEvent(&pressure_event); bme_humidity->getEvent(&humidity_event); send(msgTemp.set(temp_event.temperature, 2)); wait(100); send(msgHumid.set(bme.readHumidity(), 2)); wait(100); send(msgPressure.set(pressure, 2)); wait(100); #ifdef MY_DEBUG { Serial.println("BME done"); Serial.println("waiting for interrupt"); } #endif smartSleep(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), CHANGE, SLEEP_TIME); sendHeartbeat(); } }
Should I be doing a Wire.end() before sleep and then Wire.begin() after waking up. But I think its not waking up from Sleep after the 19th minute from interrupt.
Thank you
-
@Puneit-Thukral I have a similar sensor ( PIR + BMP280 + other stuff). I don't use smartSleep ( Since this code is old, only sleep was available ) so I can't speak about the sleep part. Maybe you could try with regular sleep just to see if brings some diference...
Regarding the BME280 (BMP in my case) , I didn't have to use the Wire.begin() / end(), and I use the same library as yours (Adafruit).
Code is bellow, in case you want to compare yourself.
/** * 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. * ******************************* * * REVISION HISTORY * (adopted from 5in1 V2.1) * Version 3.0 - RV - Shifted to BMP280 sensor, added pressure and water leakage (via ROPE https://www.amazon.com/gp/product/B004FTFQ4W/ref=ppx_od_dt_b_asin_title_s01?ie=UTF8&psc=1 ) * * * DESCRIPTION * BMP280 on std SDA/SDL pins (Temp/Pressure) * LDR on pin A1: GND ---> 10k ---> A1 <-- LDR <-- Vcc * PIR on D3 and wakeup via interrupt (in case of PIR trigger) * Smoke on D2 with interrupt wake up too. ( 4n25 4K7 on buzzer, 2M7 Pullup resistor recommended ) * Water Sensing cable on A2: GND --> 100k --> A2 <-- X--X <-- Vcc * (https://www.amazon.com/gp/product/B004FTFQ4W/ref=ppx_od_dt_b_asin_title_s01?ie=UTF8&psc=1) * * Battery voltage is as battery percentage (Internal message), and optionally as a sensor value (See defines below) * */ // Enable debug prints to serial monitor #define MY_DEBUG // Board type #define DRAGON // PRO_MINI // DRAGON / SENSEBENDER // Define a static node address, AUTO or 1-255 fixed #define MY_NODE_ID 25 // AUTO #define MY_PARENT_NODE_ID AUTO // Enable and select radio type attached #define MY_RADIO_RF24 // MY_RADIO_RFM69 // Uncomment the line below, to transmit battery voltage as a normal sensor value #define BATT_SENSOR 199 #define NAME "8in1 Sensor" #define RELEASE "3.3" // Pin definitions for sensors #define SDA_PIN A5 // Just to document std IC2 interface #define SCL_PIN A4 // Just to document std IC2 interface #define LDR_PIN A1 // Analog Light sensor (LDR) #define WATER_PIN A2 // Analog Water Leak sensor (rope) #define SMOKE_PIN 2 // Digital Smoke sensor (0/1) #define PIR_PIN 3 // PIR Sensor (0/1) #define TRIGGER_PIN 4 // Trigger for HC-SR04 sensor #define ECHO_PIN 5 // Echo for HC-SR04 sensor #ifdef DRAGON // #define SPIFLASH_PIN 8 #define LED_PIN 9 #define TEST_PIN A0 #define MY_RF24_CE_PIN 7 #define MY_RF24_CS_PIN 10 // #define MY_SOFTSPI // #define MY_SOFT_SPI_SCK_PIN 13 // #define MY_SOFT_SPI_MISO_PIN 12 // #define MY_SOFT_SPI_MOSI_PIN 11 #endif #ifdef SENSEBENDER #define SPIFLASH_PIN 8 #define TEST_PIN A0 #define OTA_ENABLE A1 #define LED_PIN A2 #define ATSHA204_PIN 17 // A3 #endif #ifdef PRO_MINI #define LED_PIN 8 #endif // Includes /////////////////////////////////////////// #include <SPIMemory.h> #include <SPI.h> #include <MySensors.h> //#include <Wire.h> //#include <EEPROM.h> //#include <sha204_library.h> //#include <Adafruit_Sensor.h> #include <Adafruit_BMP280.h> /// Sketch parameters SETUP //////////////////////////// // Child sensor ID's #define CHILD_ID_TEMP 1 #define CHILD_ID_HUM 2 #define CHILD_ID_PRESS 3 #define CHILD_ID_LIGHT 4 #define CHILD_ID_PIR 5 #define CHILD_ID_SMOKE 6 #define CHILD_ID_WATER 7 #define CHILD_ID_TANK 8 // How many milli seconds should we wait for OTA? #define OTA_WAIT_PERIOD 500 // How many milli seconds between each measurement #define MEASURE_INTERVAL 720000 // 12min // How many wakeups to send battery level #define BAT_INTERVAL 100 // around 20 hours // FORCE_TRANSMIT_INTERVAL, this number of times of wakeup, the sensor is forced to report all values to the controller #define FORCE_TRANSMIT_INTERVAL 10 // around 2 hours // 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 // HUMI_TRANSMIT_THRESHOLD tells how much the humidity should have changed since last time it was transmitted. Likewise with // TEMP_TRANSMIT_THRESHOLD for temperature threshold. #define HUMI_TRANSMIT_THRESHOLD 5 #define TEMP_TRANSMIT_THRESHOLD 0.5 #define LIGHT_TRANSMIT_THRESHOLD 5 #define PRESS_TRANSMIT_THRESHOLD 50 // Flash memory #ifdef SPIFLASH_PIN SPIFlash flash( SPIFLASH_PIN ); #endif // ATSHA204 #ifdef ATSHA204_PIN atsha204Class sha204( ATSHA204_PIN ); #endif //Weather Sensor BMP280 on IC2 (Temp/Hum/Pressure): #ifdef SDA_PIN and SCL_PIN Adafruit_BMP280 weather_sensor; #endif // Sensor messages MyMessage msgHum(CHILD_ID_HUM, V_HUM); MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP); MyMessage msgPressure(CHILD_ID_PRESS, V_PRESSURE ); MyMessage msgLight(CHILD_ID_LIGHT, V_LIGHT_LEVEL); MyMessage msgMotion(CHILD_ID_PIR, V_TRIPPED); MyMessage msgSmoke(CHILD_ID_SMOKE, V_TRIPPED ); MyMessage msgWater(CHILD_ID_WATER, V_TRIPPED ); MyMessage msgDist(CHILD_ID_TANK, V_DISTANCE ); #ifdef BATT_SENSOR MyMessage msgBatt(BATT_SENSOR, V_VOLTAGE); #endif // Global settings int measureCount; int sendBattery; boolean isMetric = true; boolean highfreq = true; boolean transmission_occured = false; // Storage of old measurements float lastTemperature = -100; float lastHumidity = -100; float lastPressure = -100; long lastBattery = -100; int lastPir = -1; int lastLight = -100; int lastSmoke = -1; int lastWater = -1; int lastDist = -1; /**************************************************** * * Setup code * ****************************************************/ void setup() { #ifdef LED_PIN pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, HIGH); #endif Serial.begin( MY_BAUD_RATE ); // Default for MySensors is 115200 // Test Mode ////////////////////////// #ifdef TEST_PIN pinMode(TEST_PIN,INPUT_PULLUP); if (!digitalRead(TEST_PIN)) testMode(); pinMode(TEST_PIN,INPUT); #endif // Pin Mode Setup ////////////////////// #ifdef BAT_PIN pinMode(BAT_PIN , INPUT); // Ext. Batery meter (1M / 470K resistors) #endif #ifdef SMOKE_PIN pinMode(SMOKE_PIN , INPUT ); #endif #ifdef PIR_PIN pinMode(PIR_PIN , INPUT); #endif #ifdef TRIGGER_PIN pinMode(PIR_PIN , OUTPUT); #endif #ifdef ECHO_PIN pinMode(ECHO_PIN , INPUT); #endif // Startup Info Serial.print("Board:"); Serial.print( ARDUINO ); Serial.print( "\t" ); Serial.print( F_CPU / 1000000 ); Serial.print(" Mhz\t"); Serial.print( NAME ); Serial.print(" "); Serial.println( RELEASE ); Serial.print("Nrf24 CE/CS:"); Serial.print( MY_RF24_CE_PIN); Serial.print("/"); Serial.print( MY_RF24_CS_PIN ); Serial.print("\tNODE ID:"); Serial.print(hwReadConfig(EEPROM_NODE_ID_ADDRESS)); isMetric = getControllerConfig().isMetric; Serial.print(F("\tisMetric:")); Serial.println(isMetric); #ifdef OTA_WAIT_PERIOD Serial.print("OTA FW Enabled"); #endif // SPI Flash #ifdef SPIFLASH_PIN SPI.begin(); Serial.print(F("\tFlash:")); if ( flash.begin() ) { Serial.print( flash.getCapacity() / 8000 , 0 ); Serial.print( "KB"); flash.powerDown(); } else Serial.print( flash.error(VERBOSE) ); #endif // BMP280 init //////////////////////// #ifdef SDA_PIN and SCL_PIN Serial.print(F("\tBMP280:")); if ( weather_sensor.begin() ) { Serial.print(F("OK")); /* Default settings from datasheet. */ weather_sensor.setSampling(Adafruit_BMP280::MODE_NORMAL, /* Operating Mode. */ Adafruit_BMP280::SAMPLING_X1, /* Temp. oversampling */ Adafruit_BMP280::SAMPLING_X1, /* Pressure oversampling */ Adafruit_BMP280::FILTER_OFF ); /* Filtering. */ } else Serial.print(F("ERROR!")); #endif // Force 1st transmission of all sensors measureCount = FORCE_TRANSMIT_INTERVAL; sendBattery = BAT_INTERVAL; #ifdef LED_PIN digitalWrite(LED_PIN, LOW); #endif Serial.println(F("\n///////////////////// ONLINE /////////////////////")); Serial.flush(); } void presentation() { sendSketchInfo( NAME , RELEASE); #ifdef SDA_PIN present(CHILD_ID_TEMP,S_TEMP); present(CHILD_ID_HUM,S_HUM); present(CHILD_ID_PRESS, S_BARO ); #endif #ifdef LDR_PIN present(CHILD_ID_LIGHT,S_LIGHT_LEVEL); #endif #ifdef PIR_PIN present(CHILD_ID_PIR,S_MOTION); #endif #ifdef SMOKE_PIN present(CHILD_ID_SMOKE, S_SMOKE); #endif #ifdef WATER_PIN present(CHILD_ID_WATER, S_WATER_LEAK ); #endif #ifdef TRIGER_PIN present(CHILD_ID_TANK, S_DISTANCE ); #endif #ifdef BATT_SENSOR present(BATT_SENSOR, S_POWER); #endif } /*********************************************** * * Main loop function * ***********************************************/ void loop() { #ifdef LED_PIN digitalWrite( LED_PIN , HIGH ); #endif boolean forceTransmit = false; transmission_occured = false; if ( ++measureCount > FORCE_TRANSMIT_INTERVAL ) { // force a transmission forceTransmit = true; Serial.print(F("[Force Transmission]")); measureCount = 0; } // Light, PIR, Smoke, Water leak sendLight(forceTransmit); sendPir(forceTransmit); sendSmoke(forceTransmit); sendWater(forceTransmit); sendWeather(forceTransmit); sendDistance(forceTransmit); // Battery level report if ( ++sendBattery > BAT_INTERVAL ) { sendBattLevel(true); sendBattery = 0; } // Wait for FW update... if (transmission_occured) { wait(OTA_WAIT_PERIOD); measureCount = 0; } #ifdef LED_PIN digitalWrite( LED_PIN , LOW ); #endif Serial.println(); // Trick to avoid false triggering on PIR sleep(1000); // Sleep until interval or PIR or smoke trigger if ( lastSmoke == 1 ) // In case of Smoke Alarm, don't sleep too much... sleep( 45000 ); else if ( lastPir == 1 ) // In case of Motion, stop PIR detecting for 1 complete cycle... sleep( 0 , CHANGE , MEASURE_INTERVAL ); else sleep( 0 , CHANGE , 1 , CHANGE, MEASURE_INTERVAL); // Default: Wake up on any PIR and Smoke... // To avoid false Smoke alarm wait(100); // Wake Serial.print( millis() ); Serial.print("[WAKE]"); } /********************************************* * * Sends Motion status * *********************************************/ void sendDistance(bool force) { long duration; int distance; #ifdef TRIGER_PIN digitalWrite( TRIGER_PIN, LOW); delayMicroseconds(2); digitalWrite( TRIGER_PIN , HIGH); delayMicroseconds(10); digitalWrite( TRIGER_PIN , LOW); // Reads the echoPin, returns the sound wave travel time in microseconds duration = pulseIn( ECHO_PIN , HIGH); // Calculating the distance distance = duration * 0.034 / 2; if ( distance != lastDist || force ) { Serial.print(" D:");Serial.print(distance); send(msgDist.set(distance)); transmission_occured = true; lastDist = distance; } #endif } /********************************************* * * Sends Motion status * *********************************************/ void sendPir(bool force) { #ifdef PIR_PIN int currPir = digitalRead( PIR_PIN ); if ( lastPir != currPir || force ) { Serial.print(" M:");Serial.print(currPir); send(msgMotion.set(currPir)); transmission_occured = true; lastPir = currPir; } #endif } /********************************************* * * Sends Smoke status * *********************************************/ void sendSmoke(bool force) { #ifdef SMOKE_PIN int currSmoke = !digitalRead( SMOKE_PIN ); // Low = Smoke Triggered if ( lastSmoke != currSmoke || force ) { Serial.print(" S:");Serial.print(currSmoke); send(msgSmoke.set(currSmoke)); transmission_occured = true; lastSmoke = currSmoke; } #endif } /********************************************* * * Sends Smoke status * *********************************************/ void sendWater(bool force) { #ifdef WATER_PIN int currWater = ( analogRead( WATER_PIN ) > 500 ? 1 : 0 ) ; //Serial.println( analogRead( WATER_PIN ) ); if ( lastWater != currWater || force ) { Serial.print(" W:");Serial.print(currWater); send(msgWater.set(currWater)); transmission_occured = true; lastWater = currWater; } #endif } /********************************************* * * Sends Light Level based on LDR * * Parameters * - force : Forces transmission of a value (even if it's the same as previous measurement) * *********************************************/ void sendLight(bool force) { #ifdef LDR_PIN int currLight = map( analogRead( LDR_PIN ) , 0, 1024 , 0 , 100 ); int diffLight = abs( lastLight - currLight ); if (isnan(diffLight) || diffLight >= LIGHT_TRANSMIT_THRESHOLD || force ) { Serial.print(" L:");Serial.print(currLight); send(msgLight.set(currLight)); lastLight = currLight; transmission_occured = true; } #endif } /********************************************* * * Sends temperature and humidity from Si7021 sensor * * Parameters * - force : Forces transmission of a value (even if it's the same as previous measurement) * *********************************************/ void sendWeather(bool force) { #ifdef SDA_PIN and SCL_PIN bool tx = force; // Sensor reading float temp = weather_sensor.readTemperature(); //float humd = "N/A" ; // Hum is not supported on BMP280 (But it is in BME280) float pres = weather_sensor.readPressure(); // Temperature delta float diffTemp = abs( lastTemperature - temp ); if (diffTemp >= TEMP_TRANSMIT_THRESHOLD) tx = true; // Humidity delta //float diffHum = abs( lastHumidity - humd ); //if ( isnan(diffHum) || diffHum >= HUMI_TRANSMIT_THRESHOLD) tx = true; // Pressure delta float diffPress = abs( lastPressure - pres ); if (diffPress >= PRESS_TRANSMIT_THRESHOLD) tx = true; if (tx) { measureCount = 0; Serial.print(" T:");Serial.print(temp,1); //Serial.print(" H:");Serial.print(humd,1); Serial.print(" P:");Serial.print(pres,1); send(msgTemp.set(temp,1)); //send(msgHum.set(humd,1)); send(msgPressure.set(pres,1)); lastTemperature = temp; //lastHumidity = humd; lastPressure = pres; transmission_occured = true; } // BUG? High consumption ... //digitalWrite( SDA_PIN , LOW ); //digitalWrite( SCL_PIN , LOW ); #endif } /******************************************** * * Sends battery information (battery percentage) * * Parameters * - force : Forces transmission of a value * *******************************************/ void sendBattLevel(bool force) { #ifdef BAT_PIN long vcc = ( analogRead( BAT_PIN ) * 3300.0 / 1024.0 ) * 3.13; #else long vcc = readVcc(); #endif if ( abs( ( vcc - lastBattery ) ) > 100 || force) { lastBattery = vcc; #ifdef BATT_SENSOR float send_voltage = float(vcc)/1000.0f; send(msgBatt.set(send_voltage,3)); #endif // Calculate percentage vcc = vcc - 1900; // subtract 1.9V from vcc, as this is the lowest voltage we will operate at long percent = vcc / 13.0; //long percent = constrain( map( vcc, 4000 , 9000, 0, 100 ) , 0 , 100 ); Serial.print(" Batt%:"); Serial.print( percent ); sendBatteryLevel(percent); transmission_occured = true; } } /******************************************* * * Internal battery ADC measuring * *******************************************/ 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 } /**************************************************** * * 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; boolean fail = false; #ifdef LED_PIN digitalWrite(LED_PIN, HIGH); // Turn on LED. #endif Serial.println(F(" - TestMode")); Serial.println(F("Testing peripherals!")); Serial.flush(); #ifdef SDA_PIN Serial.print(F(" IC2 weather sensor ")); Serial.flush(); if ( weather_sensor.begin() && weather_sensor.readPressure() && weather_sensor.readTemperature() > 900 ) { Serial.println(F("ok!")); } else { Serial.println(F("failed!")); fail = true; } Serial.flush(); #endif #ifdef SPIFLASH_PIN Serial.print(F("-> Flash : ")); Serial.flush(); if (flash.begin()) { Serial.println(F("ok!")); } else { Serial.println(F("failed!")); fail = true; } Serial.flush(); #endif #ifdef ATSHA204_PIN 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); fail = true; } 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(")"); } } Serial.flush(); #endif Serial.println(F("Test finished")); if ( !fail ) { Serial.println(F("Selftest ok!")); while (1) // Blink OK pattern! { #ifdef LED_PIN digitalWrite(LED_PIN, HIGH); delay(200); digitalWrite(LED_PIN, LOW); delay(200); #endif } } else { Serial.println(F("----> Selftest failed!")); while (1) // Blink FAILED pattern! Rappidly blinking.. { } } }