maanantai 9. maaliskuuta 2015

Danfoss-lämpöpumpun salaisuudet

Olinkin jo edellisissä postauksissa maininnut, että haluaisin automaatioprojektissani myös ohjata maalämpöpumppuani. Mutta Danfossin edustaja ei halunnut kertoa, miten heidän nelipinninen liitin ulkoisille laitteille toimii. Niinpä totesin:

Jos ei muu auta, niin TermIQ:lla tuota tulen ohjaamaan, mutta olisihan sen lisäksi kiva tietää, mitä pinnit oikeasti tekee. Joten otin yleismittarin ja ekana katsoin TermIQ:n puolelta statistiikkaa. Neljäs pinni (alin) on GND, ja kolmessa muussa pinnissa oli 2.45V kun USB-piuha on kytkettynä sisään (ilman että on Danfossissa kiinni).

Ekana luulin, että liittimessä kulkisi serial TTL liikennettä 9600 8N1, kun Talologger projektin sorsissa vähän niin annettiin ymmärtää. Joten ekana kun ThermiQ:n pistin laitteeseen kiinni, niin minulla oli signaalianalysaattorit pistetty sarjaliikenne muotoon. Ja ekana luulin että pinnit olisi tx,rx,vcc,gnd järjestyksessä, joten olin analysaattoriin pistänyt tallennuksen alkuun pulssin triggeriksi ekaan pinnin. Se olikin väärä arvaus ja sitä triggeriä ei laukaistu missään vaiheessa. Joten siirsin triggerin sitten toiseen ja kolmanteen pinniin. Johan alkoi lyyti kirjoittamaan, mutta eipä analysaattori tunnistanut sitä sarjaliikenteeksi. Joten päättelin (olammin kommentin perusteella, kiitos siitä) sitten, että talologgerin sorsien ThermiaSerial koodi käyttää "Husdata"-kaapelin StatLink.exen formaattia ja kyseistä kaapelia ei enään voi ostaa mistään uutena.

Joten tämänhetkinen arvaukseni on 5V logiikalla toimiva I2C seriaali (8-bittinen signalointi). Vaihtoehtoisesti liikenne olisi voinut olla COMLI-protokolla (eräs ruotsalainen sivusto näin väittää) joka myös on I2C:n päällä. Ja voihan se ollakin COMLI:n joku variaatio, jossa komennot on yleensä 12-bittisiä, voi olla että analysaattori pilkkoo ne vain 8-bittiseen formaattiin (COMLI:stä esimerkki c-toteutusta löytyy esim.: http://fossies.org/linux/nut/drivers/al175.c ja Java referenssi toteutus: http://www.avineas.org/index.php?page=abb-comli). Itse kyllä I2C seriaalina tuota tällähetkellä kohtelen koodissani (ja sillä myös tuntuu toimivan).

Eli nykyinen arvaukseni (tai siis tieto mittausten jälkeen kytkettynä Danfossiin) pinnien järjestyksestä on:



VCC 5V
SCL
SDA
GND

Ja totta tosiaan, tuolla oletuksella kun conffaa analysaattorin kiinni pinneihin, niin logeihin jää oikean näköistä dataa, joka matchaa ThermIQ terminaalin AT-komentojen tuottamaan dataa. Eli kuka vain voisi ottaa sopivan edullisen 5V Arduinon tai Raspberryn (kunhan käyttää 3.3V<->5V bidirectional level convertteria.) ja rakentaa I2C:n päälle oman kaapelin ihan murto-osalla kaupallisten vaihtoehtojen hinnasta. Itse asiassa normaalit Raspberryt ei tue I2C slave modea, joten Raspberry käyttö menee vaikeaksi. Uusimmissa B+ malleissa GPIO19 (CLK) on jo saatavilla, mutta edelleen se taitaa vaatia omaa I2C koodia, kun normaali I2C kirjasto tukee vain master modea. Tässä pistän mietintämyssyn päähän, että jos minulla olisi tarpeeksi vapaa-aikaa, niin voisin rakentaa ja myydä omia custom kaapeleita tuohon. Katsotaan mitä saan tämän kanssa aikaiseksi (jos haluat ostaa minulta custom Thermia/Danfoss-kaapelin, niin blogin sähköpostiosoitteeseen vain yhteydenottoja. Lupaan olla yli puolet halvempi kuin ThermIQ. Tällähetkellä työn alla on kaapeli joka emuloi suoraan ThermIQ sarjaportin AT-komentoja (jolloin voi olemassa olevia softia käyttää suoraan). Osien tilaus Kiinasta saattaa kestää muutaman viikon, jos minulla ei juuri sillähetkellä ole osia hyllyssä.).

Mutta tässä nykyinen tilanneraportti, ThermIQ toimii hienosti Danfossin lämpöpumpun kanssa, tuossa ylenpänä on piuhan pinnijärjestys kirjattuna. Ja tässä screenshotti analysaattorin maagisesta toiminnasta:

Tuon kun zoomaa auki, niin näkee, että Danfoss masterin ja I2C slaven välisessä liikenteessä kulkee neljä tavua 0x5C, 0x06, 0x18, 0x0 ([7-bittinen osoite + read|write bitti], rekisterin osoite, rekisterin arvo vähiten merkitsevät bitit, rekisterin arvo eniten merkitsevät bitit(yleensä 0x0 koska arvot on < 256)) eli tuossa tapauksessa Danfossin rekisterin nro 6 arvo on 0x18. Ja esim. Talologgerista tai googlaamalla löytää mitä eri rekisterin arvot tarkoittaa. Samantyylisiä arvauksia dataformaatissa on myös maalämpöfoorumissa, vaikkakin olettavat datan olevan 9600 serial muodossa (tai sitten ovat mitanneet ThermiQ/Husdata:n usb puolen sarjaliikennettä, joka on 9600 8n1 seriaali), vaikka oikeasti se on I2C kortin ja pumpun välillä. Tässä tapauksessa "['return line temp', 6, TYPE_INT16]," -> paluuveden lämpötila on 24C.

Avataan I2C protokollan ensimmäistä tavua vielä hieman lisää, tässä vaiheessa on hyvä olla calculaattori joka osaa näyttää hex-numerot myös binaarina.

0x5C = 0b01011100 -> I2C 7-bit osoite desimaalina on 46 (0b00101110 -> 0x2e)
0x5D = 0b01011101 -> I2C 7-bit osoite desimaalina on 46 (0b00101110 -> 0x2e)

Eli viimeinen bitti punaisella merkittynä on 1=read 0=write, ja 7 ensimmäistä bittiä on itse I2C osoite. Tuon perusteella pitäisi jo pystyä koodaamaan oma kaapeli :-)

Mutta ihan vaan akateemisessa mielessä avataanpas tätä viestiliikennettä hieman enemmänkin, ettei tule semmoista mielikuvaa, että pitäisin osan salassa omaa kaapelitoteutusta varten. Eli kun rekisterin luku on edellä käsitelty (ATR), niin pitäähän sitä varmaan rekisteriin kirjoituskin käsitellä, että voi etänä ohjata haluttuja arvoja.

Analysaattori kiinni ja katsotaan mitä write (ATW370001) pitää sisällään (Tällä kertaa ajoin analysaattoria Macissä):

0x5D = 0b01011101 Setup Read to [] (0x5D] + ACK
0xB7 = 0b10110111 Red == Write/Set Value, Blue (0x00110111 == 0x37 == 55 == ['curve +5', 55, TYPE_INT16])
0x01 = 0b00000001 Vähiten merkitsevä tavu (low byte)
0x00 = 0b00000000 Eniten merkitsevä tavu (high byte)

Joten rekisteriin kirjoitus on aika suoraviivaista; 0x5D, kohde rekisteri|0x80 ja seuraavat on vähiten merkiksevä tavu ja sitten eniten merkitsevä tavu.

Ainiin ja menee tuolla linjalla myös jotain keepalive/ping tyylisiä viestejä, 11111111(0xFF) && 11111110(0xFE), villi arvaus että noi on jotain propriatary broadcast tyylisiä pollaus viestejä read/write lipuilla (koodasin kaapelin vastaamaan pong(FF) noihin ping(FE) viesteihin, jos jonossa ei ole komentoja).

Nyt kun on read ja write komentojen salat kaivettu esille, niin seuraavaksi katsotaan ja varmistetaan, että liikenne tosiaan on I2C:tä, eli pistetään linjan perään Raspberry Pi tai Arduino ja tehdään I2C scanni ja katsotaan montako laitetta vastaa linjan perästä.... ja eikun tuumasta toimeen. Rakensin 3.3V <-> 5V bidirectional level converter piuhan ja kytkin sen Raspberryyn kiinni: i2cdetect ei löydä mitään, joten taisi sittenkin tulla väärä arvaus protokollan suhteen tai vaatii jonkun salaisen kättelyn linjan herättämiseksi. Nostan hetkeksi kädet pystyyn, kunnes ehdin taas jatkamaan debuggausta eli to be continued. Toistaiseksi ohjailen tuota ThermiQ:n läpi, kunnes keksin miten tuo ThermiQ laittaa tuon väylän I2C tilaan.

Päivän verran olin lannistuneena tuosta ekan yrityksen epäonnistumisesta, mutta sitten pistin mietintämyssyn päähän ja päätin aloittaa debuggauksen uudestaan eri näkökulmasta. Rakensin ethernet-kaapelista splitterin, jonka pistin pumpun ja näytön väliin, yleismittarilla kun mittaa signaalintasot niin 12V näyttää olevan ainakin kahdessa johtimessa, ja minun halpa signaalianalysaattori on max 5V jännitteille, joten jätin ethernet portin tutkimisen toistaiseksi jäähylle. Otin uudeksi lähestymistavaksi mitata ensimmäiset 10 sekunttia laitteen käynnistymisestä, joten pistin TermiQ:n kiinni analysaattorin ja käynnistin laitteen, kiva logi tuli. Sitten päätin vielä ottaa toisen boottilogin ilman TerhmiQ:ta, sillä oletuksella että linjan pitäisi olla hiljainen. Mutta eipä ollutkaan, joten bingo välähti mielessäni.

ThermIQ laite ei olekaan masteri vaan se toimii slavena, joten ei olekaan ihme, ettei i2cdetect suoraan portissa löytänyt mitään, kun linjassa ei olekaan muuta kuin pumppu, joka on masteri. Logia kun katsoo, niin se on itse asiassa pumppu, joka lähettää pingia väylälle ja etsii, että onko siellä laitteita. Se etsii 0x2e:tä (jota ThermiQ oikeasti emuloi, joten minun omakin koodin pitää olla 0x2e osoitteessa oleva slave. Samoin se vielä kyselee, että onko 0x2e olemassa, ekana 1.5s bootin kohdalla lähettämällä 0xFD ja 0xFE 7.3s:stä lähtien, johon ThermiQ sitten vastaa 0xFF. Pumppu myös etsii myös 0x32- ja 0x37-laitteita 0x00-viestillä, en sitten ruvennut tutkimaan, että mitä laitteita se etsii: mahdollisesti extra näyttöjä, verkkokortteja, modeemeja tms. Lähinnä akateemisessa mielessä kerron, että pumppu scannaa kolmea eri laitetta väylältä. Meitä lähinnä kiinnostaa matkia ThermiQ:n toimintaa, joten keskityn 0x2e:hen. Joku toinen voi halutessaan koittaa ihmetellä, mitä nuo muut osoitteet ovat.

Tästä sitten syntyi uusi teoria, että I2C:n päällä pumppu on masteri, joka pollaa rekisteriä 0xFE 110millisekunnin välein ja slave vastaa 0xFF, jos jonossa ei ole mitään komentoja. Eli pumppu kysyy, "hei, halutko tietoa mistään?"(0xFE) ja slave vastaa "Moro, en tarvi mitään?"(0xFF), tai sitten se voi vaikka vastata, että "Joo, annappa vaikka rekisterin 50 arvo"(0x32). Näin pollaamalla saa noin 9 rekisterin arvoa sekunnissa. Eli teorian todistaminen todeksi vaatii vain I2C slave devicen koodaamisen noilla oletuksilla. Joten se oli seuraavaksi vuorossa.

Eli otin sopivan 5V logiikalla toimivan mikrokontrollerin ja koodasin sarjapinneihin AT-modeemikomento emulaation ja I2C pinneihin sitten rekisterien luku- ja kirjoituslogiikan, ja tein syntaksin matchaamaan ThermIQ kortin komentoja, jolloin nykyisiä softia pystyy käyttämään halutessaan suoraan. RTC osuuden tein euron patterivarmistetun I2C RTC kellon avulla (Vaihtoehtoisesti voisin suoraan koodata softaemuloinnin Raspberry Pi:llä, jolloin ei tarvittaisi mitään ulkoisia kontrolleja, I2C kaapelin pituudella on vain rajoituksia, eli siinä tapauksessa pitäisi Raspberry jättää Danfossin pumpun sisäpuolelle, ja vaan pistää eetteripiuha ulospäin). Mutta siis koska Raspberry toteutuksen tekeminen on vaivalloista (koska ei ole vielä mitään valmista helppokäyttöistä i2c slave kirjastoa julkaistu), niin keskityin tekemään helpomman serial<->I2C AT modeemi-emuloinnin. Wire I2C kirjasto ei suorilta kyennyt juttelemaan pumpun kanssa, koska pumppu lähettää hieman epästandardin start-bit sequenssin. Mutta muutaman illan koodaus- ja debuggaus-session jälkeen, löytyi oikea paikka Wiren puukotukseen ja nyt näyttää tältä:

Hyvältä näyttää, mokkulani vastaa AT-komentoihin samalla tavalla kuin ThermIQ:n kanssa. Minun moduulissani nostin sarjaliikenteen nopeuden 9600:sta 115200:aan, joten vastailee kyselyihin teoriassa hieman nopeammin kuin ThermIQ. Samoin kun mikrokontrolleri nyt tarjoaa serial pinnit ulospäin, niin siihen voi liittää minkä vaan usb<->serial palikan, ja voi valita käyttöjärjestelmän perusteella sopivimman yhdistelmän (Windows, Linux ja OSX).

Ja nälkähän kasvaa syödessä, joten ajattelin, että mitähän jos pistäisin vielä muutamaan ylimääräiseen pinniin toisen sarjaportin pyörimään, että siihen pääsee käsiksi vaikka kahdella usb<->ttl tikulla, niin silloin tietokoneella olisi esim /dev/ttyUSB0 ja /dev/ttyUSB1, jolloin voi toiseen deviceen pistää kiinni esim ThermIQ:n oman softan ja toisen kiinni vaikka Talologgeri-softaan. Joten ei kun koodausmyssy päähän, ja nyt minulla on myös softaversiot kahden ja kolmen sarjaliikenneportin versiosta (että voin yhtä aikaa pitää ThermIQ:ta ja Talologgeria päällä, ja pystyn vielä kolmannella muuttelemaan arvoja ennakoivasti omasta softasta esim. viiden päivän sääennusteen mukaan, niin voi kokeilla muka säästää sähköä sääennusteilla.

Seuraavaksi kun kaikki omasta mielestäni toimii, on vuoro testata, että toimiiko se nykyisten softien kanssa yhteen. Joten sitten vaan asentelemaan ja testaamaan toimintaa... Olin kakkos-seriaalin pistänyt 9600 nopeuteen ihan vaan yhteensopivuuden vuoksi, ettei tarvi configeja muuttamaan. Asensin ThermIQ-softan Raspberry Pi:hin (asennus käyttää vielä yhtä dokumentoimatonta AT komentoa, mutta sen nopeasti koodasin) ja tämmöiseltä web-liittymä näyttää:

Näyttää toimivan ihan kivasti, vielä pitää testata kuinka kauan toi mokkula toimii ilman, että sitä tarvitsee rebootata. Eli vielä en tiedä, pysyykö toi pystyssä kuukausia ilman ongelmia. Mutta toistaiseksi olen tyytyväinen tämän haasteen lopputulokseen. ;-) Muoviläystäkkeen sain kaksipuoleisella teipillä hyvin kiinni lähelle EXT-liitintä.

PS. Tässä olen kuukauden päivät ajanut ThermIQ softaa raspberryssa tolla mun omalla arduino pohjaisella kaapelilla, ja muutaman oman koodausbugin korjaamisen jälkeen tuntuu toimivan kuin junan vessa. Hyllyssä löytyy osat viiteen kaapeliin, joten nyt on tarvittaessa kaapeleita saatavilla.
PS2. Tässä on kuva uusimmasta kaapeliversiosta, on mukavasti pienemmän kokoinen kuin ensimmäinen versio.

Nytten tuota kaapelia on testattu Raspberryn perässä TaloLoggerilla, ThermIQ ja ThermIQv2 softilla, ja hyvin tuntuu toimivan. Myyntisivu: http://omakotikotitalomme.blogspot.fi/p/myydaan-tavaraa.html
Disclaimer: I2C liikennettä ei ole salattu mitenkään, joten tämä blogipostaus ei pura mitään teknistä suojausta (laitteen valmistajan haluttomuus kertoa liittimen toiminnasta ajaa heidän omia intressejään). I2C specifikaatio on vapaasti luettavissa netissä UM10204.pdf. Samoin en ota mitään vastuuta, jos onnistut hajoittamaan oman pumppusi tämän blogipostauksen johdosta.

10 kommenttia:

  1. "Joten päättelin sitten että talologgerin sorsat on vaan väärässä, että ThermiaSerial joko ei vain toimi, tai on kauhea hacki jolla sarjaliikenteellä emuloidaan I2C:tä."

    Syyllisenä sen väärän ja kauhean hackin kirjoittamiseen kommentoin, että alkuperäinen ThermiaSerial-toteutus oli tehty ympäristöön, jossa on toimiva husdata.se StatLink. Tämä oli Windowsilla pyörivä tuotos, johon käsittääkseni kuului joku "husdata"-kaapeli Thermia-pumpun ohjainta varten. Tästä selvilteltiin nimenomaan sitä kaapelin ja Statlink.exe:n välistä keskustelua, joka oli sarjaliikennepohjaista ja moduuli tehtiin sitä vasten.

    TaloLoggerin ThermIQ-moduuli taas on tehty ThermIQ:n tekijän ehdotuksesta ja hänen tarjoamiaan speksejä vasten. Moduuli on myös hänen testaamansa. ThermIQ tarjoaa tietokoneen suuntaan AT-komentorajapinnan, joka on taas erilainen sarjaliikennetapa kuin tuossa husdata.se/StatLink-kaapelissa oli.

    Kummassakaan tavassa taloLogger ei yritä liittyä suoraan pumpun liityntään ilman toisen osapuolen välimoduulia, ei yritä hackata i2c:ta sarjaliitynnän yli eikä ole minun katsantokantani mukaisesti sorsiltaan "väärässä".

    Positiivista on, että nyt joku, jolla on tuollainen pumppu (itsellähän ei siis ole vaan koodit tehty speksien/sarjaliikennemonitorointien ja testien perusteella), on selvittänyt mitä liikennettä tuo pumppu ymmärtää ja Thermia/Bosch-käyttäjät pääsevät lähemmäs kustannustehokkaampaa DIY-loggausta.

    VastaaPoista
    Vastaukset
    1. Kiitos korjaavasta kommentista, en muistanutkaan husdata-kaapelia, päivitän blogia vastaavasti.

      Poista
  2. Liittyisiköhän 0x32 tai 0x37 tai joku muu laitenumero esim. laajennuskorttiin, joka tarvitaan mm. jos talossa on kaksi erikseen säädettävää lämmityspiiriä? Minulla näin on, eli I/O-kortin EXT-liittimestä lähtee kaapeli tällaiselle laajennuskortille. Laajennuskortilla taasen on tuplaliitimet EXT-merkinnän vieressä, eli valmius I2C-väylän jatkamiseen edelleen.

    Kunhan joskus saisin aikaa ja hankittua I2C-adapterin, niin voisin katsoa, mitä liikennettä väylällä näkyy. Jotainhan siellä koko ajan kulkee, koska tällä laajennuskortilla olevat lähdöt ja inputit toimivat ja älyhän on I/O-kortilla.

    Muita väylään liitettäviä kortteja, joita tulee mieleen ovat kai: Thermia Online-kortti (liekö juuri tämä 0x2E?), ilma-vesi-laitteiden sulatuskortti, ...

    VastaaPoista
    Vastaukset
    1. Juu varmaan joku tuommoinen kortti se on.

      Poista
    2. 0xFE siis kysyy slavelta minkä "rekisterin" arvon slave haluaa seuraavaksi vastaanottaa (0x00...)/kirjoittaa (0x80...) Keksitkö muuten mikä tuo "rekisteri"/komento 0xFD on mitä pumppu kyselee? Ainakaan tuon kirjoittamasi perusteella et ole sitä tarvinnut.

      Lisää optioita, jotka tarvinnevat väyläyhteyttä: virranmittaus?

      Täytyy katsoa, jos saisi nuo netissä olevat rekisterilistat täydennettyä tuosta omasta koneesta, sillä noista listoistahan puuttuu ainakin kaikki laajennuskorttia vaativat toiminnot. Pyysin aikoinaan lisäantureita putkarilta kaupanpäälle, joilla sain (ja saisin) enabloitua monimutkaisempia toimintamoodeja "puskurisäiliö", "järjestelmäshuntti", "2. lämmityspiiri" ja varmaan muitakin ("uima-allas" tms.?). Vähintäänkin niiden mittausarvot löytyy varmasti rekisterirajapinnasta.

      Vaikutti olevan niin, että analogiainputteihin kun laittaa sopivan kuormavastukset, niin niihin liittyvät lisäominaisuudet ilmestyvät asennusvalikkoon enabloitaviksi. Sitä kautta saa mittaukset sitten valikkoon näkyviin ja ehkäpä paikannettua I2C-rekistereistäkin. Ellei joku muu ehdi ensin...

      Poista
    3. Itse arvaan 0xFD:tä "init/start" komennoksi, kun se tulee bootissa vain kerran, jonka jälkeen tulee vain 0xFE:tä. Minun koodi käsittelee 0xFD:n js 0xFE:n samalla tavalla pelkästää 0xFF vastaamalla ja hyvin tuntuu toimivan.

      Poista
  3. Hi Jonni :) Have you found out how to emulate the Room sensor on the thermia heatpumps like the Thermiq room 2 module are able to do?

    VastaaPoista
    Vastaukset
    1. Yes, I've managed to reverse engineer room2 emulation protocol. I'm currently coding esp32 based solution which does the same thing as room2, you can expect to see a blog post about it in the spring.

      Poista
    2. WOW - that is some great news :) Looking forward to hear more about it :) Good job! BTW are you on facebook / messenger?

      Poista
  4. Kirjoittaja on poistanut tämän kommentin.

    VastaaPoista