Uvažuji o stavbě domu a pokud by k tomu někdy došlo, chtěl bych si do něj nabastlit nějakou tu automatizaci. Chci se vyhnout kupování hotových věcí a jelikož je bastlení, i přes současný nedostatek času, stále mým největším koníčkem, je domek to správné "pískoviště" :-)
V první fázi by mělo jít o měření teplot v místnostech a ovládání okruhů podlahového topení dle požadovaných teplot. Když jsem se koukal okolo, jak to řeší jiní, tak mnoho lidí vezme nějaký PC (dnes nejčastěji Raspberry PI), připojí k němu 1-wire sběrnici a tu si roztahá po domě. Ono to funguje a pokud se respektují app-note od Maximu (délky vedení, odbočky, buzení, aktivní pullup apod.), tak poměrně spolehlivě. Jenže otázkou je, co dělat v případě, že bych nechtěl jen měřit teplotu? Že bych chtěl například indikovat stav topení, umožnit změnu požadované teploty z každého pokoje a třeba za 5-10 let udělat ještě něco úplně jiného? Z těchto důvodů jsem samotnou 1-wire zavrhnul a zvolil raději klasiku v podobě RS485. Oproti 1-wire je potřeba jeden drát navíc, ale univerzálnost budoucího použití předčila i větší složitost jednotlivých koncových prvků - na prosté měření teploty nestačí jen čidlo, ale MCU s RS485 řadičem.
Pricip je jednoduchý - existuje sběrnice RS485 (dva dráty A a B) a napájení (+12V a zem). K této sběrnici jsou připojeny prvky jako je např. tento teploměr (SLAVE) a prvek, který realizuje řídící člen (MASTER) - tím může být bežné PC, Raspberry a nebo v mém případě Atmel ATMega328. Master prvek poté komunikuje se slave prevky, úkoluje je a dotazuje se. Slave prvek nikdy sám nevysílá, vždy pouze na vyžádání mastera. Tím je zajištěno, že na sběrnici nemůže dojít ke kolizi - bohužel však za cenu, že slave prvek nemůže masterovi ohlásit nějakou událost ihned, ale master se musí zeptat. Ostatně toto je věc protokolu, samotná RS485 zajišťuje pouze fyzický přenos dat a to ještě bez specifikace low-level rámců.
Komunikace probíhá pomocí UART rámců rychlostí 1200bps s jedním stopbitem. Je to sice dosti malá rychlost, ale má jisté výhody:
O RS485 je toho na webech popsáno moc, ale pro úplnost je nutné připomenout, že pro správný provoz je důležité, aby byl na sběrnici definován klidový stav - tedy aby byl B(+) proti A(-) napěťově kladnější. Jelikož je v označování A a B je trochu zmatek, platí proto, že vývod 6 MAX485 musí být připojen na vývody 6 ostatních a analogicky u vývodu 7. Vývod 6 je pak kladnější než 7. Pokud se vývody prohodí, nic se nestane, pouze nebude fungovat komunikace. Bez definování klidového stavu by pak do přijímače chodil chaos, což by mohlo v určitém případě zapříčinit doručení chybných dat.
Základem je IC1 MCU ATtiny85. Výhoda tohoto kousku je v tom, že obsahuje 8kB FLASH paměti (dostatek prostoru pro firmware), dá se snadno koupit jako kusovka v GME (levněji pak z Číny) a vyrábí se v pouzdře DIP8. Nevýhoda pak, že neobsahuje HW UART, čili příjem a vysílání rámců je nutné řešit softwarově - to zabre místo ve flash a ostatní HW zdroje. Je taktován na 1MHz interním RC oscilátorem.
K MCU je připojen převodník TTL UART na RS485 MAX485, IC2. Je možné použít i levnější alternativu v podobě SN75176, ale vzhledem k tomu, že se dá MAX485 objednat z číny za témeř stejnou cenu, tak asi není co řešit. Rozdíl mezi MAX485 a SN75176 je ten, ze MAX má výrazně nižší klidovou spotřebu. Sběrnice je k MAX485 připojena přes ochranné odpory R1 a R2, které tam samozřejmě být nemusí, ale už se mi párkrát podařilo místo komunikace docílit ohňostroje :-) Ochraný odpor R3 mezi výstupem MAX485 a vstupem MCU je zde umístěn proto, že datový výstup MAX485 je napěťově docela tvrdý a znemožňoval by tak naprogramování zapájeného MCU.
1-wire sběrnice je k MCU připojena opět přes ochranný odpor R6 a ochrannou diodu D2. Obě součástky také nejsou nutné, ale jedná se o korunovou položku, která může zachránit buď MCU nebo čidla. Firmware umožňuje vyčítat teplotu až z 5-ti čidel DS1820 nebo DS18B20. Poslední volná noha MCU je využita pro indikační LED přes odpor R5. Jeho hodnotu lze volit dle použé LED a požadovaného jasu. Místo LED lze připojit cokoliv jiného (např. tranzistor a relé), proto je napájena z vývodu MCU - tak aby zapnutá LED reprezentovala log.1 na výstupu z MCU.
V předchozím textu jsem se zmínil, že MCU je taktováno na 1MHz a že jsem raději použil MAX485 místo SN75176. V obou případech byla důvodem nižší spotřeba. Jde hlavně o to, že v napájecí části je použit lineární stabilizátor 78L05. Jeho problémem je napěťový úbytek a z toho plynoucí teplo :-)Kombinace ATtiny85 na základním taktu 8MHz a SN75176 totiž žere v klidu 25mA a při tomto proudu už 78L05 nezůstává chladný - není horký, ale vlažný. Jinde by to asi nevadilo, ale jelikož v této konstrukci jde hlavně o měření teploty, představa "vytápěné" elektroinstalační krabice s čidlem na jejím povrchu je těžce snesitelná :-) Pro představu naměřené proudy:
Program pro Atmela je ke stažení dole. Jedná se o balík, který obsahuje:
Jelikož použitý MCU Atmel ATtiny85 nemá hardwarový UART, bylo zapotřebí přelouskat application note "AVR274: Single-wire Software UART" a zjednodušenou variantu implementovat. Obrázek je nad tisíc slov....
Předpoklady:
Funkce:
Maxim na svém webu umístil dokument "APPLICATION NOTE 187, 1-Wire Search Algorithm", kde prakticky popisuje jak realizovat algoritmus na vyhledání ROM kódu zařízení připojených na 1-wire sběrnici. Kód je ale příliš komplexní, takže ho trochu pokrátil a implementoval do dvou funkcí:
Teploměr komunikuje rychlostí 1200bps, 1 stopbit, žádná parita.
Formát paketu (vše ASCII znaky): * d s [fc] #
Příklad:
Jedná se o základní fukci, která vrací teploty z čidel. Teploty jsou průměrovány za poslední 4 měření, resp. za 4 poslední volání této funkce. Součástí funkce o vrácení teploty je i možnost nastavení stavu LED a to proto, aby se nemusely posílat dva příkazy - jeden na zaslání teploty a druhý na nastavení stavu LED.
*ds# Vrátí průměrovanou teplotu teploměrů.
*dsZ# Vrátí průměrovanou teplotu teploměrů a zapne LED.
*dsV# Vrátí průměrovanou teplotu teploměrů a vypne LED.
*dsR# Vrátí průměrovanou teplotu teploměrů a zapne rychlé blikání LED.
*dsP# Vrátí průměrovanou teplotu teploměrů a zapne pomalé blikání LED.
*ds?# Vrátí průměrovanou teplotu teploměrů. ? je libovolný znak mimo ZVRP.
*XM# *XMZ# *XMR# apod.
*dsl[ttt]#
*MXV4F13EA# vrací dvě teploty 4F1 (1265=26.5°C) a 3EA (1002=0.2°C) a info, že LED je vypnutá.
Každý prvek na RS485 sběrnici má adresu z intervalu A-Z. Po naprogramování MCU je výchozí adresa nastavena na X. Je tedy nutné ji změnit a k tomu slouží následující funkce.
*XMSAP# - změna adresy prvku X na P.
*ds# odsílatelem s je už nová adresa
*MP#
Teploměr umožňuje vyčítat teploty z 5-ti čidel na 1-wire sběrnici. Aby veděl, jaké má které čidlo ROM a jakého je typu, je nutné toto pomocí této funkce nastavit. Funkce na vracení teplot vrací pouze nastavená čidla, ostatní ignoruje.
*XMSC3110488B8A0208006F# - nastaví na pozici 3 čidlo DS18B20 s ROM 10488B8A0208006F
*ds|c-t-ssssssssssssssss|#
*MX|3-1-10488B8A0208006F|#
Pokud se nějaké čidlo fyzicky odstraní, lze to touto funkcí deaktivovat. Chybná teplota z neexistujícího čidla pak není vracena funkcí na vrácení teplot.
*XMSD3# - odstraní nastavení čidla z pozice 3
*ds|c-0|#
*MX|3-0|#
Funkce se pokusí prohledat všechny čidla na 1-wire sběrnici. Vráti jejich ROM, které lze použít ve funkci pro nastavení čidla. Výstup není omezen a funkce tak vrátí tolik ROM, kolik čidel na 1-wire najde.
*XMSS#
*ds|ssssssssssssssss|ssssssssssssssss|# - počet dle nalezených prvků
*MX|10488B8A0208006F|10488B65021824AA|#
Funkce vypíše nastavení všech 5-to pozic a to typ čidel a ROM kódy. Pokud je ve výpisu na místě typu čidla 0, znamená to, že čidlo není aktivní a funkce na vracení teplot ho nevrací.
*XMSR#
*ds|0-t-ssssssssssssssss|...|4-t-ssssssssssssssss|# - zkráceno, výpis pro 0-4
*MX|0-1-10488B8A0208006F|...|4-0-FFFFFFFFFFFFFFFF|#
Jedná se o diagnostickou funkci, kterou poslechou všechny prvky na RS485 sběrnici. Po přijetí příkazu odešlou svoji identifikaci do cca 30-ti sekund dle adresy. Krokuje se od A do Z po sekundě, čili prvek s adresou A odpoví hned, prvek s adresou Z až za 26 (počet písmen v abecedě) sekund.
*?M#
*ds# - odpověď příjde do 30 sekund dle adresy.
*MX#
Jedná se o diagnostickou funkci, která slouží k ověření přesnosti interního kalibrovaného RC oscilátoru. Po obdržení odpovědi se na cca. 8 sekund objeví na TXD obdélníkový signál, jehož půlperioda má délku bitu při 1200bps (tj. cca 833.34us) nebo 1.5 násobek delky bitu při 1200bps (tj. cca 1.25ms).
*XMST0#
*dsTx# - následuje obdélníkový signál
*MXT0#
Funkce pro korekci interního RC oscilátoru. Přičte nebo odečte jedničku z registru OSCCAL a diferenci uloží do EEPROM. Po provedení se spustí test časování bitrate - viz. výše.
*XMSO1#
*dsO+# - následuje obdélníkový signál
*MXO+#