Capteur de température, d'humidité et de pression atmosphérique sans fil sur nRF52832

Salutations à tous les lecteurs Habr! L'article d'aujourd'hui portera sur un capteur de température, d'humidité et de pression atmosphérique avec une longue durée de vie de la batterie. Le capteur fonctionne sur le microcontrôleur nRF52832 ( fiche technique ). Pour obtenir la température, l'humidité et la pression atmosphérique, le capteur BME280 - fiche technique a été utilisé . Le capteur est alimenté par des piles CR2430 / CR2450 / CR2477. La consommation en mode transmission est de 8mA, en mode veille de 5mA. Alors, à propos de la commande.


Il s'agit d'un projet Arduino, le programme est écrit dans l'IDE Arduino.La bibliothèque Adafruit Industries est utilisée pour faire fonctionner le capteur BME280 - capteurs github | github BME280 . Pour fonctionner avec les cartes nRF52832, l'IDE Ardeino a utilisé le projet Sandeep Mistry - github . Le transfert des données vers le contrôleur de la Smart House s'effectue selon le protocole Mysensors - cartes github | protocole | bibliothèque .

La carte capteur a été développée dans le cadre du programme Diptrace. Les dimensions de la planche sont de 36,8 mm X 25 mm.



Liste des composants utilisés
  • 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,27 mm
  • U1 - YJ-16048 nRF52832
  • U2 - BME280
  • CONNECT - interrupteur tactile KLS7-TS5401
  • RESET - bouton horloge KLS7-TS5401
  • Support de batterie KW-BS-2450-2-SMT
  • Commutateur DSC0012


Les frais ont été commandés via jlcpcb.com - 2 $ pour 5 pièces de n'importe quelle couleur.





Lien vers l'archive avec des fichiers Gerber

Le capteur fonctionne selon le protocole Mysensors. L'ajout de n'importe quel appareil au réseau Mysensors est facile. Regardons l'exemple de ce capteur, je vais omettre l'explication du code du capteur BME280, rien ne change lorsque vous travaillez avec le réseau Mysensors.

#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); //      
Présentation des capteurs et capteurs dans le contrôleur d'une maison intelligente:

  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]"); //    ,  ,  

Transfert de données vers le contrôleur de maison intelligente:
 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    


Code de programme Arduino
 #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); } 


Le boîtier du capteur a été développé dans l'éditeur 3D:



Il a été imprimé sur une imprimante 3D ANYCUBIC FOTON, une résine blanche du même fabricant a été utilisée, l'épaisseur de la couche a été choisie moyenne - 50 microns. Le temps d'impression pour le boîtier et la couverture est de 3 heures.








Le réseau MySensors dans lequel travaille le capteur communique avec le système de la maison intelligente de Magordomo. Le capteur enregistré dans le module Maysensors Majordomo ressemble à ceci:




Vidéo test



Pour ceux qui veulent faire de même pour eux-mêmes, l'article fournit des liens vers tout ce dont vous avez besoin.

Un endroit où vous êtes toujours heureux d'aider tous ceux qui veulent se familiariser avec MYSENSORS (installation de cartes, travail avec des microcontrôleurs nRF5 dans l'environnement Arduino IDE, conseils pour travailler avec le protocole mysensors - @mysensors_rus

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


All Articles