Skocz do zawartości
szczawiosław

Komora termiczna - kontrola procesu fermentacji

Pomocna odpowiedź

Jako że zdarza mi się nawarzyć piwa postanowiłem zrobić komorę fermentacyjną aby móc kontrolować proces fermentacji, a tym samym poszerzyć ilość dostępnych do wykonania gatunków. Na obecną chwilę jestem na etapie planowania, projektowania, liczenia, itp. Zakładam że w pół roku skończę cały projekt 😊 (brak czasu robi swoje).

Całą komorę wykonać chcę ze styropianu, myślałem o styrodurze ale współczynnik cena/jakoś sprawił że jest to  nieopłacalne. Dodatkowo od środka wyłożyć ekranem zagrzejnikowym (może od zewnątrz też). Do utrzymywania temperatury wykorzystać chcę 2 ogniwa peltiera 10A (TEC1-12710). Podpięte do mostków H (albo do dwóch przekaźników każde) aby móc sterować polaryzacją (i ewentualnie wykorzystując PWM także mocą). Z zewnątrz komory do ogniw zamocowany radiator razem z wentylatorem.

Myślałem o czymś takim (bądź podobnym):

obraz.thumb.png.87c04f7d0e30c0565709b2a219f32f62.png

Od strony wewnętrznej pewnie jedna wspólna płyta aluminiowa z trzema radiatorami i jeden albo dwa wentylatory. Wentylatory sterowane 0/1 bo nie widzę potrzeby tutaj sterowania dodatkowo ich prędkością. Różnica temperatur jaką chcę osiągnąć to 15˚C pomiędzy otoczeniem, a wnętrzem komory.

Pomiar temperatury wewnątrz komory za pomocą 3 czujników temperatury (TMP36GT9Z, bądź coś podobnego). Jeden umieszczony pod fermentorem, dwa na ściankach. Myślałem jeszcze o zanurzeniowym, ale ciecz ma dużą bezwładność cieplną.

Sterownik oparty na ESP32. Pomyślałem o zrobieniu PIDa, ale to plan na dalszą przyszłość bo nie cierpię dobierania nastaw. W pierwszej kolejności sterowanie histerezą. Do tego prosty panel sterowania z możliwością kontroli temperatury. Myślę jeszcze nad aplikacją BLYNK i wyświetlaczem LCD oraz przyciskami aby kontrolować parametry nie tylko zdalnie i mieć możliwość ręcznego zmieniania temperatury.

Całość zasilana z zasilacza komputerowego. Jak w końcu zdecyduję się na komponenty których chce użyć będę musiał policzyć dokładne zapotrzebowanie i wybrać moc zasilacza.

Zakładam że projekt skończę do czerwca, jak się przeciągnie nie będę płakał, a jak uda się szybciej będzie fajnie.

Na obecną chwilę mam projekt komory wykonanej ze styropianu 50mm. Z obliczeń wyszło że współczynnik izolacji cieplnej powinien być wystarczający aby osiągnąć zakładaną różnicę temperatur, a układ chłodzący nie działał cały czas. Objętość komory wynosi ok. 120l, mogę pewnie ją jeszcze zmniejszyć i użyć grubszego styropianu, ale w tym celu muszę dokładnie fermentor zmierzyć.

 obraz.thumb.png.3d3e63c842e99a845219fbf8f31aaa55.png

Do tego jestem jeszcze na etapie liczenia wszystkiego co związane z ciepłem aby sprawdzić czy projekt ma sens, mam nadzieję że skończę to w tym tygodniu. Jak będę miał to już policzone będę w stanie dobrać odpowiednie ogniwa i zabiorę się za projekt elektroniki.

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

Tak na szybko, zakładając komorę 50x50x50cm (ok. 120 litrów), styropian 0.04W/mK o grubości 5cm to pole powierzchni wychodzi 1.5m2. Chcąc uzyskać chłodzenie o 15 stopni względem temperatury otoczenia trzeba założyć, że radiatory strony ciepłej będą jeszcze o 20 stopni cieplejsze niż powietrze, ale nie znam skali tego co narysowałeś. Jeśli to jest wiatraczek od kompa i radiator od procka to przy grzaniu 100W to mogą mieć nawet i 50 stopni więcej. Zapotrzebowanie na moc chłodzenia (czyli to co przenika przez styropian do środka) wyniesie ok 18W, ale Peltiery będą widziały różnicę >35 stopni.Masz jakieś wykresy dla tych ogniw?

EDIT: O rany, jakoś zapamiętałem, że planujesz 120 litrów a na chacie widzę 40l.. Wszystkie liczby do kosza.

Edytowano przez marek1707
  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

Mój błąd, myślałem że wyjdzie ok. 40l i tyle napisałem na chacie, a po zaprojektowaniu i sprawdzeniu wymiarów komory mam 120l (i to jest w poście) 🙂 Radiator który pokazałem jest do chłodzenia procka w kompie, niby są do kupienia "dedykowane" ale po co jak coś jest w pudle z częściami 🙂

Wykres dla ogniw:

obraz.thumb.png.99af1f22bb1e866987bc9f7e9cc3e53e.png

A jak to liczyłeś? Ja korzystałem (i nadal korzystam) z jakichś skomplikowanych wzorów używanych przy docieplaniu budynków, itp.

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

W końcu przyszły ogniwa. Przeprowadziłem na szybko testy i się okazało że nawet radiator miedziany bez wentylatora daje z 2x lepsze wyniki niż aluminiowy z wentylatorem (oba zbliżonej wielkości). Przy warunkach:

  • temp. otoczenia ~23oC,
  • zasilanie 12V,
  • pobór ~7,5A,
  • miedziany radiator z wentylatorem od strony ciepłej.

Temperatura strony zimnej wynosiła -20oC. Po dołożeniu aluminiowego radiatora razem z wentylatorem na stronę zimną temperatura radiatora wynosiła ok. -10oC. Czekam teraz na mostek H oraz duży radiator aluminiowy (na stronę zimną) i będę brał się za składanie wszystkiego.

W projekcie zmieniłem grubość styropianu na 10cm, zmniejszyła mi się pojemność i powierzchnia wewnętrzna, teraz wewnątrz mam wymiary:

  • wysokość 480mm,
  • szerokość 400mm,
  • długość 400mm.

Objętość spadła do niecałych 80l. dzięki grubszym ściankom powinienem móc spokojnie osiągnąć zakładaną różnicę temperatur.

Dodatkowo zamiast płyty aluminiowej z doczepionymi radiatorami użyję dużego aluminiowego radiatora z doczepionymi 2 wentylatorami aby nie opierać się tylko na konwekcji.

 

Bez nazwy.png156115574_Beznazwy2.thumb.png.679f4914b5ac3af7f7ee3130a9d89008.png

Edytowano przez szczawiosław
  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

Złożyłem duży radiator (na razie bez wentylatorów na stronie zimnej). Trochę duży klocek wyszedł:

obraz.thumb.png.4550f7ca04e4007a458084615f1141a9.png

W testach minimalna temperatura po 15 min na zimnej stronie wynosiła ok. -15oC. Czekam jeszcze na mostek i będę brał się za elektronikę i programowanie.

Pirometr wychwycił mi minimalną temp. -45oC. Był raczej ustawiony prawidłowo, a nie jestem w stanie w taką temp uwierzyć.

Edytowano przez szczawiosław

Udostępnij ten post


Link to post
Share on other sites
Dnia 15.02.2019 o 12:22, szczawiosław napisał:

Pirometr wychwycił mi minimalną temp. -45oC. Był raczej ustawiony prawidłowo, a nie jestem w stanie w taką temp uwierzyć.

Faktycznie wydaje się trochę podejrzana taka temperatura. Z ciekawości: na jakiej powierzchni dokonywałeś pomiaru? Może tu coś zakłóciło pomiar...

Udostępnij ten post


Link to post
Share on other sites

Na stronie żebrowanej, pirometr przyłożony do żeber, aby pomiar był prostopadle do powierzchni (mam taki co mierzy wszystko jak leci, a nie na skrzyżowaniu wiązek lasera). Emisyjność ustawiona na 0,1 bo powierzchnia błyszcząca. Wcześniej wykonałem pomiar kontrolny w ten sam sposób by zobaczyć czy pokaże temp. otoczenia i było ok. Tylko ten jeden pomiar mnie dziwi.

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

W końcu znalazłem czas aby usiąść znów do tematu. Zabrałem się za pisanie kodu do sterownika. Zdecydowałem się na sterowanie temperaturą poprzez histerezę (robienie jakiegoś PIDa raczej sensu w tym wypadku nie ma, bo piwowarstwo to nie farmacja i wahania temperatury o 1°C różnicy wielkiej nie robi).

Na razie wszystko z grubsza złożone na płytce stykowej. Trzy czujniki DS18B20 do pomiaru temperatury (jeden zanurzeniowy, drugi będzie umieszczony w dnie komory od strony fermentora, natomiast trzeci najprawdopodobniej przyklejany do ścianki fermentora). Odczyt z każdego czujnika ma nadaną wagę do wyliczania średniej, ze względu na czujnik zanurzeniowy i dużą bezwładność cieplną płynów będę musiał pewnie dobrać je eksperymentalnie już w gotowej komorze. Do sterowania peltierami wykorzystam dwa pojedyncze  Monster Motor Shield oparte na układzie VNH2SP30. W teorii mógł bym zrobić na jednym, ale u majfrendów nie są drogie i będę miał pewność że wytrzymają. Testuję wszystko na jednym takim układzie z podłączonym silniczkiem. Sterowanie mocą mam zrobione stopniowe, każdy 1°C różnicy pomiędzy temperaturą faktyczną, a zadaną to wzrost mocy grzania/chłodzenia o 10%. Muszę dorobić jeszcze sterowanie wentylatorami, tutaj najpewniej zrobię to po prostu na przekaźnikach bo nie mam potrzebny regulowania prędkości obrotowej. Mają się kręcić albo nie i tyle.

Chciałem zrobić sterowanie poprzez BLYNK i prostą stronę WWW na ESP32, ale ostatecznie zdecydowałem na wykorzystanie BLYNK i VIRTUINO. Łatwiejsza implementacja niż pisanie całej strony. Jeżeli sterownik ma dostęp do Internetu mogę wykorzystać BLYNK i z dowolnego miejsca kontrolować parametry oraz sterować temperaturą. Jeżeli sterownik i telefon znajdują się w tej samej sieci mogę wykorzystać VIRTUINO bez potrzeby używania zewnętrznego serwera. Umożliwia mi to też sterowania w sytuacji kiedy sterownik nie ma dostępu do WiFi. W takim wypadku łącze się bezpośrednio z AP sterownika i przez VIRTUINO także mogę kontrolować parametry. Muszę jeszcze dokładnie przetestować działanie obu aplikacji bo trochę się gryzą, o ile wyświetlanie działa bez problemu o tyle zadawanie temperatury z dwóch aplikacji potrafi spowodować konflikt jeżeli zrobię to w niewłaściwym momencie i ustawienie wartości z kosmosu. Sporo czasu spędziłem na rozwiązaniu problemu blokowania programu przez BLYNKa w sytuacji kiedy nie miał dostępu do Internetu albo serwera, ale chyba ostatecznie udało mi się to rozwiązać przez kilka ifów sprawdzających połączenia z WiFi, Internetem i serwerem przed wywołaniem funkcji blynk.run() (nadal to testuje w różnych konfiguracjach).

Kolejnym krokiem będzie tak jak już pisałem dorobienie sterowania wentylatorami, uporządkowanie odbierania i wysyłania danych z i do aplikacji tak aby nie powodowało to konfliktów, nie wskakiwała mi randomowa temperatura (przeważnie 0°C). Zadana temperatura oczywiście jest przechowywana w EEPROMie, muszę się zastanowić czy jakieś wartości jeszcze warto zapisywać, bo danych dostępowych sieci, itp. Raczej nie potrzebuję. Nie zmieniam co 2tyg. haseł, sieć raz postawiona ma działać i tyle. No i muszę sprawdzić czy mam w piwnicy zasięg WiFi, niby w linii prostej niecałe 5m, ale po skosie przez strop żelbetowy i ścianę nośną. Jak nie to pewnie zrezygnuje z BLYNKa i od razu rozwiąże mi to problemy z konfliktem między aplikacjami 😊

Mam nadzieję do końca miesiąca uporać się z programem i zacząć budowę samej komory. To zostanie mi zaprojektowanie prostej (mam nadzieję) płytki w którą będę mógł to wszystko wpiąć i we wrześniu odpalić sprawne i działające urządzenie.

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

Skończyłem kod sterownika. Na obecną chwilę sterowanie tylko za pomocą VIRTUINO, bo niestety nie mam zasięgu w piwnicy 😞 Zastanawiam się nad dodaniem wyświetlacza LCD i kilku przycisków aby można też było podglądać parametry i je zmieniać bez konieczności używania telefonu.

Kod programu

#include "main.h"

Virtuino_ESP_WifiServer virtuino(&server);

void setup() {
  virtuino.DEBUG = true;
  Serial.begin(115200);
  sensors.begin();
  EEPROM.begin(EEPROM_SIZE);
  
  pinMode(Cooling, OUTPUT);
  pinMode(Warming, OUTPUT);

  ledcSetup(ChanelPWM, freq, resolution);
  ledcAttachPin(SignalPWM, ChanelPWM);

  ReadEEPROM();

  digitalWrite(Cooling, LOW);
  digitalWrite(Warming, LOW);
  ledcWrite(ChanelPWM, 0);

  WiFi.mode(WIFI_AP);
  WiFi.softAP(APssid, APpass); 

  virtuino.password = "1234";
  

  server.begin();

  delay(1000);  
}

void loop(void) {
  Serial.println("------------------------------");
  virtuino.run();

  SetTemp = virtuino.vMemoryRead(0);
  Serial.println("Odczytane SetTemp: " + String(SetTemp) + "*C");

  if (SetTemp!=SavedTemp) {
    WriteEEPROM();
    FirstStart = 1;   
  }
  SavedTemp = SetTemp;

  ReadTemp();
  CalcDiffTemp();
  SendingValues();
  ControlTemp();

  delay(2000);
}

void ReadTemp() {
  sensors.requestTemperatures();  
  Temp1 = sensors.getTempC(sensor1); 
  Temp2 = sensors.getTempC(sensor2);
  Temp3 = sensors.getTempC(sensor3);
}

void CalcDiffTemp() {
  AverageTemp = Temp1 * ImportanceTemp1 + Temp2 * ImportanceTemp2 + Temp3 * ImportanceTemp3;
  DiffTemp = (round((SetTemp - AverageTemp)*10)/10);

  if (DiffTemp < -0.5F) {
    digitalWrite(Cooling, HIGH);
    digitalWrite(Warming, LOW);
    virtuino.vMemoryWrite(GREEN, -2);
    virtuino.vMemoryWrite(BLUE, 1);
    virtuino.vMemoryWrite(RED, -2);
  } else if (DiffTemp > 0.5F) {
    digitalWrite(Warming, HIGH);
    digitalWrite(Cooling, LOW);
    virtuino.vMemoryWrite(GREEN, -2);
    virtuino.vMemoryWrite(BLUE, -2);
    virtuino.vMemoryWrite(RED, 1);
  } else {
    digitalWrite(Cooling, LOW);
    digitalWrite(Warming, LOW);
    virtuino.vMemoryWrite(GREEN, 1);
    virtuino.vMemoryWrite(BLUE, -2);
    virtuino.vMemoryWrite(RED, -2);
  }
}

void SendingValues() {
  Serial.println("Sensor 1: " + String(Temp1) + "*C");
  Serial.println("Sensor 2: " + String(Temp2) + "*C");
  Serial.println("Sensor 3: " + String(Temp3) + "*C");
  Serial.println("SetTemp: " + String(SetTemp) + "*C");
  Serial.println("DiffTemp: " + String(abs(DiffTemp)) + "*C");

  virtuino.vMemoryWrite(1, Temp1);
  virtuino.vMemoryWrite(2, Temp2);
  virtuino.vMemoryWrite(3, Temp3);
  virtuino.vMemoryWrite(4, AverageTemp);
}

void ControlTemp() {
  if (abs(round(DiffTemp)) <= 9) {
    ledcWrite(ChanelPWM, abs(DiffTemp)*25);
  } else {
    ledcWrite(ChanelPWM, 255);
  }
}

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);
  Serial.println("EEPROM SetTemp: " + String(SetTemp) + "*C");
  Serial.println("EEPROM SavedTemp: " + String(SavedTemp) + "*C");
  delay(1000);
}

I plik nagłówkowy


#include <OneWire.h>
#include <DallasTemperature.h>
#include <EEPROM.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include "Virtuino_ESP_WifiServer.h"

void WriteEEPROM();
void ReadEEPROM();
void SendingValues();
void ControlTemp();
void CalcDiffTemp();
void ReadTemp();

#define ONE_WIRE_BUS 15

#define EEPROM_SIZE 4

#define Cooling 32
#define Warming 33
#define SignalPWM 22

#define GREEN   10
#define BLUE    11
#define RED     12

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

String inString = "";

DeviceAddress sensor1 = { 0x28, 0xFF, 0xBE, 0x6E, 0x6E, 0x18, 0x1, 0xB5 };
DeviceAddress sensor2 = { 0x28, 0xFF, 0x79, 0x21, 0x69, 0x18, 0x3, 0x7A };
DeviceAddress sensor3 = { 0x28, 0xFF, 0xD5, 0x17, 0x69, 0x18, 0x3, 0x29 };

char APssid[] = "Komora";
char APpass[] = "Haslo";

WiFiServer server(80);

float Temp1;
float Temp2;
float Temp3;

float ImportanceTemp1 = 0.6;
float ImportanceTemp2 = 0.2;
float ImportanceTemp3 = 0.2;

float AverageTemp;
float SetTemp;
float DiffTemp;

float SavedTemp;

const int freq = 500;
const int ChanelPWM = 0;
const int resolution = 8;

int FirstStart = 0;

Na razie go testuje czy wszystko będzie działać jak należy w rożnych sytuacjach.

No i sama aplikacja

67304844_392175764768799_5979695658402054144_n.thumb.jpg.933ad4dded842200f3e0c75f0600339d.jpg

Edytowano przez szczawiosław
  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites
1 godzinę temu, szczawiosław napisał:

DiffTemp = (round((SetTemp - AverageTemp)*10)/10);

Tak się zastanawiam czy to dzielenie przez 10 jest konieczne.

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

@Belferek bez tego na wyjściu uzyskuję liczbę całkowitą, przy dzieleniu mam dokładność do jednego miejsca po przecinku.

No i jeszcze muszę trochę kod uporządkować, bo np. ustawianie koloru mogę do funkcji wywalić zamiast ustawiać każdorazowo parametry oddzielnie.

Edytowano przez szczawiosław

Udostępnij ten post


Link to post
Share on other sites

No tak tyle, że jaka to różnica by była gdyby zamiast if (DiffTemp < -0.5F) użyć if (DiffTemp < -5) ?

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

Taka że tą liczbę wykorzystuję dodatkowo do sterowania wypełnieniem PWM

ledcWrite(ChanelPWM, abs(DiffTemp)*25);

I tutaj i tak musiał bym dzielić na 10, albo mnożnik zrobić 0,25.

No i łatwiej przy kontroli działania jak wyświetlam DiffTemp nie zastanawiać się czemu jest 20 a nie 2.

Edytowano przez szczawiosław

Udostępnij ten post


Link to post
Share on other sites

@szczawiosław chyba Ci się coś niedobrego zrobiło z nawiasami... chyba chciałeś round(cośtam*10)?

Udostępnij ten post


Link to post
Share on other sites

@ethanak nawiasy są ok 🙂 Mnożę różnicę dwóch temperatur i kolejność wykonywania działań się pojawia. Chyba że bym  (SetTemp - AverageTemp) wywalił do kolejnej zmiennej.

Udostępnij ten post


Link to post
Share on other sites

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!

Gość
Napisz odpowiedź...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.


×
×
  • Utwórz nowe...