========= Digitální bateriový multifunkční teploměr ====== Vypracoval: Ondřej Jeřábek ---- ====== Zadání ====== Vytvořte teploměr s funkcí měření teploty, atmosférického tlaku a vlhkosti (čidlo BME280). Z naměřených hodnot lze vykreslit graf za posledních 24 hodin. Zobrazení aktuálně naměřených hodnot a grafů zajistí černobílý e-ink displej. Řídící MCU zvolte od firmy NXP řady Kinetis. Důraz bude kladen na celkovou spotřebu zařízení a související optimalizaci vhodných provozních režimů použitého MCU. ====== Úvod ====== Důvodem pro vytvoření tohoto zařízení bylo zejména otestovat vlastnosti a funkci E-ink displeje, který vyniká především svou velice nízkou spotřebou, avšak doprovázenou relativně malou obnovovací rychlostí. Z principu věci se tedy tento typ displeje hodí především pro zobrazování pomalu měnících se hodnot. Jako jedna z ideálních možností je využít jej v domácím teploměru či meteostanici. Venkovní i vnitřní prostředí se mění relativně pomalu, tedy obnovování zobrazených hodnot třeba jednou za 5 minut nebude energeticky náročné a přesto nám dá informaci o aktuálním stavu okolí. ====== Hardwarová část ====== Celý hardwarový návrh je relativně jednoduchý. Lze jej vidět na blokovém schématu níže. Srdcem je mikrokontrolér od firmy NXP, ke kterému jsou připojeny okolní periferie pomocí sběrnic SPI a I2C. Napájení v diagramu není zaznačeno, avšak předpokládá se využití knoflíkové baterie formátu CR2450 poskytující napětí o hodnotě 3V. {{ :2018:thermometer:diagram1.png |}} ===== BME280 ===== Jedná se o integrované multifunkční čidlo od firmy Bosch, umožňující měřit teplotu vlhkost a tlak v jeho okolí. Pro komunikaci využívá sběrnice I2C a díky internímu low power oscilátoru lze u něj nastavit periodická měření v daných časových intervalech. {{ :2018:thermometer:bme280.jpg?200 |}} ===== E-ink Displej ===== Jak už bylo výše zmíněno, výhodou tohoto displeje je především velice nízká spotřeba dosahující téměř nulových hodnot ve statickém stavu, a také výborná čitelnost na slunci rovnající se obyčejnému papíru. Pro teploměr byl zvolen dvoubarevný typ od firmy Waveshare s úhlopříčkou 2.9 palce a rozlišením 296x128 pixelů. Velmi výhodnou funkcí je možnost částečné aktualizace což umožní dosáhnout rychlejšího překreslení spolu s nižší spotřebou. Existují také varianty s třemi barvami (kromě bílé a černé také žlutá nebo červená). Avšak jejich velkým neduhem je dlouhé překreslování trvající až 15 sekund vždy celého displeje. Veškeré řízení a odesílání obrazu se provádí skrz 4-wire SPI sběrnici a jednoho signálového vodiče specifikující, zda se odesílá instrukce, či grafická data. Grafická paměť v displeji se skládá z dvou bufferů pro dva snímky. Mezitím co je jeden aktivní a do druhého se provádí zápis nových dat. V momentě aktualizace se automaticky buffery prohodí. {{ :2018:thermometer:2.9inch-e-paper-module-4.png?400 |}} ===== Mikrokontroler (MCU) ===== Jako srdce celého teploměru byl vybrán mikrokontroler od firmy NXP MKL16Z128. Tento typ obsahuje jádro Cortex M0+ zaměřené především na nízkou spotřebu, ale v případě nutnosti vyššího výkonu lze taktovací frekvenci nastavit až na 48 MHz, což se hodí především ve výpočetně náročných operacích. Tato varianta disponuje 128 kB interní paměti Flash doplněné o 16 kB RAM. Podmínkou pro výběr mikrokontroléru byla také presence RTC oscilátoru schopného pracovat i ve velice úsporných režimech procesoru, kdy může sloužit pro následné probuzení v konkrétní čas. ===== Bezdrátový modul ===== Do budoucna se počítá s rozšířením o další část, měřicí venkovní povětrnostní podmínky. Naměřená data by byla odesílána prostřednictvím bezdrátové komunikace do této vnitřní jednotky, která zajistí jejich záznam a zobrazení. Výběr padl na velice známý čip NRF24L01+. Ten komunikuje v ISM pásmu 2,4 GHz s datovou propustností až 2 Mbit/s. Pro jednodušší implementaci byla zvolena varianta modulu s integrovanou anténou. ===== Externí paměti ===== Tvoří je dvojice čipů AT25SF041-SSHD a 25LC040. Jedná se o paměť FLASH s kapacitou 4 Mbit a paměť EEPROM o velikosti 4kBit. Jejich účel je zde čistě redundantní. EEPROM paměť může do budoucna sloužit například pro ukládání nastavení, kdežto větší paměť flash pro záznam měřených hodnot v průběhu roku, nebo v momentě přehrávání firmwaru v mikrokontroléru, kdy se nejprve nová verze uloží do této paměti a až po kontrole dojde k jejímu překopírování. ===== Schéma zapojení ===== V napájecí části je hned na vstupu zařazen tranzistor pro zamezení přepólování vlivem otočené knoflíkové baterie. Jelikož použitý typ CR2450 má nominální napětí 3V, není třeba dále provádět žádné úpravy a lze jej rovnou použít k napájení celého teploměru. Zapojení ostatních periferií k mikrokontroléru je standardní dle doporučení v dokumentaci. {{ :2018:thermometer:thermometer_sch.png?400 |}} ===== Návrh plošného spoje ===== Plošný spoj rozměrově vycházel z použitého modulu E-ink displeje. Tedy navrhovaná řídící deska se umístí na distanční sloupky pod tento modul a vzájemně se propojí pomocí konektorů. Vzhledem k relativně protáhlému formátu desek plošných spojů jsou zde vloženy pouze odkazy na jednotlivé obrázky návrhu. Horní strana (Top): {{ :2018:thermometer:thermometer_top.png?linkonly|}} Spodní strana (Bottom): {{ :2018:thermometer:thermometer_bot.png?linkonly |}} Osazovací plán: {{ :2018:thermometer:thermometer_place.png?linkonly |}} {{ :2018:thermometer:board_sendwitch.jpg?400 |}} ====== Firmware ====== Celý firmware je vyvíjen za použití volně dostupného prostředí Kinetis Design Studio určeného především pro mikrokontroléry NXP řady Kinetis. Pro usnadnění práce bylo použito Kinetis-SDK spolu s knihovnami pro ovládání E-Ink displeje a kreslení na něm. Celý firmware se zdrojovými soubory je přiložen na konci této práce. Pro úspěšné buildnutí je třeba stáhnout si příslušné SDK (odkaz je na konci) a navést k němu cestu pomocí systémové proměnné KSDK-PATH v nastavení proměnného prostředí operačního systému. ===== Hlavní program ===== Samotný hlavní program vypadá relativně jednoduše, avšak velkou část výpočetního času zabere výpočet obrazu zobrazovaného E-ink displejem. Na začátku při startu je prováděna inicializace pinů mikrokontroléru spolu s nastavením taktovacího kmitočtu. Následně dochází ke konfiguraci okolních periferií. Ty zatím aktuálně nevyužité, jako je bezdrátový modul, nebo flash paměť se převedou do low-power režimu. Taktéž se provádí měření napětí baterie. V případě nedostatečného napětí je mikrokontrolér uspán a rozblikána červená LED. Program v tomto místě končí v nekonečné smyčce, kde čeká na její výměnu. Pokud ovšem napětí baterie dostačuje, pokračuje inicializací měřicího čidla a E-ink displeje. Hlavní smyčka není úplně periodická, jak se může na první pohled zdát, ale bývá pozastavena v každém cyklu úsporným režimem, kdy mikrokontrolér přechází do spánku (viz kapitola Řízení spotřeby). Taktéž bývá průběžně prováděno měření napájecího napětí, parametrů okolního prostředí (teplota, tlak, vlhkost) a obnova dat na displeji. ===== Řízení spotřeby ===== Hlavním cílem bude dostat spotřebu celého zařízení na co nejnižší hodnoty, pro dosažení maximální výdrže na baterii. V kontrastu s tímto požadavkem je sestavování obrazu pro následné vykreslení na displej které je bohužel náročné na výpočetní výkon. Proto je nutné vhodně měnit výkon mikrokontroléru a využívat jeho úsporné profily. Celkově jsou používány 3 výkonové režimy: * Fast mód: Výkonný režim s mikroprocesorem taktovaným na 24 MHz * Slow mód: Úsporný režim s taktovacím kmitočtem 4 MHz * Sleep mód: Velice úsporný režim kdy je hlavní oscilátor zastaven a běží pouze periferie RTC Přepínání taktovacího kmitočtu je zajištěno funkcí **//switch_clk(enum e_clk_mode mode)//**, které se jako parametr zadá aktuální mód. Funkce provede zakázání systémového milisekundového časovače systick, změnu předděličky taktovacího kmitočtu a poté konfiguraci časovače už s novou frekvencí, aby byla dodržena správná perioda čítání. void switch_clk(enum e_clk_mode mode) { systick_disable(); if (mode == E_CLK_FAST_MODE) { CLOCK_HAL_SetOutDiv1(SIM, 1); // Core clock division 1x -> 24MHz } else if (mode == E_CLK_SLOW_MODE) { CLOCK_HAL_SetOutDiv1(SIM, 6); // Core clock division 6x -> 4MHz } SystemCoreClockUpdate(); SysTick_Config(SystemCoreClock/1000); systick_enable(); } Poslední sleep mód je více komplexní a skládá se ze 3 procedur. Spoléhá se především na úsporný RTC oscilátor s čítačem, kterému je nastaven čas, kdy má dojít k probuzení, tzv. RTC Alarm, nebo je probouzen periodicky v sekundových intervalech. Před vstupem do sleep režimu je volána funkce **//before_sleep()//**. Tato funkce zajistí vynulování některých stavových proměnných, inicializaci pinů do předem definované úrovně, zastavení nepotřebných periferií a nastavení přerušení od RTC čítače. Poté dojde k volání funkce **//POWER_SYS_SetMode()//** zajišťující přepnutí celého mikrokontroléru do režimu VLPS (Very low power sleep), kdy je hlavní oscilátor zastaven. Z tohoto režimu jej lze probudit pouze přerušením např. od tlačítek, či výše zmíněného RTC alarmu. Po probuzení zajistí funkce **//after_sleep()//** rekonfiguraci všech potřebných periferií do provozního režimu. Do sleep módu se vstoupí pouze v případě, pokud není vznesen požadavek na zahájení měření čidlem BME280. if (!flags.measure) { before_sleep(); // Prepare MCU to sleep POWER_SYS_SetMode(1U, kPowerManagerPolicyAgreement); after_sleep(); // Prepare MCU to run } ===== Měření parametrů čidlem BME280 ===== Samotné měření obstarává funkce **//bmp_measure_handle()//** volaná v sekundových intervalech (pokud mikrokontrolér zrovna nespí). Měření probíhá každých 5 minut a je vyvoláno přerušením RTC Alarm v daný časový okamžik. V tento moment je nastaven příznak požadavku na měření, kdy dojde k odstartování měření na čidlu. V následující sekundě poté jsou naměřená data vyčtena a zpracována funkcí **//bmp_read_data()//**. Zpracování dat definuje dokumentace k čidlu BME280, kdy je nutné provést korekci hodnot dle kalibračních křivek uložených v čidlu. uint8_t bmp_read_data(int16_t * temp, uint16_t * humid, uint32_t * press) { uint8_t press_raw[3]; uint8_t temp_raw[3]; uint8_t hum_raw[2]; static int32_t temp_c; static uint32_t press_c; static uint32_t hum_c; if (bmp_is_busy()) return 0; if (bmp_read_block(BMP_press_msb, press_raw, 3)) return 0; if (bmp_read_block(BMP_temp_msb, temp_raw, 3)) return 0; if (bmp_read_block(BMP_hum_msb, hum_raw, 2)) return 0; temp_c = (int32_t)(((uint32_t)temp_raw[2] >> 4) | ((uint32_t)temp_raw[1] << 4) | ((uint32_t)temp_raw[0] << 12)); press_c = ((uint32_t)press_raw[2] >> 4) | ((uint32_t)press_raw[1] << 4) | ((uint32_t)press_raw[0] << 12); hum_c = (uint32_t)hum_raw[1] | ((uint32_t)hum_raw[0] << 8); temp_c = bmp280_compensate_T_int32(temp_c); press_c = bmp280_compensate_P_int64(press_c); hum_c = bme280_compensate_H_int32(hum_c); *temp = (int16_t)temp_c; *press = press_c >> 8; *humid = (hum_c * 100) >> 10; return 1; } ===== Vykreslování a ovládání ===== Vykreslování veškerých obrazovek a obsluha tlačítek je definována ve zdrojovém souboru **ui.c**. Periodicky volaná funkce v hlavní smyčce **//ui_handle()//** obsluhuje reakce na stisknutá tlačítka následovaná vykreslováním daných typů obrazovek. V momentě vytváření obrazu se mění výkonový režim na Fast mode, k vůli vyšší výpočetní náročnosti. Výsledek je rovnou odesílán do E-ink displeje a po jeho kompletním odeslání se spustí překreslení. V rámci probíhající obnovy displeje se mikrokontrolér z důvodu úspory energie uspí. Probuzení zajistí přerušení od pinu busy. Funkce pro vykreslování využívají volně dostupnou knihovnu přímo od výrobce displeje Waveshare. Obsahuje několik druhů fontů s různou velikostí a funkce vykreslující geometrické tvary. Nejdůležitější částí, bez které není možno E-ink vůbec řídit je obnovovací sekvence tvořená look-up tabulkou, která musí být do něj nahrána. Její podobu definuje výrobce a zajistí správné obnovení. Pro tento typ displeje existují dva typy tabulek. Jedna provádí částečný update, kdežto druhá aktualizuje celý displej. const unsigned char lut_full_update[] = { 0x02, 0x02, 0x01, 0x11, 0x12, 0x12, 0x22, 0x22, 0x66, 0x69, 0x69, 0x59, 0x58, 0x99, 0x99, 0x88, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xB4, 0x13, 0x51, 0x35, 0x51, 0x51, 0x19, 0x01, 0x00 }; const unsigned char lut_partial_update[] = { 0x10, 0x18, 0x18, 0x08, 0x18, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x14, 0x44, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; Ovládání a navigace probíhá pomocí tří tlačítek na pravé straně. Při jejich stisku dojde k přerušení a probuzení mikrokontroléru ze spánku. Ten poté provede definovanou činnost dle aktuální obrazovky. K tlačítkům jsou v průběhu ovládání na displeji vypisovány aktuální funkce. Strukturu ovládání a možnosti, které displej nabízí lze vidět na blokovém schématu níže. Detailnější popis s demonstrací funkce lze nalézt v přiloženém videu na konci této práce. {{ :2018:thermometer:program_struct.png?600 |}} ====== Problémy s napájením ====== V průběhu programování a následného testování se ukázalo, že aktualizace E-Ink displeje je velice proudově náročná operace. Při kompletní obnově dosahuje špičkově až 100 mA, což způsobuje problémy u více vybitých knoflíkových baterií. Vlivem vnitřního odporu poklesne napětí až pod hraniční mez, kdy E-Ink displej dokáže správně fungovat. Ve většině případů došlo k zaseknutí v nedefinovaném stavu a vysokému proudovému odběru, který vybil celou baterii. Dočasně je tedy celé zařízení napájeno ze dvou tužkových baterií, které jsou celkem nevzhledně umístěné ve slotu přilepeném na spodní straně. S nimi teploměr funguje bez problémů i při použití více vybitých kusů. Řešení tohoto problému tedy spočívá buď v použití jiného typu baterie, nebo zařazením superkondenzátoru v napájecí větvi, který by dokázal vykrýt tyto odběrové špičky. ====== Závěr ====== Navrhované zařízení je plně funkční a lze jej využívat jako plnohodnotný domácí teploměr schopný zobrazovat i detailnější informace jako vlhkost či atmosférický tlak. Z naměřených hodnot jsou průběžně vytvářeny grafy, díky kterým si lze prohlédnout změny za posledních 24 hodin. Taktéž si lze vyvolat minimální a maximální naměřené hodnoty za celou dobu provozu teploměru, případně je lze v menu vynulovat. Aktuální návrh je také velice úsporný na baterii, kdy v režimu nečinnosti odebírá pouze 7 μA. Měření teploty s překreslením displeje se provádí jednou za 5 minut se skokovým nárůstem spotřeby trvajícím přibližně 0,3 - 1 sekundu. Dle propočtů tedy vychází celková průměrná spotřeba na 50 µA a při použití baterie CR2450 s kapacitou 500 mAh činí výdrž přibližně 1 rok. Bohužel se v průběhu vývoje vyskytly potíže s nedostatečným napájením na obnovu E-Ink displeje. Chyba byla prozatím vyřešena použitím tužkových baterií a bude opravena v další iteraci revizí hardwarového návrhu. Návrh lze dále v budoucnu rozšířit o venkovní teplotní čidlo, nebo přímo meteostanici, která bude svá naměřená data bezdrátově odesílat tomuto teploměru a ten se postará o jejich vyhodnocení a zobrazení. Výhodné by bylo také použít jiný bezdrátový modul, například s technologií LoRa umožňující komunikaci se vzdálenějším senzorem či připojení do LoRaWAN IoT sítě. ====== Video a fotografie ====== {{ :2018:thermometer:thermometer_completed.jpg?400 |}} {{ :2018:thermometer:themometer_completed2.jpg?400 |}} {{ youtube>AyAU04ToL1Y?medium |}} ====== Firmware a schémata ====== {{ :2018:thermometer:thermometer.zip |}} ====== Zdroje ====== Čidlo BME280: [[https://www.bosch-sensortec.com/bst/products/all_products/bme280]] E-Ink display: [[https://www.waveshare.com/wiki/2.9inch_e-Paper_Module]] Mikrokontroler: [[https://www.nxp.com/part/MKL16Z128VFT4]] Kinetis SDK: [[https://bit.ly/2M5GvDZ]]