Garage ShoutBox
Tylko zalogowani użytkownicy mogą wejść do czatu
lub Zarejestruj aby założyć posty i tematy.

Sterownik wentylatora cieczy w samochodzie

Witam ...
Dalej ciągnę tematykę samochodową ...
Jeżdżę samochodem , który jest pozbawiony wentylatora i zamiast tego jest zamontowane Wisko.
Takie rozwiązanie jest dobre o ile działa. Kiedy przestaje działać zaczynają się problemy i znaczne koszty.

Dlatego zdecydowałem się na pozbycie Wisko i zamontowanie tradycyjnego wentylatora oraz dorobienie
troszkę elektroniki sterującej pracą wentylatora.

O wentylatorze :
Wentylator dobrałem do wielkości chłodnicy i z zamontowanym w obudowie rezystorem rozruchowym.
Dzięki rezystorowi rozruchowemu nie ma efektu przygasania świateł podczas rozruchu wentylatora.
To podczas rozruchu wentylatora przez krótki czas płynie prąd zwarciowy i czasami bywa, że efektem
jest przygasanie świateł . To jest taki efekt mrugnięcia. Spada napięcie na akumulatorze i co daje właśnie taki efekt.
Aby temu zapobiec w pierwszej fazie rozruchowej warto podłączyć w szereg z wentylatorem do momentu
kiedy wentylator osiągnie pewną prędkość . Później już można przełączyć wentylator na pełną moc pomijając
rezystor. Uzyskałem to poprzez dwa przekaźniki samochodowe sterowane oczywiście z kontrolera temperatury.

Podłaczenie wentylatoraSchemat jest bardzo prosty i chyba nie wymaga wyjaśnień i właściwie to wszystko jeśli chodzi o podłączenie
samego wentylatora.

Sterownik :
Myślałem długo nad samym sterownikiem bo musi spełnić kilka warunków :
1. Powinien być niezawodny
3. Sterowalny  z możliwością programowania kilku wartości : temperatura załączenia, temperatura wyłączenia, czas załączenia rezystora

W końcu padło na wybur ESP8266 .
Daje mi to możliwość programowania nawet z telefonu, a w przypadku mojego samochodu nawet z ekranu
komputera pokładowego. Dlatego w samym programie zawarłem serwer www do którego można się odwołać
z każdego telefonu lub/i komputera pokładowego opartego na androidzie albo umożliwiającego wyświetlenie strony.

 

Spoiler

/* * Program napisal CyberDuck, 29.01.2021
* Zawiera serwer www i polaczenie do wybranej sieci WiFi
*
* http://10.10.11.120:400/?op=2&danaa=25&danab=27&danac=6 - zaladowanie ustawien i podanie statusu
* http://10.10.11.120:400/?op=1 - podanie statusu
*
*
*
*/

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>
#include <Adafruit_NeoPixel.h>
#include <OneWire.h>
#include <DallasTemperature.h>
ESP8266WebServer server(400); // Port na jakim ma dzialac serwer www

#define ONE_WIRE_BUS 0
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature DS18B20(&oneWire);
#define PINSTER 13 // pin sterujacy diodami RGB
#define PINWENTREZ 5 // przekaznik wlaczajacy wentylator przez rezystor
#define PINWENTYL 4 // przekaznik wlaczajacy wentylator

int tempMin, tempMax, czasRezys;

word dana1 = 0; // zmienna http
word dana2 = 0; // zmienna http
word dana3 = 0; // zmienna http
word dana4 = 0; // zmienna http
word opcja = 0; // opcja do rozpoznawania opcji
byte mac[6]; // przechowuje adres MAC
String macAddr = ""; // bedzie przechowywac w postaci String adress MAC
String KomText; // zmienna do przechowywania informacji zwrotnych
String IpAdressWysw;

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(2, PINSTER, NEO_GRB + NEO_KHZ800);

unsigned long sec = 0; // zmienna zawierajaca ilosc sekund jaka uplynela od startu
unsigned long secWentNas = 0; // nastawa kiedy ma sie wylaczyc wentylator
float TempI = 0;
float TempII = 0;

String ssid; // SSID sieci WiFi
String password; // domyslne haslo do sieci WiFi

void handleRoot() {
opcja = server.arg("op").toInt();
dana1 = server.arg("danaa").toInt();
dana2 = server.arg("danab").toInt();
dana3 = server.arg("danac").toInt();
dana4 = server.arg("danad").toInt();

if (opcja == 1) { // podanie statusu
daneDoStat();
}

if (opcja == 2) { // podanie danych do zapisu i wyswietlenie statusu

EEPROM.write(0, dana1);
EEPROM.write(1, dana2);
EEPROM.write(2, dana3);
EEPROM.commit();

tempMin = dana1;
tempMax = dana2;
czasRezys = dana3;

daneDoStat();
KomText += "|OK";
}

if (opcja == 3) { // restart
ESP.restart();
delay(1000);
}

if (opcja == 8) {
IpAdressWysw = WiFi.localIP().toString();
KomText = "<script language='JavaScript'>";
KomText += "parent.document.getElementById('temperI').innerHTML = '";
KomText += TempI;
KomText += "*C';";
KomText += "parent.document.getElementById('rssihtt').innerHTML = '";
KomText += WiFi.RSSI();
KomText += "';";
KomText += "</script>";

KomText += "<meta http-equiv='Refresh' content='5; url=http://";
KomText += IpAdressWysw;
KomText += ":400/?op=8'>";

}

if (opcja == 9) { // zmiana ssid i hasla
sec = millis() / 1000;

if (dana1 > 1 && dana2 > 1 && dana3 > 0 && dana2 > dana1) {
EEPROM.write(0, dana1);
EEPROM.write(1, dana2);
EEPROM.write(2, dana3);
EEPROM.commit();

tempMin = dana1;
tempMax = dana2;
czasRezys = dana3;
}

KomText = "<form autocomplete='off' action='' method='get'>";
KomText += "<input class='wpis' type='text' name='op' value='9'";
KomText += " style='display:none'>";
KomText += "<br>";
KomText += "<div class='myDiv'>";
KomText += "<table style='font-size:25px'>";
KomText += "<tr>";
KomText += "<td width='10px'><td>";
KomText += "<td width='300px'>Temp Min</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td><td>";
KomText += "<td>";
KomText += "<input class='wpis' type='text' name='danaa' value='";
KomText += tempMin;
KomText += "'>";
KomText += "</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td><td>";
KomText += "<td>Temp Max</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td><td>";
KomText += "<td>";
KomText += "<input class='wpis' type='text' name='danab' value='";
KomText += tempMax;
KomText += "'>";
KomText += "</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td><td>";
KomText += "<td>Czas Rezystora</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td><td>";
KomText += "<td>";
KomText += "<input class='wpis' type='text' name='danac' value='";
KomText += czasRezys;
KomText += "'>";
KomText += "</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td><td>";
KomText += "<td><br>Aktualna Temp : ";
KomText += "<span id='temperI'></span>";
KomText += "<br>RSSI : ";
KomText += "<span id='rssihtt'></span>";
KomText += "</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td><td>";
KomText += "<td>";
KomText += "<input class='wpis' type='submit' value='Zapisz' style='display:none;'>";
KomText += "</td>";
KomText += "</tr>";

KomText += "</table>";
KomText += "</div>";

KomText += "</form>";

KomText += "<iframe name='ramka' marginwidth='0' marginheight='0' align='top' border='0' frameborder='0' ";
KomText += "width='1px' height='1px' ";
KomText += "src='https://";
KomText += IpAdressWysw;
KomText += ":400/?op=8' scrolling='no'></iframe>";

KomText += "<style>";
KomText += "body {";
KomText += "background-image: url('https://i.ibb.co/N1pNVvz/tapSsang.png');";
KomText += "background-repeat: no-repeat;";
KomText += "background-position: center;";
KomText += "background-size: 90% 100%;";
KomText += "font-size: 50px;";
KomText += "color: #fff000;";
KomText += "}";

KomText += ".wpis {";
KomText += "font-size: 18px;";
KomText += "padding: 12px 12px;";
KomText += "margin: 8px 0;";
KomText += "display: inline-block;";
KomText += "border: 1px solid #ccc;";
KomText += "border-radius: 4px;";
KomText += "box-sizing: border-box;";
KomText += "font-weight: bold;";
KomText += "}";
KomText += ".myDiv {";
KomText += "padding: 50px 12px;";
KomText += "border: 5px outset brown;";
KomText += "text-align: center;";
KomText += "width: 350px;";
KomText += "margin: 10px 100px;";
KomText += "background-color: rgba(255, 10, 0, 0.3);";
KomText += "}";
KomText += "</style>";

delay(10);
}

char html[2000];

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

void handleNotFound() {
String message = "File Not Found\n\n";
message += "URI: ";
message += server.uri();
message += "\nMethod: ";
message += ( server.method() == HTTP_GET ) ? "GET" : "POST";
message += "\nArguments: ";
message += server.args();
message += "\n";

for ( uint8_t i = 0; i < server.args(); i++ ) {
message += " " + server.argName ( i ) + ": " + server.arg ( i ) + "\n";
}

server.send ( 404, "text/plain", message );
}

void setup() {
pinMode(PINWENTREZ, OUTPUT);
pinMode(PINWENTYL, OUTPUT);
digitalWrite(PINWENTREZ, 0);
digitalWrite(PINWENTYL, 0);

Serial.begin(115200);
pixels.begin();
EEPROM.begin(1024);
delay(100);

pixels.setPixelColor(0, 0, 0, 0);
pixels.setBrightness(0);
pixels.show(); // przesylam do diod

ssid = "CybDroid";
password = "gosc1111";

delay(10);

DS18B20.begin();
readEpromZmienne();
// -------------------------------------------

delay(200);

WiFiClient client;
WiFi.softAPdisconnect(true);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println(" ");
Serial.println("Laczenie do sieci WiFi :");
for (int polacz = 0; polacz <= 20; polacz++) {
if (WiFi.status() != WL_CONNECTED) {
pixels.setPixelColor(0, 0, 126, 255);
pixels.setBrightness(100);
pixels.show(); // przesylam do diod
delay(100);
pixels.setPixelColor(0, 255, 0, 0);
pixels.setBrightness(50);
pixels.show(); // przesylam do diod
Serial.print(".");
delay(100);
} else {
Serial.println();
Serial.print("Adres IP :");
Serial.println(WiFi.localIP());
IpAdressWysw = WiFi.localIP().toString();
Serial.print("MacAddres : ");
WiFi.macAddress(mac);
macAddr = String(mac[0], HEX);
macAddr += (":");
macAddr += String(mac[1],HEX);
macAddr += (":");
macAddr += String(mac[2],HEX);
macAddr += (":");
macAddr += String(mac[3],HEX);
macAddr += (":");
macAddr += String(mac[4],HEX);
macAddr += (":");
macAddr += String(mac[5],HEX);
Serial.println(macAddr);
Serial.print("RSSI : ");
Serial.println(WiFi.RSSI());
pixels.setPixelColor(0, 0, 126, 255);
pixels.setBrightness(50);
pixels.show(); // przesylam do diod
break;
}
}
ESP.wdtEnable(8000);

server.on ( "/", handleRoot );
server.on ( "/inline", []() {
server.send ( 200, "text/plain", "this works as well" );
} );
server.onNotFound ( handleNotFound );

server.begin();
WiFi.macAddress(mac);
macAddr = String(mac[0], HEX);
macAddr += (":");
macAddr += String(mac[1],HEX);
macAddr += (":");
macAddr += String(mac[2],HEX);
macAddr += (":");
macAddr += String(mac[3],HEX);
macAddr += (":");
macAddr += String(mac[4],HEX);
macAddr += (":");
macAddr += String(mac[5],HEX);
}

// Odczyt z pamieci EEPROM do zmiennych ustawien
void readEpromZmienne() {
tempMin = EEPROM.read(0); // temperatura minimalna chlodziwa - wylaczenie wentylatora
tempMax = EEPROM.read(1); // temperatura maxymalna chlodziwa - wlaczenie wentylatora
czasRezys = EEPROM.read(2); // czas przez jaki ma byc wlaczony rezystor zanim zalaczy sie zasilanie glowne w sek
}

/*
char *IPAddress::toCharArray()
{
static char szRet[20];
String str = String(_address.bytes[0]);
str += ".";
str += String(_address.bytes[1]);
str += ".";
str += String(_address.bytes[2]);
str += ".";
str += String(_address.bytes[3]);
str.toCharArray(szRet, 20);
}
*/
// przygotowanie danych dla statusu
void daneDoStat() {
sec = millis() / 1000;
KomText = TempI;
KomText += "|";
KomText += TempII;
KomText += "|";
KomText += tempMin;
KomText += "|";
KomText += tempMax;
KomText += "|";
KomText += czasRezys;
KomText += "|";
KomText += sec;
KomText += "|";
KomText += macAddr;
KomText += "|";
KomText += WiFi.RSSI();
}

// zalaczenie przekaznika do wlaczania monitora

void loop() {

DS18B20.requestTemperatures();
TempI = DS18B20.getTempCByIndex(0);
TempII = DS18B20.getTempCByIndex(1);
server.handleClient();
sec = millis() / 1000;
// rozruch wentylatora przez rezystor
if (TempI > tempMax && digitalRead(PINWENTREZ) == 0 && digitalRead(PINWENTYL) == 0) {
secWentNas = sec + czasRezys;
digitalWrite(PINWENTREZ,1);
}
// po ustalonym czasie wlaczenie wentylatora bez rezystora
if (secWentNas < sec && digitalRead(PINWENTREZ) == 1) {
digitalWrite(PINWENTYL,1);
delay(100);
digitalWrite(PINWENTREZ,0);
}
// jesli wentylator dziala i temperatura spadnie poiniezej ustalownej wartosci to wylaczenie wentylatora
if (TempI < tempMin && digitalRead(PINWENTYL) == 1) {
digitalWrite(PINWENTYL,0);
}

ESP.wdtFeed();
delay(50);

}

 

Program :
Do zmiennych :

ssid = "CybDroid";
password = "gosc1111";

wpisujemy dane tyczące się połączenia do naszego acesspointa utworzonego w telefonie.
Po wystartowaniu programu ESP będzie się łączyć do naszego telefonu.
Z poziomu telefonu można odczytać adres ESP i od tej pory można w normalnej przeglądarce otworzyć nasz panel :

Zrzut pulpitu telefonu

Obrazek w programie :
Załadowanie obrazka do ESP byłoby dość trudne chociaż nie niemożliwe, ale całą sprawę można sobie znacznie
ułatwić. Po stworzeniu obrazka do tła należy przesłać go na jakiś serwer hostingowy obrazków, a później w linii programu :

omText += "background-image: url('https://i.ibb.co/N1pNVvz/tapSsang.png');";

podajemy jego adres i już. Telefon sam ściągnie sobie grafikę do tła pod warunkiem posiadania połączenia do internetu.

Połączenia:
D1 i D2  ESP - to odpowiednio sterowanie przekaźnikami oczywiście poprzez jakieś mosfety:
Podlaczenie mosfetu do mikrokontrolera

Schemat połączenia też jest trywialny.
Pozostają czujniki temperatury i tutaj zastosowałem DS18B20. Bardzo popularne i łatwe do implementacji.
Zastosowałem dwa, które mierzą temperaturę w dwóch różnych miejscach. Podłączenie samych czujników można znaleźć
chociażby tutaj :
https://www.sensate.io/sensors/dallas-ds18b20

Ja podłączyłem je do D7 mikrokontrolera ESP.
Jest jeszcze podłączona do układu dioda RGB, ale nie trzeba jej podłączać. Sygnalizuje mi jedynie stan układu którego i tak
nie będzie widać pod maską samochodu.

Opis działania:
Układ jest podłączony przez mini przetwortnicę do zasilania pierwszego stopnia stacyjki. Znaczy to tyle, że wystarczy włożyć
kluczyk i przekręcić na pierwszy stopień. To ten jeszcze przed zapłonem.
Po włączeniu zasilania startuje program i w pierwszej fazie próbuje się połączyć do do ustalonego Wifi w programie.
Oczywiście nie jest to konieczne do samego działania i sterowania wentylatorem.
Połączenie WiFi pozwala jedynie na wywołanie strony i wyregulowanie wartości sterowania.
Stronkę można wywołać poprzez link :

http://adres_Esp_odczytany_z_telefonu:400/?op=9

Zgłosi się strona której zrzut zamieściłem wcześniej.

Po podłączeniu lub nie program odczytuje wartości nastaw z EEPROM ESP.
Następnie przechodzi do pętli głównej i zaczyna reagować na zmiany temperatury.
Jeśli temperatura cieczy przekroczy wartość maxymalną to zostanie włączony przekaźnik NR1 na czas określony w ustawieniach jako
" Czas Rezystora". Po tym czasie załączy się przekaźnik NR2 i wyłączy po 10ms przekaźnik NR1.
Jeśli temperatura opadnie poniżej wartości minimalnej ustawionej przekaźnik NR2 zostanie rozłączony .
Program przetestowałem i działa bez problemów.

Gdyby w czasie działania w polu widzenia WiFi znalazł się zadeklarowany Acesspoint z telefonu to układ sam się do niego podłączy
bez potrzeby jego restartowania.

Jest w nim zawarte nieco więcej bo w odpowiedni sposób można dokonać zdalnie restartu całego układu wywołując adres
sterownika z op=3.
op=2 pozwala na zaprogramowanie wartości poza strona podając status w postaci :

25.31|23.31|25|27|6|30478|48:3f:da:6c:29:9f|-58

gdzie kolejne wartości oddzielone znakiem | to temperatura czujnik NR1 (tego regulacyjnego), wartość czujnika NR2, temperatura minimalna nastawiona,
temperatura maxymalna nastawiona, czas właczenia rezystora nastawiona, czas jaki upłynął od włączenia ESP, mac adress ESP w sieci WiFi, oraz RSSI czyli
siła sygnału sieci WiFi. Czasami stosuję taki zapis bo wystarczy w php explode albo w javascript split i już mam dane do prezentacji w dowolnym
miejscu gotowe w osobnych komórkach tabeli.

op=1 to podanie wyłącznie statusu.

Koniec:
Chętnie pomogę jeśli ktoś będzie zainteresowany takim niekonwencjonalnym rozwiązaniem w implementacji układu.
W razie zmian poinformuję i zamieszczę ewentualne zmiany w programie, które pewnie i tak nastąpią bo już teraz mam chęć
dodania statusu samych przekażników.

 

 

Jestem winien Wam schemat połączeń. Moduł ESP8266 jest zasilany z przetwornicy mini zakupionej na Allegro.
Dość często wykorzystuję te przetwornice i sprawują się bardzo dobrze :
https://allegro.pl/oferta/przetwornica-step-down-mini360-arduino-9215972351?snapshot=MjAyMS0wMS0wNFQyMTo1NzozNi45OTFaO2J1eWVyOzMyM2JjYzZlYTQyOTQ5Y2U5Mjk3NzI3MGQ0MDM0MGQ2YWIxNzI3MGE1YTA3Y2NlNGFiMWUzZjA5ODI2M2Y4NmU%3D

Na wyjściu przetwornicy należy wyregulować napięcie na około 5,10V i podłączyć do wejścia modułu +5V Esp :

Schemat ideowy połączeń :

Schemat ideowy sterownika wentylatora w samochodzie

Przekaźniki nie muszą być jakoś bardzo wydajne prądowo bo w pierwszej fazie kiedy zostaje załączony
przekaźnik zasilający wentylator przez rezystor to cały prąd na siebie bierze własnie szeregowy rezystor.
Kiedy już silnik wentylatora się rozpędzi zostaje załączony drugi przekaźnik i już nie popłynie prąd zwarciowy/rozruchowy
wentylatora. Można zastosować 20 amperowe przekaźniki mini typu samochodowego.
P1 - zacisk  + zasilania wentylatora.
P2 - można podłączyć do zapłonu samochodu. Czyli tam gdzie się pojawia +12V jeśli zapłon jest włączony.
W przypadku wykorzystania tego wejścia samą przetwornicę zasilającą moduł podłączamy do pierwszego stopnia kluczyka. Czyli
tam gdzie się pojawia +12V jeśli się przekręci kluczyk na pierwszy stopień (radiowy). Wtedy jeśli przed wyłączeniem silnika
wentylator się kręcił to będzie jeszcze po wyłączeniu zapłonu kręcić się przez jedną minutę.
Jeśli nie chcemy wykorzystywać tej funkcji to do zapłonu należy podłączyć zacisk P2 i zasilanie modułu.
IC1 i IC2 to są popularne czujniki DS18b20. Ja je włożyłem do metalowej gilzy zatapiając w wysokotemperaturową pastę
silikonową dalej łącząc gilzę z przewodem podwójną izolacją termokurczliwą.
Jeśli nie zamontuje się IC2 to nie będzie on brany w żaden sposób pod uwagę w programie, a dokładniej nie będzie wyświetlana
jego wartość na stronce. Można dodać dodatkowy czujnik umieszczając go jedynie w celach informacyjnych. W ten sposób można
mierzyć temperaturę na wyjściu z silnika i dla przykładu za chłodnicą.
LEDRGB - to popularna dioda NeoPixel.
R2- 20 Kohm
R3 - 4,7 Kohm

No i sam program który znacznie zmieniłem i dodałem parę zabezpieczeń i ustawień.
U góry strony dodałem dwa guziki. STR to poprostu odświeżenie strony. Guzik AUTO po naciśnięciu zmienia
się kolejno na : AUTO -> ON -> OFF -> ... AUTO i oznacza dokładnie to jak w oznaczeniach. Czyli jeśli przyciśnie się AUTO po zmianie na ON
można w ten sposób wymusić włączenie się wentylatora na max 1 minutę. Po tym czasie urządzenie samo przejdzie w stan AUTO. Jeśli przyciśnie
się kolejny raz ten przycisk to zmieni się na OFF i wentylator zostanie na stałe wyłączony. AUTO to autoregulacja.
Dodałem też aktualny status wentylatora.  Jak pisałem wcześniej dioda RGB jedynie stanowi informację tyczącą się stanu całego sterownika.
Jeśli do niczego się nam nie przyda można jej nie montować . Po włączeniu się urządzenia dioda miga kolorem niebieskim czyli urządzenie
próbuje się połączyć do WiFi w telefonie lub komputerze pokładowym. Jeśli się połączy zapala się na niebiesko. W przeciwnym wypadku na czerwono.
Po czasie 30 sekund gaśnie całkowicie i zaczyna migać co 10 sekund  na jedną sekundę z małą jasnością.
Moduł nawet jeśli po włączeniu zasilania nie podłączył się do WiFI bo powiedzmy nie było znanego WiFI w zasięgu to podłączy się jeśli
tylko dane znane WiFi pojawi się w polu widzenia sterownika. Nie trzeba się więc martwić o to żeby koniecznie WiFi w naszym telefonie
było włączone przed włączeniem zasilania modułu.

Teraz tabelka sterownika wygląda tak :

Zrzut w pulpitu

Program :

Spoiler

/* * Program napisal CyberDuck, 29.01.2021
* Zawiera serwer www i polaczenie do wybranej sieci WiFi
*
* http://10.10.11.120:400/?op=2&danaa=25&danab=27&danac=6 - zaladowanie ustawien i podanie statusu
* http://10.10.11.120:400/?op=1 - podanie statusu
*
*
*
*/

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>
#include <Adafruit_NeoPixel.h>
#include <OneWire.h>
#include <DallasTemperature.h>
ESP8266WebServer server(400); // Port na jakim ma dzialac serwer www

#define ONE_WIRE_BUS 0 // D3
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature DS18B20(&oneWire);
#define PINSTER 13 // D7 pin sterujacy diodami RGB
#define PINWENTREZ 5 // D1 przekaznik wlaczajacy wentylator przez rezystor
#define PINWENTYL 4 // D2 przekaznik wlaczajacy wentylator
#define WEJZAPLON A0 // A0 wejscie sterujace maxymalnym czasem trwania wlaczenia wentylatora podlaczyc do zaplonu

int tempMin, tempMax, czasRezys;

word dana1 = 0; // zmienna http
word dana2 = 0; // zmienna http
word dana3 = 0; // zmienna http
word dana4 = 0; // zmienna http
word opcja = 0; // opcja do rozpoznawania opcji
byte mac[6]; // przechowuje adres MAC
String macAddr = ""; // bedzie przechowywac w postaci String adress MAC
String KomText; // zmienna do przechowywania informacji zwrotnych
String IpAdressWysw;
int autoSter = 3;
int wartoscAO = 0;
int tWlaczPRez = 0;
String dodInfo = "";

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(2, PINSTER, NEO_GRB + NEO_KHZ800);

unsigned long sec = 0; // zmienna zawierajaca ilosc sekund jaka uplynela od startu
unsigned long secWentNas = 0; // nastawa kiedy ma sie wylaczyc wentylator
unsigned long secWentWyl = 10; // nastawa po jakim czasie ma sie wylaczyc wentylator jesli byl wlaczony po wylaczeniu zaplonu
unsigned long TikTak = sec; // w petli loop roznica miedzy sec i TikTak oznacza ze juz uplynela wlasnie kolejna sekunda
int PolaczTak = 0; // czy jest polaczenie
unsigned long tWylDiod = 30; // czas o jakim trzeba wylaczyc diode RGB
int DiodWl = 1;

float TempI = 0;
float TempII = 0;

String ssid; // SSID sieci WiFi
String password; // domyslne haslo do sieci WiFi

void handleRoot() {
opcja = server.arg("op").toInt();
dana1 = server.arg("danaa").toInt();
dana2 = server.arg("danab").toInt();
dana3 = server.arg("danac").toInt();
dana4 = server.arg("danad").toInt();

if (opcja == 1) { // podanie statusu
daneDoStat();
}

if (opcja == 2) { // podanie danych do zapisu i wyswietlenie statusu

EEPROM.write(0, dana1);
EEPROM.write(1, dana2);
EEPROM.write(2, dana3);
EEPROM.commit();

tempMin = dana1;
tempMax = dana2;
czasRezys = dana3;

daneDoStat();
KomText += "|OK";
}

if (opcja == 3) { // restart
KomText = "RESTART";
ESP.restart();
delay(1000);
}

// ramka do strony
if (opcja == 8) {
IpAdressWysw = WiFi.localIP().toString();
KomText = "<script language='JavaScript'>";
KomText += "parent.document.getElementById('temperI').innerHTML = '";
KomText += TempI;
KomText += "';";
KomText += "parent.document.getElementById('rssihtt').innerHTML = '";
KomText += WiFi.RSSI();
KomText += "';";
if (digitalRead(PINWENTYL) == 0 && digitalRead(PINWENTREZ) == 0) {
KomText += "parent.document.getElementById('statWent').innerHTML = ' ☣';";
} else {
KomText += "parent.document.getElementById('statWent').innerHTML = ' ☢';";
}
if (TempII != -127) {
KomText += "parent.document.getElementById('tempII').innerHTML = '";
KomText += TempII;
KomText += "';";
}

KomText += dodInfo;
KomText += "</script>";

KomText += "<meta http-equiv='Refresh' content='3; url=http://";
KomText += IpAdressWysw;
KomText += ":400/?op=8'>";

dodInfo = "";
}

// wywolanie strony
if (opcja == 9) {

if (dana1 > 1 && dana2 > 1 && dana3 > 0 && dana2 > dana1) {
EEPROM.write(0, dana1);
EEPROM.write(1, dana2);
EEPROM.write(2, dana3);
EEPROM.commit();

tempMin = dana1;
tempMax = dana2;
czasRezys = dana3;
}

KomText = "<form autocomplete='off' action='' method='get'>";
KomText += "<input class='wpis' type='text' name='op' value='9' style='display:none'>";
KomText += "<br>";
KomText += "<div class='myDiv'>";
KomText += "<table style='font-size:25px'>";
KomText += "<tr>";
KomText += "<td width='10px'><td>";
KomText += "<td width='300px'><div align='right'><a href='?op=9'>STR</a>";
KomText += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
KomText += "<span id='dodInfo'>";
if (dana4 > 0) {
autoSter = dana4;
}
if (autoSter == 3) {
KomText += "<a href='?op=9&danad=1'>AUTO</a>";
}
if (autoSter == 1) {
KomText += "<a href='?op=9&danad=2'>ON</a>";
}
if (autoSter == 2) {
KomText += "<a href='?op=9&danad=3'>OFF</a>";
}
KomText += "</span></div>Temp Min</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td><td>";
KomText += "<td>";
KomText += "<input class='wpis' type='text' name='danaa' value='";
KomText += tempMin;
KomText += "'>";
KomText += "</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td><td>";
KomText += "<td>Temp Max</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td><td>";
KomText += "<td>";
KomText += "<input class='wpis' type='text' name='danab' value='";
KomText += tempMax;
KomText += "'>";
KomText += "</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td><td>";
KomText += "<td>Czas Rezystora</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td><td>";
KomText += "<td>";
KomText += "<input class='wpis' type='text' name='danac' value='";
KomText += czasRezys;
KomText += "'>";
KomText += "</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td><td>";
KomText += "<td><br>Aktualna Temp : ";
KomText += "<span id='temperI'></span> ℃";
KomText += "<br>Status Went : ";
KomText += "<span id='statWent'></span>";
KomText += "<br>RSSI : ";
KomText += "<span id='rssihtt'></span>&nbsp;&nbsp;";
if (TempII != -127) {
KomText += "Cz 2 : <span id='tempII'></span> ℃";
}
KomText += "</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td><td>";
KomText += "<td>";
KomText += "<input class='wpis' type='submit' value='Zapisz' style='display:none;'><br>";
KomText += "</td>";
KomText += "</tr>";

KomText += "</table>";
KomText += "</div>";

KomText += "</form>";

KomText += "<iframe name='ramka' marginwidth='0' marginheight='0' align='top' border='0' frameborder='0' ";
KomText += "width='1px' height='1px' ";
KomText += "src='https://";
KomText += IpAdressWysw;
KomText += ":400/?op=8' scrolling='no'></iframe>";

KomText += "<style>";
KomText += "body {";
KomText += "background-image: url('https://i.ibb.co/N1pNVvz/tapSsang.png');";
KomText += "background-repeat: no-repeat;";
KomText += "background-position: center;";
KomText += "background-size: 90% 100%;";
KomText += "font-size: 50px;";
KomText += "color: #fff000;";
KomText += "}";

KomText += ".wpis {";
KomText += "font-size: 18px;";
KomText += "padding: 12px 12px;";
KomText += "margin: 8px 0;";
KomText += "display: inline-block;";
KomText += "border: 1px solid #ccc;";
KomText += "border-radius: 4px;";
KomText += "box-sizing: border-box;";
KomText += "font-weight: bold;";
KomText += "}";
KomText += ".myDiv {";
KomText += "padding: 1px 12px;";
KomText += "border: 5px outset brown;";
KomText += "text-align: center;";
KomText += "width: 350px;";
KomText += "margin: 10px 100px;";
KomText += "background-color: rgba(255, 10, 0, 0.3);";
KomText += "}";
KomText += "</style>";

delay(10);
}

char html[2000];
server.send ( 200, "text/html", KomText );
KomText = "";
}

void handleNotFound() {
String message = "File Not Found\n\n";
message += "URI: ";
message += server.uri();
message += "\nMethod: ";
message += ( server.method() == HTTP_GET ) ? "GET" : "POST";
message += "\nArguments: ";
message += server.args();
message += "\n";

for ( uint8_t i = 0; i < server.args(); i++ ) {
message += " " + server.argName ( i ) + ": " + server.arg ( i ) + "\n";
}

server.send ( 404, "text/plain", message );
}

void setup() {
pinMode(PINWENTREZ, OUTPUT);
pinMode(PINWENTYL, OUTPUT);
// pinMode(WEJZAPLON, INPUT_PULLUP);
digitalWrite(PINWENTREZ, 0);
digitalWrite(PINWENTYL, 0);

Serial.begin(115200);
pixels.begin();
EEPROM.begin(1024);
delay(100);

pixels.setPixelColor(0, 0, 0, 0);
pixels.setBrightness(0);
pixels.show(); // przesylam do diod

ssid = "CybDroid";
password = "gosc1111";

delay(10);

DS18B20.begin();
readEpromZmienne();
// -------------------------------------------

delay(200);

WiFiClient client;
WiFi.softAPdisconnect(true);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println(" ");
Serial.println("Laczenie do sieci WiFi :");
for (int polacz = 0; polacz <= 20; polacz++) {
if (WiFi.status() != WL_CONNECTED) {
// brak polaczenia
pixels.setPixelColor(0, 0, 126, 255);
pixels.setBrightness(100);
pixels.show(); // przesylam do diod
delay(100);
pixels.setPixelColor(0, 255, 0, 0);
pixels.setBrightness(50);
pixels.show(); // przesylam do diod
Serial.print(".");
delay(100);
PolaczTak = 0;
} else {
// polaczono do wifi
Serial.println();
Serial.print("Adres IP :");
Serial.println(WiFi.localIP());
IpAdressWysw = WiFi.localIP().toString();
Serial.print("MacAddres : ");
WiFi.macAddress(mac);
macAddr = String(mac[0], HEX);
macAddr += (":");
macAddr += String(mac[1],HEX);
macAddr += (":");
macAddr += String(mac[2],HEX);
macAddr += (":");
macAddr += String(mac[3],HEX);
macAddr += (":");
macAddr += String(mac[4],HEX);
macAddr += (":");
macAddr += String(mac[5],HEX);
Serial.println(macAddr);
Serial.print("RSSI : ");
Serial.println(WiFi.RSSI());
pixels.setPixelColor(0, 0, 126, 255);
pixels.setBrightness(20);
pixels.show(); // przesylam do diod
PolaczTak = 1;
break;
}
}
ESP.wdtEnable(8000);

server.on ( "/", handleRoot );
server.on ( "/inline", []() {
server.send ( 200, "text/plain", "this works as well" );
} );
server.onNotFound ( handleNotFound );

server.begin();
WiFi.macAddress(mac);
macAddr = String(mac[0], HEX);
macAddr += (":");
macAddr += String(mac[1],HEX);
macAddr += (":");
macAddr += String(mac[2],HEX);
macAddr += (":");
macAddr += String(mac[3],HEX);
macAddr += (":");
macAddr += String(mac[4],HEX);
macAddr += (":");
macAddr += String(mac[5],HEX);
}

// Odczyt z pamieci EEPROM do zmiennych ustawien
void readEpromZmienne() {
tempMin = EEPROM.read(0); // temperatura minimalna chlodziwa - wylaczenie wentylatora
tempMax = EEPROM.read(1); // temperatura maxymalna chlodziwa - wlaczenie wentylatora
czasRezys = EEPROM.read(2); // czas przez jaki ma byc wlaczony rezystor zanim zalaczy sie zasilanie glowne w sek
}

// przygotowanie danych dla statusu
void daneDoStat() {
sec = millis() / 1000;
KomText = TempI;
KomText += "|";
KomText += TempII;
KomText += "|";
KomText += tempMin;
KomText += "|";
KomText += tempMax;
KomText += "|";
KomText += czasRezys;
KomText += "|";
KomText += sec;
KomText += "|";
KomText += macAddr;
KomText += "|";
KomText += WiFi.RSSI();
}

// zalaczenie przekaznika do wlaczania monitora

void loop() {
sec = millis() / 1000;
DS18B20.requestTemperatures();
TempI = DS18B20.getTempCByIndex(0);
TempII = DS18B20.getTempCByIndex(1);
server.handleClient();

wartoscAO = analogRead(WEJZAPLON);

// sprawdzenie czy jest wlaczony zaplon, i jesli jest wlaczony to nastawa wylaczenia wentylatora po 60 sek.
if (wartoscAO > 500) { // wartosc powyzej 500 oznacza ze jest wlaczony zaplon
secWentWyl = sec + 60;
}

if (autoSter == 3 && secWentWyl > sec) {

// rozruch wentylatora przez rezystor
if (TempI > tempMax && digitalRead(PINWENTREZ) == 0 && digitalRead(PINWENTYL) == 0) {
secWentNas = sec + czasRezys;
digitalWrite(PINWENTREZ,1);
}
// po ustalonym czasie wlaczenie wentylatora bez rezystora
if (secWentNas < sec && digitalRead(PINWENTREZ) == 1) {
digitalWrite(PINWENTYL,1);
delay(100);
digitalWrite(PINWENTREZ,0);
}
// jesli wentylator dziala i temperatura spadnie poiniezej ustalownej wartosci to wylaczenie wentylatora
if (TempI < tempMin && digitalRead(PINWENTYL) == 1) {
digitalWrite(PINWENTYL,0);
}
} else {
if (autoSter == 1 && digitalRead(PINWENTYL) == 0) {
digitalWrite(PINWENTYL,1);
secWentWyl = sec + 60;
}
if (autoSter == 2 && digitalRead(PINWENTYL) == 1) {
digitalWrite(PINWENTYL,0);
secWentWyl = sec + 60;
}
}

// sprawdzenie czy jest (wlaczony wentylator i jesli czas pracy przekroczyl czas wlaczenia wentylatora) to wylaczyc wentylator
if (secWentWyl < sec && digitalRead(PINWENTYL) == 1) {
digitalWrite(PINWENTYL,0);
autoSter = 3;
dodInfo = "parent.document.getElementById('dodInfo').innerHTML = 'AUTO';";
}

// Serial.println(wartoscAO);
ESP.wdtFeed();

// sprawdzenie czy jest wlaczony przekaznik rezystora powyzej 20 sekund
if (digitalRead(PINWENTREZ) == 0) {
tWlaczPRez = 0;
}
if (digitalRead(PINWENTREZ) == 1 && sec != TikTak) {
tWlaczPRez++;
}
if (tWlaczPRez > 20) {
digitalWrite(PINWENTREZ, 0);
}

if (WiFi.status() != WL_CONNECTED) { // sprawdzenie czy jest polaczenie
PolaczTak = 0;
} else {
PolaczTak = 1;
IpAdressWysw = WiFi.localIP().toString();
}

if (sec > tWylDiod && DiodWl == 1) {
pixels.setPixelColor(0, 0, 0, 0);
pixels.setBrightness(0);
pixels.show();
tWylDiod = sec + 10;
DiodWl = 0;
}

if (sec > tWylDiod && DiodWl == 0) {
pixels.setBrightness(20);
pixels.setPixelColor(0, 0, 126, 255);
pixels.show();
tWylDiod = sec + 1;
DiodWl = 1;
}

// Serial.println(sec);

TikTak = sec; // zostawic na koncu petli loop. Roznica miedzy tymi zmiennymi oznacza, ze uplynela kolejna sekunda.
}

 

 

No i jak to bywa w projektach oto finalna wersja schematu :

Schemat 3

Dodałem parę rezystorów. Szczególnie przy mosfetach. Podczas startu układu w poprzedniej wersji powstawał nieprzyjemny efekt
szybkiego włączenia i wyłączenia przekaźników. Powstawał bo zanim program wystartuje to wyjścia utrzymują się w stanie nieokreślonym.
Do tego czasu na mosfetach przy dużym wzmocnieniu bramki na źródle utrzymuje się w stanie nasycenia i przekaźniki na moment zostają
załączone. Po starcie mikrokontrolera linie te zostają ustalone na  wyjście i logicznie na 0 czyli masa. Przy takim potencjale
mosfety przechodzą w stan wysokiej impedancji , a same przekaźniki są rozłączone. Aby temu zapobiec od samego startu/podłączenia zasilania
dzięki podłączonym rezystorom mosfety od razu przechodzą w stan wysokiej impedancji. Później już zależy wszystko od linii mikrokontrolera i jego
programu.
Następną zmianą to przekaźnik podtrzymujący zasilanie i dioda prostownicza. Ma to na celu podtrzymanie zasilania na określony czas
po wyłączenia zapłonu. Zacisk P3 i P2 można połączyć z sobą i dalej do zapłonu samochodu. W ten sposób jeśli zostanie załączony zapłon zostanie poprzez
diodę D1 podane zasilanie na układ. Program po starcie włączy przekaźnik i załączy stałe zasilanie z zacisku P4 który jest podłączony do stałego zasilania.
Dla przykładu z +12 V akumulatora oczywiście przez bezpiecznik. Po wyłączeniu zapłonu to przez ile jeszcze będzie działać układ będzie zależeć już wyłącznie
od programu. Ustaliłem ten czas w programie na 2 minuty.

A oto program finalny, który steruje całością :

Spoiler

/* * Program napisal CyberDuck, 29.01.2021
* Zawiera serwer www i polaczenie do wybranej sieci WiFi
*
* http://10.10.11.120:400/?op=2&danaa=25&danab=27&danac=6 - zaladowanie ustawien i podanie statusu
* http://10.10.11.120:400/?op=1 - podanie statusu
*
*
*
*/

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>
#include <Adafruit_NeoPixel.h>
#include <OneWire.h>
#include <DallasTemperature.h>
ESP8266WebServer server(400); // Port na jakim ma dzialac serwer www

#define ONE_WIRE_BUS 0 // D3
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature DS18B20(&oneWire);
#define PINSTER 13 // D7 pin sterujacy diodami RGB
#define PINWENTREZ 5 // D1 przekaznik wlaczajacy wentylator przez rezystor
#define PINWENTYL 4 // D2 przekaznik wlaczajacy wentylator
#define WEJZAPLON A0 // A0 wejscie sterujace maxymalnym czasem trwania wlaczenia wentylatora podlaczyc do zaplonu
#define SAMOPODTRZ 14 // D5 samopodtrzymanie zasilania

int tempMin, tempMax, czasRezys;

word dana1 = 0; // zmienna http
word dana2 = 0; // zmienna http
word dana3 = 0; // zmienna http
word dana4 = 0; // zmienna http
word opcja = 0; // opcja do rozpoznawania opcji
byte mac[6]; // przechowuje adres MAC
String macAddr = ""; // bedzie przechowywac w postaci String adress MAC
String KomText; // zmienna do przechowywania informacji zwrotnych
String IpAdressWysw;
int autoSter = 3;
int wartoscAO = 0;
int tWlaczPRez = 0;
String dodInfo = "";
unsigned long tSAMOPODTRZ = 30; // kiedy ma sie wylaczyc samopodtrzymanie przekaznika samopotrzymania
int tPODTRZZASIL = 600; // ile nalezy potrzymac zasilanie po wylaczeniu zaplonu

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(2, PINSTER, NEO_GRB + NEO_KHZ800);

unsigned long sec = 0; // zmienna zawierajaca ilosc sekund jaka uplynela od startu
unsigned long secWentNas = 0; // nastawa kiedy ma sie wylaczyc wentylator
unsigned long secWentWyl = 10; // nastawa po jakim czasie ma sie wylaczyc wentylator jesli byl wlaczony po wylaczeniu zaplonu
unsigned long TikTak = sec; // w petli loop roznica miedzy sec i TikTak oznacza ze juz uplynela wlasnie kolejna sekunda
int PolaczTak = 0; // czy jest polaczenie
unsigned long tWylDiod = 30; // czas o jakim trzeba wylaczyc diode RGB
int DiodWl = 1;

float TempI = 0;
float TempII = 0;

String ssid; // SSID sieci WiFi
String password; // domyslne haslo do sieci WiFi

void handleRoot() {
opcja = server.arg("op").toInt();
dana1 = server.arg("danaa").toInt();
dana2 = server.arg("danab").toInt();
dana3 = server.arg("danac").toInt();
dana4 = server.arg("danad").toInt();

if (opcja == 1) { // podanie statusu
daneDoStat();
}

if (opcja == 2) { // podanie danych do zapisu i wyswietlenie statusu

EEPROM.write(0, dana1);
EEPROM.write(1, dana2);
EEPROM.write(2, dana3);
EEPROM.commit();

tempMin = dana1;
tempMax = dana2;
czasRezys = dana3;

daneDoStat();
KomText += "|OK";
}

if (opcja == 3) { // restart
KomText = "RESTART";
ESP.restart();
delay(1000);
}

// ramka do strony
if (opcja == 8) {
IpAdressWysw = WiFi.localIP().toString();
KomText = "<script language='JavaScript'>";
KomText += "parent.document.getElementById('temperI').innerHTML = '";
KomText += TempI;
KomText += "';";
KomText += "parent.document.getElementById('rssihtt').innerHTML = '";
KomText += WiFi.RSSI();
KomText += "';";
if (digitalRead(PINWENTYL) == 0 && digitalRead(PINWENTREZ) == 0) {
KomText += "parent.document.getElementById('statWent').innerHTML = ' ☣';";
} else {
KomText += "parent.document.getElementById('statWent').innerHTML = ' ☢';";
}
if (TempII != -127) {
KomText += "parent.document.getElementById('tempII').innerHTML = '";
KomText += TempII;
KomText += "';";
}

KomText += dodInfo;
KomText += "</script>";

KomText += "<meta http-equiv='Refresh' content='3; url=http://";
KomText += IpAdressWysw;
KomText += ":400/?op=8'>";

dodInfo = "";
}

// wywolanie strony
if (opcja == 9) {

if (dana1 > 1 && dana2 > 1 && dana3 > 0 && dana2 > dana1) {
EEPROM.write(0, dana1);
EEPROM.write(1, dana2);
EEPROM.write(2, dana3);
EEPROM.commit();

tempMin = dana1;
tempMax = dana2;
czasRezys = dana3;
}

KomText = "<form autocomplete='off' action='' method='get'>";
KomText += "<input class='wpis' type='text' name='op' value='9' style='display:none'>";
KomText += "<br>";
KomText += "<div class='myDiv'>";
KomText += "<table style='font-size:25px'>";
KomText += "<tr>";
KomText += "<td width='10px'><td>";
KomText += "<td width='300px'><div align='right'>";
KomText += "<a style='text-decoration: none; cursor:pointer; color: cyan;' href='?op=9'>STR</a>";
KomText += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
KomText += "<span id='dodInfo'>";
if (dana4 > 0) {
autoSter = dana4;
}
if (autoSter == 3) {
KomText += "<a style='text-decoration: none; cursor:pointer; color: cyan;' href='?op=9&danad=1'>AUTO</a>";
}
if (autoSter == 1) {
KomText += "<a style='text-decoration: none; cursor:pointer; color: cyan;' href='?op=9&danad=2'>ON</a>";
}
if (autoSter == 2) {
KomText += "<a style='text-decoration: none; cursor:pointer; color: cyan;' href='?op=9&danad=3'>OFF</a>";
}
KomText += "</span></div>Temp Min</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td><td>";
KomText += "<td>";
KomText += "<input class='wpis' type='text' name='danaa' value='";
KomText += tempMin;
KomText += "'>";
KomText += "</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td><td>";
KomText += "<td>Temp Max</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td><td>";
KomText += "<td>";
KomText += "<input class='wpis' type='text' name='danab' value='";
KomText += tempMax;
KomText += "'>";
KomText += "</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td><td>";
KomText += "<td>Czas Rezystora</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td><td>";
KomText += "<td>";
KomText += "<input class='wpis' type='text' name='danac' value='";
KomText += czasRezys;
KomText += "'>";
KomText += "</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td><td>";
KomText += "<td><br>Aktualna Temp : ";
KomText += "<span id='temperI'></span> ℃";
KomText += "<br>Status Went : ";
KomText += "<span id='statWent'></span>";
KomText += "<br>RSSI : ";
KomText += "<span id='rssihtt'></span>&nbsp;&nbsp;";
if (TempII != -127) {
KomText += "Cz 2 : <span id='tempII'></span> ℃";
}
KomText += "</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td><td>";
KomText += "<td>";
KomText += "<input class='wpis' type='submit' value='Zapisz' style='display:none;'><br>";
KomText += "</td>";
KomText += "</tr>";

KomText += "</table>";
KomText += "</div>";

KomText += "</form>";

KomText += "<iframe name='ramka' marginwidth='0' marginheight='0' align='top' border='0' frameborder='0' ";
KomText += "width='1px' height='1px' ";
KomText += "src='https://";
KomText += IpAdressWysw;
KomText += ":400/?op=8' scrolling='no'></iframe>";

KomText += "<style>";
KomText += "body {";
KomText += "background-image: url('https://i.ibb.co/N1pNVvz/tapSsang.png');";
KomText += "background-repeat: no-repeat;";
KomText += "background-position: center;";
KomText += "background-size: 90% 100%;";
KomText += "font-size: 50px;";
KomText += "color: #fff000;";
KomText += "}";

KomText += ".wpis {";
KomText += "font-size: 18px;";
KomText += "padding: 12px 12px;";
KomText += "margin: 8px 0;";
KomText += "display: inline-block;";
KomText += "border: 1px solid #ccc;";
KomText += "border-radius: 4px;";
KomText += "box-sizing: border-box;";
KomText += "font-weight: bold;";
KomText += "}";
KomText += ".myDiv {";
KomText += "padding: 1px 12px;";
KomText += "border: 5px outset brown;";
KomText += "text-align: center;";
KomText += "width: 350px;";
KomText += "margin: 10px 100px;";
KomText += "background-color: rgba(255, 10, 0, 0.3);";
KomText += "}";
KomText += "</style>";

delay(10);
}

char html[2000];
server.send ( 200, "text/html", KomText );
KomText = "";
}

// strony nie znaleziono
void handleNotFound() {
String message = "File Not Found\n\n";
message += "URI: ";
message += server.uri();
message += "\nMethod: ";
message += ( server.method() == HTTP_GET ) ? "GET" : "POST";
message += "\nArguments: ";
message += server.args();
message += "\n";

for ( uint8_t i = 0; i < server.args(); i++ ) {
message += " " + server.argName ( i ) + ": " + server.arg ( i ) + "\n";
}

server.send ( 404, "text/plain", message );
}

void setup() {
pinMode(PINWENTREZ, OUTPUT);
pinMode(PINWENTYL, OUTPUT);
pinMode(SAMOPODTRZ, OUTPUT);
// pinMode(WEJZAPLON, INPUT_PULLUP);
digitalWrite(PINWENTREZ, 0);
digitalWrite(PINWENTYL, 0);
digitalWrite(SAMOPODTRZ, 1);

Serial.begin(115200);
pixels.begin();
EEPROM.begin(1024);
delay(100);

pixels.setPixelColor(0, 0, 0, 0);
pixels.setBrightness(0);
pixels.show(); // przesylam do diod

ssid = "CybDroid";
password = "gosc1111";

delay(10);

DS18B20.begin();
readEpromZmienne();
// -------------------------------------------

delay(200);

WiFiClient client;
WiFi.softAPdisconnect(true);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println(" ");
Serial.println("Laczenie do sieci WiFi :");
for (int polacz = 0; polacz <= 20; polacz++) {
if (WiFi.status() != WL_CONNECTED) {
// brak polaczenia
pixels.setPixelColor(0, 0, 126, 255);
pixels.setBrightness(100);
pixels.show(); // przesylam do diod
delay(100);
pixels.setPixelColor(0, 255, 0, 0);
pixels.setBrightness(50);
pixels.show(); // przesylam do diod
Serial.print(".");
delay(100);
PolaczTak = 0;
} else {
// polaczono do wifi
Serial.println();
Serial.print("Adres IP :");
Serial.println(WiFi.localIP());
IpAdressWysw = WiFi.localIP().toString();
Serial.print("MacAddres : ");
WiFi.macAddress(mac);
macAddr = String(mac[0], HEX);
macAddr += (":");
macAddr += String(mac[1],HEX);
macAddr += (":");
macAddr += String(mac[2],HEX);
macAddr += (":");
macAddr += String(mac[3],HEX);
macAddr += (":");
macAddr += String(mac[4],HEX);
macAddr += (":");
macAddr += String(mac[5],HEX);
Serial.println(macAddr);
Serial.print("RSSI : ");
Serial.println(WiFi.RSSI());
pixels.setPixelColor(0, 0, 126, 255);
pixels.setBrightness(20);
pixels.show(); // przesylam do diod
PolaczTak = 1;
break;
}
}
ESP.wdtEnable(8000);

server.on ( "/", handleRoot );
server.on ( "/inline", []() {
server.send ( 200, "text/plain", "this works as well" );
} );
server.onNotFound ( handleNotFound );

server.begin();
WiFi.macAddress(mac);
macAddr = String(mac[0], HEX);
macAddr += (":");
macAddr += String(mac[1],HEX);
macAddr += (":");
macAddr += String(mac[2],HEX);
macAddr += (":");
macAddr += String(mac[3],HEX);
macAddr += (":");
macAddr += String(mac[4],HEX);
macAddr += (":");
macAddr += String(mac[5],HEX);
}

// Odczyt z pamieci EEPROM do zmiennych ustawien
void readEpromZmienne() {
tempMin = EEPROM.read(0); // temperatura minimalna chlodziwa - wylaczenie wentylatora
tempMax = EEPROM.read(1); // temperatura maxymalna chlodziwa - wlaczenie wentylatora
czasRezys = EEPROM.read(2); // czas przez jaki ma byc wlaczony rezystor zanim zalaczy sie zasilanie glowne w sek
}

// przygotowanie danych dla statusu
void daneDoStat() {
sec = millis() / 1000;
KomText = TempI;
KomText += "|";
KomText += TempII;
KomText += "|";
KomText += tempMin;
KomText += "|";
KomText += tempMax;
KomText += "|";
KomText += czasRezys;
KomText += "|";
KomText += sec;
KomText += "|";
KomText += macAddr;
KomText += "|";
KomText += WiFi.RSSI();
}

// petla programu

void loop() {
sec = millis() / 1000;
DS18B20.requestTemperatures();
TempI = DS18B20.getTempCByIndex(0);
TempII = DS18B20.getTempCByIndex(1);
server.handleClient();

wartoscAO = analogRead(WEJZAPLON);

// sprawdzenie czy jest wlaczony zaplon, i jesli jest wlaczony to nastawa wylaczenia wentylatora po 60 sek.
if (wartoscAO > 500) { // wartosc powyzej 500 oznacza ze jest wlaczony zaplon
secWentWyl = sec + 60; // jesli zaplon wylaczony to max po 60 sekundach ma sie wylaczyc wentylator
tSAMOPODTRZ = sec + tPODTRZZASIL; // jesli zaplon wylaczony to max po 600 sekundach samopotrzymanie ma sie wylaczyc
}

if (autoSter == 3 && secWentWyl > sec) {

// rozruch wentylatora przez rezystor
if (TempI > tempMax && digitalRead(PINWENTREZ) == 0 && digitalRead(PINWENTYL) == 0) {
secWentNas = sec + czasRezys;
digitalWrite(PINWENTREZ,1);
}
// po ustalonym czasie wlaczenie wentylatora bez rezystora
if (secWentNas < sec && digitalRead(PINWENTREZ) == 1) {
digitalWrite(PINWENTYL,1);
delay(100);
digitalWrite(PINWENTREZ,0);
}
// jesli wentylator dziala i temperatura spadnie poiniezej ustalownej wartosci to wylaczenie wentylatora
if (TempI < tempMin && digitalRead(PINWENTYL) == 1) {
digitalWrite(PINWENTYL,0);
}
} else {
if (autoSter == 1 && digitalRead(PINWENTYL) == 0) {
digitalWrite(PINWENTYL,1);
tSAMOPODTRZ = sec + 3600;
secWentWyl = sec + 60;
}
if (autoSter == 2 && digitalRead(PINWENTYL) == 1) {
digitalWrite(PINWENTYL,0);
secWentWyl = sec + 60;
tSAMOPODTRZ = sec + tPODTRZZASIL;
}
}

// sprawdzenie czy jest (wlaczony wentylator i jesli czas pracy przekroczyl czas wlaczenia wentylatora) to wylaczyc wentylator
if (secWentWyl < sec && digitalRead(PINWENTYL) == 1) {
digitalWrite(PINWENTYL,0);
autoSter = 3;
dodInfo = "parent.document.getElementById('dodInfo').innerHTML = 'AUTO';";
}

// Serial.println(wartoscAO);
ESP.wdtFeed();

// sprawdzenie czy jest wlaczony przekaznik rezystora powyzej 20 sekund
if (digitalRead(PINWENTREZ) == 0) {
tWlaczPRez = 0;
}
if (digitalRead(PINWENTREZ) == 1 && sec != TikTak) {
tWlaczPRez++;
}
if (tWlaczPRez > 20) {
digitalWrite(PINWENTREZ, 0);
}

// sprawdzenie czy jest polaczenie. Jesli jest to odczyt adresu IP do zmiennej
if (WiFi.status() != WL_CONNECTED) { // sprawdzenie czy jest polaczenie
PolaczTak = 0;
} else {
PolaczTak = 1;
IpAdressWysw = WiFi.localIP().toString();
}

if (sec > tWylDiod && DiodWl == 1) {
pixels.setPixelColor(0, 0, 0, 0);
pixels.setBrightness(0);
pixels.show();
tWylDiod = sec + 10;
DiodWl = 0;
}

if (sec > tWylDiod && DiodWl == 0) {
pixels.setBrightness(20);
pixels.setPixelColor(0, 0, 126, 255);
pixels.show();
tWylDiod = sec + 1;
DiodWl = 1;
}

if (tSAMOPODTRZ < sec && digitalRead(SAMOPODTRZ) == 1) {
digitalWrite(SAMOPODTRZ, 0);
}

// Serial.println(analogRead(WEJZAPLON));

TikTak = sec; // zostawic na koncu petli loop. Roznica miedzy tymi zmiennymi oznacza, ze uplynela kolejna sekunda.

}

Na schemacie R6 jest chyba nieprawidłowo podpięty pod Q2 - powinien być analogicznie jak dla Q1 - R5.

Tak Masz rację ... Mój błąd :

Schemat ideowy

Układ już testuję piąty dzień. W samochodzie już wszystko przygotowałem.
Sygnały wyciągnąłem z puszki bezpiecznikowej umieszczonej w komorze silnika w której jest tez miejsce na elektronikę i dodatkowe przekaźniki.
Z moich obserwacji musi być bardzo dobrze podłączona masa i zasilanie. Na szczęście też tam mam gotowe sygnały włącznie z zasilaniem i masą
wprost z akumulatora. Musiałem podłączyć wentylator przewodem 2,5 kwadrat bo przy 1.5 miałem wrażenie, że wentylator nie chodził pełną mocą.
Właśnie mi się drukuje obudowa do elektroniki, która umieszczę jutro. Sam czujnik umieściłem w śrubie którą wkręcę w kolano przed czujnikiem
temperatury otwierającym większy obieg cieczy. I tutaj brawo dla konstruktorów, którzy chyba przewidzieli ewentualny montaż czujników bo jest
przewidziany na to otwór montażowy ... Wystarczy go nawiercić na wylot i wkręcić śrubę z czujnikiem 🙂 Drugi chyba zamontuję zaraz przy wylocie
z chłodnicy.

Pomyślałem, że dobrze by było aby wentylator nie włączał się od razu po włączaniu zapłonu, jeśli temperatura będzie większa niż max, przez
powiedzmy  10 sek. Dlatego dodałem kilka linijek kodu :

Spoiler

/* * Program napisal CyberDuck, 29.01.2021
* Zawiera serwer www i polaczenie do wybranej sieci WiFi
*
* http://10.10.11.120:400/?op=2&danaa=25&danab=27&danac=6 - zaladowanie ustawien i podanie statusu
* http://10.10.11.120:400/?op=1 - podanie statusu
*
*
*
*/

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>
#include <Adafruit_NeoPixel.h>
#include <OneWire.h>
#include <DallasTemperature.h>
ESP8266WebServer server(400); // Port na jakim ma dzialac serwer www

#define ONE_WIRE_BUS 0 // D3
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature DS18B20(&oneWire);

// Definicje pinow wejscia wyjscia
#define PINSTER 13 // D7 pin sterujacy diodami RGB
#define PINWENTREZ 5 // D1 przekaznik wlaczajacy wentylator przez rezystor
#define PINWENTYL 4 // D2 przekaznik wlaczajacy wentylator
#define WEJZAPLON A0 // A0 wejscie sterujace maxymalnym czasem trwania wlaczenia wentylatora podlaczyc do zaplonu
#define SAMOPODTRZ 14 // D5 samopodtrzymanie zasilania

int tempMin, tempMax, czasRezys;

word dana1 = 0; // zmienna http
word dana2 = 0; // zmienna http
word dana3 = 0; // zmienna http
word dana4 = 0; // zmienna http
word opcja = 0; // opcja do rozpoznawania opcji
byte mac[6]; // przechowuje adres MAC
String macAddr = ""; // bedzie przechowywac w postaci String adress MAC
String KomText; // zmienna do przechowywania informacji zwrotnych
String IpAdressWysw;
int autoSter = 3;
int wartoscAO = 0;
int tWlaczPRez = 0;
String dodInfo = "";
unsigned long tSAMOPODTRZ = 30; // kiedy ma sie wylaczyc samopodtrzymanie przekaznika samopotrzymania
int tPODTRZZASIL = 600; // ile nalezy potrzymac zasilanie po wylaczeniu zaplonu
int tROZRUCH = 10; // czas po jakim od wlaczenia zaplonu moze sie uruchomic wentylator
unsigned long tROZRUCHRZ = 0; // jaki czas rzeczywisty uplynal od wlaczenia zaplonu

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(2, PINSTER, NEO_GRB + NEO_KHZ800);

unsigned long sec = 0; // zmienna zawierajaca ilosc sekund jaka uplynela od startu
unsigned long secWentNas = 0; // nastawa kiedy ma sie wylaczyc wentylator
unsigned long secWentWyl = 10; // nastawa po jakim czasie ma sie wylaczyc wentylator jesli byl wlaczony po wylaczeniu zaplonu
unsigned long TikTak = sec; // w petli loop roznica miedzy sec i TikTak oznacza ze juz uplynela wlasnie kolejna sekunda
int PolaczTak = 0; // czy jest polaczenie
unsigned long tWylDiod = 30; // czas o jakim trzeba wylaczyc diode RGB
int DiodWl = 1; // dioda swieci, dioda nie swieci

float TempI = 0;
float TempII = 0;

String ssid; // SSID sieci WiFi
String password; // domyslne haslo do sieci WiFi

void handleRoot() {
opcja = server.arg("op").toInt();
dana1 = server.arg("danaa").toInt();
dana2 = server.arg("danab").toInt();
dana3 = server.arg("danac").toInt();
dana4 = server.arg("danad").toInt();

if (opcja == 1) { // podanie statusu
daneDoStat();
}

if (opcja == 2) { // podanie danych do zapisu i wyswietlenie statusu

EEPROM.write(0, dana1);
EEPROM.write(1, dana2);
EEPROM.write(2, dana3);
EEPROM.commit();

tempMin = dana1;
tempMax = dana2;
czasRezys = dana3;

daneDoStat();
KomText += "|OK";
}

if (opcja == 3) { // restart
KomText = "RESTART";
ESP.restart();
delay(1000);
}

// ramka do strony
if (opcja == 8) {
IpAdressWysw = WiFi.localIP().toString();

/*
if (danad == 3) {
KomText = "<script language='JavaScript'>";
KomText += "parent.document.getElementById('danadId').innerHTML = 'ON';";
KomText += "parent.document.getElementById('danad').value = '1';";
KomText += "</script>";
}
*/
KomText = "<script language='JavaScript'>";
KomText += "parent.document.getElementById('temperI').innerHTML = '";
KomText += TempI;
KomText += "';";
KomText += "parent.document.getElementById('rssihtt').innerHTML = '";
KomText += WiFi.RSSI();
KomText += "';";
if (digitalRead(PINWENTYL) == 0 && digitalRead(PINWENTREZ) == 0) {
KomText += "parent.document.getElementById('statWent').innerHTML = ' ☣';"; // znaczek wentylatora
} else {
KomText += "parent.document.getElementById('statWent').innerHTML = ' ☢';"; // znaczek wentylatora
}
if (TempII != -127) {
KomText += "parent.document.getElementById('tempII').innerHTML = '";
KomText += TempII;
KomText += "';";
}

KomText += dodInfo;
KomText += "</script>";

KomText += "<meta http-equiv='Refresh' content='3; url=http://";
KomText += IpAdressWysw;
KomText += ":400/?op=8'>";

dodInfo = "";
}

// wywolanie strony
if (opcja == 9) {

if (dana1 > 1 && dana2 > 1 && dana3 > 0 && dana2 > dana1) {
EEPROM.write(0, dana1);
EEPROM.write(1, dana2);
EEPROM.write(2, dana3);
EEPROM.commit();

tempMin = dana1;
tempMax = dana2;
czasRezys = dana3;
}

KomText = "<form autocomplete='off' action='' method='get'>";
KomText += "<input class='wpis' type='text' name='op' value='9' style='display:none'>";
KomText += "<br>";
KomText += "<div class='myDiv'>";
KomText += "<table style='font-size:25px'>";
KomText += "<tr>";
KomText += "<td width='10px'><td>";
KomText += "<td width='300px'><div align='right'>";
KomText += "<a style='text-decoration: none; cursor:pointer; color: cyan;' href='?op=9'>STR</a>";
KomText += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
KomText += "<span id='dodInfo'>";
if (dana4 > 0) {
autoSter = dana4;
}

/*
<input id='danad' type='text' value='3' name='danaad' style='display:none'>
<span id="danadId" style="color: cyan; cursor:pointer;" onClick='przekazAuto();'>AUTO</span>
*/

if (autoSter == 3) {
KomText += "<a style='text-decoration: none; cursor:pointer; color: cyan;' href='?op=9&danad=1'>AUTO</a>";
}
if (autoSter == 1) {
KomText += "<a style='text-decoration: none; cursor:pointer; color: cyan;' href='?op=9&danad=2'>ON</a>";
}
if (autoSter == 2) {
KomText += "<a style='text-decoration: none; cursor:pointer; color: cyan;' href='?op=9&danad=3'>OFF</a>";
}
KomText += "</span></div>Temp Min</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td><td>";
KomText += "<td>";
KomText += "<input class='wpis' type='text' name='danaa' value='";
KomText += tempMin;
KomText += "'>";
KomText += "</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td><td>";
KomText += "<td>Temp Max</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td><td>";
KomText += "<td>";
KomText += "<input class='wpis' type='text' name='danab' value='";
KomText += tempMax;
KomText += "'>";
KomText += "</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td><td>";
KomText += "<td>Czas Rezystora</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td><td>";
KomText += "<td>";
KomText += "<input class='wpis' type='text' name='danac' value='";
KomText += czasRezys;
KomText += "'>";
KomText += "</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td><td>";
KomText += "<td><br>Aktualna Temp : ";
KomText += "<span id='temperI'></span> ℃";
KomText += "<br>Status Went : ";
KomText += "<span id='statWent'></span>";
KomText += "<br>RSSI : ";
KomText += "<span id='rssihtt'></span>&nbsp;&nbsp;";
if (TempII != -127) {
KomText += "Cz 2 : <span id='tempII'></span> ℃";
}
KomText += "</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td><td>";
KomText += "<td>";
KomText += "<input class='wpis' type='submit' value='Zapisz' style='display:none;'><br>";
KomText += "</td>";
KomText += "</tr>";

KomText += "</table>";
KomText += "</div>";

KomText += "</form>";

KomText += "<iframe name='ramka' marginwidth='0' marginheight='0' align='top' border='0' frameborder='0' ";
KomText += "width='1px' height='1px' ";
KomText += "src='https://";
KomText += IpAdressWysw;
KomText += ":400/?op=8' scrolling='no'></iframe>";

KomText += "<style>";
KomText += "body {";
KomText += "background-image: url('https://i.ibb.co/88D0cGh/tapSsang.jpg');";
KomText += "background-repeat: no-repeat;";
KomText += "background-position: center;";
KomText += "background-size: 90% 100%;";
KomText += "font-size: 50px;";
KomText += "color: #fff000;";
KomText += "}";

KomText += ".wpis {";
KomText += "font-size: 18px;";
KomText += "padding: 12px 12px;";
KomText += "margin: 8px 0;";
KomText += "display: inline-block;";
KomText += "border: 1px solid #ccc;";
KomText += "border-radius: 4px;";
KomText += "box-sizing: border-box;";
KomText += "font-weight: bold;";
KomText += "}";
KomText += ".myDiv {";
KomText += "padding: 1px 12px;";
KomText += "border: 5px outset brown;";
KomText += "text-align: center;";
KomText += "width: 350px;";
KomText += "margin: 10px 100px;";
KomText += "background-color: rgba(255, 10, 0, 0.3);";
KomText += "}";
KomText += "</style>";

/*
<script language="JavaScript">
function przekazAuto {
var przekAuto = document.getElementById("danad").value;
ramka.location.href='http://adresip:400?op=8&danaaa=' + przekAuto;
}
</script>
*/

delay(10);
}

char html[2000];
server.send ( 200, "text/html", KomText );
KomText = "";
}

// strony nie znaleziono
void handleNotFound() {
String message = "File Not Found\n\n";
message += "URI: ";
message += server.uri();
message += "\nMethod: ";
message += ( server.method() == HTTP_GET ) ? "GET" : "POST";
message += "\nArguments: ";
message += server.args();
message += "\n";

for ( uint8_t i = 0; i < server.args(); i++ ) {
message += " " + server.argName ( i ) + ": " + server.arg ( i ) + "\n";
}

server.send ( 404, "text/plain", message );
}

void setup() {
pinMode(PINWENTREZ, OUTPUT);
pinMode(PINWENTYL, OUTPUT);
pinMode(SAMOPODTRZ, OUTPUT);
// pinMode(WEJZAPLON, INPUT_PULLUP);
digitalWrite(PINWENTREZ, 0);
digitalWrite(PINWENTYL, 0);
digitalWrite(SAMOPODTRZ, 1);

Serial.begin(115200);
pixels.begin();
EEPROM.begin(1024);
delay(100);

pixels.setPixelColor(0, 0, 0, 0);
pixels.setBrightness(0);
pixels.show(); // przesylam do diod

ssid = "CybDroid";
password = "gosc1111";

delay(10);

DS18B20.begin();
readEpromZmienne();
// -------------------------------------------

delay(200);

WiFiClient client;
WiFi.softAPdisconnect(true);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println(" ");
Serial.println("Laczenie do sieci WiFi :");
for (int polacz = 0; polacz <= 20; polacz++) {
if (WiFi.status() != WL_CONNECTED) {
// brak polaczenia
pixels.setPixelColor(0, 0, 126, 255);
pixels.setBrightness(100);
pixels.show(); // przesylam do diod
delay(100);
pixels.setPixelColor(0, 255, 0, 0);
pixels.setBrightness(50);
pixels.show(); // przesylam do diod
Serial.print(".");
delay(100);
PolaczTak = 0;
} else {
// polaczono do wifi
Serial.println();
Serial.print("Adres IP :");
Serial.println(WiFi.localIP());
IpAdressWysw = WiFi.localIP().toString();
Serial.print("MacAddres : ");
WiFi.macAddress(mac);
macAddr = String(mac[0], HEX);
macAddr += (":");
macAddr += String(mac[1],HEX);
macAddr += (":");
macAddr += String(mac[2],HEX);
macAddr += (":");
macAddr += String(mac[3],HEX);
macAddr += (":");
macAddr += String(mac[4],HEX);
macAddr += (":");
macAddr += String(mac[5],HEX);
Serial.println(macAddr);
Serial.print("RSSI : ");
Serial.println(WiFi.RSSI());
pixels.setPixelColor(0, 0, 126, 255);
pixels.setBrightness(20);
pixels.show(); // przesylam do diod
PolaczTak = 1;
break;
}
}
ESP.wdtEnable(8000);

server.on ( "/", handleRoot );
server.on ( "/inline", []() {
server.send ( 200, "text/plain", "this works as well" );
} );
server.onNotFound ( handleNotFound );

server.begin();
WiFi.macAddress(mac);
macAddr = String(mac[0], HEX);
macAddr += (":");
macAddr += String(mac[1],HEX);
macAddr += (":");
macAddr += String(mac[2],HEX);
macAddr += (":");
macAddr += String(mac[3],HEX);
macAddr += (":");
macAddr += String(mac[4],HEX);
macAddr += (":");
macAddr += String(mac[5],HEX);
}

// Odczyt z pamieci EEPROM do zmiennych ustawien
void readEpromZmienne() {
tempMin = EEPROM.read(0); // temperatura minimalna chlodziwa - wylaczenie wentylatora
tempMax = EEPROM.read(1); // temperatura maxymalna chlodziwa - wlaczenie wentylatora
czasRezys = EEPROM.read(2); // czas przez jaki ma byc wlaczony rezystor zanim zalaczy sie zasilanie glowne w sek
}

// przygotowanie danych dla statusu
void daneDoStat() {
sec = millis() / 1000;
KomText = TempI;
KomText += "|";
KomText += TempII;
KomText += "|";
KomText += tempMin;
KomText += "|";
KomText += tempMax;
KomText += "|";
KomText += czasRezys;
KomText += "|";
KomText += sec;
KomText += "|";
KomText += macAddr;
KomText += "|";
KomText += WiFi.RSSI();
}

// petla programu

void loop() {
sec = millis() / 1000;
DS18B20.requestTemperatures();
TempI = DS18B20.getTempCByIndex(0);
TempII = DS18B20.getTempCByIndex(1);
server.handleClient();

wartoscAO = analogRead(WEJZAPLON);

// sprawdzenie czy jest wlaczony zaplon, i jesli jest wlaczony to nastawa wylaczenia wentylatora po 60 sek.
if (wartoscAO > 500) { // wartosc powyzej 500 oznacza ze jest wlaczony zaplon
secWentWyl = sec + 60; // jesli zaplon wylaczony to max po 60 sekundach ma sie wylaczyc wentylator
tSAMOPODTRZ = sec + tPODTRZZASIL; // jesli zaplon wylaczony to max po 600 sekundach samopotrzymanie ma sie wylaczyc
} else {
tROZRUCHRZ = 0;
}

if (sec != TikTak) {
tROZRUCHRZ++;
}

if (autoSter == 3 && secWentWyl > sec) {
if (tROZRUCHRZ > tROZRUCH) { // sprawdzenie czy uplynal odpowiedni czas po wlaczeniu zaplonu i czy mozna juz wlaczyc wentylator automatycznie
// rozruch wentylatora przez rezystor
if (TempI > tempMax && digitalRead(PINWENTREZ) == 0 && digitalRead(PINWENTYL) == 0) {
secWentNas = sec + czasRezys;
digitalWrite(PINWENTREZ,1);
}
// po ustalonym czasie wlaczenie wentylatora bez rezystora
if (secWentNas < sec && digitalRead(PINWENTREZ) == 1) {
digitalWrite(PINWENTYL,1);
delay(100);
digitalWrite(PINWENTREZ,0);
}
}
// jesli wentylator dziala i temperatura spadnie poniezej ustalownej wartosci to wylaczenie wentylatora
if (TempI < tempMin && digitalRead(PINWENTYL) == 1) {
digitalWrite(PINWENTYL,0);
}
} else {
if (autoSter == 1 && digitalRead(PINWENTYL) == 0) {
digitalWrite(PINWENTYL,1);
tSAMOPODTRZ = sec + 3600;
secWentWyl = sec + 60;
}
if (autoSter == 2 && digitalRead(PINWENTYL) == 1) {
digitalWrite(PINWENTYL,0);
secWentWyl = sec + 60;
tSAMOPODTRZ = sec + tPODTRZZASIL;
}
}

// sprawdzenie czy jest (wlaczony wentylator i jesli czas pracy przekroczyl czas wlaczenia wentylatora) to wylaczyc wentylator
if (secWentWyl < sec && digitalRead(PINWENTYL) == 1) {
digitalWrite(PINWENTYL,0);
autoSter = 3;
dodInfo = "parent.document.getElementById('dodInfo').innerHTML = 'AUTO';";
}

// Serial.println(wartoscAO);
ESP.wdtFeed();

// sprawdzenie czy jest wlaczony przekaznik rezystora powyzej 20 sekund
if (digitalRead(PINWENTREZ) == 0) {
tWlaczPRez = 0;
}
if (digitalRead(PINWENTREZ) == 1 && sec != TikTak) {
tWlaczPRez++;
}
if (tWlaczPRez > 20) {
digitalWrite(PINWENTREZ, 0);
}

// sprawdzenie czy jest polaczenie. Jesli jest to odczyt adresu IP do zmiennej
if (WiFi.status() != WL_CONNECTED) { // sprawdzenie czy jest polaczenie
PolaczTak = 0;
} else {
PolaczTak = 1;
IpAdressWysw = WiFi.localIP().toString();
}

if (sec > tWylDiod && DiodWl == 1) {
pixels.setPixelColor(0, 0, 0, 0);
pixels.setBrightness(0);
pixels.show();
tWylDiod = sec + 10;
DiodWl = 0;
}

if (sec > tWylDiod && DiodWl == 0) {
pixels.setBrightness(20);
pixels.setPixelColor(0, 0, 126, 255);
pixels.show();
tWylDiod = sec + 1;
DiodWl = 1;
}

if (tSAMOPODTRZ < sec && digitalRead(SAMOPODTRZ) == 1) {
digitalWrite(SAMOPODTRZ, 0);
}

// Serial.println(analogRead(WEJZAPLON));

TikTak = sec; // zostawic na koncu petli loop. Roznica miedzy tymi zmiennymi oznacza, ze uplynela kolejna sekunda.
}

Można sobie te nastawę podczas kompilacji dowolnie ustawić w linii nr 47 :

Spoiler

int tROZRUCH = 10; // czas po jakim od wlaczenia zaplonu moze sie uruchomic wentylator

Dokonałem kilka zmian w programie. Teraz układ wyświetla jeszcze dodatkowo :
. ile działa od startu sterownik, a wiec i zarazem ile działa silnik po dłuższym 15 min postoju.
. ile działa aktualnie wentylator, ile działał poprzednio
. ile jest wyłączony wentylator, ile nie działał poprzednio
Dodałem też guzik restart i możliwość dodatkowych kilku ustawień.
U mnie w kompie pokładowym całość się ładnie wkomponowywuje w wyświetlacz.

Miałem jedynie problem z umocowaniem samych czujników w płynie chłodniczym zaraz za
wyjściem z silnika. Ponieważ są dwa czujniki to zaraz za wyjściem i wejściem.
Zrobiłem to tak :

W takiej gilzie są umocowane same czujniki DS18B20 do których jest przylutowany przewód po starym przewodzie
USB. Miałem takie 5 metrowe , ekranowane w grubej czarnej sztywnej izolacji więc nadawały się idealnie. W samą gilzę
włożyłem też przed włożeniem i zatopieniem czujnika dodatkowo wysokotemperaturową bo aż do 300 stopni
pastę termiczną.

Wcześniej nie wiedziałem o tym, ale u mnie w samochodzie pompa tłoczy ciecz do góry . Czyli wlot gorącej cieczy
jest na dole chłodnicy, a tej już ostudzonej wylot jest na górze chłodnicy. Na szczęście jak zakładał projekt
układ mierzy w dwóch punktach temperaturę więc wystarczyło bez lutowania w samym programie
zamienić czujniki miejscami 😀
Sam program po testach i kompletnych przeróbkach zamieszczę później.

Troszkę się w projekcie pozmieniało i jak go wgram do esp w samochodzie to pokażę jak aktualnie całość wygląda.
Na razie uruchomiłem dodatkowo Macrodroid w samochodowym radiu i :

Popełniłem dalsze zmiany i teraz pulpit na monitorze komputera wygląda tak po wywołaniu sterownika wentylatora :

Nakręciłem też krótki filmik :

A kod wyglada teraz tak :

Spoiler

/* * Program napisal CyberDuck, 29.01.2021
* Zawiera serwer www i polaczenie do wybranej sieci WiFi
* STEROWNIK WENTYLATORA CHLODNICY W SAMOCHODZIE
*
* http://10.10.11.120:400/?op=2&danaa=25&danab=27&danac=6 - zaladowanie ustawien i podanie statusu
* http://10.10.11.120:400/?op=1 - podanie statusu
*
*
*
*/

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>
#include <Adafruit_NeoPixel.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include "SsanWentylZmienne.h"

ESP8266WebServer server(400); // Port na jakim ma dzialac serwer www

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature DS18B20(&oneWire);

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(2, PINSTER, NEO_GRB + NEO_KHZ800);

void handleRoot() {
opcja = server.arg("op").toInt();
dana1 = server.arg("danaa").toInt();
dana2 = server.arg("danab").toInt();
dana3 = server.arg("danac").toInt();
dana4 = server.arg("danad").toInt();

if (opcja == 1) { // podanie statusu
daneDoStat();
}

// ramka do strony glownej ___________________________________________________________________________
if (opcja == 8) {
IpAdressWysw = WiFi.localIP().toString();

if (dana1 > 1) {
if (dana1 == 11) {
autoSter = 1;
}
if (dana1 == 12) {
autoSter = 2;
}
if (dana1 == 13) {
autoSter = 3;
}
}

KomText = "<script language='JavaScript'>";
KomText += "parent.document.getElementById('rssihtt').innerHTML = '";
KomText += WiFi.RSSI();
KomText += "';";
KomText += "parent.document.getElementById('TI').innerHTML = '";
KomText += TempI;
KomText += "';";
KomText += "parent.document.getElementById('tPracWent').innerHTML = '";
KomText += tPRWENT;
KomText += " , ";
KomText += tLASTPRWENT;
KomText += "';";
KomText += "parent.document.getElementById('tWylWent').innerHTML = '";
KomText += tWYLWENT;
KomText += " , ";
KomText += tLASTWYLWENt;
KomText += "';";
KomText += "parent.document.getElementById('tPracReg').innerHTML = '";
KomText += sec;
KomText += "';";

if (TempII == -127) {
KomText += "parent.document.getElementById('TII').innerHTML = 'brak';";
} else {
KomText += "parent.document.getElementById('TII').innerHTML = '";
KomText += TempII;
KomText += " ℃';";
}

if (autoSter == 1) {
KomText += "parent.document.getElementById('dodInfoI').style.color = 'white';";
KomText += "parent.document.getElementById('dodInfoII').style.color = 'blue';";
KomText += "parent.document.getElementById('dodInfoIII').style.color = 'blue';";
}
if (autoSter == 2) {
KomText += "parent.document.getElementById('dodInfoI').style.color = 'blue';";
KomText += "parent.document.getElementById('dodInfoII').style.color = 'white';";
KomText += "parent.document.getElementById('dodInfoIII').style.color = 'blue';";
}
if (autoSter == 3) {
KomText += "parent.document.getElementById('dodInfoI').style.color = 'blue';";
KomText += "parent.document.getElementById('dodInfoII').style.color = 'blue';";
KomText += "parent.document.getElementById('dodInfoIII').style.color = 'white';";
}
if (digitalRead(PINWENTYL) == 0 && digitalRead(PINWENTREZ) == 0) {
KomText += "parent.document.getElementById('statWent').innerHTML = ' ☣';"; // znaczek wentylatora
} else {
KomText += "parent.document.getElementById('statWent').innerHTML = ' ☢';"; // znaczek wentylatora
}

if (dana1 == 20) {
ESP.restart();
delay(5000);
}

if (tSAMOPODTRZ > sec) {
KomText += "parent.document.getElementById('tWylSter').innerHTML = '";
KomText += (tSAMOPODTRZ - sec);
KomText += " sec';";
} else {
KomText += "parent.document.getElementById('tWylSter').innerHTML = '0';";
}
if (dana1 == 30) {
if (CzyZamian == 1) {
CzyZamian = 0;
EEPROM.write(3, 0);
} else {
CzyZamian = 1;
EEPROM.write(3, 1);
}
EEPROM.commit();
}

if (CzyZamian == 1) {
KomText += "parent.document.getElementById('ZnaczZamCzuj').innerHTML = '⇳';";
} else {
KomText += "parent.document.getElementById('ZnaczZamCzuj').innerHTML = 'X';";
}

String textDoInje = "";
for (int x=0; x<ilWykresikow ; x++) {
textDoInje += tabPomiar[x];
textDoInje += ",";
}
KomText += "parent.document.getElementById('DanDoWykr').value = '";
KomText += textDoInje;
KomText += "';";

KomText += "</script>";

KomText += "<meta http-equiv='Refresh' content='3; url=http://";
KomText += IpAdressWysw;
KomText += ":400/?op=8'>";

dodInfo = "";
}

// wywolanie strony glownej ______________________________________________________________________________
if (opcja == 9) {
IpAdressWysw = WiFi.localIP().toString();

if (dana1 > 1 && dana2 > 1 && dana3 > 0 && dana2 > dana1) {
EEPROM.write(0, dana1);
EEPROM.write(1, dana2);
EEPROM.write(2, dana3);
EEPROM.commit();

tempMin = dana1;
tempMax = dana2;
czasRezys = dana3;
}

KomText = "<form autocomplete='off' action='' method='get'>";
KomText += "<input class='wpis' type='text' name='op' value='9' style='display:none'>";
KomText += "<table style='margin: 10px 70px;'><tr><td width='390px'>";
KomText += "<div class='myDiv'>";
KomText += "<table style='font-size:23px'>";
KomText += "<tr>";
KomText += "<td width='10px'></td>";
KomText += "<td width='290px'>";
KomText += "<br>";
KomText += "Temp Min</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td></td>";
KomText += "<td>";
KomText += "<input class='wpis' type='text' name='danaa' value='";
KomText += tempMin;
KomText += "' style='width: 220px;'>";
KomText += "</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td></td>";
KomText += "<td>Temp Max</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td></td>";
KomText += "<td>";
KomText += "<input class='wpis' type='text' name='danab' value='";
KomText += tempMax;
KomText += "' style='width: 220px;'>";
KomText += "</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td></td>";
KomText += "<td>Czas Rozruchu</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td></td>";
KomText += "<td>";
KomText += "<input class='wpis' type='text' name='danac' value='";
KomText += czasRezys;
KomText += "' style='width: 220px;'>";
KomText += "</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td></td>";
KomText += "<td>";
KomText += "<br>RSSI : ";
KomText += "<span id='rssihtt'></span>&nbsp;&nbsp;";
KomText += "</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td></td>";
KomText += "<td>";

KomText += "<input type='submit' value='Zapisz' style='display:none;'>";
KomText += "<input id='DanDoWykr' type='text' name='DaneWykresu' value='' style='display:none;'>";
KomText += "<br>";

KomText += "<div style='width: 300px;'>";
KomText += "<div style='float:left; font-size: 11px; width: 20px; text-align: center;'>100<br><br><br><br>50<br><br><br><br>0</div>";
KomText += "<div style='float:left; background-color:yellow; height:100px; width:1px;'></div>";
KomText += "<div id='wykresCaly' class='myDivIV'></div>";
KomText += "</div>";
KomText += "<br>";

KomText += "</td>";
KomText += "</tr>";

KomText += "</table>";
KomText += "</div>";

KomText += "</td><td valign='top'>";

KomText += "<div class='myDivII'>";
KomText += "<table style='font-size:23px'><tr><td width='10px'> </td><td><br>";
KomText += "Aktualna TempI &nbsp;: <span id='TI'></span> ℃<br>";
KomText += "Aktualna TempII : <span id='TII'></span><br><br>";
KomText += "Status Went : <span id='statWent'></span><br>";
KomText += "Czas pracy Wen : <span id='tPracWent'></span><br>";
KomText += "Czas wyl Wen : <span id='tWylWent'></span><br>";
KomText += "Czas pracy Sterownika : <span id='tPracReg'></span><br>";
KomText += "Czas do wyl Ster : <span id='tWylSter'></span><br><br>";
KomText += "<a style='text-decoration: none; cursor:pointer; color: cyan;' href='http://";
KomText += IpAdressWysw;
KomText += ":400/?op=9'>STR</a>";
KomText += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&nbsp;&nbsp;";
KomText += "<span id='dodInfoI' onClick='WlaczWyl(11);' style='color:blue; cursor:pointer;'>ON</span>&nbsp;&nbsp;";
KomText += "<span id='dodInfoII' onClick='WlaczWyl(12);' style='color:blue; cursor:pointer;'>OFF</span>&nbsp;&nbsp;";
KomText += "<span id='dodInfoIII' onClick='WlaczWyl(13);' style='color:blue; cursor:pointer;'>AUTO</span>&nbsp;&nbsp;]";

KomText += "<br><br><br><br><br><br>";

KomText += "<span onClick='WlaczWyl(20);' style='color:blue; cursor:pointer;'>[ Reset ]</span>&nbsp;&nbsp;&nbsp;&nbsp;";
KomText += "<span onClick='WlaczWyl(30);' style='color:blue; cursor:pointer;'>[ Zam Czujnik </span>";
KomText += "<span id='ZnaczZamCzuj' style='color:blue; cursor:pointer;'>⇳</span> ]";
KomText += "<br><br>";
KomText += "</td></tr></table>";
KomText += "</div>";
KomText += "</td></tr></table>";

KomText += "</form>";

KomText += "<iframe id='dolStrony' name='ramka' marginwidth='0' marginheight='0' align='top' border='0' frameborder='0' ";
KomText += "width='1px' height='1px' ";
KomText += "src='https://";
KomText += IpAdressWysw;
KomText += ":400/?op=8' scrolling='no'></iframe>";

KomText += "<div id='OkienkoInf' class='myDivIII' style='display:none'>";
KomText += "..:: Prosze czekac ::..";
KomText += "</div>";

KomText += "<style>";
KomText += "html{";
KomText += "scroll-behavior: smooth;";
KomText += "}";

KomText += "body {";
KomText += "background-image: url('https://i.ibb.co/88D0cGh/tapSsang.jpg');";
KomText += "background-repeat: no-repeat;";
KomText += "background-position: center;";
KomText += "background-size: 100% 100%;";
KomText += "font-size: 25px;";
KomText += "color: #fff000;";
KomText += "}";

KomText += ".wpis {";
KomText += "font-size: 20px;";
KomText += "padding: 6px 6px;";
KomText += "margin: 6px 0;";
KomText += "display: inline-block;";
KomText += "border: 1px solid #ccc;";
KomText += "border-radius: 4px;";
KomText += "box-sizing: border-box;";
KomText += "font-weight: bold;";
KomText += "}";

KomText += ".myDiv {";
KomText += "padding: 1px 8px;";
KomText += "border: 5px outset brown;";
KomText += "text-align: center;";
KomText += "width: 330px;";
KomText += "background-color: rgba(255, 10, 0, 0.3);";
KomText += "}";

KomText += ".myDivII {";
KomText += "width: 390px;";
KomText += "font-size:25px;";
KomText += "padding: 1px 8px;";
KomText += "border: 5px outset brown;";
KomText += "background-color: rgba(255, 10, 0, 0.3);";
KomText += "}";

KomText += ".myDivIII {";
KomText += "width: 390px;";
KomText += "position: absolute;";
KomText += "text-align: center;";
KomText += "padding: 50px 0;";
KomText += "z-index: 3;";
KomText += "left: 240px;";
KomText += "top: 200px;";
KomText += "font-size:25px;";
KomText += "border: 5px outset brown;";
KomText += "background-color: rgba(255, 0, 0, 0.9);";
KomText += "}";

KomText += ".myDivIV {";
KomText += "border: 2px outset brown;";
KomText += "background-color: rgba(140, 0, 0, 0.9);";
KomText += "vertical-align: bottom;";
KomText += "height: 100px;";
KomText += "width: ";
KomText += ilWykresikow + 20;
KomText += "px;";
KomText += "background-color: red;";
KomText += "}";

KomText += ".myDivV {";
KomText += "float:left;";
KomText += "width:1px;";
KomText += "background-color: rgba(140, 0, 0, 0.02);";
KomText += "box-shadow: inset 5px 5px 10px;";
KomText += "}";

KomText += "</style>";

KomText += "<script language='JavaScript'>";
KomText += "function WlaczWyl(SposSter) {";
KomText += "var SposSter = SposSter;";
KomText += "if (SposSter == 20) {";
KomText += " document.getElementById('OkienkoInf').style.display = ''; ";
KomText += " setTimeout('OdswierzStrone();', 10000); ";
KomText += "}";
KomText += "ramka.location.href='http://";
KomText += IpAdressWysw;
KomText += ":400/?op=8&danaa=' + SposSter;";
KomText += "}";

KomText += "function OdswierzStrone() {";
KomText += "document.location.href='http://";
KomText += IpAdressWysw;
KomText += ":400/?op=9';";
KomText += "}";

KomText += "function wyswietlWykres() {";
KomText += "danZInp = document.getElementById('DanDoWykr').value;";
KomText += "TabZDanymi = danZInp.split(',');";
KomText += "ll = ";
KomText += ilWykresikow;
KomText += ";";
KomText += "wysSlup = 100;"; // maksymalna wysokosc slupka w px
KomText += "wysKropki = 2;"; // jesli kropkowy to wysokosc kropki
KomText += "slupkowy = 0;"; // czy slupkowy czy kropkowy wykres 0 - kropkowy, 1 - slupkowy
KomText += "dokumentWyk = '';";

KomText += "for (x=0; x<ll; x++) {";
KomText += "if (slupkowy == 1) {";
KomText += "dokumentWyk = dokumentWyk + `<div class='myDivV'>`;";
KomText += "dokumentWyk = dokumentWyk + `<div style='height: `;";
KomText += "dokumentWyk = dokumentWyk + (wysSlup - TabZDanymi[x]);";
KomText += "dokumentWyk = dokumentWyk + `px; background-color: red;'></div>`;";
KomText += "dokumentWyk = dokumentWyk + `<div style='height: `;";
KomText += "dokumentWyk = dokumentWyk + TabZDanymi[x];";
KomText += "dokumentWyk = dokumentWyk + `px; background-color: blue;'></div>`;";
KomText += "dokumentWyk = dokumentWyk + `</div>`;";
KomText += "} else {";
KomText += "dokumentWyk = dokumentWyk + `<div class='myDivV'>`;";
KomText += "dokumentWyk = dokumentWyk + `<div style='height: `;";
KomText += "dokumentWyk = dokumentWyk + (wysSlup - TabZDanymi[x] - wysKropki);";
KomText += "dokumentWyk = dokumentWyk + `px; background-color: red;'></div>`;";
KomText += "dokumentWyk = dokumentWyk + `<div style='height: ` + wysKropki + `px; background-color: blue;'></div>`;";
KomText += "dokumentWyk = dokumentWyk + `<div style='height: `;";
KomText += "dokumentWyk = dokumentWyk + TabZDanymi[x];";
KomText += "dokumentWyk = dokumentWyk + `px; background-color: red;'></div>`;";
KomText += "dokumentWyk = dokumentWyk + `</div>`;";
KomText += "}";
KomText += "}";

KomText += "document.getElementById('wykresCaly').innerHTML = dokumentWyk;";
KomText += "setTimeout('wyswietlWykres();', 3000);";
KomText += "}";
KomText += "setTimeout('wyswietlWykres();', 3000);";

KomText += "</script>";

delay(10);

}

char html[4000];
server.send ( 200, "text/html", KomText );
KomText = "";
}

// strony nie znaleziono
void handleNotFound() {
String message = "File Not Found\n\n";
message += "URI: ";
message += server.uri();
message += "\nMethod: ";
message += ( server.method() == HTTP_GET ) ? "GET" : "POST";
message += "\nArguments: ";
message += server.args();
message += "\n";

for ( uint8_t i = 0; i < server.args(); i++ ) {
message += " " + server.argName ( i ) + ": " + server.arg ( i ) + "\n";
}

server.send ( 404, "text/plain", message );
}

void setup() {
pinMode(PINWENTREZ, OUTPUT);
pinMode(PINWENTYL, OUTPUT);
pinMode(SAMOPODTRZ, OUTPUT);
// pinMode(WEJZAPLON, INPUT_PULLUP);
digitalWrite(PINWENTREZ, 0);
digitalWrite(PINWENTYL, 0);
digitalWrite(SAMOPODTRZ, 1);

Serial.begin(115200);
pixels.begin();
EEPROM.begin(1024);
delay(100);

pixels.setPixelColor(0, 0, 0, 0);
pixels.setBrightness(0);
pixels.show(); // przesylam do diod

ssid = "CybDroid";
password = "gosc1111";

delay(10);

DS18B20.begin();
readEpromZmienne();
// -------------------------------------------

delay(200);

WiFiClient client;
WiFi.softAPdisconnect(true);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println(" ");
Serial.println("Laczenie do sieci WiFi :");
for (int polacz = 0; polacz <= 20; polacz++) {
if (WiFi.status() != WL_CONNECTED) {
// brak polaczenia
pixels.setPixelColor(0, 0, 126, 255);
pixels.setBrightness(100);
pixels.show(); // przesylam do diod
delay(100);
pixels.setPixelColor(0, 255, 0, 0);
pixels.setBrightness(50);
pixels.show(); // przesylam do diod
Serial.print(".");
delay(100);
PolaczTak = 0;
} else {
// polaczono do wifi
Serial.println();
Serial.print("Adres IP :");
Serial.println(WiFi.localIP());
IpAdressWysw = WiFi.localIP().toString();
Serial.print("MacAddres : ");
WiFi.macAddress(mac);
macAddr = String(mac[0], HEX);
macAddr += (":");
macAddr += String(mac[1],HEX);
macAddr += (":");
macAddr += String(mac[2],HEX);
macAddr += (":");
macAddr += String(mac[3],HEX);
macAddr += (":");
macAddr += String(mac[4],HEX);
macAddr += (":");
macAddr += String(mac[5],HEX);
Serial.println(macAddr);
Serial.print("RSSI : ");
Serial.println(WiFi.RSSI());
pixels.setPixelColor(0, 0, 126, 255);
pixels.setBrightness(20);
pixels.show(); // przesylam do diod
PolaczTak = 1;
break;
}
}
ESP.wdtEnable(8000);

server.on ( "/", handleRoot );
server.on ( "/inline", []() {
server.send ( 200, "text/plain", "this works as well" );
} );
server.onNotFound ( handleNotFound );

server.begin();
WiFi.macAddress(mac);
macAddr = String(mac[0], HEX);
macAddr += (":");
macAddr += String(mac[1],HEX);
macAddr += (":");
macAddr += String(mac[2],HEX);
macAddr += (":");
macAddr += String(mac[3],HEX);
macAddr += (":");
macAddr += String(mac[4],HEX);
macAddr += (":");
macAddr += String(mac[5],HEX);
}

// Odczyt z pamieci EEPROM do zmiennych ustawien
void readEpromZmienne() {
tempMin = EEPROM.read(0); // temperatura minimalna chlodziwa - wylaczenie wentylatora
tempMax = EEPROM.read(1); // temperatura maxymalna chlodziwa - wlaczenie wentylatora
czasRezys = EEPROM.read(2); // czas przez jaki ma byc wlaczony rezystor zanim zalaczy sie zasilanie glowne w sek
CzyZamian = EEPROM.read(3); // czy zamieniac czujniki miejscami
}

// przygotowanie danych dla statusu
void daneDoStat() {
sec = millis() / 1000;
KomText = TempI;
KomText += "|";
KomText += TempII;
KomText += "|";
KomText += tempMin;
KomText += "|";
KomText += tempMax;
KomText += "|";
KomText += czasRezys;
KomText += "|";
KomText += sec;
KomText += "|";
KomText += macAddr;
KomText += "|";
KomText += WiFi.RSSI();
}

// petla programu

void loop() {
sec = millis() / 1000;
DS18B20.requestTemperatures();
// czy zamiana czujnikow
TempI = DS18B20.getTempCByIndex(0);
TempII = DS18B20.getTempCByIndex(1);
// czy zamiana czujnikow
if (CzyZamian == 1) {
float temporary = TempI;
TempI = TempII;
TempII = temporary;
}

server.handleClient();

wartoscAO = analogRead(WEJZAPLON);

// sprawdzenie czy jest wlaczony zaplon, i jesli jest wlaczony to nastawa wylaczenia wentylatora po 60 sek.
if (wartoscAO > 600) { // wartosc powyzej 500 oznacza ze jest wlaczony zaplon
secWentWyl = sec + 60; // jesli zaplon wylaczony to max po 60 sekundach ma sie wylaczyc wentylator
tSAMOPODTRZ = sec + tPODTRZZASIL; // jesli zaplon wylaczony to max po 600 sekundach samopotrzymanie ma sie wylaczyc
} else {
tROZRUCHRZ = 0;
}

if (sec != TikTak) {
tROZRUCHRZ++;
}

if (autoSter == 3 && secWentWyl > sec) {
if (tROZRUCHRZ > tROZRUCH) { // sprawdzenie czy uplynal odpowiedni czas po wlaczeniu zaplonu i czy mozna juz wlaczyc wentylator automatycznie
// rozruch wentylatora przez rezystor
if (TempI > tempMax && digitalRead(PINWENTREZ) == 0 && digitalRead(PINWENTYL) == 0) {
secWentNas = sec + czasRezys;
digitalWrite(PINWENTREZ,1);
}
// po ustalonym czasie wlaczenie wentylatora bez rezystora
if (secWentNas < sec && digitalRead(PINWENTREZ) == 1) {
digitalWrite(PINWENTYL,1);
delay(100);
digitalWrite(PINWENTREZ,0);
}
}
// jesli wentylator dziala i temperatura spadnie poniezej ustalownej wartosci to wylaczenie wentylatora
if (TempI < tempMin && digitalRead(PINWENTYL) == 1) {
digitalWrite(PINWENTYL,0);
}
} else {
if (autoSter == 1 && digitalRead(PINWENTYL) == 0) {
digitalWrite(PINWENTYL,1);
tSAMOPODTRZ = sec + 3600;
secWentWyl = sec + 60;
}
if (autoSter == 2 && digitalRead(PINWENTYL) == 1) {
digitalWrite(PINWENTYL,0);
secWentWyl = sec + 60;
tSAMOPODTRZ = sec + tPODTRZZASIL;
}
}

// sprawdzenie czy jest (wlaczony wentylator i jesli czas pracy przekroczyl czas wlaczenia wentylatora) to wylaczyc wentylator
if (secWentWyl < sec && digitalRead(PINWENTYL) == 1) {
digitalWrite(PINWENTYL,0);
autoSter = 3;
dodInfo = "parent.document.getElementById('dodInfo').innerHTML = 'AUTO';";
}

// Serial.println(wartoscAO);
ESP.wdtFeed();

// sprawdzenie czy jest wlaczony przekaznik rezystora powyzej 20 sekund
if (digitalRead(PINWENTREZ) == 0) {
tWlaczPRez = 0;
}
if (digitalRead(PINWENTREZ) == 1 && sec != TikTak) {
tWlaczPRez++;
}
if (tWlaczPRez > 20) {
digitalWrite(PINWENTREZ, 0);
}

// sprawdzenie czy jest polaczenie. Jesli jest to odczyt adresu IP do zmiennej
if (WiFi.status() != WL_CONNECTED) { // sprawdzenie czy jest polaczenie
PolaczTak = 0;
} else {
PolaczTak = 1;
IpAdressWysw = WiFi.localIP().toString();
}

if (sec > tWylDiod && DiodWl == 1) {
pixels.setPixelColor(0, 0, 0, 0);
pixels.setBrightness(0);
pixels.show();
tWylDiod = sec + 10;
DiodWl = 0;
}

if (sec > tWylDiod && DiodWl == 0) {
pixels.setBrightness(20);
pixels.setPixelColor(0, 0, 126, 255);
pixels.show();
tWylDiod = sec + 1;
DiodWl = 1;
}

if (tSAMOPODTRZ < sec && digitalRead(SAMOPODTRZ) == 1) {
digitalWrite(SAMOPODTRZ, 0);
delay(500);
}

if (TikTak != sec && digitalRead(PINWENTYL) == 1) {
tPRWENT++;
}
if (TikTak != sec && digitalRead(PINWENTYL) == 0) {
if (tPRWENT != 0) {
tLASTPRWENT = tPRWENT;
}
tPRWENT = 0;
}

if (TikTak != sec && digitalRead(PINWENTYL) == 0) {
tWYLWENT++;
}
if (TikTak != sec && digitalRead(PINWENTYL) == 1) {
if (tWYLWENT != 0) {
tLASTWYLWENt = tWYLWENT;
}
tWYLWENT = 0;
}

// nastepny pomiar do tablicy jesli uplynelo juz odpowiednio duzo czasu
if (TikTak != sec && nextPomiar == sec) {
nextPomiar = sec + coIlPomDoTab;
/*
// przesuniecie w tabeli do dolu wynikow pomiaru
for (int nrWTab = ilWykresikow; nrWTab > 1; nrWTab = nrWTab - 1) {
tabPomiar[(nrWTab - 1)] = tabPomiar[nrWTab];
}
*/
for (int nrWTab = 0; nrWTab < ilWykresikow + 1; nrWTab++) {
tabPomiar[nrWTab] = tabPomiar[nrWTab + 1];
}
if (TempI > 0) {
/*
int tempo = random(1, 95);
if (tabPomiar[ilWykresikow] <= tempo) {
tabPomiar[ilWykresikow+1] = tabPomiar[ilWykresikow] + 1;
if (tabPomiar[ilWykresikow+1] > 100) {
tabPomiar[ilWykresikow+1] = 100;
}
} else {
tabPomiar[ilWykresikow+1]--;
if (tabPomiar[ilWykresikow+1] < 1) {
tabPomiar[ilWykresikow+1] = 1;
}
}
*/

tabPomiar[ilWykresikow + 1] = TempI;
} else {
tabPomiar[ilWykresikow + 1] = 1;
}

// if (TempI > 1) {
// tabPomiar[ilWykresikow] = random(1, 95); // TempI;
// } else {
// tabPomiar[ilWykresikow] = 1;
// }
}

// Serial.println(analogRead(WEJZAPLON));

TikTak = sec; // zostawic na koncu petli loop. Roznica miedzy tymi zmiennymi oznacza, ze uplynela kolejna sekunda.
}

 

No i drugi plik z zmiennymi :

Spoiler

// Definicje pinow wejscia wyjscia
#define ONE_WIRE_BUS 0 // D3 pin do ktorego nalezy podlaczyc czyjnik DS18B20
#define PINSTER 13 // D7 pin sterujacy diodami RGB
#define PINWENTREZ 5 // D1 przekaznik wlaczajacy wentylator przez rezystor
#define PINWENTYL 4 // D2 przekaznik wlaczajacy wentylator
#define WEJZAPLON A0 // A0 wejscie sterujace maxymalnym czasem trwania wlaczenia wentylatora podlaczyc do zaplonu
#define SAMOPODTRZ 14 // D5 samopodtrzymanie zasilania

int tempMin, tempMax, czasRezys;

word dana1 = 0; // zmienna http
word dana2 = 0; // zmienna http
word dana3 = 0; // zmienna http
word dana4 = 0; // zmienna http
word opcja = 0; // opcja do rozpoznawania opcji
byte mac[6]; // przechowuje adres MAC
String macAddr = ""; // bedzie przechowywac w postaci String adress MAC
String KomText; // zmienna do przechowywania informacji zwrotnych
String IpAdressWysw;
int autoSter = 3;
int wartoscAO = 0;
int tWlaczPRez = 0;
String dodInfo = "";
unsigned long tSAMOPODTRZ = 30; // kiedy ma sie wylaczyc samopodtrzymanie przekaznika samopotrzymania
int tPODTRZZASIL = 600; // ile nalezy potrzymac zasilanie po wylaczeniu zaplonu
int tROZRUCH = 10; // czas po jakim od wlaczenia zaplonu moze sie uruchomic wentylator
unsigned long tROZRUCHRZ = 0; // jaki czas rzeczywisty uplynal od wlaczenia zaplonu
unsigned long tPRWENT = 0; // czas pracy wentylatora
unsigned long tWYLWENT = 0; // czas wylaczenia wentylatora
unsigned long tLASTPRWENT = 0;
unsigned long tLASTWYLWENt = 0;

unsigned long sec = 0; // zmienna zawierajaca ilosc sekund jaka uplynela od startu
unsigned long secWentNas = 0; // nastawa kiedy ma sie wylaczyc wentylator
unsigned long secWentWyl = 10; // nastawa po jakim czasie ma sie wylaczyc wentylator jesli byl wlaczony po wylaczeniu zaplonu
unsigned long TikTak = sec; // w petli loop roznica miedzy sec i TikTak oznacza ze juz uplynela wlasnie kolejna sekunda
int PolaczTak = 0; // czy jest polaczenie
unsigned long tWylDiod = 30; // czas o jakim trzeba wylaczyc diode RGB
int DiodWl = 1; // dioda swieci, dioda nie swieci
int CzyZamian = 0;

int tabNr = 1; // nr tabeli w html do generowania wykresu
int ilWykresikow = 275; // ilosc slupkow do wykresu
int tabPomiar[310]; // tabela kolejnych pomiarow
int coIlPomDoTab = 5; // co ile pomiar do tablicy pomiarow
unsigned long nextPomiar = sec + coIlPomDoTab; // kiedy nastepny pomiar
String danPomDoInp = ""; // string ktory bedzie wprowadzany do html jako dane do pomiarow

float TempI = 0;
float TempII = 0;

String ssid; // SSID sieci WiFi
String password; // domyslne haslo do sieci WiFi

 

Ten plik przed kompilacją trzeba zapisać w tym samym folderze dla Arduino IDE jako : "SsanWentylZmienne.h"
Dopiero wtedy można dokonać kompilacji ponieważ plik główny (program) includuje ten plik do swojej treści.

 

Dodałem guzik reset , który powoduje zrestartowanie sterownika jeśli taka ewntualność zajdzie w konieczności 🙂
Dodałem guzik zamiany czujników miejscami. Jeśli okazałoby się, że nie tam gdzie trzeba zamontowaliśmy czujniki
to można je na stałe z wpisem o tej informacji zapamiętać w EEPROM.
Dodałem też wykres , a dane są dopisywane co 5 sek. Przy wykresie o rozmiarze 270 pixeli daje to 1350 sekund historii.
Mikrokontroler się spokojnie wyrabia i tak na prawdę jest zrobiony na divach w html. Mogłem załadować jakiś skrypt w java, ale
w tym wypadku wydaje mi się, że byłoby to na wyrost. Wszystko aktualizuje się na ekranie w tle więc widać na bierząco wyświetlane
dane bez potrzeby przeładowywania strony.

Popelnilem dosc duzy blad w skrypcie 🙂 Jedna literka, a sterownik nie chcial sie wylaczac.
Przy okazji pozmienialem dosc duzo nie tylko w C ale tez w javaskrypcie.
Mianowicie zmienilem dosc znaczaco realizacje wykresu.
Teraz jest bardzo plynny i oparty na klasie charts. Cala klase nieco zmienilem i dodalem na swoj serwerk.
Bedzie tam lezec dlugo ...
Usprawnilem tez pare podprogramow. Wszystko testowalem w tym czasie i dziala bardzo dobrze.

Główny program :

/* * Program napisal CyberDuck, 29.01.2021
* Zawiera serwer www i polaczenie do wybranej sieci WiFi
* STEROWNIK WENTYLATORA CHLODNICY W SAMOCHODZIE
*
* http://10.10.11.120:400/?op=2&danaa=25&danab=27&danac=6 - zaladowanie ustawien i podanie statusu
* http://10.10.11.120:400/?op=1 - podanie statusu
*
*
*
*/

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>
#include <Adafruit_NeoPixel.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include "SsanWentylZmienne.h"

ESP8266WebServer server(400); // Port na jakim ma dzialac serwer www

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature DS18B20(&oneWire);

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(2, PINSTER, NEO_GRB + NEO_KHZ800);

void handleRoot() {
opcja = server.arg("op").toInt();
dana1 = server.arg("danaa").toInt();
dana2 = server.arg("danab").toInt();
dana3 = server.arg("danac").toInt();
dana4 = server.arg("danad").toInt();

if (opcja == 1) { // podanie statusu
daneDoStat();
}

// ramka do strony glownej ___________________________________________________________________________
if (opcja == 8) {
IpAdressWysw = WiFi.localIP().toString();

if (dana1 > 1) {
if (dana1 == 11) {
autoSter = 1;
}
if (dana1 == 12) {
autoSter = 2;
}
if (dana1 == 13) {
autoSter = 3;
}
}

KomText = "<script language='JavaScript'>";
KomText += "parent.document.getElementById('rssihtt').innerHTML = '";
KomText += WiFi.RSSI();
KomText += "';";
KomText += "parent.document.getElementById('TI').innerHTML = '";
KomText += TempI;
KomText += "';";
KomText += "parent.document.getElementById('tPracWent').innerHTML = '";
KomText += tPRWENT;
KomText += " , ";
KomText += tLASTPRWENT;
KomText += "';";
KomText += "parent.document.getElementById('tWylWent').innerHTML = '";
KomText += tWYLWENT;
KomText += " , ";
KomText += tLASTWYLWENt;
KomText += "';";
KomText += "parent.document.getElementById('tPracReg').innerHTML = '";
KomText += sec;
KomText += "';";

if (TempII == -127) {
KomText += "parent.document.getElementById('TII').innerHTML = 'brak';";
} else {
KomText += "parent.document.getElementById('TII').innerHTML = '";
KomText += TempII;
KomText += " ℃';";
}

if (autoSter == 1) {
KomText += "parent.document.getElementById('dodInfoI').style.color = 'white';";
KomText += "parent.document.getElementById('dodInfoII').style.color = 'blue';";
KomText += "parent.document.getElementById('dodInfoIII').style.color = 'blue';";
}
if (autoSter == 2) {
KomText += "parent.document.getElementById('dodInfoI').style.color = 'blue';";
KomText += "parent.document.getElementById('dodInfoII').style.color = 'white';";
KomText += "parent.document.getElementById('dodInfoIII').style.color = 'blue';";
}
if (autoSter == 3) {
KomText += "parent.document.getElementById('dodInfoI').style.color = 'blue';";
KomText += "parent.document.getElementById('dodInfoII').style.color = 'blue';";
KomText += "parent.document.getElementById('dodInfoIII').style.color = 'white';";
}
if (digitalRead(PINWENTYL) == 0 && digitalRead(PINWENTREZ) == 0) {
KomText += "parent.document.getElementById('statWent').innerHTML = ' ☣';"; // znaczek wentylatora
} else {
KomText += "parent.document.getElementById('statWent').innerHTML = ' ☢';"; // znaczek wentylatora
}

if (dana1 == 20) {
ESP.restart();
delay(5000);
}

if (tSAMOPODTRZ >= sec) {
KomText += "parent.document.getElementById('tWylSter').innerHTML = '";
KomText += (tSAMOPODTRZ - sec);
KomText += " sec';";
} else {
KomText += "parent.document.getElementById('tWylSter').innerHTML = '0';";
}
if (dana1 == 30) {
if (CzyZamian == 1) {
CzyZamian = 0;
EEPROM.write(3, 0);
} else {
CzyZamian = 1;
EEPROM.write(3, 1);
}
EEPROM.commit();
}

if (CzyZamian == 1) {
KomText += "parent.document.getElementById('ZnaczZamCzuj').innerHTML = '⇳';";
} else {
KomText += "parent.document.getElementById('ZnaczZamCzuj').innerHTML = 'X';";
}

// wpisywanie cykliczne do input 1 znaczy ze sterownik zyje
// if (sec < 40) { // warunek do testowania programu
KomText += "parent.document.getElementById('SprWylSterow').value = '1';";
// } // koniec warunek do testowania programu

if (NewPomReady == 1) {
KomText += "parent.document.getElementById('DanDoWykr').value = '";
KomText += tabPomiar[ilWykresikow + 1];
KomText += "';";
KomText += "parent.document.getElementById('CzyNextWart').value = '1'";
NewPomReady = 0;
}
KomText += "</script>";

KomText += "<meta http-equiv='Refresh' content='3; url=http://";
KomText += IpAdressWysw;
KomText += ":400/?op=8'>";

dodInfo = "";
}

// wywolanie strony glownej ______________________________________________________________________________
if (opcja == 0 || opcja == 9) {
IpAdressWysw = WiFi.localIP().toString();

if (dana1 > 1 && dana2 > 1 && dana3 > 0 && dana2 > dana1) {
EEPROM.write(0, dana1);
EEPROM.write(1, dana2);
EEPROM.write(2, dana3);
EEPROM.commit();

tempMin = dana1;
tempMax = dana2;
czasRezys = dana3;
}

KomText += "<!doctype html><html><head>";
KomText += "<script src='https://tomek.ec3.pl/jswykresik.js'></script>";
KomText += "<script>";
KomText += "'use strict';";

KomText += "window.chartColors = {";
KomText += "red: 'rgb(255, 99, 132)',";
KomText += "orange: 'rgb(255, 159, 64)',";
KomText += "yellow: 'rgb(255, 205, 86)',";
KomText += "green: 'rgb(75, 192, 192)',";
KomText += "blue: 'rgb(54, 162, 235)',";
KomText += "purple: 'rgb(153, 102, 255)',";
KomText += "grey: 'rgb(201, 203, 207)'";
KomText += "};";

KomText += "(function(global) {";

KomText += "Chart.defaults.global.defaultFontColor = 'yellow';";

KomText += "var MONTHS = [";
KomText += "];";

KomText += "var COLORS = [";
KomText += "];";

KomText += "var Samples = global.Samples || (global.Samples = {});";
KomText += "var Color = global.Color;";

KomText += "Samples.utils = {";
KomText += "srand: function(seed) {";
KomText += "this._seed = seed;";
KomText += "},";

KomText += "rand: function(min, max) {";
KomText += "var seed = this._seed;";
KomText += "min = min === undefined ? 0 : min;";
KomText += "max = max === undefined ? 1 : max;";
KomText += "this._seed = (seed * 9301 + 49297) % 233280;";
KomText += "return min + (this._seed / 233280) * (max - min);";
KomText += "},";

KomText += "numbers: function(config) {";
KomText += "var cfg = config || {};";
KomText += "var min = cfg.min || 0;";
KomText += "var max = cfg.max || 1;";
KomText += "var from = cfg.from || [];";
KomText += "var count = cfg.count || 8;";
KomText += "var decimals = cfg.decimals || 8;";
KomText += "var continuity = cfg.continuity || 1;";
KomText += "var dfactor = Math.pow(10, decimals) || 0;";
KomText += "var data = [];";
KomText += "var i, value;";

KomText += "for (i = 0; i < count; ++i) {";
KomText += "value = (from[i] || 0) + this.rand(min, max);";
KomText += "if (this.rand() <= continuity) {";
KomText += "data.push(Math.round(dfactor * value) / dfactor);";
KomText += "} else {";
KomText += "data.push(null);";
KomText += "}";
KomText += "}";
KomText += "return data;";
KomText += "},";

KomText += "labels: function(config) {";
KomText += "var cfg = config || {};";
KomText += "var min = cfg.min || 0;";
KomText += "var max = cfg.max || 100;";
KomText += "var count = cfg.count || 8;";
KomText += "var step = (max - min) / count;";
KomText += "var decimals = cfg.decimals || 8;";
KomText += "var dfactor = Math.pow(10, decimals) || 0;";
KomText += "var prefix = cfg.prefix || '';";
KomText += "var values = [];";
KomText += "var i;";

KomText += "for (i = min; i < max; i += step) {";
KomText += "values.push(prefix + Math.round(dfactor * i) / dfactor);";
KomText += "}";

KomText += "return values;";
KomText += "},";

KomText += "months: function(config) {";
KomText += "var cfg = config || {};";
KomText += "var count = cfg.count || 12;";
KomText += "var section = cfg.section;";
KomText += "var values = [];";
KomText += "var i, value;";

KomText += "for (i = 0; i < count; ++i) {";
KomText += "value = MONTHS[Math.ceil(i) % 12];";
KomText += "values.push(value.substring(0, section));";
KomText += "}";

KomText += "return values;";
KomText += "},";

KomText += "color: function(index) {";
KomText += "return COLORS[index % COLORS.length];";
KomText += "},";

KomText += "transparentize: function(color, opacity) {";
KomText += "var alpha = opacity === undefined ? 0.5 : 1 - opacity;";
KomText += "return Color(color).alpha(alpha).rgbString();";
KomText += "}";
KomText += "};";
KomText += "window.randomScalingFactor = function() {";
KomText += "return Math.round(Samples.utils.rand(-100, 100));";
KomText += "};";

KomText += "Samples.utils.srand(Date.now());";

KomText += "if (document.location.hostname.match(/'(www\.)?chartjs\.org$/)) {";
KomText += "(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){";
KomText += "(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),";
KomText += "m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)";
KomText += "})(window,document,'script','//www.google-analytics.com/analytics.js','ga');";
KomText += "ga('create', 'UA-28909194-3', 'auto');";
KomText += "ga('send', 'pageview');";
KomText += "}";

KomText += "}(this));";
KomText += "</script>";
KomText += "<style>";
KomText += "canvas{";
KomText += "-moz-user-select: none;";
KomText += "-webkit-user-select: none;";
KomText += "-ms-user-select: none;";
KomText += "}";
KomText += "</style>";
KomText += "</head><body>";

KomText += "<form autocomplete='off' action='' method='get'>";
KomText += "<input class='wpis' type='text' name='op' value='9' style='display:none'>";
KomText += "<table style='margin: 10px 70px;'><tr><td width='390px'>";
KomText += "<div class='myDiv'>";
KomText += "<table style='font-size:22px; text-align: left;'>";
KomText += "<tr>";
KomText += "<td width='10px'></td>";
KomText += "<td width='290px'>";
KomText += "<br>";
KomText += "Temp Min</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td></td>";
KomText += "<td>";
KomText += "<input class='wpis' type='text' name='danaa' value='";
KomText += tempMin;
KomText += "' style='width: 220px;'>";
KomText += "</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td></td>";
KomText += "<td>Temp Max</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td></td>";
KomText += "<td>";
KomText += "<input class='wpis' type='text' name='danab' value='";
KomText += tempMax;
KomText += "' style='width: 220px;'>";
KomText += "</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td></td>";
KomText += "<td>Czas Rozruchu</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td></td>";
KomText += "<td>";
KomText += "<input class='wpis' type='text' name='danac' value='";
KomText += czasRezys;
KomText += "' style='width: 220px;'>";
KomText += "</td>";
KomText += "</tr>";

KomText += "<tr>";
KomText += "<td></td>";
KomText += "<td>";

KomText += "<input type='submit' value='Zapisz' style='display:none;'>";
KomText += "<input id='DanDoWykr' type='text' name='DaneWykresu' value='1' style='display:none;'>";

KomText += "<input id='SprWylSterow' type='text' name='SprWylSterow_N' value='1' style='display:none;'>";
KomText += "<input id='CzyNextWart' type='text' name='CzyNextWart_N' value='0' style='display:none;'>"; // czy nastepny pomiar gotowy
KomText += "<br>";

KomText += "<div style='width:290px; background-color: red;'>";
KomText += " <canvas id='canvas' style='height: 300px'></canvas>";
KomText += "</div>";

KomText += "<br>";

KomText += "</td>";
KomText += "</tr>";

KomText += "</table>";
KomText += "</div>";

KomText += "</td><td valign='top'>";

KomText += "<div class='myDivII'>";
KomText += "<table style='font-size:23px'><tr><td width='10px'> </td><td><br>";
KomText += "TempI &nbsp;: <span id='TI'></span> ℃<br>";
KomText += "TempII : <span id='TII'></span><br><br>";
KomText += "Status Went : <span id='statWent'></span><br>";
KomText += "Wentylator pracuje : <span id='tPracWent'></span><br>";
KomText += "Spoczynek wentylat : <span id='tWylWent'></span><br>";
KomText += "Czas pracy sterownika : <span id='tPracReg'></span><br>";
KomText += "Wylaczenie sterownika : <span id='tWylSter'></span><br>";
KomText += "RSSI : <span id='rssihtt'></span><br><br>";

KomText += "<a style='text-decoration: none; cursor:pointer; color: cyan;' href='http://";
KomText += IpAdressWysw;
KomText += ":400'>STR</a>";
KomText += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&nbsp;&nbsp;";
KomText += "<span id='dodInfoI' onClick='WlaczWyl(11);' style='color:blue; cursor:pointer;'>ON</span>&nbsp;&nbsp;";
KomText += "<span id='dodInfoII' onClick='WlaczWyl(12);' style='color:blue; cursor:pointer;'>OFF</span>&nbsp;&nbsp;";
KomText += "<span id='dodInfoIII' onClick='WlaczWyl(13);' style='color:blue; cursor:pointer;'>AUTO</span>&nbsp;&nbsp;]";

KomText += "<br><br><br><br>";

KomText += "<span onClick='WlaczWyl(20);' style='color:blue; cursor:pointer;'>[ Reset ]</span>&nbsp;&nbsp;&nbsp;&nbsp;";
KomText += "<span onClick='WlaczWyl(30);' style='color:blue; cursor:pointer;'>[ Zam Czujnik </span>";
KomText += "<span id='ZnaczZamCzuj' style='color:blue; cursor:pointer;'>⇳</span> ]";
KomText += "<br><br>";
KomText += "</td></tr></table>";
KomText += "</div>";
KomText += "</td></tr></table>";

KomText += "</form>";

KomText += "<iframe id='dolStrony' name='ramka' marginwidth='0' marginheight='0' align='top' border='0' frameborder='0' ";
KomText += "width='1px' height='1px' ";
KomText += "src='https://";
KomText += IpAdressWysw;
KomText += ":400/?op=8' scrolling='no'></iframe>";

KomText += "<div id='OkienkoInf' class='myDivIII' style='display:none'>";
KomText += "..:: Prosze czekac ::..";
KomText += "</div>";

KomText += "<div id='OkienkoInfWyl' class='myDivIII_I' style='display:none'>";
KomText += "..:: Sterownik niedostepny ::..<br>";
KomText += "..:: lub zostal wylaczony ::..";
KomText += "</div>";

KomText += "<style>";
KomText += "html{";
KomText += "scroll-behavior: smooth;";
KomText += "}";

KomText += "body {";
KomText += "background-image: url('https://tomek.ec3.pl/tapSsang.jpg');";
KomText += "background-repeat: no-repeat;";
KomText += "background-position: center;";
KomText += "background-size: 100% 100%;";
KomText += "font-size: 25px;";
KomText += "color: #fff000;";
KomText += "}";

KomText += ".wpis {";
KomText += "font-size: 20px;";
KomText += "padding: 6px 6px;";
KomText += "margin: 6px 0;";
KomText += "display: inline-block;";
KomText += "border: 1px solid #ccc;";
KomText += "border-radius: 4px;";
KomText += "box-sizing: border-box;";
KomText += "font-weight: bold;";
KomText += "}";

KomText += ".myDiv {";
KomText += "padding: 1px 8px;";
KomText += "border: 5px outset brown;";
KomText += "text-align: center;";
KomText += "width: 330px;";
KomText += "background-color: rgba(255, 10, 0, 0.3);";
KomText += "}";

KomText += ".myDivII {";
KomText += "width: 390px;";
KomText += "font-size:25px;";
KomText += "padding: 1px 8px;";
KomText += "border: 5px outset brown;";
KomText += "background-color: rgba(255, 10, 0, 0.3);";
KomText += "}";

KomText += ".myDivIII {";
KomText += "width: 390px;";
KomText += "position: absolute;";
KomText += "text-align: center;";
KomText += "padding: 50px 0;";
KomText += "z-index: 3;";
KomText += "left: 240px;";
KomText += "top: 200px;";
KomText += "font-size:25px;";
KomText += "border: 5px outset brown;";
KomText += "background-color: rgba(255, 0, 0, 0.9);";
KomText += "}";

KomText += ".myDivIII_I {";
KomText += "width: 390px;";
KomText += "position: absolute;";
KomText += "text-align: center;";
KomText += "padding: 50px 0;";
KomText += "z-index: 4;";
KomText += "left: 240px;";
KomText += "top: 120px;";
KomText += "font-size:25px;";
KomText += "border: 5px outset brown;";
KomText += "background-color: rgba(255, 0, 0, 0.9);";
KomText += "}";

KomText += ".myDivIV {";
KomText += "border: 2px outset brown;";
KomText += "background-color: rgba(140, 0, 0, 0.9);";
KomText += "vertical-align: bottom;";
KomText += "height: 100px;";
KomText += "width: ";
KomText += ilWykresikow + 20;
KomText += "px;";
KomText += "background-color: red;";
KomText += "}";

KomText += ".myDivV {";
KomText += "float:left;";
KomText += "width:1px;";
KomText += "background-color: rgba(140, 0, 0, 0.02);";
KomText += "box-shadow: inset 5px 5px 10px;";
KomText += "}";

KomText += "</style>";

KomText += "<script>";

KomText += "var MONTHS = [''];";
KomText += "var config = {";
KomText += "type: 'line',";
KomText += " data: {";
KomText += " labels: [''],";
KomText += " datasets: [{";
KomText += " label: '',";
KomText += " fill: false,";
KomText += " backgroundColor: window.chartColors.red,";
KomText += " borderColor: window.chartColors.yellow,";
KomText += " pointRadius: 0,";
KomText += " data: [";
KomText += " 1";
KomText += " ],";
KomText += " }]";
KomText += " },";
KomText += " options: {";
KomText += " responsive: true,";

KomText += " title: {";
KomText += " display: false,";
KomText += " text: ''";
KomText += " },";

KomText += " tooltips: {";
KomText += " mode: 'index',";
KomText += " intersect: false,";
KomText += " },";
KomText += " hover: {";
KomText += " mode: 'nearest',";
KomText += " intersect: false";
KomText += " },";
KomText += " scales: {";
KomText += " xAxes: [{";
KomText += " display: false,";
KomText += " scaleLabel: {";
KomText += " display: false,";
KomText += " labelString: ''";
KomText += " }";
KomText += " }],";
KomText += " yAxes: [{";
KomText += " display: true,";
KomText += " scaleLabel: {";
KomText += " display: false,";
KomText += " labelString: ''";
KomText += " }";
KomText += " }]";
KomText += " }";
KomText += " }";
KomText += "};";

KomText += "window.onload = function() {";
KomText += " var ctx = document.getElementById('canvas').getContext('2d');";
KomText += " window.myLine = new Chart(ctx, config);";
KomText += "};";

KomText += "function powtorz() {";
KomText += " if ((document.getElementById('CzyNextWart').value) == '1') {";
KomText += " if (config.data.datasets.length > 0) {";

KomText += " var month = MONTHS[config.data.labels.length % MONTHS.length];";
KomText += " config.data.labels.shift(month);";
KomText += " config.data.datasets.forEach(function(dataset) {";
KomText += " dataset.data.shift();";
KomText += " });";

KomText += " var month = MONTHS[config.data.labels.length % MONTHS.length];";
KomText += " config.data.labels.push(month);";
KomText += " config.data.datasets.forEach(function(dataset) {";
KomText += " ostatWartosc = document.getElementById('DanDoWykr').value;";
KomText += " dataset.data.push(ostatWartosc);";

KomText += " });";
KomText += " ilosc++;";
KomText += " window.myLine.update();";
KomText += " }";

KomText += " document.getElementById('CzyNextWart').value = '0';";
KomText += " }";
KomText += " setTimeout('powtorz();', 500);";
KomText += "}";

KomText += "function powtorzI(ksksks) {";
KomText += " if (config.data.datasets.length > 0) {";
KomText += " var month = MONTHS[config.data.labels.length % MONTHS.length];";
KomText += " config.data.labels.push(month);";
KomText += " config.data.datasets.forEach(function(dataset) {";
KomText += " dataset.data.push(ksksks);";
KomText += " });";
KomText += " window.myLine.update();";
KomText += " }";
KomText += "}";

for (int sss=0; sss<=ilWykresikow; sss++) {
KomText += " setTimeout('powtorzI(";
KomText += tabPomiar[sss];
KomText += ");',(";
KomText += sss;
KomText += "*2));";
}

KomText += "ilosc = ";
KomText += ilWykresikow;
KomText += ";";
KomText += "ostatWartosc = 0;";
KomText += "setTimeout('powtorz();',2000);";

KomText += "</script>";

KomText += "<script language='JavaScript'>";
KomText += "function WlaczWyl(SposSter) {";
KomText += "var SposSter = SposSter;";
KomText += "if (SposSter == 20) {";
KomText += " document.getElementById('OkienkoInf').style.display = ''; ";
KomText += " setTimeout('OdswierzStrone();', 10000); ";
KomText += "}";
KomText += "ramka.location.href='http://";
KomText += IpAdressWysw;
KomText += ":400/?op=8&danaa=' + SposSter;";
KomText += "}";

KomText += "function OdswierzStrone() {";
KomText += "document.location.href='http://";
KomText += IpAdressWysw;
KomText += ":400';";
KomText += "}";

KomText += "function sprWylaczenie () {";
KomText += " document.getElementById('OkienkoInfWyl').style.display = 'none';";
KomText += " if (document.getElementById('SprWylSterow').value == '0') {";
KomText += " document.getElementById('OkienkoInfWyl').style.display = '';";
KomText += " } else {";
KomText += " document.getElementById('OkienkoInfWyl').style.display = 'none';";
KomText += " document.getElementById('SprWylSterow').value = '0';";
KomText += " }";
KomText += " setTimeout('sprWylaczenie();', 6000);";
KomText += "}";

KomText += "setTimeout('sprWylaczenie();', 10000);";

KomText += "</script>";
KomText += "</body></html>";

delay(10);

}

char html[4000];
server.send ( 200, "text/html", KomText );
KomText = "";
}

// strony nie znaleziono
void handleNotFound() {
String message = "File Not Found\n\n";
message += "URI: ";
message += server.uri();
message += "\nMethod: ";
message += ( server.method() == HTTP_GET ) ? "GET" : "POST";
message += "\nArguments: ";
message += server.args();
message += "\n";

for ( uint8_t i = 0; i < server.args(); i++ ) {
message += " " + server.argName ( i ) + ": " + server.arg ( i ) + "\n";
}

server.send ( 404, "text/plain", message );
}

void setup() {
pinMode(PINWENTREZ, OUTPUT);
pinMode(PINWENTYL, OUTPUT);
pinMode(SAMOPODTRZ, OUTPUT);
// pinMode(WEJZAPLON, INPUT_PULLUP);
digitalWrite(PINWENTREZ, 0);
digitalWrite(PINWENTYL, 0);
digitalWrite(SAMOPODTRZ, 1);

Serial.begin(115200);
pixels.begin();
EEPROM.begin(1024);
delay(100);

pixels.setPixelColor(0, 0, 0, 0);
pixels.setBrightness(0);
pixels.show(); // przesylam do diod

ssid = "CybDroid";
password = "gosc1111";

delay(10);

DS18B20.begin();
readEpromZmienne();
// -------------------------------------------

delay(200);

WiFiClient client;
WiFi.softAPdisconnect(true);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println(" ");
Serial.println("Laczenie do sieci WiFi :");
for (int polacz = 0; polacz <= 20; polacz++) {
if (WiFi.status() != WL_CONNECTED) {
// brak polaczenia
pixels.setPixelColor(0, 0, 126, 255);
pixels.setBrightness(100);
pixels.show(); // przesylam do diod
delay(100);
pixels.setPixelColor(0, 255, 0, 0);
pixels.setBrightness(50);
pixels.show(); // przesylam do diod
Serial.print(".");
delay(100);
PolaczTak = 0;
} else {
// polaczono do wifi
Serial.println();
Serial.print("Adres IP :");
Serial.println(WiFi.localIP());
IpAdressWysw = WiFi.localIP().toString();
Serial.print("MacAddres : ");
WiFi.macAddress(mac);
macAddr = String(mac[0], HEX);
macAddr += (":");
macAddr += String(mac[1],HEX);
macAddr += (":");
macAddr += String(mac[2],HEX);
macAddr += (":");
macAddr += String(mac[3],HEX);
macAddr += (":");
macAddr += String(mac[4],HEX);
macAddr += (":");
macAddr += String(mac[5],HEX);
Serial.println(macAddr);
Serial.print("RSSI : ");
Serial.println(WiFi.RSSI());
pixels.setPixelColor(0, 0, 126, 255);
pixels.setBrightness(20);
pixels.show(); // przesylam do diod
PolaczTak = 1;
break;
}
}
ESP.wdtEnable(8000);

server.on ( "/", handleRoot );
server.on ( "/inline", []() {
server.send ( 200, "text/plain", "this works as well" );
} );
server.onNotFound ( handleNotFound );

server.begin();
WiFi.macAddress(mac);
macAddr = String(mac[0], HEX);
macAddr += (":");
macAddr += String(mac[1],HEX);
macAddr += (":");
macAddr += String(mac[2],HEX);
macAddr += (":");
macAddr += String(mac[3],HEX);
macAddr += (":");
macAddr += String(mac[4],HEX);
macAddr += (":");
macAddr += String(mac[5],HEX);

for(int i=0; i <= ilWykresikow; i++) {
// tabPomiar[i] = random(1, 100);
tabPomiar[i] = 1;
}
}

// Odczyt z pamieci EEPROM do zmiennych ustawien
void readEpromZmienne() {
tempMin = EEPROM.read(0); // temperatura minimalna chlodziwa - wylaczenie wentylatora
tempMax = EEPROM.read(1); // temperatura maxymalna chlodziwa - wlaczenie wentylatora
czasRezys = EEPROM.read(2); // czas przez jaki ma byc wlaczony rezystor zanim zalaczy sie zasilanie glowne w sek
CzyZamian = EEPROM.read(3); // czy zamieniac czujniki miejscami
}

// przygotowanie danych dla statusu
void daneDoStat() {
sec = millis() / 1000;
KomText = TempI;
KomText += "|";
KomText += TempII;
KomText += "|";
KomText += tempMin;
KomText += "|";
KomText += tempMax;
KomText += "|";
KomText += czasRezys;
KomText += "|";
KomText += sec;
KomText += "|";
KomText += macAddr;
KomText += "|";
KomText += WiFi.RSSI();
}

// petla programu

void loop() {
sec = millis() / 1000;
DS18B20.requestTemperatures();
// czy zamiana czujnikow
TempI = DS18B20.getTempCByIndex(0);
TempII = DS18B20.getTempCByIndex(1);
// czy zamiana czujnikow
if (CzyZamian == 1) {
float temporary = TempI;
TempI = TempII;
TempII = temporary;
}

server.handleClient();
// odczyt wrtosci z wejscia odczytu zaplonu i usrednianie wartosci
wartOdczA0 = analogRead(WEJZAPLON);
if (wartoscAO < wartOdczA0) { wartoscAO = wartoscAO + 30; }
if (wartoscAO > wartOdczA0) { wartoscAO = wartoscAO - 2; }
if (wartoscAO < 1) { wartoscAO = 1; }
if (wartoscAO > 1024) { wartoscAO = 1024; }

// sprawdzenie czy jest wlaczony zaplon, i jesli jest wlaczony to nastawa wylaczenia wentylatora po 60 sek.
if (wartoscAO > 500) { // wartosc powyzej 500 oznacza ze jest wlaczony zaplon
secWentWyl = sec + 60; // jesli zaplon wylaczony to max po 60 sekundach ma sie wylaczyc wentylator
tSAMOPODTRZ = sec + tPODTRZZASIL; // jesli zaplon wylaczony to max po 600 sekundach samopotrzymanie ma sie wylaczyc
} else {
tROZRUCHRZ = 0;
}

if (sec != TikTak) {
tROZRUCHRZ++;
}

if (autoSter == 3 && secWentWyl > sec) {
if (tROZRUCHRZ > tROZRUCH) { // sprawdzenie czy uplynal odpowiedni czas po wlaczeniu zaplonu i czy mozna juz wlaczyc wentylator automatycznie
// rozruch wentylatora przez rezystor
if (TempI > tempMax && digitalRead(PINWENTREZ) == 0 && digitalRead(PINWENTYL) == 0) {
secWentNas = sec + czasRezys;
digitalWrite(PINWENTREZ,1);
}
// po ustalonym czasie wlaczenie wentylatora bez rezystora
if (secWentNas < sec && digitalRead(PINWENTREZ) == 1) {
digitalWrite(PINWENTYL,1);
delay(100);
digitalWrite(PINWENTREZ,0);
}
}
// jesli wentylator dziala i temperatura spadnie poniezej ustalownej wartosci to wylaczenie wentylatora
if (TempI < tempMin && digitalRead(PINWENTYL) == 1) {
digitalWrite(PINWENTYL,0);
}
} else {
if (autoSter == 1 && digitalRead(PINWENTYL) == 0) {
digitalWrite(PINWENTYL,1);
tSAMOPODTRZ = sec + 3600;
secWentWyl = sec + 60;
}
if (autoSter == 2 && digitalRead(PINWENTYL) == 1) {
digitalWrite(PINWENTYL,0);
secWentWyl = sec + 60;
tSAMOPODTRZ = sec + tPODTRZZASIL;
}
}

// sprawdzenie czy jest (wlaczony wentylator i jesli czas pracy przekroczyl czas wlaczenia wentylatora) to wylaczyc wentylator
if (secWentWyl < sec && digitalRead(PINWENTYL) == 1) {
digitalWrite(PINWENTYL,0);
autoSter = 3;
dodInfo = "parent.document.getElementById('dodInfo').innerHTML = 'AUTO';";
}

// Serial.println(wartoscAO);
ESP.wdtFeed();

// sprawdzenie czy jest wlaczony przekaznik rezystora powyzej 20 sekund
if (digitalRead(PINWENTREZ) == 0) {
tWlaczPRez = 0;
}
if (digitalRead(PINWENTREZ) == 1 && sec != TikTak) {
tWlaczPRez++;
}
if (tWlaczPRez > 20) {
digitalWrite(PINWENTREZ, 0);
}

// sprawdzenie czy jest polaczenie. Jesli jest to odczyt adresu IP do zmiennej
if (WiFi.status() != WL_CONNECTED) { // sprawdzenie czy jest polaczenie
PolaczTak = 0;
} else {
PolaczTak = 1;
IpAdressWysw = WiFi.localIP().toString();
}

if (sec > tWylDiod && DiodWl == 1) {
pixels.setPixelColor(0, 0, 0, 0);
pixels.setBrightness(0);
pixels.show();
tWylDiod = sec + 10;
DiodWl = 0;
}

if (sec > tWylDiod && DiodWl == 0) {
pixels.setBrightness(20);
pixels.setPixelColor(0, 0, 126, 255);
pixels.show();
tWylDiod = sec + 1;
DiodWl = 1;
}

if (TikTak != sec && digitalRead(PINWENTYL) == 1) {
tPRWENT++;
}
if (TikTak != sec && digitalRead(PINWENTYL) == 0) {
if (tPRWENT != 0) {
tLASTPRWENT = tPRWENT;
}
tPRWENT = 0;
}

if (TikTak != sec && digitalRead(PINWENTYL) == 0) {
tWYLWENT++;
}
if (TikTak != sec && digitalRead(PINWENTYL) == 1) {
if (tWYLWENT != 0) {
tLASTWYLWENt = tWYLWENT;
}
tWYLWENT = 0;
}

// nastepny pomiar do tablicy jesli uplynelo juz odpowiednio duzo czasu
if (TikTak != sec && nextPomiar == sec) {
nextPomiar = sec + coIlPomDoTab;

if (TempI > 0) {
tabPomiar[ilWykresikow + 1] = TempI;
} else {
tabPomiar[ilWykresikow + 1] = 1;
}
// tabPomiar[ilWykresikow + 1] = random(1, 100);

for (int nrWTab = 0; nrWTab < ilWykresikow + 1; nrWTab++) {
tabPomiar[nrWTab] = tabPomiar[nrWTab + 1];
}
NewPomReady = 1;
}

if ((tSAMOPODTRZ < sec) && (digitalRead(SAMOPODTRZ) == 1) && (sec > 14)) {
digitalWrite(SAMOPODTRZ, 0);
delay(500);
}

// Serial.print(wartOdczA0);
// Serial.print("\t");
// Serial.println(wartoscAO);
// delay(100);

TikTak = sec; // zostawic na koncu petli loop. Roznica miedzy tymi zmiennymi w petli loop
// oznacza, ze uplynela kolejna sekunda.
}

Skrypt z zmiennymi nalezy jak zwykle umiescic w tym samym folderze co plik INO.

// Definicje pinow wejscia wyjscia
#define ONE_WIRE_BUS 0 // D3 pin do ktorego nalezy podlaczyc czyjnik DS18B20
#define PINSTER 13 // D7 pin sterujacy diodami RGB
#define PINWENTREZ 5 // D1 przekaznik wlaczajacy wentylator przez rezystor
#define PINWENTYL 4 // D2 przekaznik wlaczajacy wentylator
#define WEJZAPLON A0 // A0 wejscie sterujace maxymalnym czasem trwania wlaczenia wentylatora podlaczyc do zaplonu
#define SAMOPODTRZ 14 // D5 samopodtrzymanie zasilania

int tempMin, tempMax, czasRezys;

word dana1 = 0; // zmienna http
word dana2 = 0; // zmienna http
word dana3 = 0; // zmienna http
word dana4 = 0; // zmienna http
word opcja = 0; // opcja do rozpoznawania opcji
byte mac[6]; // przechowuje adres MAC
String macAddr = ""; // bedzie przechowywac w postaci String adress MAC
String KomText; // zmienna do przechowywania informacji zwrotnych
String IpAdressWysw;
int autoSter = 3;
int wartoscAO = 0; // wartosc odczytana z czujnika zaplonu
int wartOdczA0 = 0;
int tWlaczPRez = 0;
String dodInfo = "";
unsigned long tSAMOPODTRZ = 30; // kiedy ma sie wylaczyc samopodtrzymanie przekaznika samopotrzymania
int tPODTRZZASIL = 600; // ile nalezy potrzymac zasilanie po wylaczeniu zaplonu
int tROZRUCH = 10; // czas po jakim od wlaczenia zaplonu moze sie uruchomic wentylator
unsigned long tROZRUCHRZ = 0; // jaki czas rzeczywisty uplynal od wlaczenia zaplonu
unsigned long tPRWENT = 0; // czas pracy wentylatora
unsigned long tWYLWENT = 0; // czas wylaczenia wentylatora
unsigned long tLASTPRWENT = 0;
unsigned long tLASTWYLWENt = 0;

unsigned long sec = 0; // zmienna zawierajaca ilosc sekund jaka uplynela od startu
unsigned long secWentNas = 0; // nastawa kiedy ma sie wylaczyc wentylator
unsigned long secWentWyl = 10; // nastawa po jakim czasie ma sie wylaczyc wentylator jesli byl wlaczony po wylaczeniu zaplonu
unsigned long TikTak = sec; // w petli loop roznica miedzy sec i TikTak oznacza ze juz uplynela wlasnie kolejna sekunda
int PolaczTak = 0; // czy jest polaczenie
unsigned long tWylDiod = 30; // czas o jakim trzeba wylaczyc diode RGB
int DiodWl = 1; // dioda swieci, dioda nie swieci
int CzyZamian = 0;

int tabNr = 1; // nr tabeli w html do generowania wykresu
int ilWykresikow = 275; // ilosc slupkow do wykresu
int tabPomiar[280]; // tabela kolejnych pomiarow
int NewPomReady = 0; // kiedy nowy pomiar wykonany to ta zmienna przyjmuje 1
int coIlPomDoTab = 5; // co ile pomiar do tablicy pomiarow
unsigned long nextPomiar = sec + coIlPomDoTab; // kiedy nastepny pomiar
String danPomDoInp = ""; // string ktory bedzie wprowadzany do html jako dane do pomiarow

float TempI = 0;
float TempII = 0;

String ssid; // SSID sieci WiFi
String password; // domyslne haslo do sieci WiFi