Домашняя метеостанция (Arduino)

В домашней метеостанции будут использоваться следующие компоненты:

  • Arduino Nano
  • модуль DS3231 — часы реального времени
  • модуль BMP280 — датчик атмосферного давления и температуры (измерение атмосферного давления в мм.рт.ст и  температуры в комнате)
  • модуль 18B20 — цифровой датчик температуры (измерение температуры на улице)
  • модуль DHT11 — датчик влажности
  • LCD 1602  на базе контроллера HD44780
BMP280 DHT11 DS3231 18B20

Так же Вам понадобятся следующие библиотеки:

В первой строке LCD 1602 выводятся показания времени, даты и месяца, во второй с периодичностью 10 секунд будут меняться показания температуры, атмосферного давления и влажности.

#include <Wire.h>
#include <SPI.h>
#include <DHT.h> 
#include <LiquidCrystal.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <DS3231.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>
DHT dht(2, DHT11); // выход DATA подключен к цыфровому входу 2
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);// RS,E,D4,D5,D6,D7
Adafruit_BMP280 bmp; // I2C
OneWire oneWire(A1);// А1 вход датчика 18b20
DallasTemperature t(&oneWire);
DS3231 clock;RTCDateTime DateTime;
 
void setup() {
  Serial.begin(9600);
  bmp.begin(); 
  dht.begin();
  lcd.begin(16,2);// LCD 16X2
  t.begin(); 
  t.setResolution(10);// 10 bit 18b20
  clock.begin();
// clock.setDateTime(__DATE__, __TIME__);// установка времени DS3231, раскомментировать и залить скетч, далее закомментировать и залить скетч повторно   
}
 
 
void loop() {
   t.requestTemperatures();
   DateTime=clock.getDateTime();   // Считываем c часов текущие значения даты и времени в сущность DateTime
   lcd.setCursor(0,0);
//   lcd.print(clock.dateFormat("H:i:s ",DateTime));// выводим часы и минуты
//   lcd.print(clock.dateFormat("d M", DateTime));// выводим дату и месяц 
 
 if(DateTime.hour<10){lcd.print("0");}lcd.print(DateTime.hour);lcd.print(":");
 if(DateTime.minute<10){lcd.print("0");}lcd.print(DateTime.minute);lcd.print(":");
 if(DateTime.second<10){lcd.print("0");}lcd.print(DateTime.second);lcd.print(" ");
 if(DateTime.day<10){lcd.print("0");}lcd.print(DateTime.day);lcd.print("-");
 if(DateTime.month<10){lcd.print("0");}lcd.print(DateTime.month);
 
   lcd.setCursor(0,1);
 
  if((DateTime.second/10)%2==0){ // каждые нечетные 10 секунд показвать температуру
   lcd.setCursor(1,1);
   lcd.print(bmp.readTemperature(),1);
   lcd.print(char(223)); lcd.print("C  ");
   t.requestTemperatures();// опрос 18b20
   lcd.print(t.getTempCByIndex(0),1); // вывод температуры 18b20
   lcd.print(char(223)); lcd.print("C");
  }
  else{
   lcd.setCursor(1,1);lcd.print("P ");
   lcd.print(bmp.readPressure()/133.3224,1);// давление в мм.рт.ст
   lcd.print("  H ");
   lcd.print(dht.readHumidity(),0);// влажность
   lcd.print("%");}
}

Если у Вас не работает датчик BMP280 после загрузки скетча, то вероятней всего адрес уст-ва не соответствует указанному в файле библиотеки Adafruit_BMP280.h, необходимо узнать адрес уст-ва, но так как на шине i2c подключены еще часы реального времени ds3132, то их необходимо временно из схемы убрать.

Для определения адреса используйте следующий скетч (сканер i2c):

#include <Wire.h>
void setup(){
    Wire.begin();    
    Serial.begin(9600);
    while (!Serial);
    Serial.println("\nI2C Scanner");
} 
 
void loop(){
    byte error, address;
    int nDevices;
 
    Serial.println("Scanning...");
 
    nDevices = 0;
    for(address = 8; address < 127; address++ ){
        Wire.beginTransmission(address);
        error = Wire.endTransmission();
        if (error == 0){
            Serial.print("I2C device found at address 0x");
            if (address<16)
                Serial.print("0");
            Serial.print(address,HEX);
            Serial.println(" !");
            nDevices++;
        }
        else if (error==4) {
            Serial.print("Unknow error at address 0x");
            if (address<16)
                Serial.print("0");
            Serial.println(address,HEX);
        } 
    }
    if (nDevices == 0)
        Serial.println("No I2C devices found\n");
    else
        Serial.println("done\n");
    delay(5000);
}

Как видно на скриншоте адрес уст-ва определился как 0х76. Далее откройте файл Adafruit_BMP280.h библиотеки и сравните адрес уст-ва с указанным в файле, если адрес отличается, то укажите свой.

Часы реального времени нуждаются в установке времени если это не было сделано ранее, установить время можно по времени компиляции, для этого раскомментируйте строчку:

clock.setDateTime(__DATE__, __TIME__);

Залейте скетч, далее закомментируйте строчу и залейте скетч повторно.

Следующая версия домашней метеостанции аналогична первой, только вместо дисплея LCD 1602 применен индикатор на базе драйвера TM1637 (модуль TM1637).

Домашняя метеостанция работает в следующих режимах (при нажатии на кнопку SA):

  • SA0 — основной режим, установлен по умолчанию, показывает время в течении 20 секунд, далее с интервалом в 10 секунд выводит поочередно температуру дома (BMP280), температуру на улице (18B20), давление и влажность.
  • SA1 — показывает только время
  • SA2 — температура дома
  • SA3 — температура на улице
  • SA4 — атмосферное давление в мм.рт.ст
  • SA5 — влажность в %
  • следующее нажатии кнопки SA активирует основной режим SA0
#include <Wire.h>
#include <SPI.h>
#include <DHT.h> 
#include <OneWire.h>
#include <DallasTemperature.h>
#include <TM1637Display.h>
#include <DS3231.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>
DHT dht(2, DHT11); // выход DATA подключен к цыфровому входу 2
Adafruit_BMP280 bmp; // I2C
OneWire oneWire(A1);// А1 вход датчика 18b20
DallasTemperature t(&oneWire);
DS3231 clock;RTCDateTime DateTime;//ds3132 A4,A5 (SDA,SCL)
TM1637Display display(12, 11);// CLK,DIO
 
void setup() {
  pinMode(4,INPUT);pinMode(10,INPUT);
  bmp.begin(); dht.begin(); t.begin(); clock.begin();
  t.setResolution(9);// 9 bit 18b20
  display.setBrightness(2);// яркость TM1637 0-7
// clock.setDateTime(__DATE__, __TIME__);// установка времени DS3231, раскомментировать и залить скетч, далее закомментировать и залить скетч повторно   
}
 int k,x,z,kn,sec;
 uint8_t date_t1[]{0x78,0x10,0,0};// t1
 uint8_t date_t2[]{0x78,0,0,0};// t2
 uint8_t date_p[]{0x73,0,0,0};// p
 uint8_t date_h[]{0x76,0,0,0};// h
 uint8_t date_kn[]{0x6d,0x77,0,0};// h
 
void loop() { 
   DateTime = clock.getDateTime(); // ОПРОС ВРЕМЕНИ
 
   if(digitalRead(10)==HIGH){kn++;if(kn>5){kn=0;}z=1;
   date_kn[3] = display.encodeDigit(kn);
   display.setSegments(date_kn);delay(500);}
 
   switch(kn){case 0: sec=DateTime.second;break;// all
              case 1: sec=10;break;// time
              case 2: sec=25;break;//t1
              case 3: sec=35;break;//t2
              case 4: sec=45;break;//p
              case 5: sec=55;break;}//h
 
  if(sec>=0&&sec<=20){z=0; k = DateTime.hour*100+DateTime.minute;} // ВРЕМЯ КАК ЧИСЛО ННММ
   if(digitalRead(4) == HIGH){x = 0x40;}else{x = 0x00;} // МИГАНИЕ ДВОЕТОЧИЯ 
 
   if(sec>20&&sec<=30){z=1;t.requestTemperatures();k=bmp.readTemperature();// вывод температуры дома t1
   date_t1[2] = display.encodeDigit((k/10)%10);
   date_t1[3] = display.encodeDigit((k%10)%10);
   display.setSegments(date_t1);}
 
   if(sec>30&&sec<=40){z=1;k=abs(t.getTempCByIndex(0));// вывод температуры на улице t2
   date_t2[2] = display.encodeDigit((k/10)%10);
   date_t2[3] = display.encodeDigit((k%10)%10);
   if(t.getTempCByIndex(0)<0){date_t2[1]=0x15;}else{date_t2[1]=0x14;}
   display.setSegments(date_t2);}
 
   if(sec>40&&sec<=50){z=1;k=bmp.readPressure()/133.3224;// вывод атмосферного давления
   date_p[1] = display.encodeDigit(k/100);
   date_p[2] = display.encodeDigit((k/10)%10);
   date_p[3] = display.encodeDigit((k%10)%10);
   display.setSegments(date_p);}
 
   if(sec>50&&sec<=59){z=1;k=dht.readHumidity();// вывод влажности
   date_h[2] = display.encodeDigit((k/10)%10);
   date_h[3] = display.encodeDigit((k%10)%10);
   display.setSegments(date_h);}
 
  if(z==0){ display.showNumberDecEx(k,x,false);}
}

Comments

    1. Найдите в библиотеке DS3231 файл DS3231.cpp
      Далее найдите строчки
      char* DS3231::dateFormat(const char* dateFormat, RTCDateTime dt)
      {
      char buffer[255];

      замените на
      char* DS3231::dateFormat(const char* dateFormat, RTCDateTime dt)
      {
      static char buffer[255];

      Должно помочь, или загрузите скетч в старой версии Arduino IDE 1,0,1

  1. Здравствуйте! Помогите пожалуйста вывести дату на дисплей, вроде часы вывел работают хотелось и дату . заменил строчку lcd.print(clock.dateFormat(«H:i:s»,DateTime));// выводим часы, минуты на эту lcd.print(DateTime.hour/10);lcd.print(DateTime.hour%10);lcd.print(«:»);
    lcd.print(DateTime.minute/10);lcd.print(DateTime.minute%10);lcd.print(«:»);
    lcd.print(DateTime.second/10);lcd.print(DateTime.second%10);

Добавить комментарий

Войти с помощью: