Авторизация
Регистрация

Напомнить пароль

BME280 - датчик температуры, давления и влажности. "Метеостанция" из трёх деталей

Приветствую.
Для проверки показаний датчика влажности у метеостанции, было решено купить более-менее точный датчик, ёмкостного типа (дешёвые резистивные вроде 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);
  }
*/
}

Планирую купить +279 Добавить в избранное
+159 +320
свернутьразвернуть
Комментарии (248)
RSS
+
avatar
+3
  • SEM
  • 18 мая 2017, 17:34
Эта вот «дырка от бублика» и есть датчик аж трёх параметров?!
+
avatar
+5
Ага. Притом, он чует даже когда его на полметра вверх-вниз двигают. Давление разное :)

Насчёт температуры на 0.3 выше — на это ко всему прочему может влиять и нагрев от других компонентов, включая нагрев от линейного стабилизатора, расположенного на плате с датчиком.
+
avatar
0
Может «разогревается» сам кристалл при непрерывных измерениях? Пишут (хотя и для DS18B20), что идеально — это проводить 1 измерение в 10 секунд, а между ними отправлять датчик в сон.
+
avatar
0
Да, может быть и сам кристалл тоже, но доки я не читал по этому поводу.

Насчёт DS18B20 — китайские (наверняка ведь подделки) у меня вообще чуть ли не на полградуса разогреваются, если опрашивать раз в секунду. Их только вырубать принудительно между опросами.
+
avatar
0
Разогреваются которые в пластике TO-92 или герметичные в металле тоже?
+
avatar
+1
Так герметичные в металле — это те же самые в ТО-92, засунутые китайцами в металл. Разве что металлическая оболочка, возможно, получше рассеивает тепло, генерируемое самим сенсором.
+
avatar
+2
  • sim31r
  • 19 мая 2017, 02:33
DS18B20 потребляет около 1 мА при измерении, при чем тут подделка? Если ставить максимальную точность в 1/16 градуса, то измеряет 0.75 секунды, вы гоняете его каждую секунду, спит он у вас всего 0.25 секунды, он и разогреется обязательно. Снижайте точность или увеличивайте период опроса.
Если будете опрашивать 1 раз в 2 секунды, спать он будет уже не 0.25 секунды, а 1.25 секунды, большую часть времени…
+
avatar
+1
  • Offi
  • 18 мая 2017, 17:40
Э… как бы датчик рядом с этим отверстием, которое для крепления болтиком к корпусу предназначено.
+
avatar
0
Как бы в датчике маленькое отверстие, если вы об этом
+
avatar
0
  • kirich
  • 18 мая 2017, 18:53
Отверстие в плате, датчик рядом, а автор мог бы фото и получше сделать, еле разглядел где вообще датчик, да и то на фото продавца.
+
avatar
+1
  • SEM
  • 19 мая 2017, 10:06
А, всё-таки та мелкая «коробочка» с дырочкой как от иголки, рядом с большой дыркой?
По фото сначала так и подумал, но смутила фраза автора…
+
avatar
+7
Уважаемый! На эту «дырку с бубликом» имеется даже datasheet. Причем, этот «бублик», на мой взгляд, очень даже хорош по параметрам. Так-же, на мой взгляд, «дырка от бублика» в Вас, а не в датчике.
+
avatar
+3
Минусов наставили, никак не аргументировали. Хотелось бы увидеть конструктивный диалог.
+
avatar
+3
  • asdfgh
  • 18 мая 2017, 21:04
Не переживай, они ни на что не влияют
+
avatar
0
Нисколько не переживаю. Но, какой-то неуч заявляет «дырка от бублика» на BME280, сразу вопрос: «А что сделал ты?».
+
avatar
0
  • asdfgh
  • 18 мая 2017, 21:30
Хочется кому-то самоутвердиться.
+
avatar
+12
  • Dimon_
  • 18 мая 2017, 17:52
Спасибо. Хоть и несложно, но приятно читать.
Плюс.

[ЗанудаModeOn]
pres /= 133.3;
Надо было делить на значение 133.321995 :)
[ЗанудаModeOff]
+
avatar
+1
Мега-зачот и лайк
+
avatar
+4
Здравствуйте. А можно фотографии, на которых хорошо видно, что с чем соединяется или схему. И ссылку на кабель для заливки скетча в Arduino, и провода для соединений. Не хочется чего-то спалить и лишнего брать. Этот обзор с подвиг меня начать движение в сторону Arduino.
+
avatar
+7
И ссылку на кабель для заливки скетча в Arduino
+
avatar
0
  • asdfgh
  • 18 мая 2017, 20:02
О, их есть у меня.
Теперь бы ссылку на программу,… как я понимаю на уровне чайника, в которую скопировать/вставить текст скетча, потом нажать «загрузить в ардуину»?

дописываю позже: вроде все нашел на arduino.ru
+
avatar
+4
Почитайте вот здесь. Пошагово и очень доступно расписано, что и как…
+
avatar
+2
  • asdfgh
  • 18 мая 2017, 22:34
Смею предположить, что конкретно данный кабель не подойдет для заливки скетча в обозреваемый Аrduino nano
+
avatar
0
На обратной стороне платы под наклейкой QC pass микросхема в SOIC — скорее всего CH340G, мост USB/UART.
+
avatar
+2
  • asdfgh
  • 19 мая 2017, 10:00
Кабель на фото- миниUSB,
У описываемого Arduino nano — разъем microUSB.
И никакого всемирного заговора.
+
avatar
+1
  • Rzzz
  • 19 мая 2017, 00:04
Она если с USB-портом, то и свой USB-TTL адаптер на борту. Без него это pro.mini.
+
avatar
0
Сборка элементарна — так как дисплей и датчик работают по I2C, то просто подсоединяем выводы SDA к пину A4 ардуины, SCK (SCL) к A5, Vin к питанию 3.3V и Gnd к земле.
+
avatar
+1
  • allll
  • 19 мая 2017, 15:43
Кабель обычный: USB -> Micro-USB. Провода для соединения — типа таких. Берём четыре, снимаем по середине изоляцию и прикручиваем/припаиваем к датчику. Разъёмами подключаем к ардуино и экрану. Готово.
Питать nano можно от компового юсб или какой-нибудь зарядки от телефона, с микро-юсб выходом.
+
avatar
0
Всем спасибо за рекомендации.
+
avatar
0
Operating range -40…+85 °C
А есть такое, но до -70?
+
avatar
+10
  • FloX
  • 18 мая 2017, 18:47
Оймякон?
+
avatar
+1
Можно бы и туда, конечно, но пока что это просто камера климатических испытаний.
+
avatar
+5
Название немного неверное «Метеостанция из трёх деталей», надо было написать «Метеостанция» из пяти деталей: трех радиокомпонентов, прямых рук и умной светлой головы.
+
avatar
+11
hands.sys & brain.sys — не детали а драйвера, это ж всем известный факт, еще со времен ФИДО!
Во кстати, выдернуто с одного известного форума:
+
avatar
+8
  • asdfgh
  • 18 мая 2017, 20:04
во времена фидо библиотека называлась pyku.sys

З.Ы. фидошник с начала 90-х годов прошлого века
+
avatar
+2
так то локализованная версия)))
+
avatar
0
До сих пор пользуетесь FidoNet?
+
avatar
0
  • asdfgh
  • 19 мая 2017, 22:44
Не, фидошничать начинал на БК-0011м (был в свое время советский персональный компьютер), а позже оПиСючился (купил IBM 386dx40). Потом появился интернет, и в начале 2000х фидошничать перестал.
+
avatar
0
Вообще-то

/dev/hands
+
avatar
0
  • vit375
  • 21 мая 2017, 11:17
Виндузятники...)
+
avatar
+6
  • X3Shim
  • 18 мая 2017, 18:40
Я на таком же датчике собрал уличный блок, и еще один жду в комнатный блок вместо 180-го.

Вопрос только один, почему не ESP? Этот датчик она прекрасно умеет, экран тоже, 3.3 на ней есть, из той же ArduinoIDE точно так же программируется. Стоит аналогично :)
+
avatar
+2
  • 644052
  • 18 мая 2017, 18:51
Вопрос только один, почему не ESP? Этот датчик она прекрасно умеет, экран тоже, 3.3 на ней есть, из той же ArduinoIDE точно так же программируется. Стоит аналогично :)
Так именно по этому…
А еще, видимо по тому что...
Arduino nano была куплена прошлой осенью
+
avatar
+1
Есть вероятность, что BME280 на улице долго не протянет. Люди жалуются. Хотя, конечно, это напрямую от условий/климата зависит.
+
avatar
0
  • X3Shim
  • 18 мая 2017, 20:19
Ну вот и проверю. Прямо вода на него попадать не должна у меня. DHT22 совсем криво показывал влажность. Так что даже не знаю что еще можно на улицу из не сильно дорогого поставить.
+
avatar
0
ИМХО, крышка у датчика металлическая, что теоретически может способствовать выпадению на ней росы. Если не обеспечить отвод из-под крышки капель воды через отверстие естественным путем, то при первом заморозке датчику придется несладко.
+
avatar
0
  • X3Shim
  • 18 мая 2017, 20:52
Да, металл. Варианты то какие?
+
avatar
0
Этот датчик мне еще не приехал, но мысли пока такие:
Плату установить горизонтально, чтобы дырка смотрела вниз. Плату покрыть лаком, крышку датчика тоже, но аккуратно, чтобы не залилось внутрь. На многих станциях вижу приточный вентилятор — вероятно это жжжж неспроста.
+
avatar
0
что-то типа si7021 (только с давлением) на них мембрана стоит. Или поискать эту мембрану отдельно.
+
avatar
0
Для датчиков влажности есть специальные корпуса с мембраной из тонкопористой прессованной PTFE пленки. Конский ценник…
+
avatar
0
Попробовать просто обернуть плату ветровлагозащитной пленкой/мембраной из строймага?
+
avatar
+1
  • FloX
  • 21 мая 2017, 08:24
от точки росы это же не спасет
+
avatar
0
  • SolarW
  • 21 мая 2017, 14:44
А можно ссылочку где жалуются?
Чешутся руки попробовать засунуть в самопальную будку Стивенсона из вентиляционных решеток…
+
avatar
0
Жаловались на форуме проекта MySensors, я сам пользуюсь MySensors и время от времени посматриваю форум. forum.mysensors.org/topic/4917/bme280-how-to-use-it-outdoors

DHT22 из «первых партий» померли на улице довольно быстро и сейчас показывают «погоду на марсе», поэтому жаба мне не позволила дорогущие BME280 оставить на улице для проверки.

Тем временем дома другие DHT22 и BME280 показывают примерно одно и то же.
+
avatar
0
пипец! вот у людей руки не из жопы. однозначно +!

себе купил ESPMeteoSmall (у меня руки из от туда) для мониторинга на narodmon.ru/
+
avatar
+2
чтобы из лего собрать заранее определенную фигуру — не надо иметь никаких рук, можно даже ногами
а вот написать безглючную библиотеку — вот где мозги нужны
+
avatar
0
  • SterX
  • 18 мая 2017, 19:36
Эх! Вот бы кто из него сделал обвязку для камеры копчения-вяления колбасы!
чтоб ТЭНы-увлажнители-вентиляторы автоматом включались и нужные параметры кнопами вводились и на дисплее отображались…
+
avatar
0
  • X3Shim
  • 18 мая 2017, 19:42
Так в этом нет проблемы. Люди и автоматические пивоварни делают :)
+
avatar
0
  • SterX
  • 18 мая 2017, 19:46
Охотно верю. По схеме соберу — только в путь. А вот ручками своими и головой — опыта не хватает
+
avatar
0
  • Sg43
  • 18 мая 2017, 19:46
На arduino.ru поищите, наверняка кто-то такое уже делал.
+
avatar
0
  • kke
  • 18 мая 2017, 19:48
А помните как в игре «цивилизация» был пункт исследований «минитюризация»? Так что я ничему не удивляюсь уже!
+
avatar
0
А можно сделать чтоб этот девайс погоду предсказывал? Показывал там тучи и дождь, или солнце.
+
avatar
0
  • kke
  • 18 мая 2017, 20:09
Можно! Если ума хватит!(без обид)
+
avatar
+2
Видел у одного товарища такую штуку, говорит если находишься на одном месте то довольно точно предсказывает, вот и стало интересно, можно ли аналогичное реализовать на ардуино.
+
avatar
0
  • sim31r
  • 19 мая 2017, 02:36
Падение давление к дождю? На Гисметео можно архивы посмотреть, что с давлением перед дождем…
+
avatar
0
  • tokmin
  • 20 мая 2017, 22:13
А если долго на одном месте находишься, то начинаешь без гисметео запоминать, «что с давлением перед дождем». :)
+
avatar
+1
  • trembo
  • 18 мая 2017, 20:09
Текущее состояние и направление движения осадков всегда смотрю вот такими прогами на мобильнике:
play.google.com/store/search?q=rain%20radar&c=apps
А конкретно вот этой:
play.google.com/store/apps/details?id=lv.mbriedis.lietus
+
avatar
0
Они берут данные из интернета? если нет 3G связи?
У Rain Radar не нашёл Россию в списке.
+
avatar
0
  • trembo
  • 18 мая 2017, 21:05
Это метеорадары аэропортов.
Обычно они раз в 5- 10 минут сканируют капли дождя в радиусе 250 км.
Можете тут ещё глянуть, там интересно​ кнопки под картинкой понажимать:
lietus.lv.
Хотя скорее всего это не ваш регион…
+
avatar
0
Реализовать хотя бы простейший алгоритм Замбретти.
+
avatar
+2
Для Замбретти еще флюгер надо приделать.
+
avatar
0
Можно, но нужно хранить в памяти предыдущие значения. Есть зависимости изменения давления/влажности/температуры и изменения погоды. Грубо «давление быстро падает, влажность растёт» — быть дождю :)
+
avatar
0
  • Bloop
  • 07 августа 2019, 18:41
Обычно относительная влажность растет уже после того, как дождь начался. В остальное время она меняется пропорционально температуре. И сколько ни пялися в графики, корреляции между падением атмосферного давления и осадками не заметил. Впрочем, все это может объясняться особенностями горной полупустынной местности…
+
avatar
-1
  • dansar
  • 18 мая 2017, 20:06
в диапазоне 20…80 %RH
т.е. как датчик влажности, он совершенно не годится?
+
avatar
+6
Вы выдернули кусочек фразы из контекста. Автор говорил про точность в 3% в этом диапазоне (от 20 до 80).

С тем же успехом можно сказать, что и как датчик давления он совершенно не годится. Ни там глубокого вакуума, ни даже банально давление в шинах не проверить.
+
avatar
0
  • dansar
  • 20 мая 2017, 11:35
Я смотрел прогноз погоды на четверг, влажность была указана 97%. Этот датчик будет показывать такую влажность?
+
avatar
0
Да что же Вы за человек такой 8)

Сейчас лично подошёл и подышал на датчик. Не уверен, сможет ли он показать 97% (кстати, при какой температуре?), но 95.4% я добился с первого раза. Датчик дома, температура около +25 градусов цельсия. Не знаю, достаточно ли Вам моих слов или надо какие-то более серьёзные доказательства.

Может быть Вы потрудитесь datasheet глянуть, вдруг там есть ответ на этот вопрос?
+
avatar
+1
Иногда и под 100% показывает. На самом деле влажность в течение дня меняется достаточно сильно:
+
avatar
0
Проблем из-за двух резисторов, подтягивающих линию данных не возникает, какие номиналы там?
+
avatar
0
  • ariss
  • 18 мая 2017, 20:26
Тут попросили мониторить теплицу — инет в доме есть. У кого нить решения есть как с минимальными затратами организовать?
+
avatar
0
MySensors гляньте, просто делается, с картинками, готовыми примерами и так далее.
+
avatar
0
  • ariss
  • 18 мая 2017, 21:57
спасибо, бум изучать
+
avatar
0
  • dansar
  • 20 мая 2017, 11:39
trembo уже написал про WiFi-IoT
Мне нравится, что прошивка сама обновляется с сайта. т.е. модуль ESP8266 к компьютеру нужно только один раз подключать. Только для полного управления скорее всего потребуется лицензия, 110 р. на модуль.
+
avatar
+3
На Али есть более дешевые датчики, без стабилизаторов на плате.
Соответственно питание на 3.3В Для более точного измерения температуры, это даже лучше.
+
avatar
+1
  • AndrVU
  • 18 мая 2017, 22:06
У них еще два вывода SDO и CSB. Для чего они?
+
avatar
+3
Это для SPI интерфейса. Датчик BME280 может по I2C и по SPI, на выбор.
+
avatar
0
  • Eeyore
  • 18 мая 2017, 20:32
Я подключил несколько таких датчиков к RaspberryPi в разных частях дома с передачей данных по SNMP на сервер, который все показывал через Cacti. Инструкции для RPi здесь www.satsignal.eu/raspberry-pi/monitoring.html
+
avatar
0
Как решили вопрос с одинаковыми i2c адресами датчиков?
+
avatar
0
  • Eeyore
  • 18 мая 2017, 20:39
Я подключал к разным RPi. Но вопрос решить можно, в датчике адрес изменяется. Инструкцию где-то видел, адрес с налета не вспомню.
+
avatar
0
Если разные то наверное подешевле было использовать esp или orange pi zero. Или они ещё что-то умное делают?
Спасибо за наводку, погуглю про смену адреса.
+
avatar
0
  • Eeyore
  • 18 мая 2017, 21:48
Ничего особо умного. На одной Kodi, другая самолеты мониторит для Flightradar24. Может с другими было бы дешевле, у меня не хватает времени и на то что есть.
+
avatar
+2
Посмотрел цены на 2«42 OLED. Стало плохо.
+
avatar
0
товарищи хелп. есть датчики давления до 16 бар?!
+
avatar
+1
Конечно!
тыц US $19.90

и тыц2 US $14.00 чуть большее давление
+
avatar
0
с ардуино будет работать? :) я просто нуб в этом деле, :)
+
avatar
+3
  • Crafty
  • 18 мая 2017, 23:09
А я такой же к ESP8266 подключил
Без дисплея, все данные получаю просто по WiFi и смотрю в браузере (+ данные логируются на сервер)
Золотистого цвета — это MH-Z19 (датчик CO2)
+
avatar
+1
А скетч где посмотреть можно?
+
avatar
0
  • Crafty
  • 19 мая 2017, 10:37
Я к сожалению, не знаю как правильно сделать скетч
Просто кусочек исходника
Оно на lua, а графики строятся на сервере с Django (куда отсылаются данные раз в 10 секунд)
К сожалению, у меня не было возможности написать код нормально, да и с lua я не знаком, использован код многих людей в частности barkon
pastebin.com/FsHKKdYJ
Тут без считывания с MH-Z19 если надо и его — пишите (он отдельными файликами)
+
avatar
0
  • mag21
  • 21 сентября 2017, 15:33
Интересует скрипт на lua для считывания MH-Z19. Скиньте плиз.
+
avatar
0
  • Crafty
  • 21 сентября 2017, 15:46
Вот данные считываются в глобальную переменную co2result через ШИМ
pastebin.com/5fTGPiW0
а вот через UART в uartresult
pastebin.com/jzGakNcA
+
avatar
0
  • mag21
  • 22 сентября 2017, 13:46
Спасибо. Скиньте плиз весь проект в архиве. Схему если есть не плохо было бы.
+
avatar
0
  • Crafty
  • 22 сентября 2017, 14:02
mega.nz/#!vwlnjJ6C!udJl-iZNRYwMvl45IWmFmnL9A1HGGXIsVWwhyXclyt4
Схемы увы нету, см. картинку выше, оно в таком виде и осталось
+
avatar
0
  • mag21
  • 22 сентября 2017, 14:23
Спасибо за быстрый ответ. С фото тяжело рассмотреть куда что соединить.
+
avatar
0
  • Surami
  • 19 мая 2017, 10:03
Меня тоже скетч интересует. Спасибо!
+
avatar
0
  • Crafty
  • 19 мая 2017, 10:39
По скетчу — ответил чуть выше
mysku.club/blog/aliexpress/52057.html#comment2062858
+
avatar
+8
Мой вариант: BME + ESP8266
Питание — солнечная панель, «usb зарядка» для лития + LM3671, акк от вертолетика.
Работает почти год, зимой были проблемки с подзарядкой, поставил панель побольше.
Тут (моя песочница) можно глянуть погоду с моего балкончика.
+
avatar
0
А солнечная панель какая? Напряжение, ток? Или хотя бы размеры.
+
avatar
+1
Брал такую 15 см х 6.9 см.
Но у меня регион северный, в средней полосе и южнее (РФ), такая большая явно не нужна.
+
avatar
0
Годная вещь. Можно еще мелкий вентилятор запитать в солнечный день.
+
avatar
0
  • Z2K
  • 19 мая 2017, 12:56
Но у меня регион северный
— а где это у Вас на северном регионе 14.05, 18.05 +45С? :) Неплохой север.
+
avatar
0
Сыктывкар, температура скачет от солнца, балкончик небольшой и в солнечную погоду, если не открывать окна, хорошенько прогревается :)
Да и сам датчик под солнечные лучи попадет
+
avatar
0
У меня сделано аналогичное, только спящий режим не допилен, поэтому заряженной за день батарейки — на всю ночь не хватает.
+
avatar
+1
  • Virtum
  • 20 мая 2017, 00:46
Очень заинтересовал ваш вариант! А не мог ли бы вы описать более конкретно вашу реализация(схему и какие использовали компоненты)? т.к. в железе не очень рублю, но подумываю над таким же устройством.
+
avatar
0
Чуть позже нарисую и покажу схемку
+
avatar
0
  • VJean
  • 20 мая 2017, 17:31
Позанудствую немного :)
Время на оси х из-за разворота текста — нечитаемо. Опечатка в «Тепмература» )
Я бы рисовал все три показателя на одном графике разным цветом. Ось х — время, ось y (слева) — температура + влажность; справа — давление.
°С / %                                                             P, мм рт.ст. 
100 |                                                            | 761.0
    |                                                            | 760.9
 90 |                                                            | 760.8
    |                                                            | 760.7
 ...
    |                                                            | 759.3
 10 |                                                            | 759.2
    |                                                            | 759.1
 0  |                                                            | 759.0
   ----------------------------------------------------------------
      00    ...
+
avatar
0
Вы правы, но на тот момент, важна была лишь работоспособность. Сейчас руки не доходят довести до ума, в планах распечатать корпус и повесить в теплице.
+
avatar
0
  • VJean
  • 21 мая 2017, 22:25
как-то так, но еще требует напильника.
+
avatar
-1
  • Apox
  • 21 мая 2017, 00:10
Этот OLED не может разными цветами.
+
avatar
0
  • VJean
  • 21 мая 2017, 00:26
А причем тут OLED?
Речь про
Тут (моя песочница) можно глянуть погоду с моего балкончика.
+
avatar
0
Скетчем не поделитесь?
+
avatar
0
Скетч достаточно старый, в нем есть костыли для корректной работы ESP8266, возможно сейчас они не актуальны
я.диск
+
avatar
0
Спасибо.
+
avatar
0
насколько ваш датчик точнее такого:
mysku.club/blog/china-stores/30078.html
и можно ли купить термометр/гигрометро уже готовый на этой BME?
+
avatar
+1
  • allll
  • 19 мая 2017, 13:08
Там гигрометр с простым резистивным датчиком, точность которого — как повезёт. При удачном варианте, в диапазоне 30-70% RH разница будет невелика. Хотя по-моему, завышение на ~10% встречается чаще.
Готовые термогигрометры на точных емкостных датчиках бывают, но считаются (полу)профессиональными и стоят прилично, скажем TFA 30.5010 больше 2 тысяч.
+
avatar
0
спасибо) придется осваивать адруино))
+
avatar
0
  • dushes
  • 19 мая 2017, 09:19
А такие есть с уже напаяными штырьками для хлебо-доски?
И еще вопрос, сравнивали ли показания с DHT11 в полевых условиях?
+
avatar
0
  • allll
  • 19 мая 2017, 10:22
C напаянными штырьками не встречал.
DHT11 выдавал влажность на десятку больше, чем метеостанция (и BME280)
+
avatar
0
  • Q2W
  • 19 мая 2017, 11:36
Если будете припаивать ножки сами, то осторожней — есть опасность перегреть датчик.
Я так BMP085 сломал.
Но потом я купил несколько BMP180 (ещё не знал о BME280) и припаял ноги к ним — вышло успешно.
Так что попытки со второй и у вас наверняка получится.
+
avatar
+4
BME280 — прекрасен для внутреннего применения.
Мне пришлось вынести датчик из корпуса, ибо нагрев прибора (реализовано на ESP-12 + мини-БП в корпусе китайского блока питания) всё портит.

+
avatar
0
с доставкой в Беларусь аж 5,55 долл.
+
avatar
0
  • DLL
  • 19 мая 2017, 11:24
а к компьютеру можно подключить этот датчик? ещё вопрос — в какой корпус будете это всё помещать или так оставите?
+
avatar
0
  • allll
  • 19 мая 2017, 15:34
Если по проводам, то проще и дешевле через ту же ардуину писать в вирт. ком-порт. (для WI-FI используют ESP8266).
I2C-USB переходники бывают, но похоже стоят дороже.
Корпус — пока не знаю ))
+
avatar
0
Обычная nano и есть переходник I2C-USB
+
avatar
0
  • tklim
  • 20 мая 2017, 08:14
А что там в ардуиновской библиотеке насчет сна? У меня такой же датчик стоит рядом с двумя 1820 — врет а ж на +2 градуса, и это при опросе раз 10 секунд. Хотя пока пока не прогреется, то все одинаково
+
avatar
0
  • f1203
  • 20 мая 2017, 18:52
Сколько стоит вся метеостанция с андруиной и прочим? Давно хотел собрать что -то подобное, только опыта нет
+
avatar
+1
  • allll
  • 20 мая 2017, 21:47
Порядка 10$ если брать в одном магазине (чего я не делал).
+
avatar
0
  • allll
  • 20 мая 2017, 23:05
И да, Arduino Nano с разъёмом Micro USB (а не мини) на сегодня явно практичней. Так что похоже одним магазином не обойтись.
+
avatar
0
  • f1203
  • 20 мая 2017, 23:21
Извиняюсь за тупой вопрос. Датчик СО2 там ещё прикрутить можно дополнительно? Контакты под доп. оборудование остались?
+
avatar
+1
  • allll
  • 21 мая 2017, 10:17
Да, можно. Задействованы только выводы I2C, а к ним можно подключить много.
+
avatar
0
  • VG1544
  • 21 мая 2017, 18:41
И у меня появился вопрос, если сделать вот такое устройство, как в этом обзоре, можно в него установить датчики температуры и влажности и что бы включался кондиционер или вентилятор по таймеру? (более простым способом, и в программной части тоже), или сделать как в том обзоре со всему этими датчиками (не получится ли много нестыковок), может и вас натолкнёт на мысль как это лучше использовать.
+
avatar
0
  • centr
  • 21 мая 2017, 12:04
Я новичёк в этом деле. Собрал, залил Ваш скетч. Температуру и давление показывает, а влажность 0 процентов. Модуль ВМР280 отличается от Вашего — с шестью пинами. Что можно сделать?
+
avatar
+3
  • rx3apf
  • 21 мая 2017, 12:25
Купить BME280. В BMP280 датчика влажности нет.
+
avatar
0
  • centr
  • 21 мая 2017, 12:31
У автора тоже Е/P, но всё равно спасибо за совет, куплю, конечно
+
avatar
+3
У автора маркером подчёрнута BME-версия, у Вас выделена чёрным маркером BMP-версия. Они крайне похожие, поэтому китайцы и делают одну плату на оба датчика.
+
avatar
0
  • centr
  • 21 мая 2017, 16:50
понял, спасибо
+
avatar
+1
  • rx3apf
  • 21 мая 2017, 12:55
Это плата под E/P, а уж какой чип будет стоять (и сколько будет стоить модуль) — совершенно другое дело.
+
avatar
0
  • f-lirt
  • 21 мая 2017, 14:00
Ребята, может кто хочет сделать метеостанцию со средним размером экрана, 2-3 выносными датчиками, чтобы менять температуру на улице и других комнатах. Можно скооперироваться и собрать что-то подобное.
+
avatar
0
  • Hydrus
  • 23 мая 2017, 17:30
чтобы менять температуру на улице и других комнатах
Я хочу такую метеостанцию. Жара летом достала, хочу менять на более комфортную температуру))
+
avatar
0
А можно ли у ардуины понизить частоту до 32 кГц (или какой там минимум в режиме «от внутреннего генератора») без перепрограммирования загрузчика?
+
avatar
0
  • kiv69
  • 22 мая 2017, 04:21
Датчик хорош, отложил в вишлист. Хотя вряд ли найду на него время. А покупать впрок не буду, и так уже набрал вкусняшек целый вагон на 20 лет вперёд :)
Ардуино непонятно, зачем приплели, можно использовать с любым МК.
Думал, ардуино в жизни не буду ставить, однако на носу сборка второго 3D принтера, придётся всё же ставить его для заливки прошивки.
+
avatar
0
«Метеостанция» из трёх деталей ??? Типа «машина из четырёх колёс»???
В первом случае не хватает станции, во втором,- машины.
Ничего не имею против идеи, и даже очень приветствую. Однако, заголовок мог быть поскромнее.
+
avatar
0
Нормально.
+
avatar
0
  • Visik
  • 15 июня 2017, 00:11
Спасибо за материал! Собрал, всё работает)
+
avatar
0
Привет вам. тоже собрал немагу скеч загрузить пишет ошибка кампиляции неподскажете вчем дела?
+
avatar
0
  • allll
  • 21 июня 2017, 10:39
Библиотеки BME280I2C и OLED_I2C установлены? Они должны быть в папке Юзер\Documents\Arduino\libraries\
Ну и среда должна выдавать что-то ещё кроме ошибки компиляции, скопируйте сюда весь вывод
+
avatar
0
OLED _ I2C установил а вот датчик немогу подскажите где взять
+
avatar
0
экран показывает! авот датчик немогу библиотеку найти
+
avatar
0
  • allll
  • 21 июня 2017, 14:06
Ссылка на библиотеку BME280 приведена выше. На гитхабе выбираете «Clone or download» и там «Download ZIP»
+
avatar
0
БОЛЬШОЕ СПАСИБО ВСЕ заработало теперь я АРДУИНЬЩИК =)))))))
+
avatar
0
Здравствуйте. Залил скетч и получил такое сообщение.Скетч использует 17238 байт (56%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 1646 байт (80%) динамической памяти, оставляя 402 байт для локальных переменных. Максимум: 2048 байт.
Недостаточно памяти, программа может работать нестабильно.
Это нормально?
+
avatar
+1
  • allll
  • 29 июня 2017, 13:06
Да это нормально и не приводит к проблемам. Много памяти забирают шрифты и 3*100 байт уходит на массив точек для графика. Если сильно напрягает, то последний можно уменьшить, сделав:
#define PLOT_LEN      60
#define STORAGE_TIME  450
+
avatar
0
Спасибо.
+
avatar
0
  • Gussif
  • 19 июля 2017, 14:08
Добрый день. Возникла проблема с компиляцией скетча, при попытке скомпилировать, выходит ошибка:
compilation terminated.
exit status 1
Ошибка компиляции для платы Arduino Nano.
Помогите разобраться в данной проблеме
+
avatar
0
Спасибо автору за простоту, собрал работает, хотя до этого с ардуино и не дружил. Посмотрел только на ютубе как загружать библиотеки и скопирал скетч.
+
avatar
0
  • dimaris
  • 28 сентября 2017, 08:31
Добрый день.
Что-то версия 2 не компилируется, ругается на drawCol…
+
avatar
0
  • allll
  • 28 сентября 2017, 13:16
А сейчас? Хотя у меня arduino на отсутствие прототипа и не ругалась.
+
avatar
0
  • dimaris
  • 28 сентября 2017, 13:23
Теперь не ругается и все залилось без проблем, спасибо!
+
avatar
0
  • oldfox
  • 18 октября 2017, 14:57
у меня при компиляции скретча выскакивает ошибка:

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&)'
+
avatar
0
  • allll
  • 18 октября 2017, 21:36
no known conversion for argument 4 from 'bool' to 'BME280::TempUnit'
А с более новой версией среды arduino (1.8.x)?
+
avatar
0
  • oldfox
  • 19 октября 2017, 09:56
Arduino: 1.8.5 (Windows 8.1), Плата:«Arduino/Genuino Uno»

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&)'
+
avatar
0
  • allll
  • 19 октября 2017, 17:45
Да действительно, после обновления либы появились ошибки. Воспользуйтесь пока версией 2.1.2 — github.com/finitespace/BME280/archive/Release_Version_2.1.2.zip
+
avatar
0
  • oldfox
  • 19 октября 2017, 18:16
Спасибо, скомпилилось. Но выдало ошибку в конце:

Скетч использует 17238 байт (53%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 1646 байт (80%) динамической памяти, оставляя 402 байт для локальных переменных. Максимум: 2048 байт.
Недостаточно памяти, программа может работать нестабильно.
+
avatar
0
  • allll
  • 19 октября 2017, 18:36
Если работает, то это предупреждение можно игнорировать. Если не работает и мигает, то либо плохой контакт с датчиком, либо у него другой адрес и тогда
нужно в скетче раскомментировать строчку «BME280I2C bme(0x1, 0x1, 0x1, 0x1, 0x5, 0x0, false, 0x77);»
и убрать BME280I2C «bme;»
+
avatar
0
  • oldfox
  • 19 октября 2017, 19:13
Сделал так, но монитор порта все равно пустой и L мигает
+
avatar
0
  • oldfox
  • 19 октября 2017, 19:24
Спасибо, понял, проверю контакт.
+
avatar
0
  • oldfox
  • 20 октября 2017, 12:02
Датчик, вроде, нормально подсоединен. А это может быть из-за того, что не подсоединен монитор?
+
avatar
0
  • allll
  • 20 октября 2017, 13:44
Монитор порта? Нет туда ничего не выводится. Очевидно всё останавливается на
while (!bme.begin()) {
    // If bme280 not found - blink LED  


Попробуйте проверить I2C scanner-ом видно ли датчик, а не только экран.
(вот он пишет в монитор порта)
// I2C Scanner
// Written by Nick Gammon
// Date: 20th April 2011

#include <Wire.h>

void setup() {
  Serial.begin (115200);

  // Leonardo: wait for serial port to connect
  while (!Serial) 
    {
    }

  Serial.println ();
  Serial.println ("I2C scanner. Scanning ...");
  byte count = 0;
  
  Wire.begin();
  for (byte i = 8; i < 120; i++)
  {
    Wire.beginTransmission (i);
    if (Wire.endTransmission () == 0)
      {
      Serial.print ("Found address: ");
      Serial.print (i, DEC);
      Serial.print (" (0x");
      Serial.print (i, HEX);
      Serial.println (")");
      count++;
      delay (1);  // maybe unneeded?
      } // end of good response
  } // end of for loop
  Serial.println ("Done.");
  Serial.print ("Found ");
  Serial.print (count, DEC);
  Serial.println (" device(s).");
}  // end of setup

void loop() {}
+
avatar
0
  • oldfox
  • 20 октября 2017, 15:19
Когда изменил скорость на 9600, выдал:

I2C scanner. Scanning…
Found address: 118 (0x76)
Done.
Found 1 device(s).
+
avatar
+1
  • allll
  • 20 октября 2017, 17:43
Адрес датчика правильный, дефолтный и по идее оно должно было работать сразу…
Правда непонятно есть ли у вас OLED-дисплей, он тоже должен быть в списке ))
Если что, запустите пример
BME280\examples\BME_280_I2C_Test\BME_280_I2C_Test.ino
он выводит инфу в монитор порта, возможно будет понятней.
+
avatar
0
  • oldfox
  • 20 октября 2017, 19:16
Эммм… дисплей пока не приехал) Я думал, в монитор порта выводиться будет.
+
avatar
0
  • allll
  • 20 октября 2017, 22:44
))

Ну тогда должно хватить этого примера.
+
avatar
0
  • oldfox
  • 21 октября 2017, 12:22
Спасибо, прошу прощения за безграмотность мою)
+
avatar
0
  • oldfox
  • 19 октября 2017, 18:23
О, нашел в коментах, что нужно сделать и сделал.
НО, теперь ардуино мигает лампой L и монитор порта девственно чист)
Почему это может быть?
+
avatar
0
  • Vasjan
  • 17 декабря 2017, 01:32
Купил дисплей OLED1.3" I2C 128х64, у него контроллер — CH1106, и он не хочет работать с библиотекой OLED_I2C. Каким образом можно при крутить библиотеку U8GLIB или Adafruit CH1106??? С Ардуиной не знаком, столкнулся первый раз.
+
avatar
0
А ни у кого не завалялась русская версия библиотеки OLED_I2C? А то по ссылке её уже нет.
+
avatar
+1
  • allll
  • 25 января 2018, 10:22
+
avatar
+3
  • Genri2
  • 20 февраля 2018, 10:13
BME280 отличный датчик. Пользуюсь уже достаточное время, что бы понять, что датчик достойный.
Собирал барометр с часами на Nano_V3_BME280_DS3231_LCD3410. И вот такой вид.
+
avatar
0
  • skadi
  • 14 марта 2018, 15:24
а что за экранчик? от нокии?
+
avatar
0
  • Genri2
  • 14 марта 2018, 16:12
от Nokia 3410.
+
avatar
0
  • agat20
  • 15 марта 2018, 20:47
у меня есть экран 5510, часы тоже есть, скетчем не поделитесь? Собрать железо и скорректировать скетч надеюсь смогу (я не писатель, а читатель)))
+
avatar
0
  • Genri2
  • 15 марта 2018, 21:40
Могу:

[code]
        #include "U8glib.h"
        #include "rus6x12.h"
        #include "rus5x7.h"
        #include "ds3231.h"
        #include <Wire.h>
        #include "cactus_io_BME280_I2C.h"
         BME280_I2C bme(0x76);

        U8GLIB_PCF8812 u8g(3, 4, 6, 5, 7);
        const uint8_t gradus[] PROGMEM = 
      {
        0x07,        
        0x05,         
        0x07,          
        0x00,         
        0x00,         
        0x00,        
        0x00,         
        0x00 };        

        #define BUFF_MAX 128

        uint8_t time[8];
        char recv[BUFF_MAX];
        unsigned int recv_size = 0;
        unsigned long prev,
        interval = 1000;
     
    void draw(void)
{
       
        char in;
        unsigned long now = millis();
        struct ts t;
        DS3231_get(&t);                       //получаем время

        u8g.setFont(rus5x7);
        u8g.drawStr( 0, 42, "Давление:");      //печатаем показания давления
        u8g.setFont(rus6x12);
        u8g.setPrintPos(54, 42);
        u8g.print(bme.getPressure_mmHq(),1);
        u8g.drawStr( 85, 42, "мм");

        u8g.setFont(rus5x7);
        u8g.drawStr( 0, 52, "Влажность:");      //печатаем показания влажности
        u8g.setFont(rus6x12);
        u8g.setPrintPos(60, 52);
        u8g.print(bme.getHumidity(),1);           
        u8g.drawStr( 90, 52, "%");

        u8g.setFont(rus5x7);
        u8g.drawStr( 0, 62, "Темпера-ра:");      //печатаем показания температуры
        u8g.setFont(rus6x12);
        u8g.setPrintPos(60, 62);                 
        u8g.print(bme.getTemperature_C()-1,1);    
        u8g.drawBitmapP( 81, 54, 1, 8, gradus); // печатаем символ градуса
        u8g.drawStr( 90, 62, "C");

        u8g.setFont(rus6x12);
        u8g.setPrintPos(16, 32);                //печатаем день недели
        printDay(t.wday);
        u8g.setPrintPos(0, 8);                 //печатаем день месяца
        u8g.print(t.mday);
        printMonth(t.mon);                      //печатаем месяц
        u8g.print((t.year)+100);                //печатаем год

        u8g.setFont(u8g_font_unifont);
        if(t.hour<10)                           // печатаем время
{
        u8g.setPrintPos(17, 22);
        u8g.print(t.hour);
}
        else 
{
        u8g.setPrintPos(17, 22);
        u8g.print(t.hour);
}
        u8g.print(":");
        if(t.min<10)
{
        u8g.print("0");
        u8g.print(t.min);
}
        else
{
        u8g.print(t.min);
}
        u8g.print(":");
        if(t.sec<10)
{
        u8g.print("0");
        u8g.print(t.sec);
}
        else 
{
        u8g.print(t.sec);
        if ((in == 10 || in == 13) && (recv_size > 0)) 
{
        parse_cmd(recv, recv_size);
        recv_size = 0;
        recv[0] = 0;
} 
        else if (in < 48 || in > 122){;        // ignore ~[0-9A-Za-z]
}
        else if (recv_size > BUFF_MAX - 2) {   // drop lines that are too long
           
        recv_size = 0;                         // drop
        recv[0] = 0;
}
        else if (recv_size < BUFF_MAX - 2)
{
        recv[recv_size] = in;
        recv[recv_size + 1] = 0;
        recv_size += 1;
}
}
}
    void setup(void)
{
  
        Wire.begin();
        bme.begin();
       
        DS3231_init(DS3231_INTCN);
     // parse_cmd("T004160727112016",16);
     // flip screen, if required
     // u8g.setRot180();                        // розворот экрана на 180, если нужно
         
        if ( u8g.getMode() == U8G_MODE_R3G3B2 ) // присвоить значение цвета по умолчанию
{
        u8g.setColorIndex(255);                 //белый
}
        else if ( u8g.getMode() == U8G_MODE_GRAY2BIT )
{
        u8g.setColorIndex(3);                   // максимальная интенсивность
}
        else if ( u8g.getMode() == U8G_MODE_BW )
{
        u8g.setColorIndex(1);                   // pixel on
}
        else if ( u8g.getMode() == U8G_MODE_HICOLOR )
{
        u8g.setHiColorByRGB(255,255,255);
}
}
    void loop(void)
{
        bme.readSensor(); 
  
     // picture loop
    
        u8g.firstPage();  
        do
{
        draw();
}
        while( u8g.nextPage() );  // восстановить картинку после задержки
        delay(50);  
}

    void parse_cmd(char *cmd, int cmdsize)
{
        uint8_t i;
        uint8_t reg_val;
        char buff[BUFF_MAX];
        struct ts t;
    
        if (cmd[0] == 84 && cmdsize == 16)
{
       
       // t.sec = inp2toi(cmd, 1);
       // t.min = inp2toi(cmd, 3);
       // t.hour = inp2toi(cmd, 5);
       // t.wday = inp2toi(cmd, 6);
       // t.mday = inp2toi(cmd, 8);
       // t.mon = inp2toi(cmd, 10);
       // t.year = inp2toi(cmd, 12) * 100 + inp2toi(cmd, 14);
      //  DS3231_set(t);
        
}       else if (cmd[0] == 49 && cmdsize == 1) {  // "1" get alarm 1
        DS3231_get_a1(&buff[0], 59);
       
}       else if (cmd[0] == 50 && cmdsize == 1) {  // "2" get alarm 1
        DS3231_get_a2(&buff[0], 59);
        
}       else if (cmd[0] == 51 && cmdsize == 1) {  // "3" get aging register
        
}       else if (cmd[0] == 65 && cmdsize == 9) {  // "A" set alarm 1
        DS3231_set_creg(DS3231_INTCN | DS3231_A1IE);
        
        for (i = 0; i < 4; i++) {
        time[i] = (cmd[2 * i + 1] - 48) * 10 + cmd[2 * i + 2] - 48; // ss, mm, hh, dd
}
        byte flags[5] = { 0, 0, 0, 0, 0 };
        DS3231_set_a1(time[0], time[1], time[2], time[3], flags);
        DS3231_get_a1(&buff[0], 59);
        
}       else if (cmd[0] == 66 && cmdsize == 7) {  // "B" Set Alarm 2
        DS3231_set_creg(DS3231_INTCN | DS3231_A2IE);
        
        for (i = 0; i < 4; i++) {
        time[i] = (cmd[2 * i + 1] - 48) * 10 + cmd[2 * i + 2] - 48; // mm, hh, dd
}
        byte flags[5] = { 0, 0, 0, 0 };
        DS3231_set_a2(time[0], time[1], time[2], flags);
        DS3231_get_a2(&buff[0], 59);
         
}       else if (cmd[0] == 67 && cmdsize == 1) {  // "C" - получить регистр температуры
        
}       else if (cmd[0] == 68 && cmdsize == 1) {  // "D" - сброс состояния регистра флага сигнализаци
        reg_val = DS3231_get_sreg();
        reg_val &= B11111100;
        DS3231_set_sreg(reg_val);
}       else if (cmd[0] == 70 && cmdsize == 1) {  // "F" - custom fct
        reg_val = DS3231_get_addr(0x5);
       
} 
        else if (cmd[0] == 71 && cmdsize == 1) {  // "G" - set aging status register
        DS3231_set_aging(0);
} 
        else if (cmd[0] == 83 && cmdsize == 1) {  // "S" - get status register
}
        else
{
}
}
    void printDay(int wday)
{
        switch(wday)
{
        case 1: u8g.print("Понедельник");break;
        case 2: u8g.print("  Вторник");break;
        case 3: u8g.print("   Среда");break;
        case 4: u8g.print("  Четверг");break;
        case 5: u8g.print("  Пятница");break;
        case 6: u8g.print("  Суббота");break;
        case 7: u8g.print("Воскресенье");break;
        default: u8g.print("Error");break;
} 
}
    void printMonth(int month)
{
        switch(month)
{
        case 1: u8g.print(" Января ");break;
        case 2: u8g.print(" Февраля ");break;
        case 3: u8g.print(" Марта ");break;
        case 4: u8g.print(" Апреля ");break;
        case 5: u8g.print(" Мая ");break;
        case 6: u8g.print(" Июня ");break;
        case 7: u8g.print(" Июля ");break;
        case 8: u8g.print(" Августа ");break;
        case 9: u8g.print(" Сентября ");break;
        case 10: u8g.print(" Октября ");break;
        case 11: u8g.print(" Ноября ");break;
        case 12: u8g.print(" Декабря ");break;
        default: u8g.print(" Error ");break;
} 
}
+
avatar
0
  • Genri2
  • 15 марта 2018, 21:45
Еще нужно создать вкладку и добавить кирилицу:

[code]
/*
  Fontname: rus5x7  (Cyrillic 5x7 LCD Font)
  Copyright: © 2015    Made by Maxim Z.  E-mail: <a href="mailto:Maxim_EV@bk.ru">Maxim_EV@bk.ru</a>
  Capital A Height: 6, '1' Height: 6
  Calculated Max Values w= 5 h= 7 x= 4 y= 4 dx= 5 dy= 0 ascent= 6 len= 7
  Font Bounding box     w= 5 h= 7 x= 0 y=-1
  Calculated Min Values           x= 0 y=-1 dx= 0 dy= 0
  Pure Font   ascent = 6 descent=-1
  X Font      ascent = 6 descent=-1
  Max Font    ascent = 6 descent=-1
*/

const u8g_fntpgm_uint8_t rus5x7[1856] U8G_FONT_SECTION(".progmem.rus5x7") = {
  0,5,7,0,255,6,1,120,2,234,32,255,255,6,255,6,
  255,0,0,0,5,4,0,1,6,6,5,2,0,128,128,128,
  128,0,128,3,3,3,5,1,3,160,160,160,5,5,5,5,
  0,0,80,248,80,248,80,5,5,5,5,0,0,112,160,112,
  40,112,4,6,6,5,0,0,128,144,32,64,144,16,4,5,
  5,5,0,0,64,160,64,160,80,1,3,3,5,2,3,128,
  128,128,2,6,6,5,1,0,64,128,128,128,128,64,2,6,
  6,5,1,0,128,64,64,64,64,128,3,5,5,5,1,0,
  160,64,224,64,160,5,5,5,5,0,0,32,32,248,32,32,
  3,3,3,5,1,255,96,64,128,3,1,1,5,1,2,224,
  2,2,2,5,1,0,192,192,4,4,4,5,0,1,16,32,
  64,128,3,6,6,5,1,0,64,160,160,160,160,64,3,6,
  6,5,1,0,64,192,64,64,64,224,4,6,6,5,0,0,
  96,144,16,32,64,240,4,6,6,5,0,0,240,16,96,16,
  144,96,4,6,6,5,0,0,32,96,160,240,32,32,4,6,
  6,5,0,0,240,128,224,16,144,96,4,6,6,5,0,0,
  96,128,224,144,144,96,4,6,6,5,0,0,240,16,32,32,
  64,64,4,6,6,5,0,0,96,144,96,144,144,96,4,6,
  6,5,0,0,96,144,144,112,16,96,2,5,5,5,1,0,
  192,192,0,192,192,3,6,6,5,0,255,96,96,0,96,64,
  128,3,5,5,5,1,0,32,64,128,64,32,4,3,3,5,
  0,1,240,0,240,3,5,5,5,1,0,128,64,32,64,128,
  3,6,6,5,1,0,64,160,32,64,0,64,4,6,6,5,
  0,0,96,144,176,176,128,96,4,6,6,5,0,0,96,144,
  144,240,144,144,4,6,6,5,0,0,224,144,224,144,144,224,
  4,6,6,5,0,0,96,144,128,128,144,96,4,6,6,5,
  0,0,224,144,144,144,144,224,4,6,6,5,0,0,240,128,
  224,128,128,240,4,6,6,5,0,0,240,128,224,128,128,128,
  4,6,6,5,0,0,96,144,128,176,144,112,4,6,6,5,
  0,0,144,144,240,144,144,144,3,6,6,5,1,0,224,64,
  64,64,64,224,4,6,6,5,0,0,16,16,16,16,144,96,
  4,6,6,5,0,0,144,160,192,192,160,144,4,6,6,5,
  0,0,128,128,128,128,128,240,4,6,6,5,0,0,144,240,
  240,144,144,144,4,6,6,5,0,0,144,208,208,176,176,144,
  4,6,6,5,0,0,96,144,144,144,144,96,4,6,6,5,
  0,0,224,144,144,224,128,128,4,7,7,5,0,255,96,144,
  144,144,208,96,16,4,6,6,5,0,0,224,144,144,224,160,
  144,4,6,6,5,0,0,96,144,64,32,144,96,3,6,6,
  5,1,0,224,64,64,64,64,64,4,6,6,5,0,0,144,
  144,144,144,144,96,4,6,6,5,0,0,144,144,144,144,96,
  96,4,6,6,5,0,0,144,144,144,240,240,144,4,6,6,
  5,0,0,144,144,96,96,144,144,3,6,6,5,1,0,160,
  160,160,64,64,64,4,6,6,5,0,0,240,16,32,64,128,
  240,3,6,6,5,1,0,224,128,128,128,128,224,4,4,4,
  5,0,1,128,64,32,16,3,6,6,5,1,0,224,32,32,
  32,32,224,3,2,2,5,1,4,64,160,4,1,1,5,0,
  0,240,2,2,2,5,1,4,128,64,4,4,4,5,0,0,
  112,144,176,80,4,6,6,5,0,0,128,128,224,144,144,224,
  3,4,4,5,0,0,96,128,128,96,4,6,6,5,0,0,
  16,16,112,144,144,112,4,4,4,5,0,0,96,176,192,96,
  4,6,6,5,0,0,32,80,64,224,64,64,4,5,5,5,
  0,255,112,144,96,128,112,4,6,6,5,0,0,128,128,224,
  144,144,144,3,6,6,5,1,0,64,0,192,64,64,224,3,
  7,7,5,1,255,32,0,32,32,32,160,64,4,6,6,5,
  0,0,128,128,160,192,160,144,3,6,6,5,1,0,192,64,
  64,64,64,224,4,4,4,5,0,0,160,240,144,144,4,4,
  4,5,0,0,224,144,144,144,4,4,4,5,0,0,96,144,
  144,96,4,5,5,5,0,255,224,144,144,224,128,4,5,5,
  5,0,255,112,144,144,112,16,4,4,4,5,0,0,224,144,
  128,128,4,4,4,5,0,0,112,192,48,224,4,6,6,5,
  0,0,64,64,224,64,64,48,4,4,4,5,0,0,144,144,
  144,112,3,4,4,5,1,0,160,160,160,64,4,4,4,5,
  0,0,144,144,240,240,4,4,4,5,0,0,144,96,96,144,
  4,5,5,5,0,255,144,144,80,32,64,4,4,4,5,0,
  0,240,32,64,240,3,6,6,5,1,0,32,64,192,64,64,
  32,1,6,6,5,2,0,128,128,128,128,128,128,3,6,6,
  5,1,0,128,64,96,64,64,128,4,2,2,5,0,4,80,
  160,255,4,5,5,5,0,255,224,144,144,224,128,3,4,4,
  5,0,0,96,128,128,96,3,4,4,5,0,0,224,64,64,
  64,4,5,5,5,0,255,144,144,80,32,64,3,7,7,5,
  1,255,192,64,64,224,160,224,64,4,4,4,5,0,0,144,
  96,96,144,4,5,5,5,0,255,144,144,144,240,16,4,4,
  4,5,0,0,144,144,112,16,5,4,4,5,0,0,168,168,
  168,248,5,5,5,5,0,255,168,168,168,248,8,4,4,4,
  5,0,0,192,96,80,96,4,4,4,5,0,0,144,208,176,
  208,4,4,4,5,0,0,128,224,144,224,3,4,4,5,1,
  0,192,96,32,192,4,4,4,5,0,0,160,208,208,160,3,
  4,4,5,0,0,96,160,96,160,4,6,6,5,0,0,96,
  144,144,240,144,144,4,6,6,5,0,0,224,128,224,144,144,
  224,4,6,6,5,0,0,224,144,224,144,144,224,4,6,6,
  5,0,0,240,128,128,128,128,128,4,7,7,5,0,255,48,
  80,80,80,80,240,144,4,6,6,5,0,0,240,128,224,128,
  128,240,5,6,6,5,0,0,168,168,112,112,168,168,4,6,
  6,5,0,0,224,16,96,16,144,96,4,6,6,5,0,0,
  144,176,176,208,208,144,4,6,6,5,0,0,208,176,176,208,
  208,144,4,6,6,5,0,0,144,160,192,192,160,144,4,6,
  6,5,0,0,48,80,80,80,80,144,4,6,6,5,0,0,
  144,240,240,144,144,144,4,6,6,5,0,0,144,144,240,144,
  144,144,4,6,6,5,0,0,96,144,144,144,144,96,4,6,
  6,5,0,0,240,144,144,144,144,144,4,6,6,5,0,0,
  224,144,144,224,128,128,4,6,6,5,0,0,96,144,128,128,
  144,96,3,6,6,5,1,0,224,64,64,64,64,64,3,6,
  6,5,1,0,160,160,160,64,64,128,3,6,6,5,1,0,
  64,224,160,160,224,64,4,6,6,5,0,0,144,144,96,96,
  144,144,4,7,7,5,0,255,144,144,144,144,144,240,16,4,
  6,6,5,0,0,144,144,144,112,16,16,5,6,6,5,0,
  0,168,168,168,168,168,248,5,7,7,5,0,255,168,168,168,
  168,168,248,8,4,6,6,5,0,0,192,64,96,80,80,96,
  4,6,6,5,0,0,144,144,208,176,176,208,4,6,6,5,
  0,0,128,128,224,144,144,224,4,6,6,5,0,0,96,144,
  48,16,144,96,4,6,6,5,0,0,160,208,208,208,208,160,
  4,6,6,5,0,0,112,144,144,112,80,144,4,4,4,5,
  0,0,112,144,176,80,4,5,5,5,0,0,96,128,224,144,
  96,4,4,4,5,0,0,224,224,144,224,4,4,4,5,0,
  0,240,128,128,128,4,5,5,5,0,255,48,80,80,240,144,
  4,4,4,5,0,0,96,176,192,96,5,4,4,5,0,0,
  168,112,112,168,3,4,4,5,0,0,224,96,32,192,4,4,
  4,5,0,0,144,176,208,144,4,6,6,5,0,0,144,96,
  144,176,208,144,4,4,4,5,0,0,144,224,160,144,4,4,
  4,5,0,0,48,80,80,144,5,4,4,5,0,0,136,216,
  168,168,4,4,4,5,0,0,144,240,144,144,4,4,4,5,
  0,0,96,144,144,96,4,4,4,5,0,0,240,144,144,144,
  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
  };
нужно еще, но здесь ограничения.
+
avatar
0
  • Genri2
  • 17 марта 2018, 07:38
Вот еще фонты:
[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]
+
avatar
0
  • Jaster
  • 15 октября 2018, 16:55
Не подскажете, для такого дисплея много изменений в вашем скетче нужно делать?
То, что предлагает ТС я уже собрал — много ума не нужно было, а вот читать скетч пока не могу, к сожалению, хотя и хочется освоить.
+
avatar
0
  • Genri2
  • 15 октября 2018, 20:27
Немного. В библиотеке выбрать свой дисплей, а затем подкорректировать размещение данных на экране.
+
avatar
0
  • Jaster
  • 15 октября 2018, 22:07
Спасибо. Тогда уж и ссылочку на библиотеку будьте добры )
Пошел заказывать дисплей…
+
avatar
0
  • Genri2
  • 16 октября 2018, 05:00
Библиотека «U8glib.h».на «hithab»-бе. Меняете строку " U8GLIB_PCF8812 u8g(3, 4, 6, 5, 7);" на строку своего дисплея.
+
avatar
0
Спасибо, все заработало с первого раза.......
+
avatar
+1
Не понятен вот этот кусок кода:

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

а именно: зачем считывать данные давления в Паскалях и затем пересчитывать в мм.рт.ст., когда можно сразу записать:
uint8_t pressureUnit(B101);
???
+
avatar
0
  • allll
  • 14 мая 2018, 17:11
Просто потому что, мне не встречались торр ))
+
avatar
0
А между тем, это и есть мм.рт.ст. :))
+
avatar
0
Добрый день уважаемый автор. Хороший проект. Только одна просьба как подкорректировать время показаний между парамметрами и графиком. Очень мало времени на отбражение температуры, влажности и давления. Хотелось бы побольше поставить время. Спасибо. Жду Вашего ответа
+
avatar
+1
  • allll
  • 20 июля 2018, 09:50
delay(1000);

  /*
    Graph
  */

  if (wait_cnt > 3) {
    wait_cnt = 0;


Первый delay это время показа значений в микросекундах, т.е. это 1 секунда.
«3» это сколько раз повторять до показа графиков.
Ну а график показывается 2 сек. — «delay(2000);» в конце.

Так что поставьте большее число вместо тройки.
+
avatar
0
Спасибо большое. Буду корректировать. Значит если я изменю параметр delay(1000) на 10000, то у меня будет 30секунд отображаться температура и т.д. я правильно вас понял?
И ещё один вопрос как я понял Вы сделали чтоб влажность на 20% меньше показывала от измененного результата датчиком. Это так? Потому что у меня рядом стоит другой проект с датчиком dht22 и bmp180. влажность не много меньше показывает, а давление почти одинаково.
+
avatar
+1
  • allll
  • 20 июля 2018, 11:15
будет 30секунд отображаться температура
Да верно.
Это так?
Нет, влажность показывается как есть. Какой-то датчик врёт. Проверить можно скажем так: ru.wikihow.com/протестировать-гигрометр
+
avatar
0
Спасибо за оперативность ответа. Я уже подкорректировал время всё хорошо. Теперь то что нужно. Благодарю.
А по поводу влажности поясняю. У меня есть одна схемка собранная на atmega8 в которой используются датчики dht22 и bmp180. Значит если сравнить показания с Вашей схемой то температура полностью совпадает, давление разница на 1мм.р.с
А вот влажность разница 6%.
Конечно про тестировать не могу по Вашей ссылке. Так как нет подручных материалов.
+
avatar
0
  • allll
  • 20 июля 2018, 18:08
А вот влажность разница 6%.
Это недалеко от погрешности датчиков. Ну и если dht22 долго использовался, то врёт скорее он.
+
avatar
0
Спасибо за труды. Выкладываю подредактированную версию скетча для BMP280
Версия скетча для BMP280
/*
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);
}
}

+
avatar
0
  • gavi34
  • 19 февраля 2019, 15:39
Заливаю скетч.
Зажимаю в руке датчик.
Отображаются min и max значения. (к примеру 22 и 60)
НО!
Через время (точно не засекал, где то меньше часа), максимальные показания берутся из этих значений:
«if (maxHum — minHum < 10) maxHum = minHum + 10;»
Т.е. показывает 22 и 32.
Ведь должно же показывать 22 и 60?
Почему теряются максимальные показания?

или через 7 минут сбрасываются показания?
+
avatar
0
  • allll
  • 19 февраля 2019, 17:49
или через 7 минут сбрасываются показания?
Да, сначала до заполнения экрана инфа выводится налету, а потом массив обнуляется и начинают писаться усреднённые значения за «7 минут».

На тот момент мне казалось полезным отфильтровать выбросы подобным образом.
+
avatar
0
  • gavi34
  • 19 февраля 2019, 19:36
а как с «выбросами» сделать?

ну т.е. чтобы посмотрел утром — и узнал сколько градусов было ночью?
+
avatar
0
  • allll
  • 19 февраля 2019, 20:51
Ну собственно оно и так это покажет и заодно будет работать как верхнее и нижнее значение графика. Но если хочется с секундным разрешением, то как-то так
код

/*
  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;

struct {
  int maxTemp = -50;
  int minTemp = 100;
  int maxHum = 0;
  int minHum = 100;
  int maxPres = 500;
  int minPres = 1000;  
} instVal;

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.5; // 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 (round(temp) > instVal.maxTemp) instVal.maxTemp = round(temp);
  if (round(temp) < instVal.minTemp) instVal.minTemp = round(temp);
  if (round(hum) > instVal.maxHum) instVal.maxHum = round(hum);
  if (round(hum) < instVal.minHum) instVal.minHum = round(hum);
  if (round(pres) > instVal.maxPres) instVal.maxPres = round(pres);
  if (round(pres) < instVal.minPres) instVal.minPres = round(pres);
    
  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(instVal.minTemp, 0, 11);
    myOLED.printNumI(instVal.maxTemp, 0, 1);

    myOLED.printNumI(instVal.minHum, 0, 34);
    myOLED.printNumI(instVal.maxHum, 0, 24);

    myOLED.printNumI(instVal.minPres, 0, 57);
    myOLED.printNumI(instVal.maxPres, 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, 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);
  }
}

+
avatar
0
  • gavi34
  • 19 февраля 2019, 23:16
Благодарю!

*ушел тестить)
+
avatar
0
  • gavi34
  • 19 февраля 2019, 20:08
т.е. если прошло 10 часов, то за какой период отображает MIN и MAX значения?
+
avatar
0
  • allll
  • 19 февраля 2019, 20:51
Воспринимайте это скорее как верхнее и нижнее значение графика.
+
avatar
0
  • gavi34
  • 23 февраля 2019, 00:47
совсем запутался:
-зажал рукой датчик.
-влажность выросла до 76 процентов.
-прошло уже 25 часов.
-а показания 76 процентов влажности («instVal.maxHum») так и отображаются.
-вроде же должны выводится MAX и MIN показания за СУТКИ?
-получается что «instVal.maxHum» — это просто максимально измеренные показания с момента включения?
+
avatar
0
Спасибо, все работает!
+
avatar
0
  • gavi34
  • 22 февраля 2019, 14:38
Благодарю ТС, все работает!

+
avatar
0
  • Jaster
  • 22 февраля 2019, 22:36
Опа! А вот с этого места прошу по-подробнее! Что за дисплей, как скетч дорабатывали?
Сознавайтесь )
+
avatar
0
  • gavi34
  • 23 февраля 2019, 00:55
Дисплей ILI9225.
Скетч надерган из разных источников + пользовался FLProg(для web страницы)
Это мой первый проект.
Пока способен только на это))

П.С. видимо мне надо было в школе учить математику и английский))
+
avatar
0
  • Jaster
  • 23 февраля 2019, 01:24
С Праздником вас и всех муськовчан!
Не владею информацией цены на такой дисплей, эта нормально?
PS: не держите в себе )))
+
avatar
0
Подскажите скетчем с вами поделились для ILI9225?
+
avatar
0
  • dimc
  • 15 апреля 2019, 19:16
Выглядит классно! Сможете поделиться скетчем?
+
avatar
0
  • gavi34
  • 24 февраля 2019, 19:26
совсем запутался:
-зажал рукой датчик.
-влажность выросла до 76 процентов.
-прошло уже 25 часов.
-а показания 76 процентов влажности («instVal.maxHum») так и отображаются.
-вроде же должны выводится MAX и MIN показания за СУТКИ?
-получается что «instVal.maxHum» — это просто максимально измеренные показания с момента включения?
+
avatar
0
Интересно, кто-нибудь пользовался достаточно долго bme280 на улице (с защитой от воды, конечно)?
У меня станция пока в тестовом режиме в доме стоит. Скоро придут некоторые платы — тогда сделаю уличный блок.

P.S. Моя система несколько другая, она по wi-fi отправляет данные на сервер, там база данных пишется. Типа того:

Шаг по времени неравномерный, т.к. на ходу редактировал время выборки. В посл.редакции интервал — 1 час.
Скетч — «Франкенштейн», собранный по мотивам нескольких сайтов, с доработкой и зачисткой от багов;-)
+
avatar
0
  • Jaster
  • 04 апреля 2019, 12:03
У меня bme280 стоит дома, как то не рискнул на улицу ставить, т.к. народ жалуется на скорую гибель датчика влажности. Если соберу нормальную тарельчатую защиту, тогда наверное рискну выставить. Пока стоит на улице DHT22, но замер влажности оставляет желать лучшего, всё вроде нормально продувается, но влагомер зашкаливает почти всегда.
Когда допилите свою станцию, — ждём обзора! )
+
avatar
0
В datasheet на bme280 в списке возможных применений имеется и «Outdoor navigation, leisure and sports applications», так что всё должно получиться, если, конечно, водой не заливать. Устройство получается маленькое, так что и метеобудка ему нужна небольшая, придумаем;-)
+
avatar
0
  • Jaster
  • 04 апреля 2019, 22:47
Согласен.
Я тоже изначально хотел его на улицу, а DHT22 дома, но что-то меня остановило)
+
avatar
0
Небольшой запор случился у Почты России, так что я, не дожидаясь платы контроллера, которую хотел установить в уличный блок, вынес туда только датчик. Кабель около 2,5 м, bme280 через него отлично работает по I2C;-)
На данный момент контроллером является ESP8266. Вот недавний суточный забор анализов с улицы:

«Будка» ещё недоделана, вент.решётка только с одной стороны, но показания очень близки к данным с метеосайта.
+
avatar
0
  • Jaster
  • 19 апреля 2019, 17:04
А я встал перед дилеммой переноса датчика на северную сторону. По кабелю не получится — слишком далеко дом огибать, а вот до беспроводного я еще не дошел — знаний не хватает (
Будку буду тоже делать под BME, т.к. DHT22 жестоко врет по влажности на улице.
+
avatar
0
А что, очень много метров получается? В интернетах читал, что у кого-то и через 15 м. работает 8-)
Там же прочитал о микросхеме 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, пока кинул в список желаний. У меня метраж небольшой, но датчиков хочу ещё добавить…
+
avatar
0
  • Jaster
  • 19 апреля 2019, 20:49
Метров? точно более 10… Микросхемы микросхемами, но мне уже поздно разрабатывать топологию и т.д., не тот возраст) Мне бы так, как в этой ветке: поди туда, копни здесь, достань репку и съешь)
ESP-шка моя зарегана коммерческой здесь: wifi-iot.com/, а вот какими заморочками удлиннить датчики, — хз. Поздно мне уже теорию учить, мозги не те, уже к земле тянет — в грядках покопаться))) На nRF24LO1 как то это делается, но разобраться старому перцу самостоятельно сложновато… Хорошо бы на живых примерах посмотреть и принять за основу)
+
avatar
0
И ещё маленькое дополнение… Прошла первая дождливая ночь в этом году, вот как отработал датчик:
Так что при высокой влажности работает нормально. Дальше интересно посмотреть работу в сильный мороз, но это нескоро;-)
По удлинителю шины: выяснил, что ещё лучше P82B96, заказал. Придут -попробую с разными проводами.
+
avatar
0
Спасибо за дельный обзор датчика BME 280, я специально зарегистрировался, что бы поставить +, но срок голосования к сожалению истёк. Поздно мне попался этот обзор. Но не плюсом, так добрым словом хочется поблагодарить автора за профессионально преподнесённый материал. Спасибо за те знания которыми вы так щедро делитесь с людьми!
Я пенсионер и кроме компьютера занимаюсь выращиванием домашних цветов для себя, хобби такое у меня. И понадобилось мне знать температуру и главное точную влажность воздуха в своей мини тепличке, погуглил и попался этот обзор. Три дня читал, вникал, пытался понять код из «скетчей», пока созрел до сборки устройства (да молодой я был пошустрей). Заказал детали, дождался, на одном дыхании спаял, благо схема несложная, да и расписано всё очень просто и доходчиво. Два дня заливал «скетчи», ставил библиотеки, в общем разбирался. В итоге всё завелось как говориться с пол тычка! Радости не было предела. Всё работало как я и хотел. Но вскоре понадобилось мне добавить ещё один датчик температуры 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);
}

}
+
avatar
0
  • gavi34
  • 27 июня 2019, 22:06
Юзай FLProg.

Там для новичков вполне понятно как подключить несколько DS18. Да и многое другое (из азов) тоже понятно.

У меня получилось разобраться с массивами и отображением МАКС-МИН значений за необходимый мне период с помощью этой проги.

ТСу — РЕСПЕКТ!!!
+
avatar
0
  • gavi34
  • 27 июня 2019, 22:56
На дисплей добавлены дни недели на русском-сокращенном + индикация wifi и наличие интернета:



+
avatar
0
  • Jaster
  • 31 июля 2019, 13:06
А вы не хотели бы обзор запилить со всеми подробностями?
Тем более, что на месте не стоите.
+
avatar
0
  • Ondap
  • 13 января 2020, 04:41
Автору большое спасибо. Работает. При питании от аккумулятора, нужен индикатор разряда.
+
avatar
0
  • allll
  • 17 апреля 2020, 11:51
Добавил вариант скетча использующий библиотеку u8g2, которая поддерживает довольно много дисплеев — интерес представляют SH1106 (OLED 1.3 дюйма) и возможно HX1230 — lcd-экран сносно работающий без подсветки.

_____________
На память — как добавить шрифт в u8g2 (там свой формат со сжатием):
Редактируем/рисуем шрифт в Fony.exe, экспортируем в DSEG7_Classic.bdf. Потом в папке u8g2-master\tools\font\bdfconv\ делаем
bdfconv -v -f 1 -b 1 -m "42-57" dseg7_classic.bdf -o u8g2_font_dseg7_cr.c  -n u8g2_font_dseg7_cr -d ../bdf/helvR12.bdf
+
avatar
0
Добрый день(вечер, ночь).
Решил собрать метеостанцию с датчиком BME280. Но не нашел ответа на вопрос (или плохо искал) — какое расстояние от датчика до ARDUINO максимально возможно? Заранее спасибо.
+
avatar
0
  • allll
  • 01 июня 2020, 10:16
Там цифровая линия I2C, так что с десятками сантиметров проблем не будет. Больше — надо смотреть даташиты.
+
avatar
0
  • Deniskyn
  • 04 сентября 2020, 23:45
Уважаемый ТС, добавьте плс индикатор заряда батареи и поменяйте местами и размером шрифта давление с температурой (температура больше, давление меньше) было бы просто супер. Проект мега зачет.
ПС
Хочу проверить сколько будет жить от 18650
+
avatar
0
Может кому пригодится, вот здесь есть сравнительная таблица некоторых датчиков измерения давления
+
avatar
0
  • JUKKIO66
  • 10 февраля 2022, 22:11
Доброго времени суток. Решил собрать проект. При компиляции ошибка в строке
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'

Этот отчёт будет иметь больше информации с
включенной опцией Файл -> Настройки ->
«Показать подробный вывод во время компиляции»
+
avatar
0
  • allll
  • 10 февраля 2022, 22:45
Старый скетч (№1 и №2) рассчитан на работу со старой версией библиотеки BME280, которая в архиве.

Последний скетч №3 работает с актуальной BME280 ver 3.0 — github.com/finitespace/BME280

А вы похоже пытаетесь использовать его со старой версией библиотеки.
(и да, я немного обновил скетч)
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.