I2C illesztése USB-re, egy hőmérő példa

Gondolkodtam azon, írjak-e erről blogot, mert kicsit kifulladt azzal a téma, hogy egy eredendően fórumba szánt, s akként is indított kérdésből az idő előrehaladtával már-már blog lett. Ugyanakkor azt tapasztalom, mostanában itt a HUP-on többeket érdekel a beágyazott rendszerek és a mikrokontrolleres cuccok, ideértve ezek hardware vonatkozásait, így aztán mégis úgy döntöttem, írok róla pár szót. A legrosszabb, ami történhet, hogy érdektelenségbe fullad.

A megoldásom tehát nem kész modulokból építkezik, hanem egyedi tervezésű, tiszta lyuk panelre összerakott hardware, egy C-ben megírt, a neten fellelhető USB stack-et használ, a célja pedig az, hogy közelebb kerüljek az USB mikrokontrolleres kezeléséhez.

Azzal kezdtem, hogy terveztem egy hardware-t, a kétirányú kommunikáció miatt legyen neki mind ki-, mind pedig bemeneti perifériája. Kimenetként egy piros és egy zöld LED, ezeket kezdetben debugolásra használtam. Bemenetként pedig legyen egy MCP9808 típusú digitális hőmérő, amely 1/16 °C felbontással kettes komplemens számábrázolással binárisan képes visszaadni a mért hőmérsékletet I2C buszon.

Szerencsére Microchip PIC mikrokontrollereket használtam már eleget, így ebbe az irányba indultam el, amikor mikrovezérlőt választottam. A kiválasztásánál szempont volt, hogy DIP tokban elérhető legyen, lehetőleg kevés lába legyen, ha van mód rá, oldja meg az USB-hez az órajel szinkront külső kvarc nélkül, lehetőleg legyen I2C-re hardware támogatása, bár ez nem fontos, software-esen kezelhető, s a legfontosabb, hogy legyen hardware-es USB device támogatás benne. Legyen könnyen és olcsón beszerezhető. Na, meg persze a meglévő fejlesztői környezetem alkalmas legyen arra, hogy programot töltsek le neki, illetve elő tudjam azt a bináris állományt állítani forrásból, amit le szeretnék neki tölteni. Így esett a választás a PIC16F1455 típusú eszközre.

Mivel a mikrokontroller I2C busza éppen azokon a lábakon van, amelyen az ICSP busz is, tehát ahol a programot le kell tölteni, valahogy meg kellett oldani, hogy letöltés közben nehogy valamit visszabeszéljen a hőmérő. Ezt a leválasztást legegyszerűbben két jumperrel lehetett volna megoldani, de ismerem magam, néhányszor elfelejtettem volna a jumperek lehúzását a tüskékről, így aztán úgy döntöttem, elegánsabban, két MOSFET-tel oldom meg ezt a kérdést. Így aztán, ha nem fut program a mikrokontrollerben, leválasztásra kerül automatikusan az I2C busz a PIC lábairól. Egyeseket zavarhat, hogy látszólag nincs felhúzás az open drain ALERT lábon, de a PIC ezen lábára lehet belső felhúzást programozni. Ettől függetlenül nem használom az ALERT-et, csak azt szerettem volna, a hardware ne legyen akadálya annak, ha mégis ezt szeretném.

Csináltam 3 fényképet róla.

Akit érdekel, annak tettem fel részletet a forrásból. A PIC-re assembly-ben van írva, ugyanakkor látszik, ez hogyan illeszkedik a C forrásba, ideértve a megszakítás kezelését is. Aztán ott van a host oldali kezelés is. Nincs letisztázva a kód, egy tesztből faragtám át. Az assembly része rendben van szerintem. Csak az nézze meg, aki bírja a horrort. :D Van egy változóm egy byte alsó 6 bitjén. Van egy másik változóm egy másik byte alsó 6 bitjén. Van egy harmadik, 4 bites változóm, amelyik az előbbi két byte fennmaradó 2-2 bitjén terül el. :) Commentre ne nagyon számítson senki. Ha lenne rá igény, megtehetném. Magamnak nem.

Hozzászólások

Céleszköz 500 Ft alatt van készen. Ehhez hasonló van is az ablakpárkányomon, bár szinte sohasem nézek rá. Viszont ebből semmit sem tanulok az USB mikrokontrolleres kezelését illetően. A blog címébe nem véletlenül írtam, hogy példa. Nem az az érdekes, hogy mérjünk hőmérsékletet, hanem az, hogy ha van egy feladat, azt képesek legyünk megoldani. Szerintem az eléggé barkács megoldás, hogy modulokból összelegózunk valamit. Olyan modulokból, amelyeknek sokszor nincs is normális specifikációja.

Aztán ez a bridge éppen azt tudja, amit a mikrokontrollerben implementáltam? Nyilván nem.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Hogy világos legyen a project célja. Kész eszköz esetén ki vagyunk szolgáltatva annak, van-e driver az eszköszhöz. Azt tudje-e, amit szeretnénk. Ebben a projectben a másik oldalon vagyunk. Nem felhasználói egy illesztőnek, hanem megalkotjuk az illesztőt. Valószínűleg a HP-nél is furcsán néznének arra a javaslatra, hogy vegyenek a Canontól nyomtatót, nem kell gyártaniuk, hiszen már van készen. :)

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Egy osszkoltseget es munkaidot irnal? (Nyakmaras, stb, stb?)---------------------------------------------------
Hell is empty and all the devils are here.
-- Wm. Shakespeare, "The Tempest"

Mivel hobby project, fogalmam sincs. Délutánonként csináltam, nagyon kényelmesen. Csináltam egy kávét magamnak, kicsit doksit olvasgattam. Találsz egy linket - jelenleg a blog végén - 3 fényképre mutat. Nincs maratott nyák, ezért is kellett DIP tok. Az egyik kép homályos, de nem is érdekes annyira.

A költség néhány ezer forint. Nem tudom pontosan, mert van egy olyan szokásom, hogy jellemzően minden alkatrészből többet veszek, hogy ha valami balul sülne el, ne akadjak el azon, hogy egy pár forintos alkatrész hiányzik. Szerintem 2000 Ft-ból megvan. Nagyjából január első felében csináltam, nagyon kényelmesen 2 hétig voltam el vele, de nyilván nem egésznapos elfoglaltságként.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

A felsorolt szempontokon kívül miért dolgozol mindig 16-os családdal?

Az alert-et én is bekötöttem. Én sem tudom miért. ;)

Munkához használtam 18-ast is. Szeretem a 16-ost a kevés utasításával. Egyszerű, mint a bot, nekem bejön. A 18-as egyre kevésbé RISC.

Ami az alert-et illeti, van egy érdekesség ebben a hőmérőben. Nem jelzi, mikor van kész a méréssel. Arra gondoltam, a legutóbbi mért eredményhez képest eggyel kisebb és eggyel nagyobb értékeket beállítok alert limitnek, így ha van változás, tudom, mikor van kész a méréssel, ha meg nincs, akkor úgyis mindegy, timeout, shutdown. De aztán úgy döntöttem, adok neki 320 ms-ot ébresztés után, utána elaltatom, majd kiolvasom a hőmérsékletet.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Mindig mondom, hogy a "rengeteg" utasítás helyett egy 2500 osztályt tartalmazó java libet a szeme közé annak aki sokallja. ;) (Ez a többiekre vonatkozik!!) A RISC nem "kevesebb utasítást" jelent. Inkább arról van szó, hogy pl. a mov utasítás rengeteg módosítóval rendelkezik. Teheti, mert széles az utasítás.
Nézd meg a 8X300-at. Bár ezt nem hívták RISC-nek, de csak 8 utasítása van! Használták rakéta irányitására is.

Az alert esetében úgy jártam, hogy csak átfutottam az adatlapot és adtam is le a rajzot nyáktervezésre. Ötletes ez a differencia jelzés, de csak önálló termosztát vagy tényleges riasztási funkció esetén érdemes használni.
Az ilyen hőmérőknek általában "kick start" a szokásos üzemmódja. Mivel úgy is csak a nyák hőmérsékletét méri, nincs értelme ilyen sűrűn mérni. Nem bonyolítottam ennyire: Először kiolvasom, majd belerúgok (SHUTDOWN=1, +ONE-SHOT). Mérés után elalszik a szerkezet, de bármikor ki lehet olvasni. A ciklusidő 4s, de ez senkit nem érdekel amíg nincs tűzvész. Akkor meg úgy is mindegy.

Örülök, ha teccik!
Adok még egy kis inspirációt: pic12hv609 kód, ezért csak semmi lapozgatás!
Egy timer it-be épített mini állapotgép ugrótáblája.

				movf		State, w
				addwf		PCL, f
				goto		Init_State
				goto		On_State
				goto		Off_State
				goto		No_TIMER1

A poén most kezdődik! Ezt egy kollégának készítettem. Fagyban a benzinkályha izzító szerkezetének ad 12V/12A áramot a bekapcsolás után 2 percig. A srác ránéz az áramkörre: Látom, 555-össel csináltad. :)))

A kód elég szokványos, ha megnézed, az _i2c_isr megszakításkezelésben hasonlóképpen csináltam meg az állapotautomatát, csak nekem volt kéznél brw utasításom, s használhatom, mert itt nem csaphat be IT.

Ami viszont a kód után jön, az tényleg poén. :) Nem tűnt fel neki egy nagyobbacska kondenzátor hiánya? ;)

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Köszi! Ilyenkor mindig úgy érzem van hova fejlődni. :)
Én is csináltam egy hobby projektet mikrovezérlőre, de én nem mentem ennyire "mélyre", és nem vagyok ilyen profi mérnők/programozó sem.
A projekt egy Arduino alapú metronóm. Nekem sok örömet okozott a készítés/tervezés. :)

Ezzel megoldhato a dolog kulon driver vagy egyeb kodolas nelkul:

http://www.harbaum.org/till/i2c_tiny_usb/index.shtml

Ezzel kapsz egy normal /dev/i2c- interface-t onnan mar lm-sensors-al vagy akarmivel kiolvashato az eszkoz.

(Persze ertem en hogy tanulas/barkacsolas, meg remlik mashonnan hogy mintha nem szeretned az AVR-t, csak akarom mutatni hogy ilyen is van)

Apropo, tovabbi projektotlet lehetne a i2c-tiny-usb protokolljat implementalni PIC-re, ha mar egyszer a kernel driver ott van a mainline-ban, biztos jol jonne masnak is.

Nem szeretem a kötöttségeket, azt, ha ki vagyok szolgáltatva kész terméknek, ennek folyományaként driver-nek, s reménykednem kell, hogy az újabb kernel forrásába is beleteszik még. Ez a project a szabadságról szól. Arról, hogy magamnak implementálom az USB device-t, host oldalról pedig a libusb függvényeire támaszkodom. Ami pedig az USB-n kívül van, az szokásos, assembly-ben azt csinálok, amit akarok szemléletű kód. :)

Korábban, ha PC-hez kellett illeszteni valamit, akkor ott volt az RS232-es soros port. A mai PC-ken viszont általában nincs már soros interface. Igen, van USB-RS232 konverter, de annyira gány az, hogy csinálunk valamit RS232-re, kell neki külső táp, és akkor még egy ilyen bridge is, amikor a mai PC-ken az USB van megálmodva a külső eszközökkel való elsődleges platformként. Ezért gondoltam azt, végre leküzdöm az akadályt, a Halálnak Hídját, az USB-t, amely eddig elvette a kedvem attól, hogy bármilyen mikrokontrolleres dolgot PC-re illesszek. Utólag visszatekintve sokkal félelmetesebbnek tűnt, mint amilyen valójában volt.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Egy csomo alaplapon a mai napig van COM1-2 port, csak nincs hatul kivezetve, kell egy parszaz forintos rear panel hozza, es csok. Van LPT is, ha vkinek az kell.

Egyedul a laptopok neccesek ilyen szempontbol, pedig elferne bennuk, a soros biztosan, az nem olyan szeles.
--
Blog | @hron84
Üzemeltető macik

Igen, ezt értem, de ha más gépére kell illeszteni a perifériát, mégsem kezdhetem azzal, hogy bocs, akkor most szétszedem a géped. Meg aztán igaz, hogy az RS232 faék egyszerűségű, meg lassú, de legalább tápfeszültséget sem ad. :( Azt most hagyjuk, hogy a handshake vonalakból kinyerünk 1-2 mA áramot. Az USB egy kulturált megoldás, bár a ló másik oldala, hogy a device bemutatkozik, több végpont lehet egy eszközben, különféle kommunikációs típusok léteznek USB-n, mindegyiknek más az erénye. Szóval földi halandó számára igen bonyolult, egy laza 600 oldallal intézték el a specifikálását, s ez csak a szabvány, még szó sincs az implementálásról.

Ezen felül a tendencia is látszik. Még csak nincs kihozva az RS232-es csatlakozó, de egyre több alaplapon már egyáltalán nem lesz, tüskesoron sem. Eljárt felette az idő.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Tök' jó, hogy beleástad magad az USB dolgaiba, ez eddig teljesen rendben van... de... pont az a jó az RS232-ben, hogy egyszerű, kiforrott, "ezer éve" használatos. A mai napig kiválóan megfelel arra, amire való, ezt vallja több neves gyártó is, mert ráteszi még az eszközeire (Cisco, Juniper, Huawei és egyebek). Nekem nem nagyon tűnik úgy, hogy a routerek, switch-ek és egyéb hasonló eszközök konzol portjai rövid időn belül átállnának másra. Nem túl régóta van már olyan öszvér megoldás, ahol a management porton megosztva található egy 10/100-as ethernet és egy handshake-ek nélküli RS232, de ezt eddig csak egy eszköz (eszközcsalád) esetében tapasztaltam. Egyébként a SOHO routerek közül is sok típus tartalmaz belül TTL szintű soros portot, pl. a TP-Link TL-WR841ND is :)

USB/RS232 átalakítók jó ideje kaphatók, az FTDI, a Prolific, a Silicon Labs vagy a WCH továbbra is gyártja a szükséges chipeket, ahogy gyártják a szintillesztőket is.

A notebookgyártók szintén kínálnak még RS232-vel szerelt példányokat - "természetesen" nem az alsó árkategóriában.

Igen, az RS232 nem ad tápfeszültséget, viszont az a néhány mA, amit ki lehet nyerni belőle, mégis elég erre-arra, pl. az RS232/RS422 átalakítók gond nélkül működnek így (feltéve, ha a soros port "rendes" jelszintekkel dolgozik, legalább +/-8..9V-tal, nem pl. +/-5..6V-tal, ami ugyan teljesíti a szabvány szerinti szinteket, de táplálásra nem mindig elég).

USB/soros átalakítóból kaphatók filléres változatok, amiken nincs szintillesztő, a VCC választhatóan 5V vagy 3,3V, így ezeket közvetlenül a mikrovezérlőre lehet kötni, és még tápfeszültséget is adnak.

Értem, hogy miért fektettél energiát az USB megismerésébe, de azért az is látható, hogy vannak még egyszerű megoldások, amik miatt a soros port tovább élhet, illetve hasonló megoldást, amit te megvalósítottál, már mások is kidolgoztak (igen, tudom, jobban hiszel a saját megvalósításban).

Nincs nekem bajom az RS232-vel, faék egyszerűségű, magam is az egyik legalmasabb dolognak tartom kis mennyiségű adatátvitelre. Az USB létrejöttét szerintem az inspirálta, hogy egyfelől lassú volt az RS232, másfelől nem volt megoldott a periféria táplálása, aztán semmit sem mondott az eszközről és az igényelt kommunikáció típusáról: fontos-e az adatátvitel merev ütemezése, cserébe megengedhető adatvesztés - tipikusan hangátvitel, streaming felhasználás -, vagy lehet az átvitelben fennakadás időben, de legyen hibátlan az adatátvitel, ezt csinálják a pendrive-ok. De lehet olyan is, hogy csak néhány byte-ot akar küldeni a periféria, mint ahogyan teszik az egerek, billentyűzetek.

Noha nekem is szimpatikus az RS232, ma már nem nagyon csinálnék vele PC-hez perifériát, mert meg kell oldanom a táplálását, valamint egy mai gépen van egy rakás USB port, de nincs RS232. Egész egyszerűen szebb egy natív USB-s illesztés, mint USB-RS232 konverter után ott állni azzal a problémával, hogy az eszköz nem azonosította magát, nincs tápfeszültségünk, és lassú az egész. Lehet, hogy többre van szükségünk.

Szerencsére vannak már mikrokontrollerek, amelyek hardware támogatást nyújtanak USB-re, készen C-ben írott USB stacket is találtam. Az assembly részét megírtam, a dolgom az volt, hogy a kódot olyan állapotba hozzam, hogy az lefordítható legyen - ez azért nem elsőre jött össze -, valamint az assembly programomat a C-ben írt USB stackbe integráljam. Ideértve megszakítás kezelést, watchdogot, ennélfogva figyelve futásidőkre, ami egy idegen, részben nem általam írt környezet esetén nem is triviális dolog.

Most van egy igazoltan működőképes vázlatom, innentől fogva erre építkezve bármikor meg tudom oldani egy periféria USB-s illesztését. Teszem azt, egy mérésadatgyűjtő rendszert, vagy mondjuk egy rádiós interface-t kell illeszteni.

Persze tudom, manapság már mindenre van előemésztett, kész megoldás. Ezzel azért vannak fenntartásaim. Ezek nem pont azt fogják tudni, ami az igényem, kissé redundánsak lesznek, hiszen két mikrokontrollerből kell összerakni, amit egyből is lehetne. Aztán ezeket az illesztőket is készítik valakik, nekik is meg kellett oldani ezt a problémát, tehát az ember lehet azon az oldalon, ahol ezeket csinálják, s nem felhasználják készen. Kész cuccok használata esetén a kiszolgáltatottság is nagyobb. Mi van, ha már nem gyártják? Mi van, ha már nem lesz támogatás hozzá a kernelben?

Nekem mindenképpen jó érzés, hogy bármit, amit csak kitalálok, vagy amire igény van, tudok PC-re illeszteni USB-n. Innen csak a fantázia szab határt, nem a körülmények korlátoznak.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Szerintem meg nem. Olyan ez, mint az IDE interface. Már csak egy van, vagy egy sincs. Viszont van egy rakás SATA. De mondom, az RS232-vel gond a tápfeszültség, de az is, hogy nem mutatkozik be az eszköz. Meg lassú. Az, hogy belülről ki lehet hozni, nem meggyőző. Amikor egy perifériát használni szeretnél, akkor azzal kezded, hogy senki ne nézzen most ide, szétszedem a gépet, kihozom a soros portot? Tényleg életszerű.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Nem kell szétszedni a gépet, mivel - ahogy írod - van rajta egy rakás USB port, amik alkalmasak arra, hogy USB/RS232 átalakítót fogadjanak. Ezt az átalakítót akár be is építheted a saját eszközödbe, akkor nem kell még külön hurcibálni hozzá, ekkor még TTL/RS232 szintillesztés se kell, sőt, ebben az esetben akár saját VID:PID párost is írhatsz bele (pl. az ATEN is ezt teszi), de ezekeről mind volt már szó itt. Téged egyszerűen érdekelt az USB port felhasználhatósága (meg akartad mászni a hegyet, mert ott volt). Most van egy saját megoldásod, ami teljesen rendben van. Akinek meg jó a bevált megoldás, az használja azt (cserében esetleg kevesebbet tud az USB-ről, viszont helyette foglalkozhat mással, ami pl. jobban érdekli, vagy fontosabbnak tartja).

Nem tudom, de ha elkepzelem a dolgot, hogy EN gyartok egy egyedi periferiat, akkor megmondom, hogy ehhez RS232-re lesz szukseg, es majd a helyi rendszergazda megoldja a dolgot (o fog odamenni a gephez, es szetszedni). Es meg fogsz lepodni, ez egyebkent a gyakorlatban is igy mukodik, foleg hazon belul gyartott/gyartatott hardver eseteben. Ha nincs meg a tudas vagy a lehetoseg az USB-s illeszteshez, akkor ahhoz fogjak illeszteni, amihez epp lehet.

Sot, tovabb megyek, a specialis periferiak teren leginkabb a gyartok diktalnak. Ha respiacra arulsz hardvert, nagyjabol azt csinalhatsz, ami akarsz, ugyis megveszik, mert nincs vagy nagyon keves mas alternativ gyarto van a piacon. Minel specifikusabb az, amit csinalsz, annal inkabb nyero helyzetben vagy.
--
Blog | @hron84
Üzemeltető macik