📜 ⬆️ ⬇️

Wireless temperature, humidity and atmospheric pressure sensor on the nRF52832

Greetings to all readers of Habr! Today's article will be about a temperature, humidity and atmospheric pressure sensor with a long battery life. The sensor works on the nRF52832 microcontroller ( datashit ). To obtain temperature, humidity and atmospheric pressure, a BME280 sensor is used - datashit . The sensor is powered by CR2430 / CR2450 / CR2477 batteries. Consumption in transmission mode is 8mA, in sleep mode 5mA. So, about everything in order.


This is the Arduino project, the program is written in the Arduino IDE. For the work of the BME280 sensor, the Adafruit Industries library is used - the githab sensors | githab bme280 . To work with nRF52832 boards in the Arduino IDE, the Sandeep Mistry project is used - githab . Data transmission to the controller of the Smart Home is carried out according to the protocol Mysensors - gitkhb boards | protocol | library .

The sensor board was developed in the program Diptreys. The dimensions of the board are 36.8mm x 25mm.
')


List of used components
  • C1 - cap0603 100nF
  • C2 - cap0603 100nF
  • R1 - res0603 332
  • R2 - res0603 85b
  • R3 - res0603 113
  • R4 - res0603 912
  • R5 - res0603 113
  • R6 - res0603 512
  • R7 - res0603 512
  • RGBL1 - led0805 rgb
  • SWD - PPHF 2x3 6p 1.27mm
  • U1 - YJ-16048 nRF52832
  • U2 - BME280
  • CONNECT - clock button KLS7-TS5401
  • RESET - KLS7-TS5401 Clock Button
  • Battery Holder KW-BS-2450-2-SMT
  • Dsc0012 switch


The fee was ordered through the site jlcpcb.com - $ 2 for 5 pieces in any color.





Link to the archive with gerber files

The sensor works according to the Mysensors protocol. Adding any device to the Mysensors network is quite simple. Let's look at the example of this sensor, I will omit the explanation on the code of the BME280 sensor itself, nothing changes there when working with the Mysensors network.

#define MY_DEBUG //   #define MY_RADIO_NRF5_ESB //   (  rfm69, rfm95, nrf24l01, nrf51-52) #define MY_RF24_PA_LEVEL (NRF5_PA_MAX) //    #define MY_DISABLED_SERIAL //   #define MY_PASSIVE_NODE //   (   mysensors), PASSIVE        ,   , ,  #define MY_NODE_ID 1 //     #define MY_PARENT_NODE_ID 0 //       //#define MY_PARENT_NODE_IS_STATIC //  PARENT_NODE        //#define MY_TRANSPORT_UPLINK_CHECK_DISABLED //      #include <MySensors.h> // -  MySensors #define TEMP_CHILD_ID 0 //     #define HUM_CHILD_ID 1 //     #define BARO_CHILD_ID 2 //      #define CHILD_ID_VOLT 254 //      MyMessage voltMsg(CHILD_ID_VOLT, V_VOLTAGE); //       MyMessage temperatureMsg(TEMP_CHILD_ID, V_TEMP); //      MyMessage humidityMsg(HUM_CHILD_ID, V_HUM); //      MyMessage pressureMsg(BARO_CHILD_ID, V_PRESSURE); //      
Presentation of sensors and sensors in the controller of a smart home:

  sendSketchInfo("BME280 Sensor", "1.0"); //  ,   present(CHILD_ID_VOLT, S_MULTIMETER, "Battery"); //    ,  ,  present(TEMP_CHILD_ID, S_TEMP, "TEMPERATURE [C or F]"); //   ,  ,  present(HUM_CHILD_ID, S_HUM, "HUMIDITY [%]"); //   ,  ,  present(BARO_CHILD_ID, S_BARO, "PRESSURE [hPa or mmHg]"); //    ,  ,  

Data transfer to the smart home controller:
 send(voltMsg.set(batteryVoltage)); //       mW sendBatteryLevel(currentBatteryPercent); //       % send(temperatureMsg.set(temperature, 1)); //    ,  1    send(humidityMsg.set(humidity, 0)); //    ,  0    send(pressureMsg.set(pressure, 0)); //    ,  0    


Arduino program code
 #include <Wire.h> #include <SPI.h> #include <Adafruit_Sensor.h> #include <Adafruit_BME280.h> //#define MY_DEBUG #define MY_RADIO_NRF5_ESB #define MY_RF24_PA_LEVEL (NRF5_PA_MAX) #define MY_DISABLED_SERIAL #define MY_PASSIVE_NODE #define MY_NODE_ID 1 #define MY_PARENT_NODE_ID 0 //#define MY_PARENT_NODE_IS_STATIC //#define MY_TRANSPORT_UPLINK_CHECK_DISABLED #include <MySensors.h> bool sleep_flag; bool metric = true; bool last_sent_value; uint16_t currentBatteryPercent; uint16_t lastBatteryPercent = 1000; uint16_t battery_vcc_min = 2150; uint16_t battery_vcc_max = 2950; uint16_t batteryVoltage; uint16_t battery_alert_level = 25; uint32_t default_sleep_time = 60000; uint32_t SLEEP_TIME; uint32_t newmillisforbatt; uint32_t battsendinterval = 3600000; float tempThreshold = 0.5; float humThreshold = 5; float presThreshold = 1; float pres_mmThreshold = 1; float temperature; float pressure; float pressure_mm; float humidity; float lastTemperature = -1; float lastHumidity = -1; float lastPressure = -1; float lastPressure_mm = -1; #define SEALEVELPRESSURE_HPA (1013.25) Adafruit_BME280 bme; #define TEMP_CHILD_ID 0 #define HUM_CHILD_ID 1 #define BARO_CHILD_ID 2 #define CHILD_ID_VOLT 254 MyMessage voltMsg(CHILD_ID_VOLT, V_VOLTAGE); MyMessage temperatureMsg(TEMP_CHILD_ID, V_TEMP); MyMessage humidityMsg(HUM_CHILD_ID, V_HUM); MyMessage pressureMsg(BARO_CHILD_ID, V_PRESSURE); void preHwInit() { pinMode(21, INPUT); pinMode(25, OUTPUT); digitalWrite(25, HIGH); pinMode(26, OUTPUT); digitalWrite(26, HIGH); pinMode(27, OUTPUT); digitalWrite(27, HIGH); } void before() { NRF_POWER->DCDCEN = 1; NRF_NFCT->TASKS_DISABLE = 1; NRF_NVMC->CONFIG = 1; NRF_UICR->NFCPINS = 0; NRF_NVMC->CONFIG = 0; if (NRF_SAADC->ENABLE) { NRF_SAADC->TASKS_STOP = 1; while (NRF_SAADC->EVENTS_STOPPED) {} NRF_SAADC->ENABLE = 0; while (NRF_SAADC->ENABLE) {} } pinMode(BLUE_LED, OUTPUT); pinMode(RED_LED, OUTPUT); digitalWrite(BLUE_LED, HIGH); digitalWrite(RED_LED, HIGH); digitalWrite(27, LOW); } void setup() { digitalWrite(27, HIGH); bme_initAsleep(); wait(100); sendBatteryStatus(); wait(100); } void presentation() { sendSketchInfo("EFEKTA BME280 Sensor", "1.2"); present(CHILD_ID_VOLT, S_MULTIMETER, "Battery"); present(TEMP_CHILD_ID, S_TEMP, "TEMPERATURE [C or F]"); present(HUM_CHILD_ID, S_HUM, "HUMIDITY [%]"); present(BARO_CHILD_ID, S_BARO, "PRESSURE [hPa or mmHg]"); } void loop() { wait(10); bme.takeForcedMeasurement(); wait(100); sendData(); if (millis() - newmillisforbatt >= battsendinterval) { sleep_flag = 1; sendBatteryStatus(); } if (sleep_flag == 0) { sleep(SLEEP_TIME); sleep_flag = 1; } } void blinky(uint8_t pulses, uint8_t repit, uint8_t ledColor) { for (int x = 0; x < repit; x++) { if (x > 0) { sleep(500); } for (int i = 0; i < pulses; i++) { if (i > 0) { sleep(100); } digitalWrite(ledColor, LOW); wait(20); digitalWrite(ledColor, HIGH); } } } void sendBatteryStatus() { wait(20); batteryVoltage = hwCPUVoltage(); wait(2); if (batteryVoltage > battery_vcc_max) { currentBatteryPercent = 100; } else if (batteryVoltage < battery_vcc_min) { currentBatteryPercent = 0; } else { if (lastBatteryPercent == 1000) { currentBatteryPercent = (100 * (batteryVoltage - battery_vcc_min)) / (battery_vcc_max - battery_vcc_min) + 5; } else { currentBatteryPercent = (100 * (batteryVoltage - battery_vcc_min)) / (battery_vcc_max - battery_vcc_min) - 5; } } sendBatteryLevel(currentBatteryPercent); wait(100); if (lastBatteryPercent < battery_alert_level) { blinky(3, 1, RED_LED); } else { blinky((last_sent_value == true ? 2 : 1), 1, BLUE_LED); } sleep_flag = 0; newmillisforbatt = millis(); } void sendData() { temperature = bme.readTemperature(); wait(20); humidity = bme.readHumidity(); wait(20); pressure = bme.readPressure() / 100.0F; if (!metric) { temperature = temperature * 9.0 / 5.0 + 32.0; } else { pressure = pressure * 0.75006375541921; } CORE_DEBUG(PSTR("MY_TEMPERATURE: %d\n"), (int)temperature); CORE_DEBUG(PSTR("MY_HUMIDITY: %d\n"), (int)humidity); CORE_DEBUG(PSTR("MY_PRESSURE: %d\n"), (int)pressure); if (abs(temperature - lastTemperature) >= tempThreshold) { send(temperatureMsg.set(temperature, 1)); lastTemperature = temperature; sleep(1000); } if (abs(humidity - lastHumidity) >= humThreshold) { send(humidityMsg.set(humidity, 0)); lastHumidity = humidity; sleep(1000); } if (abs(pressure - lastPressure) >= presThreshold) { send(pressureMsg.set(pressure, 0)); lastPressure = pressure; sleep(1000); } sleep_flag = 0; } void bme_initAsleep() { if (! bme.begin(&Wire)) { while (1); } bme.setSampling(Adafruit_BME280::MODE_FORCED, Adafruit_BME280::SAMPLING_X1, // temperature Adafruit_BME280::SAMPLING_X1, // pressure Adafruit_BME280::SAMPLING_X1, // humidity Adafruit_BME280::FILTER_OFF ); wait(1000); } 


The body for the sensor was developed in a 3D editor:



The ANYCUBIC FOTON 3D printer was printed, the white resin of the same manufacturer was used, the average layer thickness was chosen - 50 microns. Printing time of the case and cover is 3 hours.








The MySensors network in which the sensor is working communicates with the smart home system Majordomo. The registered sensor in the Mysensors Majordomo module looks like this:




Video with test



For those who want to do the same for themselves in the article are links to everything you need.

A place where you are always happy to help everyone who wants to get acquainted with MYSENSORS (installing boards, working with nRF5 microcontrollers in the Arduino IDE environment, tips on working with the mysensors protocol - @mysensors_eng

Source: https://habr.com/ru/post/455856/


All Articles