Station météo : capteur de température, humidité et pression (BME280)

Station météo : capteur de température, humidité et pression (BME280)

Il s’agit d’une station météo sans fil avec mesure de la température, de l’humidité et de la pression atmosphérique. Elle utilise un module avec un capteur BME280 et un module nrf24l01 + pour la transmission sans fil. Le cœur est un  atmega328p qui peut être programmé avec arduino.

Le BME280

Le BME280 est un capteur environnemental qui permet de mesurer la pression, l’humidité et la température avec une consommation de courant réduite (3,6 μA à 1Hz). En mode sommeil, il atteint une consommation de 0.1 μA. Niveau interface, il dispose de ports I²C et SPI.

Le module utilisé comporte  6 pins :

PIN I²C SPI
VCC +3.3v +3.3v
GND GND GND
SCK SCL (avec résistance pull-up vers VCC) SCK
SDI SDA (avec résistance pull-up vers VCC) MOSI
CSB +3.3v (par défault en mode I²C) Slave Select (SS)
SDO
  • GND : adresse 0x76(par défault)
  • +3.3v : adresse 0x77
MISO

Schéma du circuit

Le circuit s’articule autour d’un Atmega328p comme dans la plupart des circuits présentés sur ce blog. C’est le même que celui présent sur l’Arduino Uno. La partie sans fil est assurée par un module Nrf24l01+. Le BME280 est utilisé avec le mode I²C et l’adresse 0x76. Il est alimenté en 3.3V,  avec un accu LiFePO4 par exemple, qui, vu la faible consommation, peut tenir plusieurs mois.

C5,C1,C2,C3,C6 100nF
Q1 AO3401
IC1 ATMEGA328P-P + Support
R1 1.2MΩ
R2 470kΩ
R3 100kΩ
D1 LED
R8 560Ω
U2 BME280 + Support 1×6
C4 470µF
U1 nRF24L01 + Support 2×4
J1 ALIM 3.3v

Abri anti-rayonnement

L’abri protège le capteur des rayonnements du soleil et de la pluie tout en assurant la circulation d’air autour du capteur. Il est réalisé à l’imprimante 3D, pour l’instant en PLA pour le prototype, mais l’ASA (acrylonitrile styrene acrylate) sera plus résistant aux UV et aux intempéries. Il est réalisé avec OpenScad.

Le matériel nécessaire pour le boitier :

  • 4x Boulon M4x80
  • 5x écrous M4
  • 5x Vis à tôle 2.9×6.5 ou 2.9×9.5

Les écrous sont noyés dans le plastique, ainsi il est nécessaire de mettre l’impression en pause après la dernière couche des emplacements des écrous.

Les fichiers stl sont disponibles sur Thingiverse.

Le programme

#include <LowPower.h>
#include <nRF24L01.h>
#include <printf.h>
#include <RF24.h>
#include <RF24_config.h>
#include <Wire.h>
#include <stdint.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

/* -------CONFIG---------*/
#define LOGDEBUG 0
/* --------------------- */

#define NODE_ID 1
#define RF24_CH 25
/* --------------------- */


#define SLEEP_DATA 37 //5min , 8s par cycle
#define SLEEP_VOLT 450 //1h
/* --------------------- */


#define VT_PIN 14 //A0
#define RF24_ON 6
#define LED_PIN 5
/* --------------------- */

//DEBUG
#if LOGDEBUG==1
#define DEBUG_PRINT(x) Serial.print(x)
#define DEBUG_PRINTDEC(x) Serial.print(x, DEC)
#define DEBUG_PRINTLN(x) Serial.println(x)
#define DEBUG_RADIO() radio.printDetails()
#else
#define DEBUG_PRINT(x)
#define DEBUG_PRINTDEC(x)
#define DEBUG_PRINTLN(x)
#define DEBUG_RADIO()
#endif
/* --------------------- */

uint16_t nodeId = NODE_ID;
uint8_t node_address[5] = {"1Node"};
uint8_t server_address[5] = {"2Node"};
/* --------------------- */


Adafruit_BME280 bme280;
RF24 radio(9,10);

uint8_t radioBuffer[32] = {0};

uint16_t cntDATA = SLEEP_DATA;
uint16_t cntVOLT = SLEEP_VOLT;

float humidity = 0;
float temperature = 0;
float pressure = 0;
float voltage = 0;


void radioSetup(){
radio.begin();
radio.setChannel(RF24_CH);
radio.setDataRate(RF24_250KBPS);
radio.setPALevel(RF24_PA_MAX);
radio.setCRCLength(RF24_CRC_16);
radio.setRetries(10, 15);
radio.setAutoAck(1);
radio.openReadingPipe(1, node_address);
radio.openWritingPipe(server_address);

DEBUG_RADIO();
}

void setup() {
delay(500);

#if LOGDEBUG==1
Serial.begin(115200);
printf_begin();
#endif

pinMode(RF24_ON, OUTPUT);
digitalWrite(RF24_ON, HIGH);

pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);

//flash led
digitalWrite(LED_PIN, HIGH);
delay(250);
digitalWrite(LED_PIN, LOW);

//1.1V internal voltage reference
analogReference(INTERNAL);

bme280.begin(0x76);
bme280.setSampling( Adafruit_BME280::MODE_FORCED,
Adafruit_BME280::SAMPLING_X1, // temperature
Adafruit_BME280::SAMPLING_X4, // pressure
Adafruit_BME280::SAMPLING_X1, // humidity
Adafruit_BME280::FILTER_OFF );

//flash led
delay(500);
digitalWrite(LED_PIN, HIGH);
delay(1000);
digitalWrite(LED_PIN, LOW);
}

void loop() {
DEBUG_PRINTLN("Start loop");

if( (cntDATA >= SLEEP_DATA) || (cntVOLT >= SLEEP_VOLT)){
//power on radio
digitalWrite(RF24_ON, LOW);

delay(100);
radioSetup();

DEBUG_PRINTLN("Radio up");

if(cntDATA >= SLEEP_DATA){
bme280.takeForcedMeasurement();
temperature = bme280.readTemperature();
humidity = bme280.readHumidity();
pressure = bme280.readPressure();

//sea level correction, sensor altitude is 104m above sea level
pressure = bme280.seaLevelForAltitude(104.0, pressure);

DEBUG_PRINT("T=");
DEBUG_PRINT(temperature);
DEBUG_PRINT(", H=");
DEBUG_PRINT(humidity);
DEBUG_PRINT(", P=");
DEBUG_PRINTLN(pressure);


memcpy(radioBuffer, &nodeId, 2);
memcpy(radioBuffer+2, "DATA", 4);

memcpy(radioBuffer+6, &temperature, 4);
memcpy(radioBuffer+10, &humidity, 4);
memcpy(radioBuffer+14, &pressure, 4);

memset(radioBuffer+18, 0, 14);

if(radio.write(radioBuffer, 32)){
cntDATA = 0;
}
else{
if(cntDATA >= (SLEEP_DATA+5)){
//retry up to 5 cycles of 8s.
cntDATA = 0;
}
}
}

delay(250);
radio.flush_tx();

if(cntVOLT >= SLEEP_VOLT){
voltage = analogRead(VT_PIN);
voltage = voltage * 1.1 * ((1670000.0)/470000.0) / 1024.0;

DEBUG_PRINT("V=");
DEBUG_PRINTLN(voltage);


memcpy(radioBuffer, &nodeId, 2);
memcpy(radioBuffer+2, "VOLT", 4);

memcpy(radioBuffer+6, &voltage, 4);

memset(radioBuffer+10, 0, 22);


if(radio.write(radioBuffer, 32)){
cntVOLT = 0;
}
else{
if(cntVOLT >= (SLEEP_VOLT+5)){
//retry up to 5 cycles of 8s.
cntVOLT = 0;
}
}
}

delay(50);

//power down radio
radio.powerDown();
digitalWrite(RF24_ON, HIGH);
}


++cntDATA;
++cntVOLT;

//flash led
digitalWrite(LED_PIN, HIGH);
delay(1);
digitalWrite(LED_PIN, LOW);

DEBUG_PRINTLN("Sleep for 8 seconds");

LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);

}

4 réflexions sur « Station météo : capteur de température, humidité et pression (BME280) »

    1. Hello,
      Sorry, it was a copy paste mistake, I forgot a #define : #define NODE_ID 1 before.
      Any number can be defined here, it’s to identify which node send the message.

  1. Je ne suis qu’un débutant. S’il vous plaît aider. Ce qui devrait être indiqué dans les lignes:
    uint16_t nodeId = NODE_ID;
    uint8_t node_address [5] = {« 1Node »};
    uint8_t adresse_serveur [5] = {« 2Node »};

    peut un exemple

    1. node_address [5] is the current node address on five bytes.
      adresse_serveur [5] is the receiver node address. Another node on the network must have this address and must be in listen mode. Soon, a new article will explain how to make an ethernet gateway tu listen data packets.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *