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.