szczawiosław Lipiec 26, 2019 Autor tematu Udostępnij Lipiec 26, 2019 No 🙂 Przy okazji dorobiłem obsługę przekaźników do sterowania wentylatorami aby załączały mi się razem z ogniwami i wyłączały z opóźnieniem. Muszę zastanowić się czy mam taka funkcjonalność już jaką chciałem i brać się za budowę komory. No i pozbyć się zmiennych globalnych które są używane w tylko jednej funkcji, a zamiast tego użyć argumentów funkcji, ale to już zależy od tego czy mi się będzie chciało 🙂 Cytuj Link do komentarza Share on other sites More sharing options...
szczawiosław Wrzesień 23, 2019 Autor tematu Udostępnij Wrzesień 23, 2019 W końcu znalazłem trochę czasu na budowę komory. Styropian 10cm grubości, wartość oporu 3,00 m2K/W, współczynnik przewodzenia ciepła 0,033 W/mK więc mam nadzieję że wystarczy aby układ chłodzenia nie działał cały czas na pełnych obrotach, szczególnie że jego głównym zadaniem ma być utrzymywanie temperatury, a nie chłodzenie. Od środka i na zewnątrz oklejony ekranem za grzejnikowym (jako dodatkowa izolacja, tjuning optyczny i zabezpieczanie przed kruszeniem styropianu ). Przygotowałem dwie wersje pokrywy, pełną i z miejscem na układ chłodzenia (tą jeszcze kończę i zastanawiam się nad sposobem mocowania dosyć ciężkiego układu chłodzenia w styropianie). Wszystkie szczeliny wypełnione dodatkowo masą izolacyjną aby zminimalizować ilość mostków termicznych. Ekran wewnątrz klejony na zakładkę, z zewnątrz komora owinięta na około. W tym tygodniu przeprowadzę testy jak sobie radzi z utrzymaniem temperatury wewnątrz na pełnej pokrywie. Mam nadzieję że w ciągu miesiąca uda już mi się odpalić całość z układem chłodzenia. 1 Cytuj Link do komentarza Share on other sites More sharing options...
szczawiosław Październik 2, 2019 Autor tematu Udostępnij Październik 2, 2019 Wczoraj skończyłem wszystko składać. Wygląda że będzie działać 🙂 . Jak odpaliłem podpinając na krótko i wykorzystując 1/3 mocy temperatura spadła o ok. 10°C w ciągu 15min. Nie testowałem jeszcze szczelności na tej pokrywie, przy pełnej wyrównanie temperatury wewnątrz z temp. otoczenia zajęła 5 dni kiedy w środku znajdowały się 2 butelki 1,5l z wodą o temperaturze początkowej 10°C. Muszę jeszcze dodatkowo zaizolować duży radiator od góry, aby zmniejszyć wpływ otoczenia i jak wszystko dobrze wyschnie w pt pewnie będę sprawdzał jaką temperaturę minimalną uda się wewnątrz osiągnąć wykorzystując tym razem ok 1/2 mocy ogniw. 1 Cytuj Link do komentarza Share on other sites More sharing options...
Treker (Damian Szymański) Październik 2, 2019 Udostępnij Październik 2, 2019 @szczawiosław wygląda już kosmicznie 😉 Żadne upały za rok Cie nie zaskoczą! Cytuj Link do komentarza Share on other sites More sharing options...
Polecacz 101 Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Produkcja i montaż PCB - wybierz sprawdzone PCBWay! • Darmowe płytki dla studentów i projektów non-profit • Tylko 5$ za 10 prototypów PCB w 24 godziny • Usługa projektowania PCB na zlecenie • Montaż PCB od 30$ + bezpłatna dostawa i szablony • Darmowe narzędzie do podglądu plików Gerber Zobacz również » Film z fabryki PCBWay
szczawiosław Październik 2, 2019 Autor tematu Udostępnij Październik 2, 2019 Zobaczymy jak się sprawdzi i czy za dużo prądu zużywać nie będzie. Muszę jeszcze płytkę pod elektronikę zaprojektować, teraz jak znam wymiary będzie łatwiej i może do końca miesiąca wszytko zrobię. 1 Cytuj Link do komentarza Share on other sites More sharing options...
szczawiosław Październik 25, 2019 Autor tematu Udostępnij Październik 25, 2019 (edytowany) Skończyłem budować już komorę. Obecnie jestem w trakcie testów wydajności, zabezpieczeń, itp. Zmierzyłem pobór prądu przy maksymalnym obciążeniu i wyszło ~200W. Całość prezentuje się następująco: Pokrywa z układem chłodzenia oraz sterownikiem: Sam sterownik: Kod programu, main.h: #include <OneWire.h> #include <DallasTemperature.h> #include <EEPROM.h> #include <WiFi.h> #include <WiFiClient.h> #include <ArduinoJson.h> #include <Timers.h> #include "Virtuino_ESP_WifiServer.h" void WriteEEPROM(); void ReadEEPROM(); void SendingValues(); void PeltierControl(); void CalcDiffTemp(); void ReadTemp(); void FanControlON(); void FanTimeControlOFF(); void ControlSecurityStatus(); String PrepareHtmlPage(); #define ONE_WIRE_BUS 15 #define EEPROM_SIZE 4 #define CoolingPin 33 #define WarmingPin 32 #define SignalPWM 22 #define EnablePin 25 #define FanHot 26 #define FanCold 27 #define VirtuinoControlTempDisplay 25 OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); DXviXXAddrXss TXmpSXnsorXXrmXntXr = { 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xX, 0xX, 0xXX }; DXviXXAddrXss TXmpSXnsorXhamXXr = { 0xXX, 0xXX, 0xX, 0xXX, 0xXX, 0xX, 0xX, 0xXX }; DXviXXAddrXss TXmpSXnsorRadiator = { 0xXX, 0xXX, 0xXX, 0xX, 0xXX, 0xXX, 0xX, 0xXX }; DXviXXAddrXss TXmpSXnsorXontrollXr = { 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xX, 0xXX }; char APssid[] = "SSID"; char APpass[] = "PASSWORD"; WiFiServer VirtuinoServer(80); WiFiServer iSpindelServer(81); float TempiSpindel; float TempFermenter; float TempChamber; float TempController; float TempRadiator; float Gravity; float Battery; float ImportanceTempiSpindel = 0.1; float ImportanceTempChamber = 0.1; float AverageTemp; float SetTemp; float DiffTemp; float SavedTemp; const int freq = 500; const int ChanelPWM = 0; const int resolution = 8; int PWMFilling = 0; byte iSpindelReading = 0; byte SecurityStatus = 0; byte PeltierStatus = 0; unsigned long FanTime; unsigned long FanHotTime = 25000; unsigned long FanColdTime = 60000; unsigned long ReadTime; unsigned long ReadTempTime = 2000; float SecurityHighTempRadiator = 50.0; float SecurityLowTempRadiator = 35.0; float SecurityHighTempController = 50.0; float SecurityLowTempController = 35.0; byte SecurityControler = 0; byte SecurityRadiator = 0; Oraz main.cpp: #include "main.h" Virtuino_ESP_WifiServer virtuino(&VirtuinoServer); void setup() { virtuino.DEBUG = false; sensors.begin(); EEPROM.begin(EEPROM_SIZE); pinMode(CoolingPin, OUTPUT); pinMode(WarmingPin, OUTPUT); pinMode(FanHot, OUTPUT); pinMode(FanCold, OUTPUT); pinMode(EnablePin, OUTPUT); ledcSetup(ChanelPWM, freq, resolution); ledcAttachPin(SignalPWM, ChanelPWM); ReadEEPROM(); digitalWrite(CoolingPin, LOW); digitalWrite(WarmingPin, LOW); digitalWrite(FanHot, LOW); digitalWrite(FanCold, LOW); ledcWrite(ChanelPWM, 0); WiFi.mode(WIFI_AP); WiFi.softAP(APssid, APpass); virtuino.password = "1234"; VirtuinoServer.begin(); iSpindelServer.begin(); delay(1000); delay(1000); } void loop(void) { ControlSecurityStatus(); WiFiClient iSpindelClient = iSpindelServer.available(); virtuino.run(); SetTemp = virtuino.vMemoryRead(0); if (SetTemp!=SavedTemp) { WriteEEPROM(); } SavedTemp = SetTemp; if (iSpindelClient) { while (iSpindelClient.connected()) { if (iSpindelClient.available()) { String line = iSpindelClient.readStringUntil('\r'); const size_t capacity = JSON_OBJECT_SIZE(9) + 90; const char* json = line.c_str(); DynamicJsonDocument doc(capacity); deserializeJson(doc, json); if (doc["ID"] == 1234567) { TempiSpindel = doc["temperature"]; Gravity = doc["gravity"]; Battery = doc["battery"]; iSpindelReading = 1; } } }; delay(1); iSpindelClient.stop(); } if ((millis() - ReadTime) >= ReadTempTime) { ReadTemp(); ReadTime = millis(); } CalcDiffTemp(); if (PeltierStatus != 0) { PeltierControl(); } if (virtuino.lastCommunicationTime != 0) { SendingValues(); virtuino.lastCommunicationTime = 0; } FanTimeControlOFF(); yield(); } void ReadTemp() { sensors.requestTemperatures(); TempFermenter = sensors.getTempC(TempSensorFermenter); TempChamber = sensors.getTempC(TempSensorChamber); TempController = sensors.getTempC(TempSensorController); TempRadiator = sensors.getTempC(TempSensorRadiator); } void CalcDiffTemp() { if (iSpindelReading != 0) { AverageTemp = TempiSpindel * ImportanceTempiSpindel + TempChamber * ImportanceTempChamber + TempFermenter * (1.0F - ImportanceTempiSpindel - ImportanceTempChamber); } else { AverageTemp = TempChamber * ImportanceTempChamber + TempFermenter * (1.0F - ImportanceTempChamber); } DiffTemp = round((SetTemp - AverageTemp)*10)/10; PWMFilling = fabs(DiffTemp)*510; if (DiffTemp <= -0.3F) { digitalWrite(CoolingPin, HIGH); digitalWrite(WarmingPin, LOW); PeltierStatus = 1; } else if (DiffTemp >= 0.3F) { digitalWrite(CoolingPin, LOW); digitalWrite(WarmingPin, HIGH); PeltierStatus = 1; } else if (abs(DiffTemp) <= 0.1F) { digitalWrite(CoolingPin, LOW); digitalWrite(WarmingPin, LOW); PeltierStatus = 0; } } void SendingValues() { virtuino.vMemoryWrite(1, TempiSpindel); virtuino.vMemoryWrite(2, TempFermenter); virtuino.vMemoryWrite(3, TempChamber); virtuino.vMemoryWrite(4, AverageTemp); virtuino.vMemoryWrite(5, Gravity); virtuino.vMemoryWrite(6, Battery); virtuino.vMemoryWrite(7, TempController); virtuino.vMemoryWrite(8, TempRadiator); if (SecurityStatus == 0 && digitalRead(CoolingPin) != 0) { virtuino.vMemoryWrite(9, -PWMFilling); } else if (SecurityStatus == 0 && digitalRead(WarmingPin) != 0) { virtuino.vMemoryWrite(9, PWMFilling); } else { virtuino.vMemoryWrite(9, 0); } virtuino.vMemoryWrite(10, digitalRead(FanHot)); virtuino.vMemoryWrite(11, digitalRead(FanCold)); } void PeltierControl() { if (SecurityStatus == 0) { if (abs(DiffTemp) < 0.50F) { digitalWrite(EnablePin, HIGH); FanControlON(); ledcWrite(ChanelPWM, PWMFilling); } else { digitalWrite(EnablePin, HIGH); ledcWrite(ChanelPWM, 255); FanControlON(); } } } void WriteEEPROM() { EEPROM.put(0, SetTemp); delay(100); EEPROM.commit(); delay(100); } void ReadEEPROM() { SetTemp = EEPROM.get(0, SetTemp); delay(100); SavedTemp = SetTemp; virtuino.vMemoryWrite(0, SetTemp); delay(100); } void FanControlON() { digitalWrite(FanHot, HIGH); digitalWrite(FanCold, HIGH); FanTime = millis(); } void FanTimeControlOFF() { if (SecurityStatus == 0) { if ((millis() - FanTime) >= FanHotTime) { digitalWrite(FanHot, LOW); digitalWrite(EnablePin, LOW); } if ((millis() - FanTime) >= FanColdTime) { digitalWrite(FanCold, LOW); digitalWrite(EnablePin, LOW); } } } String PrepareHtmlPage() { String htmlPage = String("HTTP/1.1 200 OK\r\n") + "Content-Type: text/html\r\n" + "Connection: close\r\n" + // the connection will be closed after completion of the response "Refresh: 5\r\n" + // refresh the page automatically every 5 sec "\r\n" + "<!DOCTYPE HTML>" + "<html>" + "Analog input: " + String(analogRead(A0)) + "</html>" + "\r\n"; return htmlPage; } void ControlSecurityStatus() { if (TempRadiator >= SecurityHighTempRadiator && SecurityStatus == 0) { SecurityStatus = 1; SecurityRadiator = 1; FanControlON(); digitalWrite(EnablePin, LOW); } else if (TempController >= SecurityHighTempController && SecurityStatus == 0) { SecurityStatus = 1; SecurityControler = 1; digitalWrite(FanCold, LOW); digitalWrite(FanHot, LOW); digitalWrite(EnablePin, LOW); } else if (SecurityStatus == 1 && TempRadiator <= SecurityLowTempRadiator && SecurityControler == 0) { SecurityStatus = 0; SecurityRadiator = 0; } else if (SecurityStatus == 1 && TempController <= SecurityLowTempController && SecurityRadiator == 0) { SecurityStatus = 0; SecurityControler = 0; } } Obecnie jeszcze tak jak pisałem sprawdzam poprawność działania, testuje wartości opóźnień (np. odczyt temperatury co 2s jest zbyt częsty i bezsensowny, ale do testów przydatny). Miałem trochę zabawy z parsowaniem JSONa przesyłanego od iSpindla ale działa już tak jak powinno 🙂 No i teraz komunikacja następuje co 10s, ostatecznie pewnie będzie co 30min. Całością steruję za pomocą aplikacji stworzonej w Virtuino, myślałem o BLYNK, ale doszedłem do wniosku że sterowanie przez internet jest zbędne. Na górze aplikacji wyświetlam uśrednioną temperaturę z trzech termometrów (w iSpindlu, przyczepiony do boku pojemnika, bezpośrednio z komory) oraz zawartość cukru w płynie (na razie iSpindel nie jest skalibrowany poprawnie). Tym dużym pokrętłem reguluję temperaturę która chcę mieć. Poniżej wyświetlam moc chłodzenia/grzania (mocno zmniejszyłem histerezę względem założeń), oraz wyświetlam temperaturę z trzech czujników. Dwie pompy sygnalizują pracę wentylatorów na stronie ciepłej i zimnej. Na samym dole mam informacje o napięciu w iSpindlu, odczyt temperatury z czujnika znajdującego się obok radiatorów doczepionych do mostków, oraz czujnika przyczepionego do radiatora od ogniwa Peltiera. Chcę jeszcze dodać wyświetlacz LCD i możliwość sterowania za pomocą fizycznych przycisków, ale na razie nie mam pomysłu jak to miało by działać. Edytowano Październik 25, 2019 przez szczawiosław 1 Cytuj Link do komentarza Share on other sites More sharing options...
Treker (Damian Szymański) Październik 25, 2019 Udostępnij Październik 25, 2019 @szczawiosław wygląda bardzo fajnie, całkiem rozbudowany projekt z tego wyszedł! 4 godziny temu, szczawiosław napisał: Całością steruję za pomocą aplikacji stworzonej w Virtuino, myślałem o BLYNK, ale doszedłem do wniosku że sterowanie przez internet jest zbędne. I jak oceniasz prace z Virtuino? Dobrze się sprawdziło? Cytuj Link do komentarza Share on other sites More sharing options...
szczawiosław Październik 25, 2019 Autor tematu Udostępnij Październik 25, 2019 Do mojego zastosowania całkiem spoko się sprawdziło. BLYNK jest łatwiejszy w obsłudze, dodatkowo jeżeli postawimy własny serwer mamy praktycznie nieograniczoną wielkość aplikacji, w Viruino niestety ograniczenia nie ominiemy za wyjątkiem wersji płatnej. Sama aplikacja jest dosyć rozbudowana jednak wydaje się trochę toporna. Brakowało mi jakiegoś wigetu który umożliwia zmianę wartości przyciskami + i - (stąd pokrętło, które jest strasznie czułe). Aplikacja na pewno dobra jeżeli chcemy mieć wpływ na każdy możliwy aspekt wyglądu aplikacji. Mamy możliwość obrabiania danych w aplikacji, nie musimy tego implementować w kodzie programu. Sama praca z aplikacją przez mnogość ustawień i mała przejrzystość bywa mocno upierdliwa. Dodatkowo jeżeli chcemy mieć wykres wartości z jakiegoś okresu w przypadku braku serwera musimy przechowywać w pamięci mikrokontrolera. 1 Cytuj Link do komentarza Share on other sites More sharing options...
Pomocna odpowiedź
Dołącz do dyskusji, napisz odpowiedź!
Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!