Avtor: dr. Simon Vavpotič
2020_289_39
ESP8266 Wi-Fi moduli, kot majhna, enostavna in učinkovita 32-bitna osnova za gradnjo naprav in sistemov interneta stvari (IoT), že leta burijo domišljijo programerjev. Čeprav so novi navadno predprogramirani kot brezžični Wi-Fi modemi, jih lahko z lastno programsko opremo spremenimo v samostojne krmilnike enostavnih IoT naprav.
Polnilnik baterij z ESP32
V preteklem članku smo spletnemu radiju dodali enkoder, IR sprejemnik in zaslon, katerega shemo si lahko ogledate na spletni strani[1]. Našli boste tudi izvorno kodo vgrajene programske opreme. Kot vidimo, je novi spletni radio povsem »zadovoljen« v LEGO ohišju, ki ga z lahkoto prilagajamo novim napravam in lastnim potrebam. Nato smo se lotili predelave ESP32 modula s kamero OV2640 in preučevali njegovo praktično uporabno vrednost. Vgradili smo prenapetostno in podnapetostno zaščito in vgradili nekaj izboljšav, med katerimi velja izpostaviti možnost programskega reseta kamere ter možnost programiranja nove vgrajene programske opreme brez pretikanja mostičkov in ročnega odklapljanja in priklapljanja napajanja.
Tokrat se najprej lotimo razvoja pametnega polnilnika akumulatorskih baterij, potem pa si ogledamo še razvoj lastne programske oprema za komunikacijski most med USB in RS232 na osnovi PIC18F14K50 (opcijsko tudi MCP2200), ki ga lahko v lastnih ESP projektih uporabimo tudi kot RS232 razširitveno vezje za dodatne vhodno-izhodne priključke in ostale funkcionalnosti, ki so vgrajene v PIC18 mikrokontrolerje. Vsekakor idej ne manjka, še posebej zanimivo pa je, ker za vse potrebujemo le en dodatni čip, ki bi ga že tako ali tako potrebovali za programiranje ESP modula.
Ta vsebina je samo za naročnike
ESP32-samodejni polnilnik akumulatorskih baterij
Hitrost polnjenja akumulatorskih baterij je odvisna predvsem od polnilnega električnega toka, ki ne sme preseči proizvajalčevih omejitev. Mogoče je hitro ali počasno polnjenje, vendar moramo pri hitrem polnjenju zagotoviti samodejno prekinitev polnjenja, ko se baterija napolni, v nasprotnem jo polnilnik poškoduje in zmanjša njeno kapaciteto. Po drugi strani, počasno polnjenje, ki lahko namesto 1 ure traja tudi 16 ur, poteka tudi pri 10-krat manjšem polnilnem toku. Poškodbe baterij zaradi predolgega polnjenja so manj verjetne.
Enostavni polnilniki baterij so brez samodejnega odklopa polnjenja, zato baterije navadno polnijo z nekajkrat manjšim tokom od največjega dovoljenega. Vseeno je nazivni polnilnik tok pogosto večji od tistega, s katerim baterije ne poškodujemo kljub predolgemu polnjenju. Čas polnjenja je tako lahko tudi 16 ur, vsekakor pa tudi v tem primeru s polnjenjem ne smemo pretiravati.
Kako vemo, da so akumulatorske baterije polne? Napetost baterije med polnjenjem narašča od vrednosti napetosti izpraznjene baterije (pod 1,1 V), preko nazivne vrednosti napetosti 1,2 V za uporabno baterijo do maksimalne vrednosti, ki znaša okoli 1,5 V. Ko napetost baterije med polnjenjem doseže to vrednost, moramo polnjenje prekiniti. Sicer pa so klasični polnilniki baterij izdelani tako, da imajo sorazmerno visoko notranjo upornost zaradi česar polnilna napetost narašča skupaj z napolnjenostjo baterije, vendar je polna napetost vedno precej višja od napetosti baterije, ko skozi njo ne teče polnilni tok. Denimo pri enostavnem polnilniku Ni-Cd baterij z maksimalnim tokom 120 mA za polnjenje baterij z nazivno napetostjo 1,2 V, na kontaktih za polnjenje baterij izmerimo 4 V, ko baterija ni vstavljena, med polnjenjem pa je napetost seveda nižja, vendar običajno precej višja od 1,5 V. Zato je pametno, da pred merjenjem napolnjenosti baterij polnjenje za hip izklopimo, pomerimo napetost in nato po potrebi nadaljujemo. Merjenje napolnjenosti lahko izvajamo v časovnih intervalih. Druga možnost je neposredno merjenje polnilnega toka, ki upada z napolnjenostjo, vendar pa moramo za oceno napolnjenosti baterije upoštevati tudi njeno iztrošenost, saj ta povečuje njeno notranjo upornost in hkrati zmanjšuje njeno tokovno zmogljivost.
Načrt predelave enostavnega polnilnika baterij
Cilj je predelava enostavnega polnilnika baterij v samodejnega, tako da se polnjenje prekine, ko napetost neobremenjene baterije doseže vrednost okoli 1,5 V, oziroma najvišjo dovoljeno napetost glede na specifikacije proizvajalca. Nadzor polnjenja baterije lahko izvedemo sP-MOSFET (ali N-MOSFET) stikalnimi tranzistorji z dovolj veliko tokovno zmogljivostjo. Pri tem ni odveč, če izberemo tranzistorje, ki prenesejo večji tok kot ga lahko proizvede polnilnik v primeru kratkega stika, saj se bomo tako izognili njihovemu uničenju v primeru, ko bi vstavili povsem iztrošeno (oz. prebito) akumulatorsko baterijo, ki se ne polni, a kljub temu pri polnjenju »potegne« zelo velik tok. Polnilnik lahko uporabljamo tudi za vzdrževanje baterij, tako da jih pred polnjenjem do konca izprazni in šele potem začne nov polnilni cikel.
Moj polnilnik lahko hkrati polni do štiri A, AA ali AAA baterije ali eno 9 V baterijo, a slednjih nimam. Zato sem se odločil, da izdelam 4-kanalnik krmilnik z možnostjo vzdrževanja baterij. Kot stikala sem uporabil AP4525GEH-HF-3, ki združuje usklajen park par N-MOSFET in P-MOSFET tranzistorjev, namenjen predvsem krmiljenju elektromotorjev. Vrhnja tokovna zmogljivost je kar 15 A, kar povsem zadošča. P-MOSFET sem uporabil kot stikalo za priklop polnilne napetosti, N-MOSFET pa kot stikalo za priklop praznilne upornosti, ki omogoča nadzorovano praznjenje akumulatorske baterije.
Kaj pa krmilnik?
Čeprav bi lahko uporabil ESP8266, je ESP32 vsekakor boljša izbira, saj ima ESP8266 le en analogni vhod, kar pomeni, da bi moral sam izdelali multiplekser. Tako je dosti enostavneje uporabiti, kar ESP32 z dvema 12-bitnima A/D pretvornikoma s skupno do 18-multipleksiranimi analognimi vhodi. Kar zadeva ESP32, je tako mogoče merjenje ne samo električne napetosti posamezne baterija, ampak tudi polnilnega toka. A/D pretvornika imata merilno območje 1 V, ki ga z enostavnim uporovnim delilnikom prilagodimo na poljubno drugo merilno območje enosmerne napetosti. Paziti moramo le na morebitne negativne vrednosti napetosti, ki jih lahko preprečimo z zaščitno diodo. Slednja zniža merjeno napetost za okoli 0,7 V in tudi omeji merilni doseg, vendar napetosti, nižjih od 0,7 V niti ni potrebno meriti, saj je baterija izpraznjena že pri okoli 1,1 V. Druga možnost je vezava zaščitne diode vzporedno z vhodom, pri čemer mora biti uporovni delilnik izdelan tako, da morebitna negativna vrednost napetosti ne preseže -0,3 V, kar je zgornja meja, ki ji prenesejo vhodi ESP32. Upoštevati moramo namreč, da zaščitna dioda začne prevajati pri okoli 0,7 V. Če pri tem uporovni delilnik
vhodno napetost zniža za 10-krat, je to največ -0,07 V, kar je dovolj pod dovoljeno mejo. Vsekakor bomo delilno razmerje 1:10 potrebovali, če želimo meriti napetosti do 10 V. Če bi se odločili tudi za nadzor polnjenja 9 V baterij, bi potrebovali uporovni delilnik z razmerjem okoli 1:20. Ni odveč opozorilo, da moramo zaščitno diodo vezati vzporedno z vhodom napetostnega delilnika in ne na digitalni vhod ESP32.
Rešiti moramo le še vprašanje krmilne povezave med MOSFET in ESP32. Vsekakor si tu lahko pomagamo s staro dobro darlingtonsko vezavo bipolarnih tranzistorjev, oziroma kar čipom ULN2803, ki ima vgrajenih 8 tovrstnih vezij, ki zmorejo najvišji izhodni tok 100 mA. A nam ne gre za jakost toka, temveč za prilagoditev napetostnih nivojev, tako da zagotovimo ustrezne delovne pogoje za delovanje MOSFETov. Za krmiljenje vsakega AP4525GEH-HF-3 MOSFET para tranzistorjev potrebujemo po dva digitalna izhoda, od katerih z enim prožimo vklop in izklop krmiljenja, z drugim pa izbiramo, ali bomo odprli P-MOSFET ali N-MOSFET. Si pa ne želimo odpreti obeh hkrati, saj bi to po nepotrebnem obremenilo napajalnik polnilnika baterij. Gradnjo pametnega krmilnika baterij si lahko poenostavimo, če izpustimo možnost vzdrževalnega praznjenja baterij. Tako potrebujemo za vsak kanal le še po en močnostni P-MOSFET.
Vgrajena programska oprema
ESP32 v osnovi ni bil mišljen kot krmilna enota polnilnika baterij. Kljub temu, si lahko privoščimo marsikaj, le kakemu »sosedu« ne smemo dovoliti, da bi na kakršenkoli način posegel v potek polnjenja preko brezžične povezave. Najenostavnejša možnost je, da slednjo preprosto izklopimo, vendar je prikladneje, da prek Wi-Fi omogočimo zgolj branje podatkov o trenutnem stanju baterij, vse krmilne funkcije (npr. vzdrževanje baterije) pa upravljamo neposredno z mikrostikalno tipkovnico. Paziti moramo le še, da preprečimo kakršenkoli način sesutja vgrajene programske opreme zaradi težav z Wi-Fi povezavo. Zato moramo vgrajeno programsko kodo dodobra preizkusiti za vse mogoče situacije, predvsem odklopa ali porušitve in ponovne vzpostavitve Wi-Fi povezave. Opcijsko lahko uporabimo tudi Bluetooth, za katerega velja enaka previdnosti. Za upravljanje polnilnika lahko namesto Wi-Fi ali Bluetooth uporabimo tudi RS232 povezavo, ki jo preko MCP2200 povežemo s prostim USB priključkom osebnega računalnika.
Morda omenimo še bolj eksotično možnost uporabe Ethernet povezave, pri kateri lahko startamo električne sheme z ESP32 in LAN8720A, ki nam sicer »odžre« kar 10 GPIO priključkov ESP32, a je slednjih še vedno dovolj za upravljanje 4-kanalnega krmilnika polnjenja baterij. A se zdi krmiljenje prek USB še vedno enostavnejša možnost, saj potrebujemo most med USB in RS232 tudi za programiranje ESP32.
Tako smo prišli še do zadnjega vprašanja o najprimernejši zgradbi polnilnika baterij, ali lahko most med RS232 in USB uporabimo tudi za dodatne digitalne in analogne priključke, če bi nam jih pri ESP32 zmanjkalo. Odgovor je seveda pritrdilen, vendar ni enostavno, kot lahko preberete v nadaljevanju.
Električna shema
Potrebujemo štiri glavne gradnike, star enostavni univerzalni polnilnik akumulatorskih baterij, ESP32, ULN2803 štiri AP4525GEH-HF-3 MOSFET pare tranzistorjev. Za merjenje napetosti baterij lahko uporabimo GPIO39 (ADC1_CH3), GPIO36 (ADC1_CH3), GPIO35(ADC1_CH7) in GPIO34(ADC1_CH6), ki jih lahko povežemo s pripadajočimi kanala (v oklepajih) prvega A/D pretvornika (ADC1). Za krmiljenje AP4525GEH-HF-3 potrebujemo še 8 digitalnih izhodov. Če nameravamo krmilnik povezati v ožičeno Ethernet omrežje, moramo za modul LAN8720A rezervirati še priključke GPIO22, GPIO21, GPIO19, GPIO18, GPIO5, GPIO17, GPIO16, GPIO0, GPIO4, GPIO25, GPIO26 in GPIO27. Tako za krmiljenje ostanejo prosti GPIO2, GPIO12, GPIO13, GPIO14, GPIO15, GPIO23, GPIO32 in GPIO33, kar je ravno prav. Če želimo hkrati polniti več baterij, se lahko LAN8720A modulu odrečemo, ali pa uporabimo.
Spodnjo zamisel za USB-RS232 most, ki hkrati deluje kot razširitveni vmesnik z dodatnimi GPIO priključki, vključno z dodatnim 10-bitnim A/D pretvornikom. Tako »potolčemo dve muhi na en mah«, zagotovimo si možnost programiranja ESP32 preko USB in hkrati dobimo dodatne krmilne priključke. Res pa je, da je za marsikoga udobneje uporabiti standardni USB-RS232 most, od katerih pa ima večina implementirane samo 3 priključke, ki omogočajo enostavno RS-232 komunikacijo in posredovanje podatkov med ESP32 in osebnim računalnikom. Večina avtorjev projektov pri tem signal GPIO0, ki omogoča preklop ESP32 v načinu za nalaganje nove vgrajene programske opreme, krmili ročno s pomočjo mikrostikala. Sicer ima ESP32 pet priključkov, ki določajo način njegovega zagona, vendar imajo z vsi prednastavljene vrednosti tako, da se ESP32 normalno zažene iz SPI EEPROMa, za nalaganje nove vgrajene programske opreme v SPI EEPROM pa je dovolj, da ob zagonu za kratek čas GPIO0 zagotovimo nizko stanje.
Zdaj pa poglejmo, kako izdelamo že omenjene uporovne napetostne delilnike, s katerimi vhodno napetost na GPIO34, GPIO35, GPIO36 in GPIO39 zmanjšamo na interval med 0 in 1 V. Ker je poraba toka ESP32 izjemno majhna, lahko vsakega od štirih delilnikov izdelamo iz uporov R1 in R2, katerih skupna upornost je 10 k Ohmov. Pri določitvi merilnega območja je smiselno biti nekoliko radodaren in omogočiti merjenje napetosti do 10 V, saj bomo tako z ESP zaznali tudi, če bo šlo pri, med hkratnim polnjenjem 4 baterij, zelo obremenjenem napajalniku polnilnika kaj narobe in bomo takoj prekinili polnjenje. Pri najvišji vrednosti napetosti (10 V) mora biti tako padec napetosti na R2 9 V, na R1, katerega napetost merimo, pa 1 V. Zdaj lahko določimo vrednosti obeh uporov, ki znašata R1 = 1 k Ohm in R2 = 9 k Ohm. Ker pa bi upora 9 k Ohmov težko našli, ga lahko zamenjamo z 10 k Ohmov in imamo tako skupno upornost 11 k Ohmov, s čemer povečamo merilni doseg malo na 10 V. Pri natančnosti meritev slednje ne vpliva, saj je ADC1 12-biten. Pri polnjenju baterij imamo tako še vedno zagotovljeno več kot dovolj veliko natančnost.
Poglejmo še natančno, kako deluje krmiljenje AP4525GEH-HF-3, če si najprej ogledamo shemo 6 A krmilnika enosmernih električnih motorjev, vidimo, da P-MOSFET in N-MOSFET v vsakem paru krmilimo z enim NPN bipolarnim tranzistorjem (BC817), ki med prevajanjem s pomočjo enostavnega uporovnega vezja odpre vrata N-MOSFETa in tako zagotovi povezavo proti masi, ko pa ne prevaja, odpre P-MOSFET in zagotovi povezavo na napajanje. Ker v krmilniku enosmernih električnih motorjev uporabljamo dva AP4525GEH-HF-3, lahko obrnemo polariteto in tako motor zavrtimo v nasprotno smer. Nasprotno, pri polnjenju baterij želimo ves čas enako polariteto, zato zadošča en AP4525GEH-HF-3 čip, vendar pa moramo zagotoviti neodvisni krmiljenji P-MOSFETa in N-MOSFETa. Obenem lahko BC817 spustimo in ga nadomestimo z negatorjem z odprtim kolektorjev v ULN2803 čipu, ki združuje 8 neodvisnih negatorjev.
Poglejmo, kako deluje preurejeno vezje. Vrata N-MOSFETa (G1) preko 4,7 k Ohmskega upora vežemo na napajanje, prav tako tudi vrata P-MOSFETa (G2). V tem primeru je P-MOSFET odprt, N-MOSFET pa zaprt. Vendar želimo, da bi bil tudi P-MOSFET zaprt, zato moramo preko pripadajočega negatorja z odprtim kolektorjem v ULN2803 zagotoviti nizko stanje na G2, s čemer zapremo tudi P-MOSFET. Zato vhod omenjenega negatorja z uporom 4,7 k Ohmov vežemo na napajanje. Tako je ob zagonu ESP32 baterija, ki jo nameravamo polniti, odklopljena od napajanja, hkrati pa se ne prazni preko močnostnega upora, ki je namenjen njenemu vzdrževanju in testiranju. Vsekakor velja poudariti, da morajo biti vsi izhodi ESP32 v stanju visoke upornosti, program pa jih mora nastaviti tako, da so N-MOSFETi in P-MOSFETi pred začetkom polnjenja zaprti. Vsekakor pa moramo v programu upoštevati, da N-MOSFET in P-MOSFET v paru nikdar ne smeta biti hkrati odprta, saj v tem primeru teče ves tok iz baterij in napajalnika skozi merilno-praznilni upor (ali upore, če imamo za vsako baterijo svojega).
Po vsem napisanem, se moramo vprašati še, koliko merilno-praznilnih močnostnih uporov dejansko potrebujemo. Ker baterije najpogosteje polnimo, je dovolj tudi en sam dovolj zmogljiv upor (okoli 10 Ohmov in 1 W), na katerega vežemo izvore (S1) vseh N-MOSFETov. Pri 1,5 V napajalne napetosti iz polne baterije je tako izgubna moč okoli 200 mW, ostala zmogljivost pa je za rezervo, da se upor v plastičnem ohišju napajalnika vseeno ne bi preveč segreval in morebiti stopil ohišja. Namesto upora lahko uporabimo tudi dve vzporedno vezani kolesarski žarnici (za 3,5 V, 0,2 W).
Algoritem polnjenja
Za napajanje električnih vezij, predvsem igrač, pogosto uporabljamo po dve in več zaporedno vezanih akumulatorskih baterij. Vendar že nove akumulatorske baterije istega proizvajalca in enakega tipa niso nimajo povsem enake kapacitete in tokovne zmogljivosti, a sta obe v predpisanih tolerancah. Zaradi majhnih razlik v notranji upornosti v več ciklih polnjenja in uporabe zato nekoliko različno iztrošijo in zato se tudi po vsaki uporabi vse bolj različno izpraznijo. Zato moramo za optimalno napolnitev baterij in minimalni izrabo med polnjenjem spremljati vsako posebej. Če vnaprej določimo pavšalni čas polnjenja, denimo 16 ur, bo lahko ena izmed baterij po koncu polnjenja tik pred 100 % napolnjenostjo, drugo pa bomo polnili prekomerno npr. s 120 % potrebne energije. Slednje zmanjša kapaciteto baterije, kar lahko vidimo tudi iz grafov proizvajalcev, kjer se da idealno polnjenje prekiniti skoraj istočasno, ko baterija doseže največjo napolnjenost, vsekakor pa pri tem govorimo o minutah in ne o sekundah. Potreben odzivni čas je daljši, če baterije polnimo z nekajkrat manjšim tokom od maksimalnega, kar je res tudi v mojem primeru.
Prvi korak je ugotavljanje stanja baterij in približnega časa, potrebnega za njihovo polnitev. Pri tem izmerimo napetost neobremenjene baterije, nato pa še napetost pod znano konstantno obremenitvijo (npr. 100 ohmski upor ali žarnica). Enostavni polnilniki imajo v ta namen pogosto vgrajeno žarnico, na osnovi katere lahko približno ocenimo preostalo napolnjenost baterije.
Meritvi omogočata približno določitev notranje upornosti baterije. Če vodimo statistiko polnitev posamezne akumulatorske baterije, lahko spremljamo tudi postopno spreminjanje njene zmogljivosti, ki upada s številom polnitev. Želimo izdelati tak polnilni algoritem, da bi bil upad čim manjši.
Na osnovi ocenjene preostale zmogljivosti baterije in trenutne napolnjenosti lahko izračunamo približni minimalni čas polnjenja, med katerim ne bomo preverjali napolnjenosti baterije, saj s tem po nepotrebnem prekinjamo proces polnjenja in zmanjšujemo zmogljivost baterije. Po tem času bomo preverili, ali je baterija povsem napolnjena in jo po potrebi ponovili omenjeni polnilni cikel do polne napolnjenosti. Alternativna možnost bi bila občasno prekinjanje polnjenje in sprotno merjenje napolnjenosti, vendar je slednje smiselno le proti koncu polnjenja. Vendar je prvi princip bolj varen za baterijo, zato ga uporabljajo tudi nekateri komercialni polnilniki baterij z avtomatskim odklopom polnjenja, oziroma vsaj tisti, pri katerih proizvajalec navaja, da moramo v primeru začetka polnjenja ali premajhne napolnitve baterije le to potem, ko ugasne lučka za polnjenje, vzeti iz polnilnika in jo vanj ponovni vstaviti.
Kako napisati program?
Za ESP32 in ESP8266 Wi-Fi module je na srečo na voljo množica programskih knjižnic in veliko uporabnih primerov, saj je bilo celotno razvojno okolja izdelano tudi za programerje začetnike, zaradi česar je večina programskih struktur in funkcij programskih knjižnic sorazmerno enostavna za razumevanje in uporabo. Praviloma tudi avtorji že prevedenih programskih knjižnic programsko kodo slednjih objavijo na spletu, večina na GitHubu. Zato lahko bolj izkušeni programerji vselej nadaljujejo njihov razvoj, ali odstranijo najbolj nadležne programske hrošče.
Torej, kaj potrebujemo? Gotovo rabimo način za merjenje časa, vendar brez dodatne strojne opreme (npr. zunanjega resonatorja s 32,768 kHz). Merjenje časa mora biti zato izvedeno na osnovi sistemskega merila mikrosekund, ki pretečejo od zagona ESP modula. Pri tem imamo na voljo programske knjižnice za samostojno preračunavanje časa, kakor tudi programske knjižnice, s katerimi se lahko vselej povežemo s svetovnimi časovnimi strežniki, ki s pomočjo atomskih ur merijo čas z izjemno natančnostjo. No, tudi če polnilnik baterij ne bo imel dostopa do interneta, si še vedno lahko pomagamo z merilnikom mikrosekund, saj je pomembna dolžina polnilnega intervala, na pa realni čas. Je pa vseeno dodana vrednost, če vemo, natančno kdaj bo posamezna baterija polna.
Drugi del logistične vgrajene programske opreme skrbi za pravilno obravnavanje različnih tipov baterij z različnimi nazivnimi zmogljivostmi. Pri tem mora upoštevati specifikacije proizvajalcev glede nazivne zmogljivosti in največjega polnilnega toka ter časa polnjenja. Najboljša možnost je, da tovrstne parametre enostavno vnesemo ročno, preden začnemo polniti baterijo. Lahko pa namesto tega polnilnik pred začetkom polnjenja samodejno izvede meritev notranje upornosti baterije in na podlagi te oceni, za kakšno baterijo gre. Denimo, večje baterija, tipa AA imajo praviloma nižjo notranjo upornost kot baterije tipa AAA, iz česar je mogoče približno sklepati tudi na zmogljivost baterije in na osnovi te približno določiti čas polnjenja. Med polnjenjem je sicer prav tako mogoče tudi spremljanje spreminjanje polnilne napetosti, ki pri polnilnikih baterij brez regulacije polnilne napetosti narašča skupaj z napolnjenostjo baterije, hkrati s tem pa praviloma počasi upada tudi polnilni tok.
Ohišje in uporabniški vmesnik
Ob besedni zvezi »uporabniški vmesnik« mnogi pomislijo na programsko aplikacijo, vendar je lahko uporabniški vmesnik sestavljen tudi iz LED prikazovalnika ali posameznih LEDic ter mikrostikalne tipkovnice. Če želimo za elektroniko pametnega polnilnika baterij le prostor, ki ga proizvajalec enostavnega polnilnika baterij ni izkoristil, moramo biti pri načrtovanju vezja zelo prilagodljivi in skromni pri porabi prostora. K sreči so ESP32 in AP4525GEH-HF-3 izdelani v SMD tehniki in omogočajo odlično izrabo prostora. Nekoliko večji je le ULN2803, ki pa se ga vseeno ni treba ustrašiti, saj lahko so vsi vhodni in izhodi priključki razporejeni na nasprotnih polovicah čipa v enakih zaporedjih.
Po drugi strani, nam nihče na brani, da ne bi mogli s polnilnikov komunicirati prek Wi-Fi, ožičene Ethernet, Bluetooth ali RS232 povezave. Sam sem se odločil, kar za slednjo, saj sem imel pri roku MCP2200, ki sem ga hkrati uporabil tudi kot most za programiranje ESP32. Tako lahko polnilnik v celoti upravljam preko USB priključka osebnega računalnika in dodatna mikrostikala niso potrebna. Dovolj so že obstoječe LEDice za indikacijo polnjenja. Vse ostale funkcionalnosti je mogoče upravljati le iz osebnega računalnika, ki podrobno analizira stanje posamezne akumulatorske baterija in pripravi parametre za njeno polnjenje, ki ga nato izvaja ESP32. Če se zadovoljimo s standardnimi parametri za posamezen tip baterij, lahko ESP32 tudi samostojno izvaja polnjenje, takoj ko vstavimo prazno baterijo. Vsekakor je zanimiva tudi možnost spremljanja polnjenja prek Wi-Fi, vendar pa zaradi varnosti prek Wi-Fija ni mogoče spreminjati parametrov polnjenja. Prednost stalne USB-RS232 povezave z osebnim računalnikov je tudi v (po)nastavitvi ure realnega časa v ESP32, ki jo izvedemo, vsakič, ko se PC poveže z ESP32. V praksi se sicer izkaže, da ESP32 s pomočjo vgrajenega kristalnega oscilatorja kar dobro meri realni čas. Zato ponastavljanje vrednosti ure skoraj ni potrebo, razen po prekinitvi napajanja in še to le, če želimo videti dejanske čase napolnitve posameznih baterij.
PIC18 kot USB-RS232 komunikacijski most
Nikoli si ne bi mislil, da se bom od ESP8266 in ESP32 ponovno vrnil k programiranju PIC18, ki sem ga pred leti podrobno opisoval v seriji člankov o njegovem programiranju, a možnost izdelave lastne vgrajene programske opreme, ki omogoča zanesljiv prenos podatkov med USB in RS232 in s tem tudi programiranje ESP modulov obenem zagotavlja dodatne digitalne priključke, ki jih ESP modul lahko med normalnim delovanjem upravlja preko RS232 povezave, me je vsekakor premamila. PIC18F14K50 ponuja v ohišju z dvajset priključki poleg signalov TX, RX, RTS in CTS še 8 splošno-namenskih priključkov, ki jih lahko uporabimo za digitalno krmiljenje ESP modula, nekaj pa tudi kot dodatne analogne ali digitalne vhode in izhode, ki jih ESP modul med normalnim delovanje upravlja preko RS232 povezave. Pri programiranju ESP modula poteka prenos podatkov izključno preko USB CDC vmesnika, preko USB HID vmesnika pa lahko splošno-namenske priključke upravlja zgolj osebni računalnik.
Bistvo implementacije programske nove vgrajene kode PIC18F14K50 je v sorazmerno enostavni namenski programski kodi s čim manj zapletenimi programskimi strukturami (npr. gonilniki, hierarhično povezanimi programskimi knjižnicami ipd.), ki deluje hitro in brezhibno, v nasprotnem prenos podatkov pri nazivnih hitrostih 74.880 Baudov ali 115.200 Baudov, ki jih zahtevajo ESP moduli, ni mogoč. Z dovolj kratkimi žičnimi povezavami (okoli 2 cm) lahko podatke prenašamo tudi s hitrostmi vse do 921.600 Baudov, kar je enaka zmogljivost, kot jo ponudi MCP2200, ki ni nič drugega kot v tovarni sprogramiran PIC18F14K50. Vendar zaradi strojne zaščite vanj vgrajene programske kode ne moremo prekopirati, lahko pa jo nadomestimo z lastno. Programsko opremo za komunikacijski most USB-RS232 je mogoče prilagoditi tudi za ostale PIC18 mikrokontrolerje, s čemer se lahko pri domačih projektih elegantno izognemo zamudnemu in napornemu spajkanju MCP2200, ki je na voljo le v SMD ohišju z 20 priključki.
V primerjavi z originalno vgrajeno programsko kodo v MCP2200, mu nova programska koda omogoča več namenskost, saj dodaja funkcionalnosti, ki jih pri večini implementaciji razvojnih plošč z moduli ESP, z vgrajenim mostom USB-RS232, pogrešamo.
Kako programiramo prispajkani PIC18F14K50?
Ko sem pred nekaj leti uspel z lastnim programatorjem zamenjati vgrajeno programsko kodo v MCP2200, ki je zaradi zaščite sicer ni mogoče prebrati, z lastno, čipa nisem vgradil v električno vezje in je neslavno »obvisel na žicah«. Bil je kot ponesrečen poskus, ki zaradi spremenjene vgrajene programske opreme morda nikoli ne bi več razvil polnega potenciala. A z ESP32 in ESP8266, od katerih slednjemu pri zahtevnejših projektih kar hitro zmanjka priključkov, je spet postal zanimiv, saj lahko deluje v dvojni vlogi.
Če ga želimo programirati še tudi po tem, ko ga prispajkamo na tiskano vezje, to lahko storimo preko priključkov +D in –D, ki sta sicer uporabljena za komunikacijo prek USB in priključka RST, ki obenem služi tudi kot PGM. Sicer pa to ni nič posebnega, če si natančneje ogledamo specifikacijo PIC18F14K50 in navodila za njegovo programiranje. Vendar se moramo pri programiranju držati zahteve, da napetost na +D in –D ne preseže 3,3 V, vsaj ne, če PIC18F14K50 (oz. MCP2200) napajamo s 3,3 V. Toda, kako enkrat povezati čip z USB vtičnico, iz katere vezje tudi napaja, drugič pa s programatorjem. Čip brez vezja bi bilo sicer mogoče napajati tudi iz programatorja, vendar pa so poleg še druge komponente, zato je bolje, da napajanje zagotovimo iz drugega USB priključka, medtem, ko ima programator lastno napajanje. Zato sem izdelal trivrstični konektor s po štirimi priključki v eni vrstici. To omogoča souporabo doma narejenega USB kabla (iz žice za Ethernet, uporabil sem samo 1 parico, ostale žice so za napajanje) in posebnega kabla za povezavo s PICkit 3, s katerim čip programiramo. Pri normalnem delovanju kabel za programiranje odstranimo in prestavimo USB kabel na drug priključek, tako da prevaja tudi signala +D in –D. Tako v konfiguraciji za programiranje uporabljamo kabel s povezanima priključkoma masa in Vusb, v kombinaciji za normalno delovanja pa so povezani vsi štirje priključki.
Še nasvet, če se boste izdelave USB kabla lotili doma: rajši žrtvujte nov USB kabel, saj se Ethernet kabel zaradi togosti rad utrga in celo polomi kontakte USB konektorja, na katere prispajkamo USB kabel. Lahko pa se namesto tega odločite za močnejše industrijske USB konektorje, pri katerih je manj verjetno, da bomo polomili notranje kontakte.
Sestavljene USB naprave
Res da v spletu najdemo izvorno kodo za PIC18F14K50, s katero ga spremenimo v komunikacijski most, a ta podpira samo komunikacijo preko CDC vmesnika, a za podobno funkcionalnost kot jo ima MCP2200 potrebujemo še HID vmesnik. Žal ni izvorne kode za sestavljeno napravo, ki bi hkrati podpirala HID in CDC vmesnik. Priprava izvorna kode za tako napravo še daleč ni enostavna iz dveh razlogov. Prvi je ta, da moramo natančno opredeliti USB opisnik, v katerem moramo pravilno opisati sestavo logičnih USB modulov (sestavljena naprava, vhodna naprava, HID vmesnik, CDC vmesnik), nakar se lahko lotimo izdelave programske kode, ki pa še zdaleč ni enostavna, saj ima PIC18F14K50 zelo malo USB RAMa, katerega večino potrebujemo za CDC vmesnik. HID vmesnik moramo tako ustrezno prilagoditi majhnemu pomnilniku in maksimalno omejiti dolžino zaporedja podatkovnih bajtov pri enem USB podatkovnem prenosu. Če namesto PIC18F14K50 uporabimo PIC18F26J50 ali zmogljivejše mikrokontrolerje s 4 kB RAMa, si lahko privoščimo bistveno več, pri PIC18F14K50 pa smo omejeni z le 768 bajti RAMa. Kakorkoli, slednje ne pomeni, da ne bomo mogli implementirati vseh glavnih funkcionalnosti, le nekoliko racionalnejši moramo biti pri porabi pomnilnika. No, vsekakor moramo upoštevati tudi število končnih točk, ki jih imata CDC in HID vmesnik skupaj kar 5. CDC vmesnik je namreč znotraj razdeljen na upravljavski in podatkovni del, HID vmesnik pa ima le podatkovni del.
Je izvorna koda potrebna?
Razvoj nove izvorne kode in pripadajočih programskih knjižni komunikacijo PIC18F14K50 z osebnim računalnikom mi je vzelo kar nekaj časa, vendar pri Microchipu ne dovolijo razpečevanja izvorne kode, ki deluje na osnovi njihovih programskih knjižnic. Zato sem namesto tega pripravil že prevedeno vgrajeno programsko opremo, ki jo lahko namestite z uporabo programatorja v PIC18F14K50, ali MCP2200, na spletni strani [1] pa je tudi orodje za izvedbo nastavitve, ki je zamenjava PID in VID ter nastavitev začetnih vrednosti in načina delovanja splošno-namenskih priključkov. Še posebej zanimiva je možnost uporabe A/D pretvornika, ki omogoča 10-bitno A/D pretvorbo preklapljanje med do 11 vhodnimi kanali. Je pa res, da PIC18F14K50 nima toliko analognih vhodnih priključkov, saj lahko izbiramo le med nekaterimi priključki vrat A, B in C, oziroma le vrat C, če želimo ohraniti funkcionalnost CDC. PIC18F14K50 ima le 768 bajtov rama, od katerih lahko 256 uporablja modul USB, zato moramo biti pri pisanju lastne vgrajene programske opreme skrajno racionalni, sicer utegnemo imeti težave z nestabilnostjo programske kode.
Kaj pa PIC18F26J50? Z manjšimi modifikacijami vgrajene programske opreme je mogoče le to uporabiti tudi za ta mikrokontroler, katerega UART je enako zmogljiv, vsekakor pa sem se, razumljivo, najprej lotil razvoja kode za PIC18F14K50, saj nisem hotel odpreti preveč front hkrati. Po drugi strani, ima PIC18F26J50 bistveni prednosti: več EEPROM-a, več RAM-a (4096 bajtov, oz. 4 kB), in SDIP-28 ohišje, ki ga je enostavno prispajkati v katerokoli standardno prototipno vezje. Zato se pravkar lotevam tudi tega razvoja, vgrajeno programsko opremo pa boste lahko našli (HEX) na spletni strani [1].
Vrnimo se k začetnemu vprašanju, kaj je z izvorno kodo. Microchipova politika brez posebnega dogovora tretjim osebam prepoveduje redistribucijo programske kode programskih knjižnic, ki so del projekta. Zato je mogoče v celoti objaviti le programsko kodo, ki na osnovi zastonjskih javno dostopnih programski knjižnic.
Prihodnjič
Če se boste odločili realizirati katero od idej v tem članku, vse električne sheme in podrobna navodila najdete na spletni strani [1]. Prihodnjič bomo na osnovi ESP32 izdelali preprost osciloskop in se ukvarjali z merjenjem signalov. Videli bomo tudi, kako lahko izdelamo domačo modularno vremensko postajo.