ESP8266 c bme/bmp280 и ds18b20

Xomyc
Offline
Зарегистрирован: 10.04.2020

Народ, не пойму в чем загвоздка. Сначала настроил esp8266 и bme/bmp280. Вывод идет на адресную матрицу (пока она одна 16х16, но будет 4 штуки) бегущей строкой. Пока было это сочетание, все работало. Но вот пришел датчик ds18b20 чтобы мерить температуру на улице и поломалась бегущая строка. Данные все собирает, температуру в комнате, давление, влажность, температуру на улице, но бегущая строка ползет как черепаха. Все Dalay поубирал, проверил. Выяснил что тормозит. Вот эта команда

DS18B20.requestTemperatures(); 

Если ее убрать, то строка бежит нормально. Но не меряет температуру на улице.

Вот собственно сам скетч. Он из 4 файлов (2 шрифты, их я не буду прикладывать). Вот основной

// -------- ВРЕМЯ -------
#define GMT 3              // смещение (москва 3)
#define NTP_ADDRESS  "europe.pool.ntp.org"    // сервер времени
#define NTP_INTERVAL 60 * 1000    // обновление (1 минута)

//-------------------Библиотеки-------------------
#include <FastLED.h>
#include "font12.h"
#include "font_sm.h"
#include <WiFiManager.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include "Adafruit_Sensor.h"
#include "Adafruit_BME280.h"
#include "Wire.h"
#include <DallasTemperature.h>
#include <OneWire.h>

//-------------------Заданные значения---------------
#define MATRIX_WIDTH 16 //ширина матрицы               
#define MATRIX_HEIGHT 16 //высота матрицы
#define COLOR_ORDER GRB 
#define NUM_LEDS MATRIX_WIDTH * MATRIX_HEIGHT
#define FASTLED_INTERRUPT_RETRY_COUNT 0
#define FASTLED_ALLOW_INTERRUPTS 0
#define FASTLED_ESP8266_RAW_PIN_ORDER
#define DATA_PIN 4  //пин матрицы
#define LIGHT_PIN A0  //пин матрицы
#define ONE_WIRE_BUS D1 //контакт для передачи данных подключен к D1ES8266 12-Е (GPIO5)
CRGB leds[NUM_LEDS];
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, NTP_ADDRESS, GMT * 3600, NTP_INTERVAL);
WiFiServer server(80);
// создаем экземпляр класса oneWire; с его помощью 
// можно коммуницировать с любыми девайсами, работающими 
// через интерфейс 1-Wire, а не только с температурными датчиками
// от компании Maxim/Dallas:
OneWire oneWire(ONE_WIRE_BUS);
// передаем объект oneWire объекту DS18B20: 
DallasTemperature DS18B20(&oneWire);

const float SEA_LEVEL_PRESSURE_HPA = 1013.25;
Adafruit_BME280 bme;

// ----------------- ПЕРЕМЕННЫЕ ------------------
int symbols[] = {32,37,43,44,45,46,48,49,50,51,52,53,54,55,56,57,58,59,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,194};
int smallnum[] = {32,37,45,46,48,49,50,51,52,53,54,55,56,57,58};
uint8_t curX;
uint8_t curY;
uint16_t lineStart=0;//с какого столбца строки начинаем вопроизведение текста
uint16_t lineFin=0;//каким столбцом строки заканчиваем вопроизведение текста
uint8_t startRunLineX=MATRIX_WIDTH-1;//столбец X начала отрисовки бегущей строки
byte sl, sn, days, hs, ms, ss, my, dm;
String DayOfWeek, MonthOfYear;
unsigned long Full_tm, yy, interval, corr;
int BRIGHTNESS, RBRIGHTNESS, cc;
float h, t, p, pin, dp;
char temperatureString[6]; //температура в комнате
char dpString[6];
char humidityString[6];
char pressureString[7];
char pressureInchString[6];
char temperatureCString[6]; //температура на улице

void setup() {
  pinMode(DATA_PIN, OUTPUT);
  pinMode(LIGHT_PIN, INPUT);
  FastLED.addLeds<WS2812B, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS);
  Serial.begin(9600);
  interval = 0;
  WiFiManager wifiManager;
  wifiManager.autoConnect("Meteo-ST");
  sl = sizeof(symbols)/sizeof(symbols[0]);
  sn = sizeof(smallnum)/sizeof(smallnum[0]);
  timeClient.begin();

  Wire.begin(D6, D5);
  Wire.setClock(100000); 
  if(!bme.begin())
  {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1)
    {
      yield();
      delay(3000);
    }
  }
  //Запускаем WEB сервер
  server.begin();
  DS18B20.begin();
  cc = random(255);
}

void loop() {
  timeClient.update();

  RBRIGHTNESS = analogRead(LIGHT_PIN);
  RBRIGHTNESS = 1023 - RBRIGHTNESS;
  BRIGHTNESS = map(RBRIGHTNESS, 0, 1023, 1, 50);
  FastLED.setBrightness(BRIGHTNESS);//0-255
  FastLED.clear();
  CHSV color = CHSV(cc,255,255);

  GetData();
  
  days = timeClient.getDay();
  hs = timeClient.getHours();
  ms = timeClient.getMinutes();
  ss = timeClient.getSeconds();
  String frmdt = getDTString();
  String OutDT = DayOfWeek + ", " + dm + " " + MonthOfYear + " " + yy + " года";
  String OutTm = timeClient.getFormattedTime();
  String OutTmp = "Температура в комнате " + String(temperatureString) + "°C";
  String OutTmpOut = "Температура на улице " + String(temperatureCString) + "°C";
  String OutHum = "Влажность " + String(humidityString) + "%";
  String OutPre = "Давление " + String(pressureString) + "мм.рт.ст.";
  if (millis() - interval < 30000) {
    if (runText(OutTm, 0, color, 30) == 1){
      corr = 30000 - (millis() - interval);
      interval = interval - corr;
    }
  }
  if ((millis() - interval >= 30000)&&(millis() - interval < 60000)) {
    if (runText(OutDT, 0, color, 30) == 1){
      corr = 60000 - (millis() - interval);
      interval = interval - corr;
    }
  }
  if ((millis() - interval >= 60000)&&(millis() - interval < 90000)) {
    if (runText(OutTmp, 0, color, 30) == 1){
      corr = 90000 - (millis() - interval);
      interval = interval - corr;
    }
  }
  if ((millis() - interval >= 90000)&&(millis() - interval < 120000)) {
    if (runText(OutTmpOut, 0, color, 30) == 1){
      corr = 120000 - (millis() - interval);
      interval = interval - corr;
    }
  }
  if ((millis() - interval >= 120000)&&(millis() - interval < 150000)) {
    if (runText(OutHum, 0, color, 30) == 1){
      corr = 150000 - (millis() - interval);
      interval = interval - corr;
    }
  }  
  if ((millis() - interval >= 150000)&&(millis() - interval < 180000)) {
    if (runText(OutPre, 0, color, 30) == 1){
      corr = 180000 - (millis() - interval);
      interval = interval - corr;
    }
  }
  if (millis() - interval >= 180000) {
    interval = millis();
    cc = random(255);
  }
  FastLED.show();

  WiFiClient client = server.available();

  if (client) {
    // bolean to locate when the http request ends
    boolean blank_line = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        
        if (c == '\n' && blank_line) {
            //getWeather();
            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: text/html");
            client.println("Connection: close");
            client.println();
            // your actual web page that displays temperature
            client.println("<!DOCTYPE HTML>");
            client.println("<html>");
            //client.println("<head><META HTTP-EQUIV=\"refresh\" CONTENT=\"15; charset=Windows-1251 \"></head>");
            client.println("<head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />");
            client.println("<script>");
            client.println("setTimeout(function(){location.reload();}, 15000);");
            client.println("</script></head>");
            client.println("<body><h1>ESP8266 Weather Web Server</h1>");
            client.println("<h1>"+OutDT+"</h1>");
            client.println("<table border=\"2\" width=\"456\" cellpadding=\"10\"><tbody><tr><td>");
            client.println("<h3>");
            client.println(OutTmp);
            client.println("</h3><h3>");
            client.println(OutTmpOut);
            client.println("</h3><h3>");
            client.println(OutHum);
            client.println("</h3><h3>");
            client.println(OutPre);
             client.println("</h3></td></tr></tbody></table></body></html>");  
            break;
        }
        if (c == '\n') {
          // when starts reading a new line
          blank_line = true;
        }
        else if (c != '\r') {
          // when finds a character on the current line
          blank_line = false;
        }
      }
    }  
    // closing the client connection
    delay(1);
    client.stop();
  }
  
}

А вот файлик с процедурами.

byte runText(String text, byte startY, CHSV color, int speedText){//вывод бегущей строки
    int i, n, m;
    byte fin;
    bool isRusLetter=false;
    uint32_t vertPixels;
    unsigned long tp;

    fin = 0;
    curY=startY;
    curX=startRunLineX;
  
    int l=0;
    for (i=0;i<text.length();i++){
      byte sym = (byte)text[i];
      if ((sym == 208) || ((sym == 209)))
      {
        i++;
        sym = (byte)text[i];
      }
      if (sym == 194){
        i++;
      }

      n=getArrayIndex(sym,sl,1);
      for (byte j=0;j<12;j++){
         vertPixels=pgm_read_word(&(font12[n][j]));
         if ((j==0)||(vertPixels>0)){//только первая колонка и не пустые колонки
             if ((l>=lineStart)&&(l<=lineFin)){
               getPixel12 (vertPixels, startY, color);
             }
             l++;
         }
         if (j==11){//в конце каждого символа добавляем пробел
            if ((l>=lineStart)&&(l<=lineFin)){
                curX++;
            }
            l++;
         }
       }
    }
    lineFin++;
    if (lineFin>=MATRIX_WIDTH) {
        lineStart++;  
    }
    
    if (startRunLineX>0){//каждый кадр смещаем начало отрисовки бегущей строки на 1 пиксель влево от правого края матрицы
        startRunLineX--;
    }

    if (lineStart>l){//воспроизводим с начала
      l=0;
      lineStart=0;
      lineFin=0;
      startRunLineX=MATRIX_WIDTH-1;
      fin = 1;
    }
    
    tp = millis();
    while (millis() - tp != speedText){}
    return fin;
}

void setPixel(int X, int Y, CHSV color){
   int curLed;
   if (X%2 == 0){
      curLed = MATRIX_HEIGHT*X+Y;
   }
   else {
      curLed = (MATRIX_HEIGHT*(X+1)-1)-Y; 
   }
   leds[curLed] = color;
}

byte getPixel12 (uint32_t vertPixels, byte startY, CHSV color) {
   byte pixel;
   for (int k = 10; k >=0; k--) {//
        pixel = ((vertPixels >> k) & 0x01);
        if (pixel==1){
            setPixel (curX, curY, color);
        }
        curY++;
    }
    curY=startY;
    curX++;
}

byte getArrayIndex(byte znach, byte ln, byte an){
  for (byte n=0;n<ln;n++) {
    if (an == 1){
      if (symbols[n] == znach){
       return n;
      }
    }
    else {
      if (smallnum[n] == znach){
        return n;
      }
    }
  }
}

String getDTString() {
  unsigned long rawTime = (timeClient.getEpochTime()) / 86400L;  // in days
  unsigned long days = 0, yr = 1970;
  uint8_t month;
  static const uint8_t monthDays[]={31,28,31,30,31,30,31,31,30,31,30,31};
  static const String weekDays[]={"Понедельник","Вторник","Среда","Четверг","Пятница","Суббота","Воскресенье"};
  static const String monthNames[]={"января","февраля","марта","апреля","мая","июня","июля","августа","сентября","октября","ноября","декабря"};

  while((days += (LEAP_YEAR(yr) ? 366 : 365)) <= rawTime)
    yr++;
  rawTime -= days - (LEAP_YEAR(yr) ? 366 : 365); // now it is days in this year, starting at 0
  days=0;
  for (month=0; month<12; month++) {
    uint8_t monthLength;
    if (month==1) { // february
      monthLength = LEAP_YEAR(yr) ? 29 : 28;
    } else {
      monthLength = monthDays[month];
    }
    if (rawTime < monthLength) break;
    rawTime -= monthLength;
  }
  yy = yr;
  my = month+1;
  dm = rawTime+1;
  DayOfWeek = weekDays[timeClient.getDay()-1];
  MonthOfYear = monthNames[my-1];
  
  String monthStr = ++month < 10 ? "0" + String(month) : String(month); // jan is month 1  
  String dayStr = ++rawTime < 10 ? "0" + String(rawTime) : String(rawTime); // day of month  
  return String(yr) + "-" + monthStr + "-" + dayStr + "T" + timeClient.getFormattedTime(ss ? ss : 0) + "Z";
}

void GetData(){
    h = bme.readHumidity();
    t = bme.readTemperature();
    //dp = t-0.36*(100.0-h);
    float tempC;
    
    p = bme.readPressure()/133.3224;
    pin = 0.02953*p;
    dtostrf(t, 5, 1, temperatureString);
    dtostrf(h, 5, 1, humidityString);
    dtostrf(p, 5, 1, pressureString);
    DS18B20.requestTemperatures(); 
    tempC = DS18B20.getTempCByIndex(0);
    dtostrf(tempC, 2, 2, temperatureCString);
}

Может кто подскажет в чем проблема. Я вот думаю нельзя ли для измерения температуры датчиком ds18b20 использовать библиотеку wire.h, а не onewire.h? Пока вижу, что bmp280 по двум пинам подключается, а ds18b20 по одному. Активно рою интернет.

rkit
Offline
Зарегистрирован: 23.11.2016

Ну вроде ты сам разобрался с проблемой - requestTemperatures занимает много времени. Нет, за меньше времени этого не выполнить. Нет, wire.h и onewire.h это не одно и тоже. Может быть тебе не обязательно измерять температуру сто раз в секунду?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Много информации можно почерпнуть тут

Xomyc
Offline
Зарегистрирован: 10.04.2020

rkit пишет:

Ну вроде ты сам разобрался с проблемой - requestTemperatures занимает много времени. Нет, за меньше времени этого не выполнить. Нет, wire.h и onewire.h это не одно и тоже. Может быть тебе не обязательно измерять температуру сто раз в секунду?

Блин! Ведь собирался раз в минуту измерение сделать! Вот я идиёт!

Спасибо! Все заработало!

Xomyc
Offline
Зарегистрирован: 10.04.2020

Народ, а можно еще вопрос.

При измерении атмосферного давления, есть параметр высоты над уровнем моря. Вот датчик у меня на уровне 10 этажа. Чтобы получить точное значение на земле мне надо указать эту высоту или наоборот, если я укажу высоту, то получу давление именно на этой высоте?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Вам надо указать ту высоту над уровнем моря, на которой расположен датчик.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Xomyc пишет:

Народ, а можно еще вопрос.

При измерении атмосферного давления, есть параметр высоты над уровнем моря. Вот датчик у меня на уровне 10 этажа. Чтобы получить точное значение на земле мне надо указать эту высоту или наоборот, если я укажу высоту, то получу давление именно на этой высоте?

почитайте как самолёты берут эшелон, станет всё понятно

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

ua6em пишет:

почитайте как самолёты берут эшелон, станет всё понятно

Кстати, в РФ уже перешли на QNH или до сих пор по QFE летают ниже высоты перехода / эшелона перехода?