На сайте уже есть несколько проектов погодных станций, но с появлением у меня высокоточного датчика AHT10 я решил снова разработать погодную станцию. Погодная станция как правило имеет возможность измерять температуру в помещении и на улице, давление и влажность. Дополнительно на дисплей будет выводится время и добавлена функция будильника.
В погодной станции используются следующие компоненты:
- Датчик влажности и температуры AHT10 (модуль)
- Датчик давления BMP280 (модуль)
- Датчик температуры DS18B20
- Часы реального времени DS3231 (модуль)
- Дисплей LCD2004
- Расширитель портов PCF8574 I2C который работает совместно с LCD2004 (модуль)
- 5 кнопок
- Пьезоизлучатель
- Транзистор BC547
- Резисторы 4,7 кОм 0,125 Вт 2 шт
Параметры датчиков:
- AHT10
- Напряжение питания: 1.8 В … 3.6 В для AHT10
- Диапазон измерения температуры: -40°C .. + 85°C
- Разрешающая способность по температуре: 0.01°C
- Точность измерения температуры: ± 0.3°C
- Диапазон измерения относительной влажности: 0% .. 100%
- Разрешающая способность по влажности: 0,024%
- Точность измерения относительной влажности: ± 2% при 25°C
- Рекомендуемая частота опроса: 8 сек … 30 сек
- BMP280
- Напряжение питания: 1.71 В … 3.6 В
- Интерфейс обмена данными: I2C или SPI
- Ток потребления в рабочем режиме: 2.7 мкА при частоте опроса 1 Гц
- Диапазон измерения атмосферного давления: 300hPa – 1100hPa (±0.12hPa), что эквивалентно диапазону от -500 до 9000 м над уровнем моря
- Диапазон измерения температуры: -40°С … +85°С (±0.01°С)
- Максимальная частота работы интерфейса I2C: 3.4 МГц
- Максимальная частота работы интерфейса SPI: 10 МГц
- DS18B20
- Напряжение питания: 3 В … 5.5 В
- Протокол обмена данными: 1-Wire
- Способ подключения: прямой / по одной линии с паразитным питанием
- Разрешение преобразования температуры: 9 бит – 12 бит
- Диапазон измерения температуры: от -55 до +125 оС
- Период измерения температуры при максимальной точности 12 бит: 750 мс
- Тип индексации на линии 1-Wire: уникальный 64-битный адрес
- DS3231
- Напряжение питания: 3.3 В … 5 В
- Чип памяти: AT24C32 (32 Кб)
- Точность: ± 0.432 сек в день
- Частота кварца:32.768 кГц
- Поддерживаемый протокол: I2C
В погодной станции используется датчик DS18B20 в металлическом корпусе, он не имеет подтягивающего резистора который необходим для правильной работы, поэтому в схему добавлен подтягивающий резистор.
I2C модуль на базе микросхем PCF8574 позволяют подключить символьный дисплей 2004 к плате Arduino всего по двум проводам SDA и SCL (А4 и А5), что дает возможность не использовать цифровые выходы Arduino при подключении дисплея.
Данные с датчиков считываются каждые 10 секунд.
В качестве органов управления используются 5 кнопок, две из которых участвую в установке текущего времени и даты, эти кнопки редко используемые, поэтому выводить их на лицевую панель прибора не обязательно. Основные кнопки это кнопки отключения/включения будильника и коррекция времени будильника.
Для установки времени необходимо нажать и удерживать кнопку «УСТ. ВРЕМЯ» и нажимая на кнопки «ЧАСЫ / ДАТА» и «МИНУТЫ / МЕСЯЦ» установить часы и минуты. Рекомендую устанавливать на одну минуту больше положенного времени, это необходимо для точной установки секунд. При смене минуты необходимо удерживать кнопку «УСТ. ВРЕМЯ» и нажать на кнопку «ОБНУЛЕНИЕ СЕКУНД / ГОД / УСТ. БУДИЛЬНИКА».
Аналогичным образом устанавливается дата, месяц и год, только вместо кнопки «УСТ. ВРЕМЯ» нужно нажать и удерживать кнопку «УСТ. ДАТА-МЕСЯЦ-ГОД»
Для установки времени будильника нужно нажать и удерживать кнопку «ОБНУЛЕНИЕ СЕКУНД / ГОД / УСТ. БУДИЛЬНИКА», а кнопками «ЧАСЫ / ДАТА» и «МИНУТЫ / МЕСЯЦ» установить часы и минуты срабатывания будильника.
Показания датчиков меняются на экране каждые пять секунд (время можно изменить в скетче), первоначально выводится дата, месяц, год и температура на улице.
Потом выводятся показания других датчиков: влажность, давление в мм.рт.ст и температуры в помещении.
#include <Wire.h> #include <SPI.h> #include <LiquidCrystal_I2C.h> //Библиотека - http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1 #include <DS3231.h>//https://github.com/jarzebski/Arduino-DS3231/archive/master.zip // DS3231.zip #include <Thinary_AHT10.h> // http://rcl-radio.ru/wp-content/uploads/2020/07/AHT10-master.zip #include <Adafruit_BMP280.h> // http://rcl-radio.ru/wp-content/uploads/2018/08/Adafruit_BMP280.zip #include <OneWire.h> // http://rcl-radio.ru/wp-content/uploads/2018/07/OneWire.zip #include <DallasTemperature.h> // http://rcl-radio.ru/wp-content/uploads/2018/07/DallasTemperature.zip #include <EEPROM.h> #define IND 5000 // время смены показаний датчиков LiquidCrystal_I2C lcd(0x27,20,4); // Устанавливаем дисплей DS3231 clock;RTCDateTime DateTime;AHT10Class AHT10; Adafruit_BMP280 bmp(10); OneWire oneWire(A0);// вход датчика 18b20 DallasTemperature temp(&oneWire); byte v1[8] = {7,7,7,7,7,7,7,7}; byte v2[8] = {7,7,0, 0, 0, 0, 0, 0}; byte v3[8] = { 0, 0, 0, 0, 0,0,31,31}; byte v4[8] = {31,31, 0, 0, 0, 0,31,31}; byte v5[8] = { 28, 28, 0, 0, 0, 0, 28, 28};// byte v6[8] = {28,28,28,28,28,28,28,28}; byte v7[8] = { 0, 0, 0, 0, 0, 0,7,7}; byte v8[8] = { 31, 31,0,0,0,0,0, 0}; int a[6],hour,minut,secon,h_alarm,m_alarm,memory,alarm,yar,mount,date; byte i,d1,d2,d3,d4,d5,d6,e1,e2,e3; float temp_hous,h,p,k; unsigned long times,times1; void setup(){ Wire.begin();AHT10.begin();lcd.init();clock.begin();bmp.begin();temp.begin();temp.setResolution(10); ///clock.setDateTime(__DATE__, __TIME__); lcd.backlight();// Включаем подсветку дисплея lcd.createChar(1, v1);lcd.createChar(2, v2);lcd.createChar(3, v3);lcd.createChar(4, v4);lcd.createChar(5, v5);lcd.createChar(6, v6);lcd.createChar(7, v7);lcd.createChar(8, v8); pinMode(2,INPUT_PULLUP); // УСТ. ВРЕМЯ pinMode(7,INPUT_PULLUP); // УСТ. ДАТА-МЕСЯЦ-ГОД pinMode(3,INPUT_PULLUP); // ЧАСЫ / ДАТА pinMode(4,INPUT_PULLUP); // МИНУТЫ / МЕСЯЦ pinMode(5,INPUT_PULLUP); // ОБНУЛЕНИЕ СЕКУНД / ГОД / УСТ. БУДИЛЬНИКА pinMode(6,OUTPUT); // ZZZZZZzzzzzz..... h_alarm = EEPROM.read(11);m_alarm = EEPROM.read(12);alarm = EEPROM.read(13); } void loop(){ if(millis()-times>10000){temp_hous = AHT10.GetTemperature();h = AHT10.GetHumidity(); p = bmp.readPressure()/133.3224;temp.requestTemperatures(); k = temp.getTempCByIndex(0);times = millis();} // ОПРОС ДАТЧИКОВ КАЖДЫЕ 10 СЕК if(digitalRead(2)==LOW||digitalRead(3)==LOW||digitalRead(4)==LOW||digitalRead(5)==LOW||digitalRead(7)==LOW){times1=millis();} DateTime=clock.getDateTime(); yar = DateTime.year; mount = DateTime.month;date = DateTime.day;hour = DateTime.hour;minut = DateTime.minute;secon = DateTime.second; memory = DateTime.hour * 100 + DateTime.minute; a[0]=DateTime.hour/10; a[1]=DateTime.hour%10; a[2]=DateTime.minute/10; a[3]=DateTime.minute%10; a[4]=DateTime.second/10; a[5]=DateTime.second%10; if(digitalRead(2)==LOW&&digitalRead(3)==LOW){hour++;if(hour>23){hour=0;} clock.setDateTime(yar, mount, date, hour, minut, secon);delay(100);} if(digitalRead(2)==LOW&&digitalRead(4)==LOW){minut++;if(minut>59){minut=0;} clock.setDateTime(yar, mount, date, hour, minut, secon);delay(100); } if(digitalRead(7)==LOW&&digitalRead(3)==LOW){date++;if(date>31){date=1;} clock.setDateTime(yar, mount, date, hour, minut, secon);delay(100);} if(digitalRead(7)==LOW&&digitalRead(4)==LOW){mount++;if(mount>12){mount=1;} clock.setDateTime(yar, mount, date, hour, minut, secon);delay(100); } if(digitalRead(7)==LOW&&digitalRead(5)==LOW){yar++;if(yar>2050){yar=2015;} clock.setDateTime(yar, mount, date, hour, minut, secon);delay(100); } if(digitalRead(2)==LOW&&digitalRead(5)==LOW){secon=0; clock.setDateTime(yar, mount, date, hour, minut, secon);delay(100); } for(i=0;i<6;i++){ switch(i){ case 0: e1=0,e2=1,e3=2;break; case 1: e1=3,e2=4,e3=5;break; case 2: e1=7,e2=8,e3=9;break; case 3: e1=10,e2=11,e3=12;break; case 4: e1=14,e2=15,e3=16;break; case 5: e1=17,e2=18,e3=19;break; } switch(a[i]){ case 0: d1=1,d2=8,d3=6,d4=1,d5=3,d6=6;break; case 1: d1=32,d2=2,d3=6,d4=32,d5=32,d6=6;break; case 2: d1=2,d2=8,d3=6,d4=1,d5=4,d6=5;break; case 3: d1=2,d2=4,d3=6,d4=7,d5=3,d6=6;break; case 4: d1=1,d2=3,d3=6,d4=32,d5=32,d6=6;break; case 5: d1=1,d2=4,d3=5,d4=7,d5=3,d6=6;break; case 6: d1=1,d2=4,d3=5,d4=1,d5=3,d6=6;break; case 7: d1=1,d2=8,d3=6,d4=32,d5=32,d6=6;break; case 8: d1=1,d2=4,d3=6,d4=1,d5=3,d6=6;break; case 9: d1=1,d2=4,d3=6,d4=7,d5=3,d6=6;break; } lcd.setCursor(e1,0);lcd.write((uint8_t)d1);lcd.setCursor(e2,0);lcd.write((uint8_t)d2);lcd.setCursor(e3,0);lcd.write((uint8_t)d3); lcd.setCursor(e1,1);lcd.write((uint8_t)d4);lcd.setCursor(e2,1);lcd.write((uint8_t)d5);lcd.setCursor(e3,1);lcd.write((uint8_t)d6); } lcd.setCursor(6,0);lcd.print(".");lcd.setCursor(13,0);lcd.print(".");lcd.setCursor(6,1);lcd.print(".");lcd.setCursor(13,1);lcd.print("."); if(digitalRead(2)==LOW){lcd.setCursor(0,2);lcd.print(" TIME SET HH:MM:SS ");} else if(digitalRead(7)==LOW){lcd.setCursor(0,2);lcd.print(" TIME SET DD-MM-YY ");} else if(digitalRead(2)==HIGH&&digitalRead(7)==HIGH&&digitalRead(5)==LOW){ if(digitalRead(3)==LOW){h_alarm++; if(h_alarm>23){h_alarm=0;}delay(100);EEPROM.update(11, h_alarm);} if(digitalRead(4)==LOW){m_alarm++; if(m_alarm>59){m_alarm=0;}delay(100);EEPROM.update(12, m_alarm);} lcd.setCursor(0,2);lcd.print("ALARM CLOCK--");lcd.print(h_alarm/10);lcd.print(h_alarm%10);lcd.print(":");lcd.print(m_alarm/10);lcd.print(m_alarm%10);} else{lcd.setCursor(0,2); if(alarm==0){lcd.print("------ALARM OFF-----");} if(alarm==1){lcd.print("------ALARM ON------");} } //////////// ZZZZZZZZZzzzzzzzz...... /////////////////////// if(digitalRead(3)==LOW&&digitalRead(2)==HIGH&&digitalRead(5)==HIGH&&digitalRead(7)==HIGH){alarm=1;delay(300);EEPROM.update(13, alarm);} if(digitalRead(4)==LOW&&digitalRead(2)==HIGH&&digitalRead(5)==HIGH&&digitalRead(7)==HIGH){alarm=0;delay(300);EEPROM.update(13, alarm);} if(h_alarm*100+m_alarm==memory&&alarm==1){tone(6,1500,150);} if(millis()-times1<IND){ lcd.setCursor(1,3);lcd.print(DateTime.day/10);lcd.print(DateTime.day%10);lcd.print("-"); lcd.print(DateTime.month/10);lcd.print(DateTime.month%10);lcd.print("-");lcd.print(DateTime.year); lcd.print(" ");lcd.print(temp_hous,1);lcd.print((char)223);lcd.print("C ");} if(millis()-times1>IND){ lcd.setCursor(1,3);lcd.print(h,1);lcd.print("% "); lcd.print(p,1);lcd.print(" ");lcd.print(k,1);lcd.print((char)223);lcd.print("C "); } if(millis()-times1>IND*2){times1=millis();} }
Привет. Решил повторить проект денной погодной станции. Что бы меньше было вопросов желательно указать для дисплея второй адрес 0х3F ( у меня такой ).
Возникла проблема с датчиком bmp280.У меня он заработал только с библиотекой bme280.
Вопрос ,как их различить ? Мой с виду как на картинке в описании.
Или как в песне ,вся жизнь игра.
Если влажность изменяет то у Вас BME280, если нет то BMP280. Возможно у Вас в библиотеке BMP280 указан не подходящий Вашему модулю I2C адрес. Проверьте его в сканере I2C и сверьте с библиотекой.
В этом проекте BMP280 не использует I2C шину.
Привет. По совету проверил адрес по i2c он 0х76,при замыкании на питание ноги sdo переходит на 0х77.
Датчик показывает все,tampr,Press,Approx,Humidy.
Проверь нет проблем с библиотекой по твоей ссылке ?
В библиотеке указан адрес 0х77 в файле Adafruit_BMP280.h
Его можно поменять на другой.
Если датчик показывает влажность, то это BME280.
Для для этого проекта это не важно, датчик подключает по шине SPI
Я взял библиотеку с этого сайта ,из библиотеки пример и он не работает при любом адресе.
И не будет работать, у Вас же BME280 а не BMP280
Так тогда в скетч нужно ввести изменения ? Это сложно ?
Просто замените библиотеку на
#include
и измените строку
Adafruit_BMP280 bmp(10);
на
Adafruit_BME280 bmp(10);
У меня не подключены кнопки и нет датчика ант10. На экране не видно 3 строки сверху -пустая.
На данный момент 19 часов дергается сигмент 9 ,первый левый верхний.
пока у Вас нет всех компонентов, поэтому что не так я не могу, можете проверить как все будет работать на этом скетче — http://forum.rcl-radio.ru/viewtopic.php?pid=917#p917
Я стараюсь повторять все проекты с часами.В том проекте я просил добавить кнопки для ручного управления установкой времени. Там работает.
Подключение датчика BME280 через SPI?
Да как в схеме.
Пока датчика ант10 нет, ни чего не могу точно сказать, возможно скетч опрашивает датчик, а его нет, поэтому и происходит остановка работы программы.