RSS блога
Подписка
BME280 - датчик температуры, давления и влажности. "Метеостанция" из трёх деталей
- Цена: $3.76
- Перейти в магазин
Приветствую.
Для проверки показаний датчика влажности у метеостанции, было решено купить более-менее точный датчик, ёмкостного типа (дешёвые резистивные вроде DHT11 менее точны и не показывают влажность менее 20%). Был выбран BME280, как имеющий все сенсоры (и лучший по обзорам) и стоящий немногим дороже того же DHT22.
Также хотелось получить графики температуры/давления/влажности (и познакомиться с oled-дисплеями). Что и было реализовано.
Да, при покупке имейте в виду, что существует более дешёвая версия BMP280, без датчика влажности.
Собственно датчик: BME280 от Bosch Sensortec. Меряет температуру, давление и влажность. Работает по I2C.
Как видим, спереди на плате расположен сам датчик (металлический корпус с отверстием), а на обратной стороне находятся ldo стабилизатор 662k на 3.3В и схема согласования уровня линий данных, для использования с питанием от 5В.
В документации заявлены следующие, достаточно неплохие параметры:
Они подтверждаются сравнением разных датчиков влажности на www.kandrsmith.org/RJS/Misc/Hygrometers/calib_many.html где победил BME280.
Осталось его задействовать. Метеостанция на ардуине это конечно банально, но что делать )).
OLED-дисплей 0.96 дюймов 128X64 SSD1306 брался здесь. Питание от 3.3В. И да, он оказался совсем маленьким, это его основной недостаток. Пришлось делать переключение между отображением информации крупным шрифтом и показом графиков. Но зато идеальные углы обзора.
Сборка элементарна — так как дисплей и датчик работают по I2C, то просто подсоединяем выводы SDA к пину A4 ардуины, SCK (SCL) к A5, Vin к питанию 3.3V и Gnd к земле. И заливаем скетч.
Потребляемый ток около 20мА. Выдаваемая температура оказалась где-то на 0.3 градуса выше, чем на образцовом градуснике (что соответствует допускам) и корректируется в скетче. Влажность близка к тому, что выдаёт метеостанция (и показываются значения меньшие 20%). Давление такое же как в аэропорту, с учётом разницы высот.
Используемые библиотеки: BME280I2C ver 2.1.2 и OLED_I2C (есть её русифицированная версия, а вот Adafruit_SSD1306 мне не понравилась, либа ест больше памяти и шрифты хуже)
Добавлено. Как оказалось, есть версия платы от sparkfun, которая имеет дефолтный I2C адрес: 0x77. При её использовании нужно в скетче раскомментировать строчку «BME280I2C bme(0x1, 0x1, 0x1, 0x1, 0x5, 0x0, false, 0x77);»
Добавлено №2.
Вариант скетча с другим отображением графиков. Метки времени — каждые четыре часа (весь график — сутки). Цифры сдвигаются, для уменьшения «выгорания» oled.
Добавлено №3.
Вариант скетча с использованием библиотеки u8g2, поддерживающей много дисплеев. В частности: SSD1306, SH1106, HX1230. Библиотека ставится через среду arduino, Скетч->Подключить библиотеку->Управлять библиотеками. Библиотека bme280 ставится оттуда же — вариант от Tyler Glenn.
Для проверки показаний датчика влажности у метеостанции, было решено купить более-менее точный датчик, ёмкостного типа (дешёвые резистивные вроде DHT11 менее точны и не показывают влажность менее 20%). Был выбран BME280, как имеющий все сенсоры (и лучший по обзорам) и стоящий немногим дороже того же DHT22.
Также хотелось получить графики температуры/давления/влажности (и познакомиться с oled-дисплеями). Что и было реализовано.
Доставка
Датчик был куплен на али, с купоном вышло около 130р. Был доставлен за обычные 25 дней (трек ZA037342xxxHK). Упакован в стандартную пупырку.Да, при покупке имейте в виду, что существует более дешёвая версия BMP280, без датчика влажности.
Датчик
Собственные фото
Для проверки датчик был подключен просто проводами. Потом будет запаян нормальный соединитель.
Собственно датчик: BME280 от Bosch Sensortec. Меряет температуру, давление и влажность. Работает по I2C.
Как видим, спереди на плате расположен сам датчик (металлический корпус с отверстием), а на обратной стороне находятся ldo стабилизатор 662k на 3.3В и схема согласования уровня линий данных, для использования с питанием от 5В.
В документации заявлены следующие, достаточно неплохие параметры:
Operating range -40…+85 °C, 0…100 % rel. humidity, 300…1100 hPa
Точность измерения влажности ±3 %RH (в диапазоне 20…80 %RH)
Точность измерения давления ±1.0 hPa (в диапазоне 300 . . . 1100 hPa)
Точность измерения температуры ±0.5 °C (при 25 °C)
Они подтверждаются сравнением разных датчиков влажности на www.kandrsmith.org/RJS/Misc/Hygrometers/calib_many.html где победил BME280.
Осталось его задействовать. Метеостанция на ардуине это конечно банально, но что делать )).
Остальные детали
Arduino nano была куплена прошлой осенью — версия от RobotDyn, пожалуй это лучший вариант nano, с полноценным стабилизатором 3.3В, практичным разъёмом микро-юсб (а не мини) и нормальными кварцами. Преобразователь USB-UART — обычный CH340G.Фото
OLED-дисплей 0.96 дюймов 128X64 SSD1306 брался здесь. Питание от 3.3В. И да, он оказался совсем маленьким, это его основной недостаток. Пришлось делать переключение между отображением информации крупным шрифтом и показом графиков. Но зато идеальные углы обзора.
Фото
Собираем
Сборка элементарна — так как дисплей и датчик работают по I2C, то просто подсоединяем выводы SDA к пину A4 ардуины, SCK (SCL) к A5, Vin к питанию 3.3V и Gnd к земле. И заливаем скетч.
Потребляемый ток около 20мА. Выдаваемая температура оказалась где-то на 0.3 градуса выше, чем на образцовом градуснике (что соответствует допускам) и корректируется в скетче. Влажность близка к тому, что выдаёт метеостанция (и показываются значения меньшие 20%). Давление такое же как в аэропорту, с учётом разницы высот.
Скетч/Логика работы
С отображением цифр всё должно быть понятно, обновление идёт каждую секунду. С графиками чуть сложнее. Первые семь минут обновляем их каждую секунду. Потом переходим в долгоиграющий режим, где каждая точка это усреднение за семь минут. Точек 100, так что имеем информацию примерно за 12 часов. Графики сверху вниз — температура, влажность, давление (3 читабельные подписи на такой экран не влезают, поэтому без них). И слева пишется минимальное и максимальное значение за период.Используемые библиотеки: BME280I2C ver 2.1.2 и OLED_I2C (есть её русифицированная версия, а вот Adafruit_SSD1306 мне не понравилась, либа ест больше памяти и шрифты хуже)
Добавлено. Как оказалось, есть версия платы от sparkfun, которая имеет дефолтный I2C адрес: 0x77. При её использовании нужно в скетче раскомментировать строчку «BME280I2C bme(0x1, 0x1, 0x1, 0x1, 0x5, 0x0, false, 0x77);»
Скетч
/*
Vin (Voltage In) -> 3.3V
Gnd (Ground) -> Gnd
SDA (Serial Data) -> A4 on Uno/Pro-Mini
SCK (Serial Clock) -> A5 on Uno/Pro-Mini
*/
#include <BME280I2C.h>
#include <OLED_I2C.h>
#define PLOT_LEN 100
#define STORAGE_TIME 270
OLED myOLED(SDA, SCL, 8);
BME280I2C bme;
// Temperature Oversampling Rate, Humidity Oversampling Rate, Pressure Oversampling Rate, Mode, Standby Time, Filter, SPI Enable, BME280 Address
// BME280I2C bme(0x1, 0x1, 0x1, 0x1, 0x5, 0x0, false, 0x77); // Version for SparkFun BME280
extern uint8_t BigNumbers[];
extern uint8_t SmallFont[];
struct {
byte temp = 0;
byte hum = 0;
byte pres = 0;
} infoArr[PLOT_LEN];
struct {
float temp = 0;
float hum = 0;
float pres = 0;
int counter = 0;
} avrg;
byte wait_cnt = 0;
bool fastMode = true;
void setup() {
myOLED.begin();
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
delay(100);
digitalWrite(LED_BUILTIN, LOW);
while (!bme.begin()) {
// if bme280 not found - blink LED
delay(500);
digitalWrite(LED_BUILTIN, HIGH);
delay(500);
digitalWrite(LED_BUILTIN, LOW);
}
delay(500);
}
void loop() {
bool metric = true;
float temp(NAN), hum(NAN), pres(NAN);
uint8_t pressureUnit(0); // unit: B000 = Pa, B001 = hPa, B010 = Hg, B011 = atm, B100 = bar, B101 = torr, B110 = N/m^2, B111 = psi
bme.read(pres, temp, hum, metric, pressureUnit);
// temp -= 0.3; // correct temp
pres /= 133.3; // convert to mmHg
myOLED.setBrightness(10);
myOLED.clrScr();
myOLED.setFont(BigNumbers);
myOLED.print(String(temp, 1), 0, 0);
myOLED.print(String(hum, 0), 92, 0);
myOLED.print(String(pres, 1), 42, 40);
myOLED.setFont(SmallFont);
myOLED.print("~C", 56, 0);
myOLED.print("%", 122, 0);
myOLED.print("MM", 114, 58);
myOLED.update();
avrg.temp += temp;
avrg.hum += hum;
avrg.pres += pres;
avrg.counter++;
if (fastMode && avrg.counter >= STORAGE_TIME) {
fastMode = false;
for (int i = 0; i < PLOT_LEN - 1; i++) {
infoArr[i].temp = 0;
infoArr[i].hum = 0;
infoArr[i].pres = 0;
}
}
if (fastMode || avrg.counter >= STORAGE_TIME) {
if (avrg.counter >= STORAGE_TIME) {
temp = avrg.temp / avrg.counter;
hum = avrg.hum / avrg.counter;
pres = avrg.pres / avrg.counter;
avrg.temp = 0;
avrg.hum = 0;
avrg.pres = 0;
avrg.counter = 0;
}
for (int i = 1; i < PLOT_LEN; i++) {
infoArr[i - 1] = infoArr[i];
}
infoArr[PLOT_LEN - 1].temp = round(temp) + 50;
infoArr[PLOT_LEN - 1].pres = round(pres) - 650;
infoArr[PLOT_LEN - 1].hum = round(hum);
}
delay(1000);
/*
Graph
*/
if (wait_cnt > 3) {
wait_cnt = 0;
myOLED.clrScr();
byte minTemp = 255;
byte minHum = 255;
byte minPres = 255;
byte maxTemp = 0;
byte maxHum = 0;
byte maxPres = 0;
for (int i = PLOT_LEN - 1; i >= 0 ; i--) {
if (infoArr[i].temp == 0 && infoArr[i].hum == 0 && infoArr[i].pres == 0) break;
if (infoArr[i].temp < minTemp) minTemp = infoArr[i].temp;
if (infoArr[i].hum < minHum) minHum = infoArr[i].hum;
if (infoArr[i].pres < minPres) minPres = infoArr[i].pres;
if (infoArr[i].temp > maxTemp) maxTemp = infoArr[i].temp;
if (infoArr[i].hum > maxHum) maxHum = infoArr[i].hum;
if (infoArr[i].pres > maxPres) maxPres = infoArr[i].pres;
}
if (maxTemp - minTemp < 10) maxTemp = minTemp + 10;
if (maxHum - minHum < 10) maxHum = minHum + 10;
if (maxPres - minPres < 10) maxPres = minPres + 10;
myOLED.setFont(SmallFont);
myOLED.print(String(minTemp - 50), 0, 12);
myOLED.print(String(maxTemp - 50), 0, 2);
myOLED.print(String(minHum), 0, 34);
myOLED.print(String(maxHum), 0, 24);
myOLED.print(String(minPres + 650), 0, 56);
myOLED.print(String(maxPres + 650), 0, 46);
int x = 24;
for (int i = 0; i < PLOT_LEN - 1; i++) {
if (infoArr[i].temp == 0 && infoArr[i].hum == 0 && infoArr[i].pres == 0) continue;
myOLED.drawLine(x, map(infoArr[i].temp, minTemp, maxTemp, 18, 0), x + 1, map(infoArr[i + 1].temp, minTemp, maxTemp, 18, 0));
myOLED.drawLine(x, map(infoArr[i].hum, minHum, maxHum, 40, 22), x + 1, map(infoArr[i + 1].hum, minHum, maxHum, 40, 22));
myOLED.drawLine(x, map(infoArr[i].pres, minPres, maxPres, 62, 44), x + 1, map(infoArr[i + 1].pres, minPres, maxPres, 62, 44));
x++;
}
myOLED.update();
delay(2000);
}
wait_cnt++;
}
Добавлено №2.
Вариант скетча с другим отображением графиков. Метки времени — каждые четыре часа (весь график — сутки). Цифры сдвигаются, для уменьшения «выгорания» oled.
Скетч
/*
Vin (Voltage In) -> 3.3V
Gnd (Ground) -> Gnd
SDA (Serial Data) -> A4 on Uno/Pro-Mini
SCK (Serial Clock) -> A5 on Uno/Pro-Mini
*/
#include <BME280I2C.h>
#include <OLED_I2C.h>
#define PLOT_LEN 96
#define STORAGE_TIME 560
OLED myOLED(SDA, SCL, 8);
BME280I2C bme;
// Temperature Oversampling Rate, Humidity Oversampling Rate, Pressure Oversampling Rate, Mode, Standby Time, Filter, SPI Enable, BME280 Address
// BME280I2C bme(0x1, 0x1, 0x1, 0x1, 0x5, 0x0, false, 0x77); // Version for SparkFun BME280
extern uint8_t BigNumbers[];
extern uint8_t SmallFont[];
struct {
byte temp = 0;
byte hum = 0;
byte pres = 0;
} infoArr[PLOT_LEN];
struct {
float temp = 0;
float hum = 0;
float pres = 0;
int counter = 0;
} avrg;
byte wait_cnt = 0;
byte shift_cnt = 0;
bool fastMode = true;
// Prototypes
void drawCol(int x, int y, int yn);
void setup() {
myOLED.begin();
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
delay(100);
digitalWrite(LED_BUILTIN, LOW);
while (!bme.begin()) {
// If bme280 not found - blink LED
// Maybe you use BME280 from SparkFun with another address?
delay(100);
digitalWrite(LED_BUILTIN, HIGH);
delay(100);
digitalWrite(LED_BUILTIN, LOW);
}
delay(500);
}
void loop() {
float temp(NAN), hum(NAN), pres(NAN);
bool metric = true;
uint8_t pressureUnit(0); // unit: B000 = Pa, B001 = hPa, B010 = Hg, B011 = atm, B100 = bar, B101 = torr, B110 = N/m^2, B111 = psi
bme.read(pres, temp, hum, metric, pressureUnit);
/*
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
BME280::PresUnit presUnit(BME280::PresUnit_Pa);
bme.read(pres, temp, hum, tempUnit, presUnit);
*/
// temp -= 0.3; // correct temp
pres /= 133.3; // convert to mmHg
myOLED.setBrightness(10);
myOLED.clrScr();
myOLED.setFont(BigNumbers);
myOLED.printNumF(temp, 1, 0 + shift_cnt, 0 + shift_cnt);
myOLED.printNumI(round(hum), 89 + shift_cnt, 0 + shift_cnt);
myOLED.printNumF(pres, 1, 42 + shift_cnt, 37 + shift_cnt);
myOLED.setFont(SmallFont);
myOLED.print("~C", 56 + shift_cnt, 0 + shift_cnt);
myOLED.print("%", 119 + shift_cnt, 0 + shift_cnt);
myOLED.print("MM", 113 + shift_cnt, 54 + shift_cnt);
myOLED.update();
avrg.temp += temp;
avrg.hum += hum;
avrg.pres += pres;
avrg.counter++;
if (fastMode && avrg.counter >= STORAGE_TIME) {
fastMode = false;
for (int i = 0; i < PLOT_LEN - 1; i++) {
infoArr[i].temp = 0;
infoArr[i].hum = 0;
infoArr[i].pres = 0;
}
}
if (fastMode || avrg.counter >= STORAGE_TIME) {
if (avrg.counter >= STORAGE_TIME) {
temp = avrg.temp / avrg.counter;
hum = avrg.hum / avrg.counter;
pres = avrg.pres / avrg.counter;
avrg.temp = 0;
avrg.hum = 0;
avrg.pres = 0;
avrg.counter = 0;
}
for (int i = 1; i < PLOT_LEN; i++) {
infoArr[i - 1] = infoArr[i];
}
infoArr[PLOT_LEN - 1].temp = round(temp * 2) + 80;
infoArr[PLOT_LEN - 1].pres = round(pres * 2) - 1380;
infoArr[PLOT_LEN - 1].hum = round(hum);
}
delay(1000);
/*
Graph
*/
if (wait_cnt > 3) {
wait_cnt = 0;
shift_cnt = (shift_cnt == 0) ? 3 : 0;
myOLED.clrScr();
byte minTemp = 255;
byte minHum = 255;
byte minPres = 255;
byte maxTemp = 0;
byte maxHum = 0;
byte maxPres = 0;
for (int i = PLOT_LEN - 1; i >= 0 ; i--) {
if (infoArr[i].temp == 0 && infoArr[i].hum == 0 && infoArr[i].pres == 0) break;
if (infoArr[i].temp < minTemp) minTemp = infoArr[i].temp;
if (infoArr[i].hum < minHum) minHum = infoArr[i].hum;
if (infoArr[i].pres < minPres) minPres = infoArr[i].pres;
if (infoArr[i].temp > maxTemp) maxTemp = infoArr[i].temp;
if (infoArr[i].hum > maxHum) maxHum = infoArr[i].hum;
if (infoArr[i].pres > maxPres) maxPres = infoArr[i].pres;
}
if (maxTemp - minTemp < 10) maxTemp = minTemp + 10;
if (maxHum - minHum < 10) maxHum = minHum + 10;
if (maxPres - minPres < 10) maxPres = minPres + 10;
myOLED.setFont(SmallFont);
myOLED.printNumI(round((minTemp - 80) / 2.0), 0, 11);
myOLED.printNumI(round((maxTemp - 80) / 2.0), 0, 1);
myOLED.printNumI(minHum, 0, 34);
myOLED.printNumI(maxHum, 0, 24);
myOLED.printNumI(round((minPres + 1380) / 2.0), 0, 57);
myOLED.printNumI(round((maxPres + 1380) / 2.0), 0, 47);
int z = 0;
int x = 25;
for (int i = 0; i < PLOT_LEN; i++) {
if (infoArr[i].temp == 0 && infoArr[i].hum == 0 && infoArr[i].pres == 0) continue;
/*
myOLED.drawLine(x, map(infoArr[i].temp, minTemp, maxTemp, 18, 0), x + 1, map(infoArr[i + 1].temp, minTemp, maxTemp, 18, 0));
myOLED.drawLine(x, map(infoArr[i].hum, minHum, maxHum, 40, 22), x + 1, map(infoArr[i + 1].hum, minHum, maxHum, 40, 22));
myOLED.drawLine(x, map(infoArr[i].pres, minPres, maxPres, 62, 44), x + 1, map(infoArr[i + 1].pres, minPres, maxPres, 62, 44));
*/
drawCol(x, map(infoArr[i].temp, minTemp, maxTemp, 17, 0), 17);
drawCol(x, map(infoArr[i].hum, minHum, maxHum, 40, 23), 40);
drawCol(x, map(infoArr[i].pres, minPres, maxPres, 63, 46), 63);
z++;
if (z > 15) {z = 0; x++;}
x++;
}
myOLED.update();
delay(2000);
}
wait_cnt++;
}
void drawCol(int x, int y, int yn) {
for (int i = y; i <= yn; i++) {
myOLED.setPixel(x, i);
}
}
Добавлено №3.
Вариант скетча с использованием библиотеки u8g2, поддерживающей много дисплеев. В частности: SSD1306, SH1106, HX1230. Библиотека ставится через среду arduino, Скетч->Подключить библиотеку->Управлять библиотеками. Библиотека bme280 ставится оттуда же — вариант от Tyler Glenn.
Скетч
/*
Vin (Voltage In) -> 3.3V
Gnd (Ground) -> Gnd
SDA (Serial Data) -> A4 on Uno/Pro-Mini
SCK (Serial Clock) -> A5 on Uno/Pro-Mini
*/
#include "LowPower.h"
#include <Wire.h>
#include <BME280I2C.h>
#include <U8g2lib.h>
#define PLOT_LEN 96
#define STORAGE_TIME 560
static const unsigned char BigNumbers[] PROGMEM =
"\22\1\4\4\5\5\1\1\6\24\30\1\377\26\0\15\0\0\0\0\0\2F(\22\16\347>\374\333\371\335"
"\242d\7\213\16\16\17\12\0)\23\16\347>\374\343\300C\13\36K\264n\354|\17\10\0*\32\16\347"
"\316\30\62\42D\30\21!\211\24\322\15\21,\23\201&\311\303\377\23\0+\64\25W\77\374\377WR\210"
"\22\62f\304\230!$h\222\42\211\210\21R\214\20\42$\210\10!A\244\22!J\210(\21\242\204\210"
"\22!J\210(\21\242\304\3\3,\13\6g>\374\241 \61b\0-\16\16\347>\374CT\252\320\303"
"\177\7\0.\13\6g>\374\211\30\62\2\1/$\16\347\316\250@\42\304\10\22!D\224\10\351F\210"
"\25\61N\204TBD\10\22#BP\250\361\360\377\6\0\60<\16\347\212\232\20(\202\210\60!d\330"
"\220aC\206\15\31\66d\330\220aC\4\12\11\32\36D\320 \2\205\14\33\62l\310\260!\303\206\14"
"\33\62l\210\10\23BB\240\10\243\36\4\0\61\26\16\347>\330\300b\347c\321\341\1\7\26;\37\213"
"\16\17\34\0\62\37\16\347\212*\24\241L\210\235\217\5\241\10\243&\4\42\301c\347\255\10S!P\251"
"\7\1\0\63\36\16\347\212*\24\241L\210\235\217\5\241\10\243\12E`\261\363\225\11A(\302\250\7\1"
"\0\64(\16\347>\200\240A\4\12\31\66d\330\220aC\206\15\31\66d\330\20\201BB\240\10\243\12"
"E`\261\363\261\350\360\300\1\65\37\16\347\212\232\20\210D\230\32;o\5\207@\245\12E`\261\363\225"
"\11A(\302\250\7\1\0\66/\16\347\212\232\20\210D\230\32;o\5\207@\245&\4\212 \2\205\14"
"\33\62l\310\260!\303\206\14\33\62l\210\10\23BB\240\10\243\36\4\0\67\30\16\347\212*\24\241L"
"\210\235\217E\207\7\34X\354|,:<p\0\70>\16\347\212\232\20(\202\210\60!d\330\220aC"
"\206\15\31\66d\330\220aC\4\12\11\201\42\214\232\20(\202\10\24\62l\310\260!\303\206\14\33\62l"
"\310\260!\42L\10\11\201\42\214z\20\0\71.\16\347\212\232\20(\202\210\60!d\330\220aC\206\15"
"\31\66d\330\220aC\4\12\11\201\42\214*\24\201\305\316W&\4\241\10\243\36\4\0\0\0\0\4\377"
"\377\0";
U8G2_SH1106_128X64_NONAME_2_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
//U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
//U8G2_HX1230_96X68_F_3W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 12, /* data=*/ 11, /* cs=*/ 10, /* reset=*/ 8);
BME280I2C bme;
// Temperature Oversampling Rate, Humidity Oversampling Rate, Pressure Oversampling Rate, Mode, Standby Time, Filter, SPI Enable, BME280 Address
// BME280I2C bme(0x1, 0x1, 0x1, 0x1, 0x5, 0x0, false, 0x77); // Version for SparkFun BME280
struct {
byte temp = 0;
byte hum = 0;
byte pres = 0;
} infoArr[PLOT_LEN];
struct {
float temp = 0;
float hum = 0;
float pres = 0;
int counter = 0;
} avrg;
byte wait_cnt = 0;
byte move_cnt = 0;
bool fastMode = true;
// Prototypes
void drawCol(int x, int y, int yn);
void setup() {
u8g2.begin();
u8g2.setContrast(32);
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
delay(100);
digitalWrite(LED_BUILTIN, LOW);
Wire.begin();
while (!bme.begin()) {
// If bme280 not found - blink LED
// Maybe you use BME280 from SparkFun with another address?
delay(100);
digitalWrite(LED_BUILTIN, HIGH);
delay(100);
digitalWrite(LED_BUILTIN, LOW);
}
delay(500);
}
void loop() {
float temp(NAN), hum(NAN), pres(NAN);
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
BME280::PresUnit presUnit(BME280::PresUnit_torr);
bme.read(pres, temp, hum, tempUnit, presUnit);
//temp -= 0.5; // correct temp
/*
bool metric = true;
uint8_t pressureUnit(0); // unit: B000 = Pa, B001 = hPa, B010 = Hg, B011 = atm, B100 = bar, B101 = torr, B110 = N/m^2, B111 = psi
bme.read(pres, temp, hum, metric, pressureUnit);
pres /= 133.3; // convert to mmHg
myOLED.printNumF(temp, 1, 0 + move_cnt, 0 + move_cnt);
myOLED.printNumI(round(hum), 89 + move_cnt, 0 + move_cnt);
myOLED.printNumF(pres, 1, 39 + move_cnt, 37 + move_cnt);
*/
// arrows
int8_t presChanged = 0;
int normPres = round(pres * 2) - 1380;
for (int i = PLOT_LEN - 1; i >= 0 ; i--) {
if (infoArr[i].temp == 0 && infoArr[i].hum == 0 && infoArr[i].pres == 0) continue;
if (normPres > infoArr[i].pres + 8) {
presChanged = 1;
break;
}
if (normPres < infoArr[i].pres - 8) {
presChanged = -1;
break;
}
}
u8g2.clearBuffer();
u8g2.setFont(BigNumbers);
u8g2.firstPage();
do {
u8g2.setCursor(0 + move_cnt, 24 + move_cnt);
u8g2.print(temp, 1);
u8g2.print("*");
u8g2.setCursor(84 + move_cnt, 24 + move_cnt);
u8g2.print(round(hum));
u8g2.print("/");
u8g2.setCursor(42 + move_cnt, 61 + move_cnt);
u8g2.print(pres, 1);
u8g2.print("+");
if (presChanged) {
u8g2.setCursor(28 + move_cnt, 61 + move_cnt);
u8g2.print(presChanged == 1 ? ")" : "(");
}
} while ( u8g2.nextPage() );
avrg.temp += temp;
avrg.hum += hum;
avrg.pres += pres;
avrg.counter++;
if (fastMode && avrg.counter >= STORAGE_TIME) {
fastMode = false;
for (int i = 0; i < PLOT_LEN - 1; i++) {
infoArr[i].temp = 0;
infoArr[i].hum = 0;
infoArr[i].pres = 0;
}
}
if (fastMode || avrg.counter >= STORAGE_TIME) {
if (avrg.counter >= STORAGE_TIME) {
temp = avrg.temp / avrg.counter;
hum = avrg.hum / avrg.counter;
pres = avrg.pres / avrg.counter;
avrg.temp = 0;
avrg.hum = 0;
avrg.pres = 0;
avrg.counter = 0;
}
for (int i = 1; i < PLOT_LEN; i++) {
infoArr[i - 1] = infoArr[i];
}
infoArr[PLOT_LEN - 1].temp = round(temp * 2) + 80;
infoArr[PLOT_LEN - 1].pres = round(pres * 2) - 1380;
infoArr[PLOT_LEN - 1].hum = round(hum);
}
//delay(1000);
LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF);
/*
Graph
*/
if (wait_cnt > 3) {
wait_cnt = 0;
move_cnt = (move_cnt == 0) ? 3 : 0;
byte minTemp = 255;
byte minHum = 255;
byte minPres = 255;
byte maxTemp = 0;
byte maxHum = 0;
byte maxPres = 0;
for (int i = PLOT_LEN - 1; i >= 0 ; i--) {
if (infoArr[i].temp == 0 && infoArr[i].hum == 0 && infoArr[i].pres == 0) break;
if (infoArr[i].temp < minTemp) minTemp = infoArr[i].temp;
if (infoArr[i].hum < minHum) minHum = infoArr[i].hum;
if (infoArr[i].pres < minPres) minPres = infoArr[i].pres;
if (infoArr[i].temp > maxTemp) maxTemp = infoArr[i].temp;
if (infoArr[i].hum > maxHum) maxHum = infoArr[i].hum;
if (infoArr[i].pres > maxPres) maxPres = infoArr[i].pres;
}
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_profont12_mn);
u8g2.firstPage();
do {
u8g2.setCursor(0, 18);
u8g2.print(round((minTemp - 80) / 2.0));
u8g2.setCursor(0, 8);
u8g2.print(round((maxTemp - 80) / 2.0));
u8g2.setCursor(0, 41);
u8g2.print(minHum);
u8g2.setCursor(0, 31);
u8g2.print(maxHum);
u8g2.setCursor(0, 64);
u8g2.print(round((minPres + 1380) / 2.0));
u8g2.setCursor(0, 54);
u8g2.print(round((maxPres + 1380) / 2.0));
/*
if (maxTemp - minTemp < 10) maxTemp = minTemp + 10;
if (maxHum - minHum < 10) maxHum = minHum + 10;
if (maxPres - minPres < 10) maxPres = minPres + 10;
myOLED.setFont(SmallFont);
myOLED.printNumI(round((minTemp - 80) / 2.0), 0, 11);
myOLED.printNumI(round((maxTemp - 80) / 2.0), 0, 1);
myOLED.printNumI(minHum, 0, 34);
myOLED.printNumI(maxHum, 0, 24);
myOLED.printNumI(round((minPres + 1380) / 2.0), 0, 57);
myOLED.printNumI(round((maxPres + 1380) / 2.0), 0, 47);
*/
int z = 0;
int x = 25;
for (int i = 0; i < PLOT_LEN; i++) {
if (infoArr[i].temp == 0 && infoArr[i].hum == 0 && infoArr[i].pres == 0) continue;
drawCol(x, map(infoArr[i].temp, minTemp, (maxTemp - minTemp < 10) ? minTemp + 10 : maxTemp, 17, 0), 17);
drawCol(x, map(infoArr[i].hum, minHum, (maxHum - minHum < 10) ? minHum + 10 : maxHum, 40, 23), 40);
drawCol(x, map(infoArr[i].pres, minPres, (maxPres - minPres < 10) ? minPres + 10 : maxPres, 63, 46), 63);
z++;
if (z > 15) {
z = 0;
x++;
}
x++;
}
} while ( u8g2.nextPage() );
//delay(2000);
LowPower.powerDown(SLEEP_2S, ADC_OFF, BOD_OFF);
}
wait_cnt++;
}
void drawCol(int x, int y, int yn) {
u8g2.drawVLine(x, y, yn-y+1);
/*
for (int i = y; i <= yn; i++) {
u8g2.drawPixel(x, i);
}
*/
}
Самые обсуждаемые обзоры
+20 |
2444
149
|
+26 |
1428
45
|
+79 |
4396
107
|
Насчёт температуры на 0.3 выше — на это ко всему прочему может влиять и нагрев от других компонентов, включая нагрев от линейного стабилизатора, расположенного на плате с датчиком.
Насчёт DS18B20 — китайские (наверняка ведь подделки) у меня вообще чуть ли не на полградуса разогреваются, если опрашивать раз в секунду. Их только вырубать принудительно между опросами.
Если будете опрашивать 1 раз в 2 секунды, спать он будет уже не 0.25 секунды, а 1.25 секунды, большую часть времени…
По фото сначала так и подумал, но смутила фраза автора…
Плюс.
[ЗанудаModeOn]
Надо было делить на значение 133.321995 :)
[ЗанудаModeOff]
Теперь бы ссылку на программу,… как я понимаю на уровне чайника, в которую скопировать/вставить текст скетча, потом нажать «загрузить в ардуину»?
дописываю позже: вроде все нашел на arduino.ru
У описываемого Arduino nano — разъем microUSB.
И никакого всемирного заговора.
Питать nano можно от компового юсб или какой-нибудь зарядки от телефона, с микро-юсб выходом.
Во кстати, выдернуто с одного известного форума:
З.Ы. фидошник с начала 90-х годов прошлого века
/dev/hands
Вопрос только один, почему не ESP? Этот датчик она прекрасно умеет, экран тоже, 3.3 на ней есть, из той же ArduinoIDE точно так же программируется. Стоит аналогично :)
А еще, видимо по тому что...
Плату установить горизонтально, чтобы дырка смотрела вниз. Плату покрыть лаком, крышку датчика тоже, но аккуратно, чтобы не залилось внутрь. На многих станциях вижу приточный вентилятор — вероятно это жжжж неспроста.
Чешутся руки попробовать засунуть в самопальную будку Стивенсона из вентиляционных решеток…
DHT22 из «первых партий» померли на улице довольно быстро и сейчас показывают «погоду на марсе», поэтому жаба мне не позволила дорогущие BME280 оставить на улице для проверки.
Тем временем дома другие DHT22 и BME280 показывают примерно одно и то же.
себе купил ESPMeteoSmall (у меня руки из от туда) для мониторинга на narodmon.ru/
а вот написать безглючную библиотеку — вот где мозги нужны
чтоб ТЭНы-увлажнители-вентиляторы автоматом включались и нужные параметры кнопами вводились и на дисплее отображались…
play.google.com/store/search?q=rain%20radar&c=apps
А конкретно вот этой:
play.google.com/store/apps/details?id=lv.mbriedis.lietus
У Rain Radar не нашёл Россию в списке.
Обычно они раз в 5- 10 минут сканируют капли дождя в радиусе 250 км.
Можете тут ещё глянуть, там интересно кнопки под картинкой понажимать:
lietus.lv.
Хотя скорее всего это не ваш регион…
С тем же успехом можно сказать, что и как датчик давления он совершенно не годится. Ни там глубокого вакуума, ни даже банально давление в шинах не проверить.
Сейчас лично подошёл и подышал на датчик. Не уверен, сможет ли он показать 97% (кстати, при какой температуре?), но 95.4% я добился с первого раза. Датчик дома, температура около +25 градусов цельсия. Не знаю, достаточно ли Вам моих слов или надо какие-то более серьёзные доказательства.
Может быть Вы потрудитесь datasheet глянуть, вдруг там есть ответ на этот вопрос?
Ну и как писал sluchatel narodmon.ru
Мне нравится, что прошивка сама обновляется с сайта. т.е. модуль ESP8266 к компьютеру нужно только один раз подключать. Только для полного управления скорее всего потребуется лицензия, 110 р. на модуль.
Соответственно питание на 3.3В Для более точного измерения температуры, это даже лучше.
Спасибо за наводку, погуглю про смену адреса.
тыц US $19.90
и тыц2 US $14.00 чуть большее давление
Без дисплея, все данные получаю просто по WiFi и смотрю в браузере (+ данные логируются на сервер)
Золотистого цвета — это MH-Z19 (датчик CO2)
Просто кусочек исходника
Оно на lua, а графики строятся на сервере с Django (куда отсылаются данные раз в 10 секунд)
К сожалению, у меня не было возможности написать код нормально, да и с lua я не знаком, использован код многих людей в частности barkon
pastebin.com/FsHKKdYJ
Тут без считывания с MH-Z19 если надо и его — пишите (он отдельными файликами)
pastebin.com/5fTGPiW0
а вот через UART в uartresult
pastebin.com/jzGakNcA
Схемы увы нету, см. картинку выше, оно в таком виде и осталось
mysku.club/blog/aliexpress/52057.html#comment2062858
Питание — солнечная панель, «usb зарядка» для лития + LM3671, акк от вертолетика.
Работает почти год, зимой были проблемки с подзарядкой, поставил панель побольше.
Тут (моя песочница) можно глянуть погоду с моего балкончика.
Но у меня регион северный, в средней полосе и южнее (РФ), такая большая явно не нужна.
Да и сам датчик под солнечные лучи попадет
Время на оси х из-за разворота текста — нечитаемо. Опечатка в «Тепмература» )
Я бы рисовал все три показателя на одном графике разным цветом. Ось х — время, ось y (слева) — температура + влажность; справа — давление.
Речь про
я.диск
mysku.club/blog/china-stores/30078.html
и можно ли купить термометр/гигрометро уже готовый на этой BME?
Готовые термогигрометры на точных емкостных датчиках бывают, но считаются (полу)профессиональными и стоят прилично, скажем TFA 30.5010 больше 2 тысяч.
И еще вопрос, сравнивали ли показания с DHT11 в полевых условиях?
DHT11 выдавал влажность на десятку больше, чем метеостанция (и BME280)
Я так BMP085 сломал.
Но потом я купил несколько BMP180 (ещё не знал о BME280) и припаял ноги к ним — вышло успешно.
Так что попытки со второй и у вас наверняка получится.
Мне пришлось вынести датчик из корпуса, ибо нагрев прибора (реализовано на ESP-12 + мини-БП в корпусе китайского блока питания) всё портит.
I2C-USB переходники бывают, но похоже стоят дороже.
Корпус — пока не знаю ))
Ардуино непонятно, зачем приплели, можно использовать с любым МК.
Думал, ардуино в жизни не буду ставить, однако на носу сборка второго 3D принтера, придётся всё же ставить его для заливки прошивки.
В первом случае не хватает станции, во втором,- машины.
Ничего не имею против идеи, и даже очень приветствую. Однако, заголовок мог быть поскромнее.
Ну и среда должна выдавать что-то ещё кроме ошибки компиляции, скопируйте сюда весь вывод
Глобальные переменные используют 1646 байт (80%) динамической памяти, оставляя 402 байт для локальных переменных. Максимум: 2048 байт.
Недостаточно памяти, программа может работать нестабильно.
Это нормально?
compilation terminated.
exit status 1
Ошибка компиляции для платы Arduino Nano.
Помогите разобраться в данной проблеме
Что-то версия 2 не компилируется, ругается на drawCol…
Arduino: 1.6.12 (Windows 8.1), Плата:«Arduino/Genuino Uno»
C:\Users\User\AppData\Local\Temp\arduino_modified_sketch_904805\sketch_oct18b.ino: In function 'void loop()':
sketch_oct18b:61: error: no matching function for call to 'BME280I2C::read(float&, float&, float&, bool&, uint8_t&)'
bme.read(pres, temp, hum, metric, pressureUnit);
^
C:\Users\User\AppData\Local\Temp\arduino_modified_sketch_904805\sketch_oct18b.ino:61:49: note: candidate is:
In file included from C:\Users\User\Desktop\arduino\arduino-1.6.12\libraries\BME280-master\src/BME280I2C.h:33:0,
from C:\Users\User\AppData\Local\Temp\arduino_modified_sketch_904805\sketch_oct18b.ino:8:
C:\Users\User\Desktop\arduino\arduino-1.6.12\libraries\BME280-master\src/BME280.h:166:11: note: void BME280::read(float&, float&, float&, BME280::TempUnit, BME280::PresUnit)
void read(
^
C:\Users\User\Desktop\arduino\arduino-1.6.12\libraries\BME280-master\src/BME280.h:166:11: note: no known conversion for argument 4 from 'bool' to 'BME280::TempUnit'
exit status 1
no matching function for call to 'BME280I2C::read(float&, float&, float&, bool&, uint8_t&)'
C:\Users\User\Desktop\arduino\sketch_oct19a\sketch_oct19a.ino: In function 'void loop()':
sketch_oct19a:61: error: no matching function for call to 'BME280I2C::read(float&, float&, float&, bool&, uint8_t&)'
bme.read(pres, temp, hum, metric, pressureUnit);
^
C:\Users\User\Desktop\arduino\sketch_oct19a\sketch_oct19a.ino:61:49: note: candidate is:
In file included from C:\Program Files (x86)\Arduino\libraries\BME280-master\src/BME280I2C.h:33:0,
from C:\Users\User\Desktop\arduino\sketch_oct19a\sketch_oct19a.ino:8:
C:\Program Files (x86)\Arduino\libraries\BME280-master\src/BME280.h:166:11: note: void BME280::read(float&, float&, float&, BME280::TempUnit, BME280::PresUnit)
void read(
^
C:\Program Files (x86)\Arduino\libraries\BME280-master\src/BME280.h:166:11: note: no known conversion for argument 4 from 'bool' to 'BME280::TempUnit'
exit status 1
no matching function for call to 'BME280I2C::read(float&, float&, float&, bool&, uint8_t&)'
Скетч использует 17238 байт (53%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 1646 байт (80%) динамической памяти, оставляя 402 байт для локальных переменных. Максимум: 2048 байт.
Недостаточно памяти, программа может работать нестабильно.
Попробуйте проверить I2C scanner-ом видно ли датчик, а не только экран.
(вот он пишет в монитор порта)
I2C scanner. Scanning…
Found address: 118 (0x76)
Done.
Found 1 device(s).
Правда непонятно есть ли у вас OLED-дисплей, он тоже должен быть в списке ))
Если что, запустите пример он выводит инфу в монитор порта, возможно будет понятней.
Ну тогда должно хватить этого примера.
НО, теперь ардуино мигает лампой L и монитор порта девственно чист)
Почему это может быть?
Собирал барометр с часами на Nano_V3_BME280_DS3231_LCD3410. И вот такой вид.
[code]
/*
Fontname: rus6x12 (Cyrillic 6x12 LCD Font)
Copyright: © 2015 Made by Maxim Z. E-mail: Maxim_EV@bk.ru
Capital A Height: 7, '1' Height: 7
Calculated Max Values w= 5 h=10 x= 5 y= 5 dx= 6 dy= 0 ascent=10 len=10
Font Bounding box w= 6 h=12 x= 0 y=-2
Calculated Min Values x= 0 y=-2 dx= 0 dy= 0
Pure Font aascent = 7 descent=-2
X Font ascent = 8 descent=a-2
Max Font ascent =10 descent=-2
*/
const u8g_fntpgm_uint8_t rus6x12[2041] U8G_FONT_SECTION(".progmem.rus6x12") = {
0,6,12,0,254,7,1,152,3,46,32,255,254,10,254,8,
254,0,0,0,6,5,255,1,7,7,6,2,0,128,128,128,
128,128,0,128,3,3,3,6,1,5,160,160,160,5,6,6,
6,0,0,80,248,80,80,248,80,5,9,9,6,0,255,32,
112,168,160,112,40,168,112,32,5,7,7,6,0,0,200,200,
16,32,64,152,152,5,7,7,6,0,0,64,160,160,64,168,
144,104,1,3,3,6,2,5,128,128,128,3,9,9,6,1,
255,32,64,64,128,128,128,64,64,32,3,9,9,6,1,255,
128,64,64,32,32,32,64,64,128,5,7,7,6,0,0,32,
168,112,32,112,168,32,5,5,5,6,0,1,32,32,248,32,
32,3,3,3,6,0,255,96,96,192,3,1,1,6,1,3,
224,2,2,2,6,1,0,192,192,5,7,7,6,0,0,8,
16,16,32,64,64,128,4,7,7,6,1,0,96,144,144,144,
144,144,96,3,7,7,6,1,0,64,192,64,64,64,64,224,
5,7,7,6,0,0,112,136,8,16,32,64,248,5,7,7,
6,0,0,248,8,16,48,8,136,112,5,7,7,6,0,0,
16,48,80,144,248,16,16,5,7,7,6,0,0,248,128,240,
8,8,136,112,5,7,7,6,0,0,48,64,128,240,136,136,
112,5,7,7,6,0,0,248,8,16,16,32,32,32,5,7,
7,6,0,0,112,136,136,112,136,136,112,5,7,7,6,0,
0,112,136,136,120,8,16,96,2,5,5,6,1,0,192,192,
0,192,192,3,6,6,6,0,255,96,96,0,96,96,192,3,
5,5,6,1,1,32,64,128,64,32,5,3,3,6,0,2,
248,0,248,3,5,5,6,1,1,128,64,32,64,128,5,7,
7,6,0,0,112,136,16,32,32,0,32,5,7,7,6,0,
0,112,136,184,168,184,128,112,5,7,7,6,0,0,112,136,
136,248,136,136,136,5,7,7,6,0,0,240,72,72,112,72,
72,240,5,7,7,6,0,0,112,136,128,128,128,136,112,5,
7,7,6,0,0,240,72,72,72,72,72,240,5,7,7,6,
0,0,248,128,128,240,128,128,248,5,7,7,6,0,0,248,
128,128,240,128,128,128,5,7,7,6,0,0,112,136,128,128,
152,136,112,5,7,7,6,0,0,136,136,136,248,136,136,136,
3,7,7,6,1,0,224,64,64,64,64,64,224,5,7,7,
6,0,0,56,16,16,16,16,144,96,5,7,7,6,0,0,
136,144,160,192,160,144,136,5,7,7,6,0,0,128,128,128,
128,128,128,248,5,7,7,6,0,0,136,216,168,136,136,136,
136,5,7,7,6,0,0,136,136,200,168,152,136,136,5,7,
7,6,0,0,112,136,136,136,136,136,112,5,7,7,6,0,
0,240,136,136,240,128,128,128,5,7,7,6,0,0,112,136,
136,136,168,144,104,5,7,7,6,0,0,240,136,136,240,160,
144,136,5,7,7,6,0,0,112,136,128,112,8,136,112,5,
7,7,6,0,0,248,32,32,32,32,32,32,5,7,7,6,
0,0,136,136,136,136,136,136,112,5,7,7,6,0,0,136,
136,136,136,80,80,32,5,7,7,6,0,0,136,136,136,136,
168,168,80,5,7,7,6,0,0,136,136,80,32,80,136,136,
5,7,7,6,0,0,136,136,80,32,32,32,32,5,7,7,
6,0,0,248,8,16,32,64,128,248,3,9,9,6,1,255,
224,128,128,128,128,128,128,128,224,5,7,7,6,0,0,128,
64,64,32,16,16,8,3,9,9,6,1,255,224,32,32,32,
32,32,32,32,224,5,3,3,6,0,5,32,80,136,5,1,
1,6,0,254,248,3,3,3,6,1,5,128,64,32,5,5,
5,6,0,0,112,8,120,136,120,5,7,7,6,0,0,128,
128,240,136,136,136,240,5,5,5,6,0,0,112,136,128,136,
112,5,7,7,6,0,0,8,8,120,136,136,136,120,5,5,
5,6,0,0,112,136,240,128,112,5,7,7,6,0,0,48,
72,64,224,64,64,64,5,7,7,6,0,254,112,136,136,136,
120,8,112,5,7,7,6,0,0,128,128,240,136,136,136,136,
3,7,7,6,1,0,64,0,192,64,64,64,224,4,9,9,
6,1,254,16,0,48,16,16,16,16,144,96,5,7,7,6,
0,0,128,128,136,144,224,144,136,3,7,7,6,1,0,192,
64,64,64,64,64,224,5,5,5,6,0,0,208,168,168,168,
168,5,5,5,6,0,0,176,200,136,136,136,5,5,5,6,
0,0,112,136,136,136,112,5,7,7,6,0,254,240,136,136,
136,240,128,128,5,7,7,6,0,254,120,136,136,136,120,8,
8,5,5,5,6,0,0,176,200,128,128,128,5,5,5,6,
0,0,120,128,112,8,240,5,7,7,6,0,0,32,32,248,
32,32,32,24,5,5,5,6,0,0,136,136,136,152,104,5,
5,5,6,0,0,136,136,136,80,32,5,5,5,6,0,0,
136,136,168,168,80,5,5,5,6,0,0,136,80,32,80,136,
5,7,7,6,0,254,136,136,136,80,32,64,128,5,5,5,
6,0,0,248,16,32,64,248,3,9,9,6,1,255,32,64,
64,64,128,64,64,64,32,1,9,9,6,2,255,128,128,128,
128,128,128,128,128,128,3,9,9,6,1,255,128,64,64,64,
32,64,64,64,128,5,3,3,6,0,2,72,168,144,255,5,
7,7,6,0,254,240,136,136,136,240,128,128,5,5,5,6,
0,0,112,136,128,136,112,5,5,5,6,0,0,248,32,32,
32,32,5,7,7,6,0,254,136,136,136,136,120,8,112,5,
9,9,6,0,254,32,32,112,168,168,168,112,32,32,5,5,
5,6,0,0,136,80,32,80,136,5,7,7,6,0,254,144,
144,144,144,248,8,8,5,5,5,6,0,0,136,136,120,8,
8,5,5,5,6,0,0,168,168,168,168,248,5,7,7,6,
0,254,168,168,168,168,248,8,8,5,5,5,6,0,0,192,
64,112,72,112,5,5,5,6,0,0,136,136,200,168,200,4,
5,5,6,1,0,128,128,224,144,224,4,5,5,6,1,0,
224,16,112,16,224,5,5,5,6,0,0,144,168,232,168,144,
4,5,5,6,1,0,112,144,112,80,144,5,7,7,6,0,
0,112,136,136,248,136,136,136,5,7,7,6,0,0,240,128,
128,240,136,136,240,5,7,7,6,0,0,240,136,136,240,136,
136,240,5,7,7,6,0,0,248,128,128,128,128,128,128,5,
8,8,6,0,255,48,80,80,80,80,80,248,136,5,7,7,
6,0,0,248,128,128,240,128,128,248,5,7,7,6,0,0,
168,168,112,32,112,168,168,5,7,7,6,0,0,112,136,8,
112,8,136,112,5,7,7,6,0,0,136,136,152,168,200,136,
136,5,10,10,6,0,0,136,112,0,136,136,152,168,200,136,
136,5,7,7,6,0,0,136,144,160,192,160,144,136,5,7,
7,6,0,0,56,72,72,72,72,72,136,5,7,7,6,0,
0,136,216,168,136,136,136,136,5,7,7,6,0,0,136,136,
136,248,136,136,136,5,7,7,6,0,0,112,136,136,136,136,
136,112,5,7,7,6,0,0,248,136,136,136,136,136,136,5,
7,7,6,0,0,240,136,136,240,128,128,128,5,7,7,6,
0,0,112,136,128,128,128,136,112,5,7,7,6,0,0,248,
32,32,32,32,32,32,5,7,7,6,0,0,136,136,136,136,
120,8,112,5,7,7,6,0,0,32,112,168,168,168,112,32,
5,7,7,6,0,0,136,136,80,32,80,136,136,5,9,9,
6,0,254,144,144,144,144,144,144,248,8,8,5,7,7,6,
0,0,136,136,136,120,8,8,8,5,7,7,6,0,0,168,
168,168,168,168,168,248,5,9,9,6,0,254,168,168,168,168,
168,168,248,8,8,5,7,7,6,0,0,192,64,64,112,72,
72,112,5,7,7,6,0,0,136,136,136,200,168,168,200,4,
7,7,6,1,0,128,128,128,224,144,144,224,5,7,7,6,
0,0,112,136,8,120,8,136,112,5,7,7,6,0,0,144,
168,168,232,168,168,144,5,7,7,6,0,0,120,136,136,120,
40,72,136,5,5,5,6,0,0,112,8,120,136,120,5,7,
7,6,0,0,112,128,240,136,136,136,112,5,5,5,6,0,
0,240,136,240,136,240,5,5,5,6,0,0,248,128,128,128,
128,5,6,6,6,0,255,48,80,80,80,248,136,5,5,5,
6,0,0,112,136,240,128,112,5,5,5,6,0,0,168,112,
32,112,168,5,5,5,6,0,0,112,136,48,136,112,5,5,
5,6,0,0,136,152,168,200,136,5,8,8,6,0,0,136,
112,0,136,152,168,200,136,4,5,5,6,1,0,144,160,192,
160,144,5,5,5,6,0,0,56,72,72,72,136,5,5,5,
6,0,0,136,216,168,136,136,5,5,5,6,0,0,136,136,
248,136,136,5,5,5,6,0,0,112,136,136,136,112,5,5,
5,6,0,0,248,136,136,136,136,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255};
[/code]
То, что предлагает ТС я уже собрал — много ума не нужно было, а вот читать скетч пока не могу, к сожалению, хотя и хочется освоить.
Пошел заказывать дисплей…
а именно: зачем считывать данные давления в Паскалях и затем пересчитывать в мм.рт.ст., когда можно сразу записать:
???
Первый delay это время показа значений в микросекундах, т.е. это 1 секунда.
«3» это сколько раз повторять до показа графиков.
Ну а график показывается 2 сек. — «delay(2000);» в конце.
Так что поставьте большее число вместо тройки.
И ещё один вопрос как я понял Вы сделали чтоб влажность на 20% меньше показывала от измененного результата датчиком. Это так? Потому что у меня рядом стоит другой проект с датчиком dht22 и bmp180. влажность не много меньше показывает, а давление почти одинаково.
Нет, влажность показывается как есть. Какой-то датчик врёт. Проверить можно скажем так: ru.wikihow.com/протестировать-гигрометр
А по поводу влажности поясняю. У меня есть одна схемка собранная на atmega8 в которой используются датчики dht22 и bmp180. Значит если сравнить показания с Вашей схемой то температура полностью совпадает, давление разница на 1мм.р.с
А вот влажность разница 6%.
Конечно про тестировать не могу по Вашей ссылке. Так как нет подручных материалов.
Vin (Voltage In) -> 3.3V
Gnd (Ground) -> Gnd
SDA (Serial Data) -> A4 on Uno/Pro-Mini
SCK (Serial Clock) -> A5 on Uno/Pro-Mini
*/
#include <Adafruit_BMP280.h>
#include <OLED_I2C.h>
#define PLOT_LEN 100
#define STORAGE_TIME 270
OLED myOLED(SDA, SCL, 8);
Adafruit_BMP280 bmp;
// Temperature Oversampling Rate, Humidity Oversampling Rate, Pressure Oversampling Rate, Mode, Standby Time, Filter, SPI Enable, bmp280 Address
// bmp280I2C bmp(0x1, 0x1, 0x1, 0x1, 0x5, 0x0, false, 0x77); // Version for SparkFun bmp280
extern uint8_t BigNumbers[];
extern uint8_t SmallFont[];
struct {
byte temp = 0;
byte hum = 0;
byte pres = 0;
} infoArr[PLOT_LEN];
struct {
float temp = 0;
float hum = 0;
float pres = 0;
int counter = 0;
} avrg;
byte wait_cnt = 0;
byte shift_cnt = 0;
bool fastMode = true;
int move = 0;
void setup() {
myOLED.begin();
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
delay(100);
digitalWrite(LED_BUILTIN, LOW);
while (!bmp.begin()) {
// if bmp280 not found — blink LED
delay(500);
digitalWrite(LED_BUILTIN, HIGH);
delay(500);
digitalWrite(LED_BUILTIN, LOW);
}
delay(500);
}
void loop() {
bool metric = true;
float temp(NAN), hum(NAN), pres(NAN);
uint8_t pressureUnit(0); // unit: B000 = Pa, B001 = hPa, B010 = Hg, B011 = atm, B100 = bar, B101 = torr, B110 = N/m^2, B111 = psi
// bmp.read(pres, temp, hum, metric, pressureUnit);
// temp -= 0.3; // correct temp
temp = bmp.readTemperature();
//hum = bmp.readTemperature();
pres = bmp.readPressure();
pres /= 133.3; // convert to mmHg
if (move > 50) {move = 0;} // перемещение цифр для уменьшения «выгорания» oled.
myOLED.setBrightness(10);
myOLED.clrScr();
myOLED.setFont(BigNumbers);
myOLED.print(String((temp*1), 0), move, 0); //(temp, 1) -цифра-это количество знаков после запятой
//myOLED.print(String(hum, 0), 78, 0);
myOLED.print(String(pres, 0), move, 36); //(pres, 1) -цифра-это количество знаков после запятой
myOLED.setFont(SmallFont);
myOLED.print("~C", (move+32), 0);
//myOLED.print(«M», 122, 17);
myOLED.print(«mmHg», (move+50), 54);
myOLED.update();
avrg.temp += temp;
avrg.hum += hum;
avrg.pres += pres;
avrg.counter++;
if (fastMode && avrg.counter >= STORAGE_TIME) {
fastMode = false;
for (int i = 0; i < PLOT_LEN — 1; i++) {
infoArr[i].temp = 0;
infoArr[i].hum = 0;
infoArr[i].pres = 0;
}
}
if (fastMode || avrg.counter >= STORAGE_TIME) {
if (avrg.counter >= STORAGE_TIME) {
temp = avrg.temp / avrg.counter;
hum = avrg.hum / avrg.counter;
pres = avrg.pres / avrg.counter;
avrg.temp = 0;
avrg.hum = 0;
avrg.pres = 0;
avrg.counter = 0;
}
for (int i = 1; i < PLOT_LEN; i++) {
infoArr[i — 1] = infoArr[i];
}
infoArr[PLOT_LEN — 1].temp = round(temp) + 50;
infoArr[PLOT_LEN — 1].pres = round(pres) — 650;
infoArr[PLOT_LEN — 1].hum = round(hum);
}
delay(1000);
/*
Graph
*/
if (wait_cnt > 3) {
wait_cnt = 0;
shift_cnt = (shift_cnt == 0)? 3: 0;
myOLED.clrScr();
byte minTemp = 255;
//byte minHum = 255;
byte minPres = 255;
byte maxTemp = 0;
//byte maxHum = 0;
byte maxPres = 0;
for (int i = PLOT_LEN — 1; i >= 0; i--) {
if (infoArr[i].temp == 0 && infoArr[i].hum == 0 && infoArr[i].pres == 0) break;
if (infoArr[i].temp < minTemp) minTemp = infoArr[i].temp;
//if (infoArr[i].hum < minHum) minHum = infoArr[i].hum;
if (infoArr[i].pres < minPres) minPres = infoArr[i].pres;
if (infoArr[i].temp > maxTemp) maxTemp = infoArr[i].temp;
//if (infoArr[i].hum > maxHum) maxHum = infoArr[i].hum;
if (infoArr[i].pres > maxPres) maxPres = infoArr[i].pres;
}
if (maxTemp — minTemp < 10) maxTemp = minTemp + 10;
//if (maxHum — minHum < 10) maxHum = minHum + 10;
if (maxPres — minPres < 10) maxPres = minPres + 10;
/*
myOLED.setFont(SmallFont);
myOLED.printNumI(round((minTemp — 20) / 2.0), 0, 11);
myOLED.printNumI(round((maxTemp — 20) / 2.0), 0, 1);
//myOLED.printNumI(minHum, 0, 34);
//myOLED.printNumI(maxHum, 0, 24);
myOLED.printNumI(round((minPres + 1380) / 2.0), 0, 57);
myOLED.printNumI(round((maxPres + 1380) / 2.0), 0, 47);
*/
myOLED.setFont(SmallFont);
myOLED.print(String(minTemp — 50), 0, 12);
myOLED.print(String(maxTemp — 50), 0, 2);
//myOLED.print(String(minHum), 0, 34);
//myOLED.print(String(maxHum), 0, 24);
myOLED.print(String(minPres + 650), 0, 56);
myOLED.print(String(maxPres + 650), 0, 46);
int z = 0;
int x = 25;
for (int i = 0; i < PLOT_LEN; i++) {
if (infoArr[i].temp == 0 && infoArr[i].hum == 0 && infoArr[i].pres == 0) continue;
/*
myOLED.drawLine(x, map(infoArr[i].temp, minTemp, maxTemp, 18, 0), x + 1, map(infoArr[i + 1].temp, minTemp, maxTemp, 18, 0));
myOLED.drawLine(x, map(infoArr[i].hum, minHum, maxHum, 40, 22), x + 1, map(infoArr[i + 1].hum, minHum, maxHum, 40, 22));
myOLED.drawLine(x, map(infoArr[i].pres, minPres, maxPres, 62, 44), x + 1, map(infoArr[i + 1].pres, minPres, maxPres, 62, 44));
*/
drawCol(x, map(infoArr[i].temp, minTemp, maxTemp, 17, 0), 17);
//drawCol(x, map(infoArr[i].hum, minHum, maxHum, 40, 23), 40);
drawCol(x, map(infoArr[i].pres, minPres, maxPres, 63, 46), 63);
z++;
if (z > 15) {z = 0; x++;}
x++;
}
myOLED.update();
move = move+1; // перемещение цифр для уменьшения «выгорания» oled.
delay(8000);
}
wait_cnt++;
}
void drawCol(int x, int y, int yn) {
for (int i = y; i <= yn; i++) {
myOLED.setPixel(x, i);
}
}
Зажимаю в руке датчик.
Отображаются min и max значения. (к примеру 22 и 60)
НО!
Через время (точно не засекал, где то меньше часа), максимальные показания берутся из этих значений:
«if (maxHum — minHum < 10) maxHum = minHum + 10;»
Т.е. показывает 22 и 32.
Ведь должно же показывать 22 и 60?
Почему теряются максимальные показания?
или через 7 минут сбрасываются показания?
На тот момент мне казалось полезным отфильтровать выбросы подобным образом.
ну т.е. чтобы посмотрел утром — и узнал сколько градусов было ночью?
*ушел тестить)
-зажал рукой датчик.
-влажность выросла до 76 процентов.
-прошло уже 25 часов.
-а показания 76 процентов влажности («instVal.maxHum») так и отображаются.
-вроде же должны выводится MAX и MIN показания за СУТКИ?
-получается что «instVal.maxHum» — это просто максимально измеренные показания с момента включения?
Сознавайтесь )
Скетч надерган из разных источников + пользовался FLProg(для web страницы)
Это мой первый проект.
Пока способен только на это))
П.С. видимо мне надо было в школе учить математику и английский))
Не владею информацией цены на такой дисплей, эта нормально?
PS: не держите в себе )))
я брал у этого https://aliexpress.com/item/item/2-0-inch-TFT-LCD-module-SPI-serial-interface-module-176-220-Minimum-occupancy-4-IO/32826271402.html
-зажал рукой датчик.
-влажность выросла до 76 процентов.
-прошло уже 25 часов.
-а показания 76 процентов влажности («instVal.maxHum») так и отображаются.
-вроде же должны выводится MAX и MIN показания за СУТКИ?
-получается что «instVal.maxHum» — это просто максимально измеренные показания с момента включения?
У меня станция пока в тестовом режиме в доме стоит. Скоро придут некоторые платы — тогда сделаю уличный блок.
P.S. Моя система несколько другая, она по wi-fi отправляет данные на сервер, там база данных пишется. Типа того:
Шаг по времени неравномерный, т.к. на ходу редактировал время выборки. В посл.редакции интервал — 1 час.
Скетч — «Франкенштейн», собранный по мотивам нескольких сайтов, с доработкой и зачисткой от багов;-)
Когда допилите свою станцию, — ждём обзора! )
Я тоже изначально хотел его на улицу, а DHT22 дома, но что-то меня остановило)
На данный момент контроллером является ESP8266. Вот недавний суточный забор анализов с улицы:
«Будка» ещё недоделана, вент.решётка только с одной стороны, но показания очень близки к данным с метеосайта.
Будку буду тоже делать под BME, т.к. DHT22 жестоко врет по влажности на улице.
Там же прочитал о микросхеме PCA9515 (I2C повторитель), их 2 шт. ставится на концах линии. В документации написано, что работает до 400 pF ёмкости кабеля. Посмотрел APPLICATION NOTE AN255-02 (https://www.nxp.com/docs/en/application-note/AN255.pdf), там всё не так оптимистично, как в непроверенной информации из ненадёжных источников, говорится примерно о 4 метрах…
Но в этом же AN есть и P82B715, вот та реально до 50 м. работает (max C 3500 pF). Нашёл на Алишке за US $0.64, пока кинул в список желаний. У меня метраж небольшой, но датчиков хочу ещё добавить…
ESP-шка моя зарегана коммерческой здесь: wifi-iot.com/, а вот какими заморочками удлиннить датчики, — хз. Поздно мне уже теорию учить, мозги не те, уже к земле тянет — в грядках покопаться))) На nRF24LO1 как то это делается, но разобраться старому перцу самостоятельно сложновато… Хорошо бы на живых примерах посмотреть и принять за основу)
Так что при высокой влажности работает нормально. Дальше интересно посмотреть работу в сильный мороз, но это нескоро;-)
По удлинителю шины: выяснил, что ещё лучше P82B96, заказал. Придут -попробую с разными проводами.
Я пенсионер и кроме компьютера занимаюсь выращиванием домашних цветов для себя, хобби такое у меня. И понадобилось мне знать температуру и главное точную влажность воздуха в своей мини тепличке, погуглил и попался этот обзор. Три дня читал, вникал, пытался понять код из «скетчей», пока созрел до сборки устройства (да молодой я был пошустрей). Заказал детали, дождался, на одном дыхании спаял, благо схема несложная, да и расписано всё очень просто и доходчиво. Два дня заливал «скетчи», ставил библиотеки, в общем разбирался. В итоге всё завелось как говориться с пол тычка! Радости не было предела. Всё работало как я и хотел. Но вскоре понадобилось мне добавить ещё один датчик температуры DS18B20, опять гуглил, читал, разбирался. В итоге из двух скетчей собрал один, всё вроде работает но графики не сохраняют информацию за день. Висят с одним и тем же, не обновляются.
Хотелось бы попросить знающих людей помочь мне, посмотрите и пожалуйста откорректируйте скетч. Схему проверял несколько раз, нет ошибок. Где то в коде я сделал ошибку, а опыта почти нет. Даже код неполучилось спрятать под спойлер, вы уж извините старика…
/*
Vin (Voltage In) -> 3.3V
Gnd (Ground) -> Gnd
SDA (Serial Data) -> A4 on Uno/Pro-Mini
SCK (Serial Clock) -> A5 on Uno/Pro-Mini
*/
#include <OneWire.h>
#include <Wire.h>
#include <DallasTemperature.h>
#include <BME280I2C.h>
#include <OLED_I2C.h>
#define ONE_WIRE_BUS 8 // номер пина к которому подключен DS18B20
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
char buffer[25];
char buffer1[25];
OLED myOLED(SDA, SCL, 8); // Подключение дисплея hardware SDA, SCL
extern uint8_t RusFont[]; // Русский шрифт
extern uint8_t MegaNumbers[]; // Подключение больших шрифтов
extern uint8_t SmallFont[]; // Базовый шрифт без поддержки русскийх символов.
#define PLOT_LEN 96
#define STORAGE_TIME 560
BME280I2C bme;
// Temperature Oversampling Rate, Humidity Oversampling Rate, Pressure Oversampling Rate, Mode, Standby Time, Filter, SPI Enable, BME280 Address
// BME280I2C bme(0x1, 0x1, 0x1, 0x1, 0x5, 0x0, false, 0x77); // Version for SparkFun BME280
extern uint8_t BigNumbers[];
extern uint8_t SmallFont[];
struct {
byte temp = 0;
byte hum = 0;
byte pres = 0;
} infoArr[PLOT_LEN];
struct {
float temp = 0;
float hum = 0;
float pres = 0;
int counter = 0;
} avrg;
byte wait_cnt = 0;
byte shift_cnt = 0;
bool fastMode = true;
// Prototypes
void drawCol(int x, int y, int yn);
void setup() {
myOLED.begin();
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
delay(100);
digitalWrite(LED_BUILTIN, LOW);
while (!bme.begin()) {
// If bme280 not found — blink LED
// Maybe you use BME280 from SparkFun with another address?
delay(100);
digitalWrite(LED_BUILTIN, HIGH);
delay(100);
digitalWrite(LED_BUILTIN, LOW);
myOLED.begin();
myOLED.setBrightness(20); // Установка яркости экрана, чем меньше тем темнее
myOLED.setFont(RusFont);
}
delay(500);
}
void loop() {
{
// Выводим на экран показания температуры
sensors.requestTemperatures();
myOLED.clrScr(); // очищаем экран
myOLED.setFont(RusFont);
myOLED.print(«Ntvgthfnehf», CENTER, 0); // вывод текста русскими буквами
myOLED.setFont(SmallFont);
myOLED.print(«DS18x20», CENTER, 55); // вывод текста
myOLED.setFont(MegaNumbers);
myOLED.print(String(sensors.getTempCByIndex(0), 1), CENTER, 10); // Отображение значения температуры, с точностью до десятых
myOLED.update();
delay(5000); // Пауза 2 секунды
}
// Выводим на экран показания давления, влажность, температура
float temp(NAN), hum(NAN), pres(NAN);
bool metric = true;
uint8_t pressureUnit(0); // unit: B000 = Pa, B001 = hPa, B010 = Hg, B011 = atm, B100 = bar, B101 = torr, B110 = N/m^2, B111 = psi
bme.read(pres, temp, hum, metric, pressureUnit);
/*
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
BME280::PresUnit presUnit(BME280::PresUnit_Pa);
bme.read(pres, temp, hum, tempUnit, presUnit);
*/
// temp -= 0.3; // correct temp
pres /= 133.3; // convert to mmHg
myOLED.clrScr();
myOLED.setFont(BigNumbers);
myOLED.printNumF(temp, 1, 0 + shift_cnt, 0 + shift_cnt);
myOLED.printNumI(round(hum), 89 + shift_cnt, 0 + shift_cnt);
myOLED.printNumF(pres, 1, 42 + shift_cnt, 37 + shift_cnt);
myOLED.setFont(SmallFont);
myOLED.print("~C", 56 + shift_cnt, 0 + shift_cnt);
myOLED.print("%", 119 + shift_cnt, 0 + shift_cnt);
myOLED.print(«MM», 113 + shift_cnt, 54 + shift_cnt);
myOLED.update();
avrg.temp += temp;
avrg.hum += hum;
avrg.pres += pres;
avrg.counter++;
if (fastMode && avrg.counter >= STORAGE_TIME) {
fastMode = false;
for (int i = 0; i < PLOT_LEN — 1; i++) {
infoArr[i].temp = 0;
infoArr[i].hum = 0;
infoArr[i].pres = 0;
}
}
if (fastMode || avrg.counter >= STORAGE_TIME) {
if (avrg.counter >= STORAGE_TIME) {
temp = avrg.temp / avrg.counter;
hum = avrg.hum / avrg.counter;
pres = avrg.pres / avrg.counter;
avrg.temp = 0;
avrg.hum = 0;
avrg.pres = 0;
avrg.counter = 0;
}
for (int i = 1; i < PLOT_LEN; i++) {
infoArr[i — 1] = infoArr[i];
}
infoArr[PLOT_LEN — 1].temp = round(temp * 2) + 80;
infoArr[PLOT_LEN — 1].pres = round(pres * 2) — 1380;
infoArr[PLOT_LEN — 1].hum = round(hum);
}
delay(5000);
/*
Graph
*/
if (wait_cnt > 0) { // if (wait_cnt > 3) { «3» это сколько раз повторять до показа графиков
wait_cnt = 0;
shift_cnt = (shift_cnt == 0)? 3: 0;
myOLED.clrScr();
byte minTemp = 255;
byte minHum = 255;
byte minPres = 255;
byte maxTemp = 0;
byte maxHum = 0;
byte maxPres = 0;
for (int i = PLOT_LEN — 1; i >= 0; i--) {
if (infoArr[i].temp == 0 && infoArr[i].hum == 0 && infoArr[i].pres == 0) break;
if (infoArr[i].temp < minTemp) minTemp = infoArr[i].temp;
if (infoArr[i].hum < minHum) minHum = infoArr[i].hum;
if (infoArr[i].pres < minPres) minPres = infoArr[i].pres;
if (infoArr[i].temp > maxTemp) maxTemp = infoArr[i].temp;
if (infoArr[i].hum > maxHum) maxHum = infoArr[i].hum;
if (infoArr[i].pres > maxPres) maxPres = infoArr[i].pres;
}
if (maxTemp — minTemp < 10) maxTemp = minTemp + 10;
if (maxHum — minHum < 10) maxHum = minHum + 10;
if (maxPres — minPres < 10) maxPres = minPres + 10;
myOLED.setFont(SmallFont);
myOLED.printNumI(round((minTemp — 80) / 2.0), 0, 11);
myOLED.printNumI(round((maxTemp — 80) / 2.0), 0, 1);
myOLED.printNumI(minHum, 0, 34);
myOLED.printNumI(maxHum, 0, 24);
myOLED.printNumI(round((minPres + 1380) / 2.0), 0, 57);
myOLED.printNumI(round((maxPres + 1380) / 2.0), 0, 47);
int z = 0;
int x = 25;
for (int i = 0; i < PLOT_LEN; i++) {
if (infoArr[i].temp == 0 && infoArr[i].hum == 0 && infoArr[i].pres == 0) continue;
/*
myOLED.drawLine(x, map(infoArr[i].temp, minTemp, maxTemp, 18, 0), x + 1, map(infoArr[i + 1].temp, minTemp, maxTemp, 18, 0));
myOLED.drawLine(x, map(infoArr[i].hum, minHum, maxHum, 40, 22), x + 1, map(infoArr[i + 1].hum, minHum, maxHum, 40, 22));
myOLED.drawLine(x, map(infoArr[i].pres, minPres, maxPres, 62, 44), x + 1, map(infoArr[i + 1].pres, minPres, maxPres, 62, 44));
*/
drawCol(x, map(infoArr[i].temp, minTemp, maxTemp, 17, 0), 17);
drawCol(x, map(infoArr[i].hum, minHum, maxHum, 40, 23), 40);
drawCol(x, map(infoArr[i].pres, minPres, maxPres, 63, 46), 63);
z++;
if (z > 15) {
z = 0;
x++;
}
x++;
}
myOLED.update();
delay(5000);
}
wait_cnt++;
}
void drawCol(int x, int y, int yn) {
for (int i = y; i <= yn; i++) {
myOLED.setPixel(x, i);
}
}
Там для новичков вполне понятно как подключить несколько DS18. Да и многое другое (из азов) тоже понятно.
У меня получилось разобраться с массивами и отображением МАКС-МИН значений за необходимый мне период с помощью этой проги.
ТСу — РЕСПЕКТ!!!
Тем более, что на месте не стоите.
_____________
На память — как добавить шрифт в u8g2 (там свой формат со сжатием):
Редактируем/рисуем шрифт в Fony.exe, экспортируем в DSEG7_Classic.bdf. Потом в папке u8g2-master\tools\font\bdfconv\ делаем
Решил собрать метеостанцию с датчиком BME280. Но не нашел ответа на вопрос (или плохо искал) — какое расстояние от датчика до ARDUINO максимально возможно? Заранее спасибо.
ПС
Хочу проверить сколько будет жить от 18650
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
Куда копать?
Arduino: 1.8.12 (Windows 7), Плата:«Arduino Pro or Pro Mini, ATmega328P (5V, 16 MHz)»
C:\Users\Андрей\Documents\Arduino\MeteoArd_BME280\MeteoArd_BME280.ino: In function 'void loop()':
MeteoArd_BME280:86:11: error: 'TempUnit' is not a member of 'BME280'
MeteoArd_BME280:87:11: error: 'PresUnit' is not a member of 'BME280'
MeteoArd_BME280:89:29: error: 'tempUnit' was not declared in this scope
C:\Users\Андрей\Documents\Arduino\MeteoArd_BME280\MeteoArd_BME280.ino:89:29: note: suggested alternative: 'temp'
MeteoArd_BME280:89:39: error: 'presUnit' was not declared in this scope
C:\Users\Андрей\Documents\Arduino\MeteoArd_BME280\MeteoArd_BME280.ino:89:39: note: suggested alternative: 'pres'
exit status 1
'TempUnit' is not a member of 'BME280'
Этот отчёт будет иметь больше информации с
включенной опцией Файл -> Настройки ->
«Показать подробный вывод во время компиляции»
Последний скетч №3 работает с актуальной BME280 ver 3.0 — github.com/finitespace/BME280
А вы похоже пытаетесь использовать его со старой версией библиотеки.
(и да, я немного обновил скетч)