Navrhli jsme si (nejen) bazénový teploměr pro měření teploty vody v něm. Chtěli jsme vytvořit zařízení, které nemá téměř žádnou spotřebu a na vyžádání ukáže teplotu vody. Úpravou kódu lze ale docílit i odesílání data na nějakou službu – například TMEP.
Celé zařízení je napájeno z baterie, ta se nabíjí ze solárního panelu. Teplota je měřena voděodolným čidlem DS18B20, napětí baterie pak řídící deskou Meteo Mini a napětí a nabíjecí proud ze solárního panelu pak modulem INA219. Údaje jsou zobrazeny na OLED 128x32px.
Vývoj bazénového teploměru potřeboval několik iterací vývoje 🙂 Nejprve zjištění, že původně vybraný solární panel nedokázal, bez změny rezistoru určujícího nabíjecí proud, nabít baterii – kvůli malému dodanému proudu – a navíc celá krabička byla velmi malá a delší kabel voděodolného teplotního čidla DS18B20 dokázalo celý celou krabičku potopit.
Teď tu máme druhou verzi, která už funguje tak, jak má.
Hardware
Celý projekt řídí univerzální deska s čipem ESP32-C3 Meteo Mini, který dokáže komunikovat přes Wi-Fi nebo Bluetooth. My jsme ani Wi-Fi ani Bluetooth nevyužili právě kvůli co nejnižší spotřebě.
Pokud je ale třeba, stačí upravit kód a Meteo Mini může posílat data na web. Třeba TMEP.cz, který ukládá a zobrazuje tvá data jak na webu, tak i třeba aplikaci na telefon.
Pokud budeš chtít využít Wi-Fi nebo Bluetooth – doporučujeme koupit verzi s externí anténou. Bazén asi budeš mít nějaký ten kus cesty od tvého routeru.
Jako teplotní čidlo jsme zvolili voděodolný DS18B20. Kabel si zastřihneš na potřebnou délkou – jen pozor, aby kabel nebyl moc dlouhý a „nepotopil“ celý projekt pod vodu. My máme zastřihnuto na 20cm a plave.
Údaje – teplota vody, napětí baterie, napětí a proud ze soláru – zobrazujeme na našem OLED 128×32 px přes náš uŠup konektor. Výhoda spočívá v možnosti odpojení napájení čidla a snížení tak spotřeby na minimum.
Údaje ze soláru pak měříme taky námi navrženým modulem pro měření napětí a proudu s INA219. I napájení tohoto modulu měřící aktuální údaje ze solárního panelu vypínáme díky připojení přes I2C uŠup konektor (co to je?).
Na základě našeho kódu se měření provede jedenkrát za 15 minut, údaje se zobrazí na OLED displeji a po několika sekundách se opět zařízení vypne do co nejnižší spotřeby. Pokud se chceš na teplotu podívat okamžitě, můžeš zařízení probudit přes kapacitní tlačítko umístěné uvnitř krabičky – Kapacitní Dotykové tlačítko s TTP223.
O nabíjení se stará solární panel 136×110 s hodnotami 6V/2W. Nabíjecí obvod je umístěn přímo na Meteo Mini.
Vzhledem k použitému solárnímu panelu doporučujeme změnit maximální nabíjecí proud na 260mA, to uděláš tak, že přeřízneš na spodní straně Meteo Mini pájecí most označený jako 0.4A a zapájíš 0.26A.
Pro uchycení všech modulů do těla krabičky jsme použili šrouby do plastu s půlkulatou hlavou a křížovou drážkou 2,2×5.
Jako baterii jsme zvolili LiPol 2500 mAh, která by měla mít dostatek kapacity na dlouhodobý provoz i bez funkčního solárního panelu.
Zapojení celého bazénového teploměru je velmi jednoduché.
GND solárního panelu je připojen na „-“ konektor SOLAR (pokud nemáš protikus konektoru JST-PH 2.0, můžete jej připojit na GND.
Napětí ze solárního panelu vede na INA219 a poté na druhý vstup konektoru SOLAR (pokud nemáš protikus konektoru JST-PH 2.0, můžeš jej připojit na VCC).
uŠup kabel připoj mezi Meteo Mini a INA219, a poté z INA219 na OLED. Zkontroluj, že alespoň na jedné desce/modulu jsou připojené pull-up rezistory na I2C (pájecí propojka).
LiPol baterii připoj na vstup BATTERY.
Voděodolné čidlo DS18B20 připoj na Meteo Mini, pozice označená jako DS18B20.
Kapacitní tlačítko připoj k Meteo Mini – VCC tlačítka na 3.3V Meteo Mini, GND na GND, I/O na GPIO4.
3D tisk krabičky
Krabička, ve které je (nejen) bazénový teploměr umístěn, je 3D tištěná. To má výhody a nevýhody.
Výhody: jednoduché na výrobu, jednoduchý úpravy a opakovatelnost.
Nevýhody: nutnost 3D tiskárny, nutné úpravy pro zvýšení voděodolnosti krabičky
Pro tisk doporučujeme materiál PETG nebo ABS.
Počet perimetrů – kompletně vyplnit boky krabičky. Tedy kompletní výplň.
Úprava po vytištění. Pro zvýšení voděodolnosti velmi doporučujeme přestříkat voděodolným lakem – v několika vrstvách.
Otvor pro OLED displej je potřeba tisknout s podpěrami. OLED musí být ochráněn před vodou z venku. My využili čirý tvrdý plast z krabičky vývojového kitu STM Nucleo a obdelník z tohoto plastu nalepili pomocí sanitárního silikonu.
Pro uchycení všech modulů do těla krabičky jsme použili šrouby do plastu s půlkulatou hlavou a křížovou drážkou 2,2×5.
Držák pro uchycení krabičky mimo bazén jsme využili systém od Vladimíra Waase (printables). A to je možná odpověď na tvou otázku „Proč píšou „(nejen) bazénový teploměr“ ???“ – protože v zimě mrzne a bazeň je buď zakrytovaný nebo vypuštěný. Proto můžeš tento teploměr připevnit například na tyč na tvé zahradě a místo měření teploty vody budeš měřit teplotu vzduchu – pak by se hodil i radiační štít.
Solární panel jsme ke krabičce také přilepili sanitárním silikonem.
Model krabičky je ke stažení na Bazénový teploměr s velmi malou spotřebou a nabíjením ze solárního panelu by LaskaKit
Software
Napsali jsme velmi jednoduchý kód s ohledem na co nejnižší spotřebu.
Po startu se modulům připojeným přes I2C připojí napájení vyjma kapacitního tlačítka TTP223, které je připojené na napájení přímo.
Toto tlačítko je připojené na pin IO4 a jen tento IO vstup může probudit Meteo Mini – ESP32-C3 – ze spánku.
Po změření napětí baterie, napětí a proudu ze solárního panelu a teploty vody/vzduchu a zobrazení údajů na OLED se opět uspí na 15 minut nebo až do dalšího probuzení přes kapacitní tlačítko.
Při kompilaci kódu v Arduino IDE můžeš ovlivnit snížit spotřebu ESP32-C3 i díky triku se snížením frekvence na kterém jádro běží. Pokud nepoužíváš Wi-Fi nebo Bluetooth, můžeš snížit frekvenci na 40 MHz. Výrazně tak snížíš odběr proudu ESP32-C3 během doby, kdy čeká na změřena data – napětí baterie, solárního panelu, proud solárním panelem a teplota vody/vzduchu.
#include <Wire.h>
#include <Adafruit_INA219.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <OneWire.h>
#include <DallasTemperature.h>
// Pin assignments
#define ONE_WIRE_BUS 10
#define BATTERY_PIN 0
#define WAKEUP_PIN 4
#define PWR_PIN 3
#define SLEEP_TIME 300 // in s
// OLED display settings
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define SCREEN_ADDRESS 0x3C // 0x3C for 128x32
#define BATT_DIV_RATION 1.7693877551 // Voltage devider ratio on ADC pin 1MOhm + 1.3MOhm
// Create objects for DS18B20, INA219, and OLED display
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
Adafruit_INA219 ina219;
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
void setup()
{
Serial.begin(115200);
pinMode(PWR_PIN, OUTPUT);
digitalWrite(PWR_PIN, HIGH); // turn on the I2C power
Wire.begin(19,18);
delay(500);
// Initialize DS18B20 sensor
sensors.begin();
// Initialize INA219 sensor
if (!ina219.begin()) {
Serial.println("Failed to find INA219 chip");
digitalWrite(PWR_PIN, LOW);
Serial.flush();
esp_sleep_enable_timer_wakeup(SLEEP_TIME * 1000000);
esp_deep_sleep_start();
}
// Initialize OLED display
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
digitalWrite(PWR_PIN, LOW);
Serial.flush();
esp_sleep_enable_timer_wakeup(SLEEP_TIME * 1000000);
esp_deep_sleep_start();
}
// Setup wakeup pin
pinMode(WAKEUP_PIN, INPUT_PULLUP);
esp_deep_sleep_enable_gpio_wakeup(1 << WAKEUP_PIN, ESP_GPIO_WAKEUP_GPIO_HIGH); // Wake up on low signal
// Print initial values to the display
updateDisplay();
digitalWrite(PWR_PIN, LOW);
Serial.flush();
esp_sleep_enable_timer_wakeup(SLEEP_TIME * 1000000);
esp_deep_sleep_start();
}
void loop()
{
}
void updateDisplay()
{
// Read temperature from DS18B20
sensors.requestTemperatures();
delay(1000);
float temperatureC = sensors.getTempCByIndex(0);
// Read battery voltage
Serial.print("BATT: "); Serial.println(analogReadMilliVolts(BATTERY_PIN));
float batteryVoltage = (analogReadMilliVolts(BATTERY_PIN) * BATT_DIV_RATION / 1000);
// Read solar panel voltage and current from INA219
float shuntVoltage = ina219.getShuntVoltage_mV();
float busVoltage = ina219.getBusVoltage_V();
float current_mA = ina219.getCurrent_mA();
float loadVoltage = busVoltage + (shuntVoltage / 1000);
// Update the OLED display with the current values
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.print("Bat: ");
display.print(batteryVoltage);
display.println(" V");
display.println("Solar: ");
display.print(loadVoltage);
display.print(" V");
display.println();
display.print(current_mA);
display.println(" mA");
display.setCursor(80, 0);
display.println("Temp: ");
display.setCursor(60, 12);
display.setTextSize(2);
display.print(String(temperatureC, 1));
display.display();
Serial.print("Temp: ");
Serial.print(temperatureC);
Serial.println(" C");
Serial.print("Bat: ");
Serial.print(batteryVoltage);
Serial.println(" V");
Serial.print("Sol V: ");
Serial.print(loadVoltage);
Serial.println(" V");
Serial.print("Sol I: ");
Serial.print(current_mA);
Serial.println(" mA");
delay(5000);
}
Problémy, které bych mohly nastat i když my se s nimi nesetkali:
– falešný dotek, odizolovat modul kapacitního tlačítka od krabička
– potopená krabička kvůli dlouhému kabelu voděodolného čidla, kratší kabel čidla
– nevyvážená krabička (např. jiná baterka), uprav váhu uvnitř krabičky tak, aby byla váha rovnoměrně rozložená napříč celou krabičkou