ARDUINO Часы-метеостанция. Обсуждение проекта

z49u

✩✩✩✩✩✩✩
30 Дек 2018
6
1
Из примеров wire запустите сканер i2c, он высветит обнаруженные адреса устройств. И будет понятно надо ли искать файл Adafruit_BME280.h в каталоге библиотек и править его или нет
он его видит

Scanning...
I2C device found at address 0x27 !
I2C device found at address 0x57 !
I2C device found at address 0x68 !
I2C device found at address 0x76 !
done

Где дальше копать?
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,192
1,281
Москва
27 - это адрес экрана. Такой стоит ? На всякий проверить
И да, у вас адрес BME 76.
В моих докуметнах, ардуино, лайбрерис, есть каталог Adafruit_BME280_Library, а в ней файл для правки Adafruit_BME280.h
 
  • Лойс +1
Реакции: z49u

everbeer

✩✩✩✩✩✩✩
21 Дек 2019
1
0
Наверно больше месяца мои метео-часы валялись без корпуса. Сегодня руки дошли и сделал.
Я старался. Если кому надо выложу STL . Корпус адаптирован под 3D печать. Толщина стенки 1мм.

Посмотреть вложение 13184 Посмотреть вложение 13185 Посмотреть вложение 13186 Посмотреть вложение 13187 Посмотреть вложение 13188 Посмотреть вложение 13189
Очень понравился твой корпус, если есть возможность выложи .STL ))))))))))
 

2012de

✩✩✩✩✩✩✩
24 Мар 2020
25
0
Приветствую мужики!
Подскажите, пожалуйста.
Купил недавно OLED дисплей, на замену LCD.
IMG20200905212906.jpg
Но оказывается на ней нельзя уменьшать яркость, на ночь. Только уменьшать контраст (видел на видео, в Ютюб, вот ссылка на видео)
Вот код, который уменьшал у меня яркость, на старом дисплее

C++:
void checkBrightness() {
  if (!light_min && (analogRead(PHOTO) < BRIGHT_THRESHOLD)) {
    if (!light_tim) {
      timing = millis();
      light_tim = true;
    }
    light_min = true;
  }
  if (light_min && (analogRead(PHOTO) > BRIGHT_THRESHOLD)) {
    if (!light_tim) {
      timing = millis();
      light_tim = true;
    }
    light_min = false;
  }
  if (light_tim)
    if (millis() - timing > PERIOD_TIME) {
      light_tim = false;
      if ((hm(hrs, mins) >= hm(23, 20) || hm(hrs, mins) <= hm(7, 30)) && light_min) { // по времени и если темно, то яркость-
        analogWrite(BACKLIGHT, LCD_BRIGHT_MIN);

#if (LED_MODE == 0)
        LED_ON = (LED_BRIGHT_MIN);
#else
        LED_ON = (255 - LED_BRIGHT_MIN);
#endif

      } else
        analogWrite(BACKLIGHT, LCD_BRIGHT_MAX);
    }
}
Но как можно изменить его, или что добавить может в него, чтобы уменьшать контраст на OLED ?
 

bakson

✩✩✩✩✩✩✩
22 Авг 2020
15
7
@2012de, там же русским по черному написано
Как вы можете видеть на видео, только SPI-дисплей может работать при изменении ...... Дисплей I2C просто ничего не отображает, поэтому метод отключения не может быть использован на дисплее I2C.
 
24 Ноя 2019
10
-1
Привет всем подскажите проблема мигает дисплей и произвольно появляются и пропадают пиксели зарядка 5в 1а
 

Bortnik27

★✩✩✩✩✩✩
9 Фев 2019
63
22
А если пины контраста/яркости напрямую с дисплея подключить к неким пинам aрдуино, минуя плату i2c..?
На видео диммирование, надо модуль диммера как в проекте будильник рассвет, гуглите в эту сторону
 
  • Лойс +1
Реакции: Zod123

DenisChel

✩✩✩✩✩✩✩
19 Янв 2020
8
1
Добрый день.
Подключил в метеостанцию li-ion аккумулятор как в варианте от https://github.com/Norovl/meteoClock. Сперва купил модуль заряда похожий на тот, что у Norovl, но он оказался без контроля переразряда. Тогда купил TP4056, но это выдает 4в вместо 5в на нагрузку. Будет ли станция нормально работать на 4в?
Если надо 5в - то как лучше поступить: купить в дополнение к TP4056 повышающий модуль, или модуль защиты в дополнение к 1му модулю (какой)?
 

Bortnik27

★✩✩✩✩✩✩
9 Фев 2019
63
22
Добрый день.
Подключил в метеостанцию li-ion аккумулятор как в варианте от https://github.com/Norovl/meteoClock. Сперва купил модуль заряда похожий на тот, что у Norovl, но он оказался без контроля переразряда. Тогда купил TP4056, но это выдает 4в вместо 5в на нагрузку. Будет ли станция нормально работать на 4в?
Если надо 5в - то как лучше поступить: купить в дополнение к TP4056 повышающий модуль, или модуль защиты в дополнение к 1му модулю (какой)?
TP4056 выдает не 4в а напряжение аккумулятора, когда он разрядется выдаст менее 3х и вот там уже точно могут быть проблемы, теоретически от 3В большинство может питаться, но смысла ловить глюки нет, либо добавьте повышающий модуль типа МТ3608 или возьмите готовый модуль с повышением до 5В, чаще всего на Али они называются модуль Power bank, просто USB выход надо будет отпаять для компактности
 
  • Лойс +1
Реакции: DenisChel

Vasilevs2020

✩✩✩✩✩✩✩
25 Окт 2020
2
2
Подскажите и мне по датчику MH-Z19B:
Всё собрал, всё работало и содержание СО2 показывало.
1. Решил сделать автокабровку (замыканием на землю пина HD в парке. Замкнул, подождал с час наверное. Если важно, температура воздуха была градусов 5)
2. Датчик показал 410 и всё, выше не поднимается. Пытался несколько раз делать так же калибровку дома, оставлял на ночь.
3. Сейчас при включении показывает 410, через несколько минут начинает показывать 400 и не менят показания.
4. Залил скетч для снятия данных с пина PWM (PWM цепляется на D5), Данные выводит в мониторинг порта.
Первые несколько секунд (может с минуту) датчик показывал 700-2500-1700 (прогревался), потом 400 - 395 показывает и всё.
Есть какой-то алгоритм по его оживлению?

C++:
#define pwmPin 5
#define LedPin 13

int prevVal = LOW;
long th, tl, h, l, ppm;

void setup() {
  Serial.begin(9600);
  pinMode(pwmPin, INPUT);
  pinMode(LedPin, OUTPUT);
}

void loop() {
  long tt = millis();
  int myVal = digitalRead(pwmPin);

  //Если обнаружили изменение
  if (myVal == HIGH) {
    digitalWrite(LedPin, HIGH);
    if (myVal != prevVal) {
      h = tt;
      tl = h - l;
      prevVal = myVal;
    }
  }  else {
    digitalWrite(LedPin, LOW);
    if (myVal != prevVal) {
      l = tt;
      th = l - h;
      prevVal = myVal;
      ppm = 5000 * (th - 2) / (th + tl - 4);
      Serial.println("PPM = " + String(ppm));
    }
  }
}
 

Bortnik27

★✩✩✩✩✩✩
9 Фев 2019
63
22
Попробуй этим прошить, у меня работал, правдо вот либы адафрутовские не найду, но они в свободном доступе
 

Вложения

Vasilevs2020

✩✩✩✩✩✩✩
25 Окт 2020
2
2
Кстати, если вдруг кому-то интересно, вот такой рукожопный вариант корпуса :)
Часто надо собрать потроха хоть в какую-то коробку, чтобы они не цеплялись, не ломались.
Ну вот в коробке из-под чая :).
P.S.: из детсва помню, что картонные корпуса совсем неплохие, обычно коробочка под руками, легко режется, поставить на полку или на стол можно легко. Если покрасить из баллончика, то не позорно
Метео.jpeg
 
  • Лойс +1
Реакции: d9143724 и Alejandro

Aleksey79

✩✩✩✩✩✩✩
28 Апр 2020
23
5
Добрый всем! Поставил долгожданный датчик СО2. Всё работает, но каждые 5сек начал мигать экран(подсветка). Кто сталкивался с таким явлением?
 

DrDimedrol

✩✩✩✩✩✩✩
19 Окт 2020
8
7
Добрый всем! Поставил долгожданный датчик СО2. Всё работает, но каждые 5сек начал мигать экран(подсветка). Кто сталкивался с таким явлением?
На этой ветке несколько раз обсуждали, надо на парралельно линий питания подключать танталовую емкость. Хотя я подключил 2 конденсатора по 100мФ плюс 0.1мФ, но мерцания до конца так и не победил.
Кстати, доработал скетч для ESP6288. В веб версии страницы добавил отображение графиков. Код ниже:
const char* otaServerIndex = "<form method='POST' action='/update' enctype='multipart/form-data'><input type='file' name='update'><input type='submit' value='Update'></form>";


String printDigits(int digits)
{
String f=String(digits);
if (digits < 10) return ("0"+f); else return f;
}


String genPlot(int *plot_input){
int max_value = -32000;
int min_value = 32000;
String data;
String circleData;
// int point;

for (byte i = 0; i < 15; i++) {
max_value = max(plot_input , max_value);
min_value = min(plot_input , min_value);
}
if (min_value >= max_value) max_value = min_value + 1;

circleData = " ";
data += R"rawliteral(
<div class="float">
<svg viewBox="0 0 460 140" class="chart">
<line x1="1" x2="500" y1="125" y2="125" style="stroke:#ccc;stroke-width:1"></line>
<line x1="35" x2="35" y1="1" y2="140" style="stroke:#ccc;stroke-width:1" ></line>
)rawliteral";
data += "<g class=\"labels x-labels\"><text x=\"1\" y=\"10\">" + String(max_value) + "</text>\n<text x=\"1\" y=\"123\">" + String(min_value) + "</text></g>\n";

data += "<polyline fill=\"none\" stroke=\"#0074d9\" stroke-width=\"3\" points=\"";

for (byte i = 0; i < 15; i++) {
data += " " + String(i*31+35) + "," + String(125-map(plot_input, min_value, max_value, 0, 120)) + " ";
circleData += "<circle cx=\"" + String(i*31+35) + "\" cy=\"" + String(125-map(plot_input, min_value, max_value, 0, 120)) + "\" data-value=\"" + String(plot_input) + "\" r=\"4\"><title>" + String(plot_input) + "</title></circle>\n";
}
data += "\"/>\n<g class=\"plotData\"> \n" + circleData + " </g>\n</svg></div>\n";
return data;
}


// function to calculete Humidex
float calculate_humidex(float temperature, float humidity) {
float e;
e = (6.112 * pow(10, (7.5 * temperature / (237.7 + temperature))) * humidity / 100); //vapor pressure
float humidex = temperature + 0.55555555 * (e - 10.0); //humidex
return humidex;
}


void HandleClient() {
unsigned long webpageLoad = millis();
char daysOfTheWeek[9][12] = {" Sunday", " Monday", " Tuesday", "Wednesday", " Thursday", " Friday", " Saturday"};
DateTime now = rtc.now();
String webpage;
webpage = "<html>\n<head><title>"+hostName+"</title><meta charset='UTF-8' http-equiv='refresh' content='60' >\n";
webpage += R"rawliteral( <style>
body {font-family: Sans; Color: #00979d;}
h2 {line-height: 10%;}
p {line-height: 20%;}
.chart { height: 140px; width: 500; }
.chart .grid { stroke: #ccc; stroke-dasharray: 0; stroke-width: 2;}
.labels { font-size: 13px;}
.chart .plotData { fill: red; stroke-width: 1;}
.float { float: left;}
.floatclear { clear: both;}
</style>
</head>
<body>)rawliteral";
webpage += "<p><br><b>&nbsp;&nbsp; " + hostName + " </b></p><br>\n";

webpage += "<div class=\"floatclear\"></div><br><p>&nbsp; температура </p>\n";
webpage += "<h2><br>&nbsp;&nbsp;&nbsp;&nbsp;" + String(dispTemp) + " °C</h2>\n";
webpage += "<p> &nbsp; чувствуется как:</p>\n";
webpage += "<h2><br>&nbsp;&nbsp;&nbsp;&nbsp;" + String(calculate_humidex(dispTemp,dispHum)) + " °C</h2>\n";
webpage += genPlot((int*)tempHour);
webpage += genPlot((int*)tempDay);

#if (EXT_SENS == 1)
webpage += "<div class=\"floatclear\"></div><br><p>&nbsp; внешняя температура </p>\n";
webpage += "<h2><br>&nbsp;&nbsp;&nbsp;&nbsp;";

if(extSensorStatus == 200) webpage += String(dispExtTemp) + " °C</h2>\n";
else webpage += "-Sensor Error-</h2>\n";

webpage += "<p> &nbsp; чувствуется как:</p>\n";
webpage += "<h2><br>&nbsp;&nbsp;&nbsp;&nbsp;" + String(calculate_humidex(dispExtTemp,dispExtHum)) + " °C</h2>\n";
webpage += genPlot((int*)tempExtHour);
webpage += genPlot((int*)tempExtDay);
#endif

webpage += "<div class=\"floatclear\"></div><br><p>&nbsp; влажность </p>\n";
webpage += "<h2><br>&nbsp;&nbsp;&nbsp;&nbsp;" + String(dispHum) + " % </h2>\n";

webpage += genPlot((int*)humHour);
webpage += genPlot((int*)humDay);

#if (EXT_SENS == 1)
webpage += "<div class=\"floatclear\"></div><br><p>&nbsp;внешняя влажность </p>\n";
webpage += "<h2><br>&nbsp;&nbsp;&nbsp;&nbsp;" + String(dispExtHum) + " % </h2>\n";
#endif

webpage += "<div class=\"floatclear\"></div><br><p>&nbsp; атмосферное давление </p>\n";
webpage += "<h2><br>&nbsp;&nbsp;&nbsp;&nbsp;" + String(dispPres) + " hPa</h2>\n";

webpage += genPlot((int*)pressHour);
webpage += genPlot((int*)pressDay);

webpage += "<div class=\"floatclear\"></div><br><p>&nbsp; вероятность осадков </p>\n";
webpage += "<h2><br>&nbsp;&nbsp;&nbsp;&nbsp;" + String(dispRain) + " %</h2><br>\n";
webpage += "<p>&nbsp; содержание CO2 </p>\n";
webpage += "<h2><br>&nbsp;&nbsp;&nbsp;&nbsp;" + String(dispCO2) + " ppm</h2>\n";

for (byte i = 0; i < 15; i++) { //cleaning zero values from empty cells and
if((co2Hour<CO2_MIN) && (dispCO2>=CO2_MIN)) co2Hour = dispCO2; //filter out cold sensor readings
if((co2Day<CO2_MIN) && (dispCO2>=CO2_MIN)) co2Day = dispCO2;
}
webpage += genPlot((int*)co2Hour);
webpage += genPlot((int*)co2Day);

webpage += "<div class=\"floatclear\"></div>\n<p><br>&nbsp;&nbsp;&nbsp;&nbsp; RTC:" + printDigits(now.hour()) + ":" + printDigits(now.minute()) + ":" + printDigits(now.second()) + " &nbsp;&nbsp;" + daysOfTheWeek[now.dayOfTheWeek()];
webpage += " &nbsp;" + printDigits(now.day()) + "/" + printDigits(now.month()) + "/" + String(now.year()) + "</p>&nbsp;&nbsp;\n";

webpage += "<p>&nbsp;&nbsp;&nbsp;&nbsp; NTP:" + printDigits(hour()) + ":" + printDigits(minute()) + ":" + printDigits(second()) + " &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n";
webpage += " &nbsp;" + printDigits(day()) + "/" + printDigits(month()) + "/" + String(year()) + "</p>&nbsp;&nbsp;\n";
webpage += "<p>&nbsp;&nbsp;&nbsp;&nbsp;Uptime: "+Uptime()+", WiFi signal: "+ String( WiFi.RSSI()) + "dBm, </p><p>&nbsp;&nbsp;&nbsp;&nbsp;Battery: "+String(batteryVoltCalc()/100)+"V ("+analogRead(BATTERY)+"), Page generation: "+String(millis()-webpageLoad)+"msec</p><br><br>\n";

webpage += "<p>&nbsp;&nbsp; \n<a href='http://"+String(myIP)+"/set_WI_FI'>НАСТРОЙКИ</a></p>&nbsp;&nbsp;<p>\n";
webpage += "</body>\n";
webpage += "</html>\n";
server.send(200, "text/html", webpage);
}

void handleRoot() {
String webpage;
webpage = "<html>";
webpage += "<head><title> Setup </title><meta charset='UTF-8'>";
webpage += "<style>";
webpage += "body { font-family: Verdana; Color: #00979d;}";
webpage += "</style>";
webpage += "</head>";
webpage += "<body>";

String str = "";
str += webpage;
str += "<boy>\
<form method=\"POST\" action=\"ok\">\
<input type=\"radio\" value=\"1\" name=\"otaflag\"> Загрузить новую прошивку (после перезагрузки зайдите на страницу устройства и запустите процедуру)</br></br>\
<input type=\"text\" value=\"" + ssid + "\" name=\"ssid\" maxlength=32> WiFi SSID</br></br>\
<input type=\"password\" value=\"" + pass + "\" name=\"pswd\" maxlength=64> PASSWORD</br></br>\
<input type=\"text\" value=\"" + TIMEZONE + "\" name=\"tzn\" maxlength=3> TIMEZONE</br></br>\
<input type=\"text\" value=\"" + mqtt_ip + "\" name=\"mqtt_ip\" maxlength=15> MQTT IP</br></br>\
<input type=\"text\" value=\"" + mqtt_port + "\" name=\"mqtt_port\" maxlength=5> MQTT PORT</br></br>\
<input type=\"text\" value=\"" + mqtt_auth + "\" name=\"mqtt_auth\" maxlength=32> MQTT USER</br></br>\
<input type=\"password\" value=\"" + mqtt_pass + "\" name=\"mqtt_pass\" maxlength=32> MQTT PWD</br></br>\
<input type=\"text\" value=\"" + mqtt_Temp + "\" name=\"mqtt_temp\" maxlength=64> MQTT Topic (temperature)</br></br>\
<input type=\"text\" value=\"" + mqtt_Hum + "\" name=\"mqtt_hum\" maxlength=64> MQTT Topic (humidity)</br></br>\
<input type=\"text\" value=\"" + mqtt_Press + "\" name=\"mqtt_press\" maxlength=64> MQTT Topic (pressure)</br></br>\
<input type=\"text\" value=\"" + mqtt_CO2 + "\" name=\"mqtt_co2\" maxlength=64> MQTT Topic (CO2)</br></br>\
<input type=SUBMIT value=\"Save\">\
</form>\
</body>\
</html>";

server.send ( 200, "text/html", str );
}

void handleOk(){
String webpage;
webpage = "<html>";
webpage += "<head><title>settings save </title><meta charset='UTF-8'>";
webpage += "<style>";
webpage += "body { font-family: Verdana; Color: #00979d;}";
webpage += "</style>";
webpage += "</head>";
webpage += "<body>";
String ssid_ap = server.arg("ssid");
String pass_ap = server.arg("pswd");
String TZN_ap = server.arg("tzn");
String mqtt_ip_ap = server.arg("mqtt_ip");
String mqtt_port_ap = server.arg("mqtt_port");
String mqtt_auth_ap = server.arg("mqtt_auth");
String mqtt_pass_ap = server.arg("mqtt_pass");
String mqtt_temp_ap = server.arg("mqtt_temp");
String mqtt_hum_ap = server.arg("mqtt_hum");
String mqtt_press_ap = server.arg("mqtt_press");
String mqtt_CO2_ap = server.arg("mqtt_co2");
String otaFlag_ap = server.arg("otaflag");
int tz;
String str = "";

str += webpage;
str += "<body>";
tz = TZN_ap.toInt();

(otaFlag_ap == "0") ? otaFlag = 0 : otaFlag = 1;

if( (tz > -12) && (tz < 12) ) TIMEZONE = tz;
mqtt_ip = mqtt_ip_ap;
mqtt_port = mqtt_port_ap;

mqtt_auth_ap.replace("%2F","/");
mqtt_auth = mqtt_auth_ap;

mqtt_pass_ap.replace("%2F","/");
mqtt_pass = mqtt_pass_ap;

mqtt_temp_ap.replace("%2F","/");
mqtt_Temp = mqtt_temp_ap;

mqtt_hum_ap.replace("%2F","/");
mqtt_Hum = mqtt_hum_ap;

mqtt_press_ap.replace("%2F","/");
mqtt_Press = mqtt_press_ap;

mqtt_CO2_ap.replace("%2F","/");
mqtt_CO2 = mqtt_CO2_ap;

ssid_ap.replace("%2F","/");
pass_ap.replace("%2F","/");

str +="Configuration saved in FS</br>\
<a href=\"/\">Return</a> to settings page</br>";
str += "</body></html>";
server.send ( 200, "text/html", str );

saveConfig();

if( (ssid_ap != String(ssid)) || (pass_ap != String(pass)) ){
ssid = ssid_ap;
pass = pass_ap;
saveConfig();
delay(1000);
ESP.restart();
delay(100);
}
if( otaFlag ) {
lcd.clear();
lcd.print("Rebooting...");
delay(1000);
ESP.restart();
delay(100);
}
}

void handleOTA() {
Serial.println("Starting OTA mode.");
Serial.printf("Sketch size: %u\n", ESP.getSketchSize());
Serial.printf("Free size: %u\n", ESP.getFreeSketchSpace());
MDNS.begin(host);
server.on("/", HTTP_GET, [](){
server.sendHeader("Connection", "close");
server.sendHeader("Access-Control-Allow-Origin", "*");
server.send(200, "text/html", otaServerIndex);
});
server.on("/update", HTTP_POST, [](){
server.sendHeader("Connection", "close");
server.sendHeader("Access-Control-Allow-Origin", "*");
server.send(200, "text/plain", (Update.hasError())?"FAIL":"OK");
setOtaFlag(0);
lcd.clear();
delay(100);
ESP.restart();
},[](){
HTTPUpload& upload = server.upload();
if(upload.status == UPLOAD_FILE_START){
//Serial.setDebugOutput(true);
WiFiUDP::stopAll();
Serial.printf("Update: %s\n", upload.filename.c_str());
otaCount=300;
uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
if(!Update.begin(maxSketchSpace)){//start with max available size
Update.printError(Serial);
}
} else if(upload.status == UPLOAD_FILE_WRITE){
if(Update.write(upload.buf, upload.currentSize) != upload.currentSize){
Update.printError(Serial);
}
} else if(upload.status == UPLOAD_FILE_END){
if(Update.end(true)){ //true to set the size to the current progress
Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
} else {
Update.printError(Serial);
}
Serial.setDebugOutput(false);
}
yield();
});
server.begin();
Serial.printf("Ready! Open http://%s.local in your browser\n", host);
MDNS.addService("http", "tcp", 80);
otaTickLoop.attach(1, otaCountown);
}



 
  • Лойс +1
Реакции: Terristor и Ky6AHb

Aleksey79

✩✩✩✩✩✩✩
28 Апр 2020
23
5
На этой ветке несколько раз обсуждали, надо на парралельно линий питания подключать танталовую емкость. Хотя я подключил 2 конденсатора по 100мФ плюс 0.1мФ, но мерцания до конца так и не победил.
Кстати, доработал скетч для ESP6288. В веб версии страницы добавил отображение графиков. Код ниже:
const char* otaServerIndex = "<form method='POST' action='/update' enctype='multipart/form-data'><input type='file' name='update'><input type='submit' value='Update'></form>";


String printDigits(int digits)
{
String f=String(digits);
if (digits < 10) return ("0"+f); else return f;
}


String genPlot(int *plot_input){
int max_value = -32000;
int min_value = 32000;
String data;
String circleData;
// int point;

for (byte i = 0; i < 15; i++) {
max_value = max(plot_input , max_value);
min_value = min(plot_input , min_value);
}
if (min_value >= max_value) max_value = min_value + 1;

circleData = " ";
data += R"rawliteral(
<div class="float">
<svg viewBox="0 0 460 140" class="chart">
<line x1="1" x2="500" y1="125" y2="125" style="stroke:#ccc;stroke-width:1"></line>
<line x1="35" x2="35" y1="1" y2="140" style="stroke:#ccc;stroke-width:1" ></line>
)rawliteral";
data += "<g class=\"labels x-labels\"><text x=\"1\" y=\"10\">" + String(max_value) + "</text>\n<text x=\"1\" y=\"123\">" + String(min_value) + "</text></g>\n";

data += "<polyline fill=\"none\" stroke=\"#0074d9\" stroke-width=\"3\" points=\"";

for (byte i = 0; i < 15; i++) {
data += " " + String(i*31+35) + "," + String(125-map(plot_input, min_value, max_value, 0, 120)) + " ";
circleData += "<circle cx=\"" + String(i*31+35) + "\" cy=\"" + String(125-map(plot_input, min_value, max_value, 0, 120)) + "\" data-value=\"" + String(plot_input) + "\" r=\"4\"><title>" + String(plot_input) + "</title></circle>\n";
}
data += "\"/>\n<g class=\"plotData\"> \n" + circleData + " </g>\n</svg></div>\n";
return data;
}


// function to calculete Humidex
float calculate_humidex(float temperature, float humidity) {
float e;
e = (6.112 * pow(10, (7.5 * temperature / (237.7 + temperature))) * humidity / 100); //vapor pressure
float humidex = temperature + 0.55555555 * (e - 10.0); //humidex
return humidex;
}


void HandleClient() {
unsigned long webpageLoad = millis();
char daysOfTheWeek[9][12] = {" Sunday", " Monday", " Tuesday", "Wednesday", " Thursday", " Friday", " Saturday"};
DateTime now = rtc.now();
String webpage;
webpage = "<html>\n<head><title>"+hostName+"</title><meta charset='UTF-8' http-equiv='refresh' content='60' >\n";
webpage += R"rawliteral( <style>
body {font-family: Sans; Color: #00979d;}
h2 {line-height: 10%;}
p {line-height: 20%;}
.chart { height: 140px; width: 500; }
.chart .grid { stroke: #ccc; stroke-dasharray: 0; stroke-width: 2;}
.labels { font-size: 13px;}
.chart .plotData { fill: red; stroke-width: 1;}
.float { float: left;}
.floatclear { clear: both;}
</style>
</head>
<body>)rawliteral";
webpage += "<p><br><b>&nbsp;&nbsp; " + hostName + " </b></p><br>\n";

webpage += "<div class=\"floatclear\"></div><br><p>&nbsp; температура </p>\n";
webpage += "<h2><br>&nbsp;&nbsp;&nbsp;&nbsp;" + String(dispTemp) + " °C</h2>\n";
webpage += "<p> &nbsp; чувствуется как:</p>\n";
webpage += "<h2><br>&nbsp;&nbsp;&nbsp;&nbsp;" + String(calculate_humidex(dispTemp,dispHum)) + " °C</h2>\n";
webpage += genPlot((int*)tempHour);
webpage += genPlot((int*)tempDay);

#if (EXT_SENS == 1)
webpage += "<div class=\"floatclear\"></div><br><p>&nbsp; внешняя температура </p>\n";
webpage += "<h2><br>&nbsp;&nbsp;&nbsp;&nbsp;";

if(extSensorStatus == 200) webpage += String(dispExtTemp) + " °C</h2>\n";
else webpage += "-Sensor Error-</h2>\n";

webpage += "<p> &nbsp; чувствуется как:</p>\n";
webpage += "<h2><br>&nbsp;&nbsp;&nbsp;&nbsp;" + String(calculate_humidex(dispExtTemp,dispExtHum)) + " °C</h2>\n";
webpage += genPlot((int*)tempExtHour);
webpage += genPlot((int*)tempExtDay);
#endif

webpage += "<div class=\"floatclear\"></div><br><p>&nbsp; влажность </p>\n";
webpage += "<h2><br>&nbsp;&nbsp;&nbsp;&nbsp;" + String(dispHum) + " % </h2>\n";

webpage += genPlot((int*)humHour);
webpage += genPlot((int*)humDay);

#if (EXT_SENS == 1)
webpage += "<div class=\"floatclear\"></div><br><p>&nbsp;внешняя влажность </p>\n";
webpage += "<h2><br>&nbsp;&nbsp;&nbsp;&nbsp;" + String(dispExtHum) + " % </h2>\n";
#endif

webpage += "<div class=\"floatclear\"></div><br><p>&nbsp; атмосферное давление </p>\n";
webpage += "<h2><br>&nbsp;&nbsp;&nbsp;&nbsp;" + String(dispPres) + " hPa</h2>\n";

webpage += genPlot((int*)pressHour);
webpage += genPlot((int*)pressDay);

webpage += "<div class=\"floatclear\"></div><br><p>&nbsp; вероятность осадков </p>\n";
webpage += "<h2><br>&nbsp;&nbsp;&nbsp;&nbsp;" + String(dispRain) + " %</h2><br>\n";
webpage += "<p>&nbsp; содержание CO2 </p>\n";
webpage += "<h2><br>&nbsp;&nbsp;&nbsp;&nbsp;" + String(dispCO2) + " ppm</h2>\n";

for (byte i = 0; i < 15; i++) { //cleaning zero values from empty cells and
if((co2Hour<CO2_MIN) && (dispCO2>=CO2_MIN)) co2Hour = dispCO2; //filter out cold sensor readings
if((co2Day<CO2_MIN) && (dispCO2>=CO2_MIN)) co2Day = dispCO2;
}
webpage += genPlot((int*)co2Hour);
webpage += genPlot((int*)co2Day);

webpage += "<div class=\"floatclear\"></div>\n<p><br>&nbsp;&nbsp;&nbsp;&nbsp; RTC:" + printDigits(now.hour()) + ":" + printDigits(now.minute()) + ":" + printDigits(now.second()) + " &nbsp;&nbsp;" + daysOfTheWeek[now.dayOfTheWeek()];
webpage += " &nbsp;" + printDigits(now.day()) + "/" + printDigits(now.month()) + "/" + String(now.year()) + "</p>&nbsp;&nbsp;\n";

webpage += "<p>&nbsp;&nbsp;&nbsp;&nbsp; NTP:" + printDigits(hour()) + ":" + printDigits(minute()) + ":" + printDigits(second()) + " &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n";
webpage += " &nbsp;" + printDigits(day()) + "/" + printDigits(month()) + "/" + String(year()) + "</p>&nbsp;&nbsp;\n";
webpage += "<p>&nbsp;&nbsp;&nbsp;&nbsp;Uptime: "+Uptime()+", WiFi signal: "+ String( WiFi.RSSI()) + "dBm, </p><p>&nbsp;&nbsp;&nbsp;&nbsp;Battery: "+String(batteryVoltCalc()/100)+"V ("+analogRead(BATTERY)+"), Page generation: "+String(millis()-webpageLoad)+"msec</p><br><br>\n";

webpage += "<p>&nbsp;&nbsp; \n<a href='http://"+String(myIP)+"/set_WI_FI'>НАСТРОЙКИ</a></p>&nbsp;&nbsp;<p>\n";
webpage += "</body>\n";
webpage += "</html>\n";
server.send(200, "text/html", webpage);
}

void handleRoot() {
String webpage;
webpage = "<html>";
webpage += "<head><title> Setup </title><meta charset='UTF-8'>";
webpage += "<style>";
webpage += "body { font-family: Verdana; Color: #00979d;}";
webpage += "</style>";
webpage += "</head>";
webpage += "<body>";

String str = "";
str += webpage;
str += "<boy>\
<form method=\"POST\" action=\"ok\">\
<input type=\"radio\" value=\"1\" name=\"otaflag\"> Загрузить новую прошивку (после перезагрузки зайдите на страницу устройства и запустите процедуру)</br></br>\
<input type=\"text\" value=\"" + ssid + "\" name=\"ssid\" maxlength=32> WiFi SSID</br></br>\
<input type=\"password\" value=\"" + pass + "\" name=\"pswd\" maxlength=64> PASSWORD</br></br>\
<input type=\"text\" value=\"" + TIMEZONE + "\" name=\"tzn\" maxlength=3> TIMEZONE</br></br>\
<input type=\"text\" value=\"" + mqtt_ip + "\" name=\"mqtt_ip\" maxlength=15> MQTT IP</br></br>\
<input type=\"text\" value=\"" + mqtt_port + "\" name=\"mqtt_port\" maxlength=5> MQTT PORT</br></br>\
<input type=\"text\" value=\"" + mqtt_auth + "\" name=\"mqtt_auth\" maxlength=32> MQTT USER</br></br>\
<input type=\"password\" value=\"" + mqtt_pass + "\" name=\"mqtt_pass\" maxlength=32> MQTT PWD</br></br>\
<input type=\"text\" value=\"" + mqtt_Temp + "\" name=\"mqtt_temp\" maxlength=64> MQTT Topic (temperature)</br></br>\
<input type=\"text\" value=\"" + mqtt_Hum + "\" name=\"mqtt_hum\" maxlength=64> MQTT Topic (humidity)</br></br>\
<input type=\"text\" value=\"" + mqtt_Press + "\" name=\"mqtt_press\" maxlength=64> MQTT Topic (pressure)</br></br>\
<input type=\"text\" value=\"" + mqtt_CO2 + "\" name=\"mqtt_co2\" maxlength=64> MQTT Topic (CO2)</br></br>\
<input type=SUBMIT value=\"Save\">\
</form>\
</body>\
</html>";

server.send ( 200, "text/html", str );
}

void handleOk(){
String webpage;
webpage = "<html>";
webpage += "<head><title>settings save </title><meta charset='UTF-8'>";
webpage += "<style>";
webpage += "body { font-family: Verdana; Color: #00979d;}";
webpage += "</style>";
webpage += "</head>";
webpage += "<body>";
String ssid_ap = server.arg("ssid");
String pass_ap = server.arg("pswd");
String TZN_ap = server.arg("tzn");
String mqtt_ip_ap = server.arg("mqtt_ip");
String mqtt_port_ap = server.arg("mqtt_port");
String mqtt_auth_ap = server.arg("mqtt_auth");
String mqtt_pass_ap = server.arg("mqtt_pass");
String mqtt_temp_ap = server.arg("mqtt_temp");
String mqtt_hum_ap = server.arg("mqtt_hum");
String mqtt_press_ap = server.arg("mqtt_press");
String mqtt_CO2_ap = server.arg("mqtt_co2");
String otaFlag_ap = server.arg("otaflag");
int tz;
String str = "";

str += webpage;
str += "<body>";
tz = TZN_ap.toInt();

(otaFlag_ap == "0") ? otaFlag = 0 : otaFlag = 1;

if( (tz > -12) && (tz < 12) ) TIMEZONE = tz;
mqtt_ip = mqtt_ip_ap;
mqtt_port = mqtt_port_ap;

mqtt_auth_ap.replace("%2F","/");
mqtt_auth = mqtt_auth_ap;

mqtt_pass_ap.replace("%2F","/");
mqtt_pass = mqtt_pass_ap;

mqtt_temp_ap.replace("%2F","/");
mqtt_Temp = mqtt_temp_ap;

mqtt_hum_ap.replace("%2F","/");
mqtt_Hum = mqtt_hum_ap;

mqtt_press_ap.replace("%2F","/");
mqtt_Press = mqtt_press_ap;

mqtt_CO2_ap.replace("%2F","/");
mqtt_CO2 = mqtt_CO2_ap;

ssid_ap.replace("%2F","/");
pass_ap.replace("%2F","/");

str +="Configuration saved in FS</br>\
<a href=\"/\">Return</a> to settings page</br>";
str += "</body></html>";
server.send ( 200, "text/html", str );

saveConfig();

if( (ssid_ap != String(ssid)) || (pass_ap != String(pass)) ){
ssid = ssid_ap;
pass = pass_ap;
saveConfig();
delay(1000);
ESP.restart();
delay(100);
}
if( otaFlag ) {
lcd.clear();
lcd.print("Rebooting...");
delay(1000);
ESP.restart();
delay(100);
}
}

void handleOTA() {
Serial.println("Starting OTA mode.");
Serial.printf("Sketch size: %u\n", ESP.getSketchSize());
Serial.printf("Free size: %u\n", ESP.getFreeSketchSpace());
MDNS.begin(host);
server.on("/", HTTP_GET, [](){
server.sendHeader("Connection", "close");
server.sendHeader("Access-Control-Allow-Origin", "*");
server.send(200, "text/html", otaServerIndex);
});
server.on("/update", HTTP_POST, [](){
server.sendHeader("Connection", "close");
server.sendHeader("Access-Control-Allow-Origin", "*");
server.send(200, "text/plain", (Update.hasError())?"FAIL":"OK");
setOtaFlag(0);
lcd.clear();
delay(100);
ESP.restart();
},[](){
HTTPUpload& upload = server.upload();
if(upload.status == UPLOAD_FILE_START){
//Serial.setDebugOutput(true);
WiFiUDP::stopAll();
Serial.printf("Update: %s\n", upload.filename.c_str());
otaCount=300;
uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
if(!Update.begin(maxSketchSpace)){//start with max available size
Update.printError(Serial);
}
} else if(upload.status == UPLOAD_FILE_WRITE){
if(Update.write(upload.buf, upload.currentSize) != upload.currentSize){
Update.printError(Serial);
}
} else if(upload.status == UPLOAD_FILE_END){
if(Update.end(true)){ //true to set the size to the current progress
Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
} else {
Update.printError(Serial);
}
Serial.setDebugOutput(false);
}
yield();
});
server.begin();
Serial.printf("Ready! Open http://%s.local in your browser\n", host);
MDNS.addService("http", "tcp", 80);
otaTickLoop.attach(1, otaCountown);
}
Спасибо за оперативность, а почему электролит не подойдет? Тантал же вроде только размером отличается, для смд.
 

DrDimedrol

✩✩✩✩✩✩✩
19 Окт 2020
8
7
а почему электролит не подойдет?
Думаю что подойдет, просто качественный тантал можно купить не дорого, и паять приятнее, и служит дольше чем непонятные нынешные электолиты, и выглядит "профессиональнее" :).
 

Aleksey79

✩✩✩✩✩✩✩
28 Апр 2020
23
5
подключил датчик перед разъемом питания ардуино, добавил ёмкостей на 3000мкФ- всё равно мигает :(
 

Aleksey79

✩✩✩✩✩✩✩
28 Апр 2020
23
5
Даже фигня была, вроде калибровка помогла.

Ни у кого дисплей не мигает с этим датчиком co2? У меня каждые 5 секунд, видимо при обновлении данных с него мигает. Пробовал разные бп, к пк подключать - не помогает.
как побороли мигание?
 

jk36

✩✩✩✩✩✩✩
13 Сен 2019
1
0
Друзья, надеюсь на вашу помощь с проектом метеостанции. Сделал некоторые измения кода, а именно перевёл величины давления в гПа, изменил названия дней недели в немецкий язык и переменил rain в немецкий Regen. Пришлось немного переместить всё это на дисплее. Обнаружил ошибку показании первой и второй клетки на первой строчке. При переходе времени на новую минуту с изображением всё нормально, после 20 -30 секунд названные клетки изчезают с дисплея до последующей новой минуте. Кто нибудь из Вас знает как изправить? Заранее благодарю. С прветом Герольф Кунде (Германия)
Это произошло из-за того, что Вы изменили текст в нижней строке. У меня то же получилось, когда я добавил Hg к mm. Исправил таки образом:

lcd.setCursor(0, 3);
lcd.print(String(dispPres) + " mmHg rain ");
lcd.print(F(" ")); //исправил ошибку: если добавили Hg в строке выше, то в кавычках убрать два пробела
lcd.setCursor(15, 3);
lcd.print(String(dispRain) + "%");
 

Ky6AHb

✩✩✩✩✩✩✩
13 Дек 2019
12
0
55
Привет, добавил звуковой модуль - кукушка и бой часов. И еще сенсорную кнопку для управления звуком: коротко - переключение типа звука, долго - включить/выключить звук. И немного подрихтовал для упрощения скетч. Звуки пришлось разбить по нескольким архивам - не пропускает форум. Они должны быт в одном директории mp3.
Повторил проект с MP3 модулем. НО...
Есть две проблемы:

1. При первом включении, при времени в полчаса один раз бой курантов играет, но после этого в остальных случаях наступления получаса не играет никогда.

файл functions_v5 строка 213 if (mins == 30 and mins != prev_mins) { // играем полчаса

2. При долгом нажатии кнопки управления звуком не проигрываются файлы о включении или выключении звука (и нет соответствующей надписи на экране ?), но смена режима звука происходит норм.

файл functions_v5 строка 166 Serial.println("кнопка удержана");
строка 169 mp3_play(501); // проигрываем файл выключения звука
строка 179 mp3_play(500); // проигрываем файл включения звука

необходимые файлы озвучки смены режимов звука лежат в целевой папке mp3
0500_sound_on_2c.mp3
0501_sound_off_2-5c.mp3


3. Мигание экрана при каждой активации датчика CO2 происходит, несмотря на параллельно подключенные по питанию 1500мкФх6,3в и неполярного 0,1мкФ конденсаторов.
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,192
1,281
Москва
строка 169 mp3_play(501); //
строка 179 mp3_play(500); //
А на карте реально есть 501 файл со звуками ?
не смотрел как с такой библиотекой, но вот с библиотекой dfrobot указывает номер файла по порядку записи на карту.

Для теста сделайте простой пример, где файлы будут проигрываться по номерам от 1 до сколько там у вас на карте файлов, с выводом номера в монитор порта и задержкой между проигрываниями секунда в 3-5. Ну и сделайте сравнение.
 

Ky6AHb

✩✩✩✩✩✩✩
13 Дек 2019
12
0
55
Нет, набор состоит из группы по часам для кукушки и группы по часам для курантов. Отдельно два файла на озвучку переключения режима со звуком и без звука. Все файлы проигрывает норм и для курантов и для кукушки, а вот режим не озвучивается, но переключает.
 

Вложения

bakson

✩✩✩✩✩✩✩
22 Авг 2020
15
7
@DrDimedrol,
Так то да, конечно интересно, вот только схему подключения еще увидеть.