SpaceX je med počitnicami s testiranjem prileganja še nedokončanih prototipov rakete SN20 in boosteja BN4 znova slikovito prikazal, kako pomembno vlogo pri razvoju nove strojne opreme ima hitro prototipiranje. Kako hitro in enostavno razvijati? Kako testirati in dopolnjevati ugnezdeno programsko opremo? Kaj narediti, da bo zanesljivo delovalo tudi, ko gre kaj narobe? Kdaj začeti vsakodnevno uporabljati?
Avtor: dr. Simon Vavpotič
https://sites.google.com/site/pcusbprojects
2021-299-33
V preteklem nadaljevanju smo najprej preverili možnost izdelave tipkovnice, ki jo z mikrokontrolerjem povežemo le preko enega analognega vhoda. Videli smo, kako enostavno je izdelati generator znakov za grafični prikazovalnik in kako odpraviti težave z zamaknjeno sliko, do katerih lahko pride pri uporabi programskih knjižnic ali vzorčnih programskih aplikacij, prirejenih za podobne zaslone. Nekateri grafični prikazovalniki omogočajo uporabo komunikacijskih protokolov I2C in SPI, zato smo si ogledali, katere spremembe moramo narediti v programski kodi, če želimo namesto I2C uporabiti hitrejši SPI. Pokazali smo tudi, kako zagotovimo stabilno komunikacijo med dvema Arduino napravama preko diagnostičnih RS-232 vmesnikov, pri čemer si moramo pomagati z ustreznim označevanjem blokov podatkov. Preverili smo tudi možnosti za programsko zamenjavo asinhronega komunikacijskega protokola RS-232 s hitrejšim sinhronim protokolom, SPI ali I2C. To je mogoče, ker je v sodobnih mikrokontrolerjih podpora za večino zaporednih komunikacijskih protokolov združena v enoti UART ali USART in ker je mogoče večini digitalnih priključkov mikrokontrolerja programsko spreminjati funkcionalnosti. Enoto UART ali USART lahko tako preprosto reprogramirano za delovanje z drugim komunikacijskim protokolom, ki ga nato uporabimo za prenos podatkov po istih komunikacijskih vodnikih. Le pri SPI moramo dodati še četrti vodnik za prenos urinega signala.
Ta vsebina je samo za naročnike
Tokrat bo ponovno veliko zanimivega, saj bomo odsluženi ESP8266-13 Wi-Fi modul zamenjali z novejšim in zmogljivejšim ESP32-WROOM, 5-voltni HC SR-04 modul za ultrazvočno merjenje razdalj bomo na različne načina povezali s 3,3-voltnim mikrokontrolerjem (npr. Raspberry Pi, ESP32, PIC32,..), ne da bi slednjega poškodovali….
Kako »scvreti« ESP8266-13?
Čeprav so miniaturne ESP razvojne ploščice še kar odporne na težave z napetostnimi nivoji pri komunikaciji z drugimi napravami, se kdaj pa kdaj vseeno zgodi nesreča. Meni je zaradi slabih kontaktov pri napajanju pregorel RS-232 vhod RxD0, ki ga je uničila negativa napetost. Zanimivo pa je ESP8266-13 še vedno deloval, čeprav se je pregreval tako, da bi lahko na njem pekel jajca in obenem kot za šalo praznil baterije.
Čeprav sem najprej pomislil, da bi lahko modul uporabil za kak drug projekt, pri katerem ne bi potreboval priključka RxD0, reprogramiranje modula prek RS-232 ni mogoče. Bi pa lahko ESP8266 modul še vedno uporabil, če bi njegov mikrokontroler zagnal iz zunanjega pomnilnika in ne iz notranjega EEPROMa, kot je to običajno, no ampak tako eksperimentiranje raje pustimo za kdaj drugič, saj tak način delovanja in zaenkrat dobro dokumentiran.
Kako ESP8266 zamenjati z ESP32?
Zamenjava se zdi sorazmerno enostavna, saj Arduino razvojno okolje večinoma odlično zakrije razlike med mikrokontrolerji v različnih Arduino modulih. ESP8266 in ESP32 moduli imajo zaradi zmogljivejše strojne zasnove kar nekaj posebnosti, ki odstopajo od klasične Arduino funkcionalnosti. Vendar so se tvorci Arduino programske podpore za ESP8266 nekoliko bolj potrudili in implementirali več standardnih Arduino funkcij, medtem ko so pri ESP32 marsikaj izpustili. Denimo, če potrebujemo PWM modulacijo, razočarani ugotovimo, da funkcija analogWrite pri ESP32 ne deluje.
Tako moramo prej preprosto programsko kodo za upravljanje krtačnih elektromotorjev precej prilagoditi za uporabo ESP32 PWM funkcij. Če želimo strojno podpro PWM funkcionalnosti, lahko podoben nabor funkcij uporabimo tudi pri ESP8266, ki ima 4 PWM kanale, vendar so fiksno povezani z izhodi GPIO12 (PWM kanal 0), GPIO15 (PWM kanal 1), GPIO14 (PWM kanal 2 ) in GPIO4 (PWM kanal 3). Pred njihovo uporabo moramo v program vključiti programsko knjižnico pwm.h. Nabor funkcij je: pwm_init, pwm_set_duty, pwm_set_period, pwm_get_duty, pwm_get_period, pwm_start in get_pwm_version. Funkcije izvajamo nad PWM kanali.
ESP32 ima strojno podporo za generiranje do 8 signalov PWM. Generatorje PWM prav tako imenujemo kanali, vendar moramo slednje programsko povezati z izhodnimi priključki. Funkcije za upravljanje PWM kanalov so nekoliko bolj optimizirane kot pri ESP8266. Vsakemu kanalu moramo ob inicializaciji določiti osnovno frekvenco (PWMfreq) in ločljivost (PWMres) ter širino impulza: ledcSetup(n, PWMfreq, PWMres). Ločljivost določamo v bitih in pomeni, kako natančno lahko nastavljamo širino impulza, vsekakor pa moramo pri tem upoštevati tudi nastavitev osnovne frekvence za PWM. Če je ta nižja, je glede na procesorski takt, s katerim merimo trajanje dolžne impulza, mogoče doseči večjo ločljivost, če pa je osnovna frekvenca zelo visoka (npr. 200 kHz), je ločljivost pogojena tudi s hitrostjo procesorske ure. Npr., če je ta 200 MHz, osnovna frekvenca PWM pa je 200 kHz, bomo v času do naslednjega PWM impulza lahko namerili največ 1000 časovnih enot; torej ločljivost ne bo mogla biti več kot nekaj manj kot 10 bitov.
Naslednji korak je povezovanje kanalov in izhodnih priključkov, ki ga izvedemo z ukazom ledcAttachPin(n_pin, PWMch). Parametra sta dva, številka priključka modula (n_pin) in številka kanala (PWMch), s katerim ga povežemo. Zadnji ukaz, ledcWrite(PWMch,val), sproži generiranje PWM moduliranega signala širine val na kanalu PWMch, ki smo ga seveda prej povezali z enim od izhodnih priključkov mikrokontrolerja. Kot vodimo, pri ESP32 trije ukazi nadomeščajo en sam ukaz pri ESP8266, vendar dajejo tudi več možnosti nastavitev PWM modulacije. Hkrati je mogoče isti PWM kanal uporabiti za krmiljenje več naprav, tako da kanal preklapljamo med izhodnimi priključki mikrokontrolerja. Kakorkoli pa je lahko naenkrat aktivnih 8 PWM kanalov. Lahko pa dodatne signale PWM ustvarimo tudi programsko s pomočjo sistemskega časovnika.
Kako nadomestiti funkcijo analogWrite?
Čeprav se zdijo zgoraj navedene funkcije še kar enostavne, je uporaba funkcije analogWrite veliko večja potuha za programerja, kot bi si prva mislili, saj funkcija digitalWrite, ki sledi analogWrite nad istim izhodnim priključkom, izključi PWM modulacijo in nato pravilno nastavi vrednost tega priključka na 0 ali 1. Pri uporabi zgoraj navedenih ukazov, moramo paziti, da pred uporabo digitalWrite(n_pin, val) pokličemo funkcijo ledcDetachPin(n_pin). V nasprotnem bo priključek še naprej generiral PWM modulacijo, kot da se ni nič zgodilo. Delo z izhodnimi priključki ESP32 si lahko poenostavimo z nekoliko izpopolnjeno funkcijo eXdigitalWrite(n_pin, val) – extended digitalWrite -, ki najprej preveri, ali je izbrani priključen povezan s PWM kanalom. Če je, kanal samodejno odklopi z ukazom ledcDetachPin(n_pin), nakar v vsakem primeru sledi klic običajne funkcije digitalWrite(n_pin, val). Poglejmo še programsko kodo:
void eXdigitalWrite(uint8_t n_pin, bool val){ if(getPWMchannel(n_pin)!=255){ ledcDetachPin(n_pin); } digitalWrite(n_pin, val); }
Kot vidimo, funkcija eXdigitalWrite pridobi podatek o tem, ali je izbrani priključek povezan s PWM kanalom s posebno funkcijo, ki pozna preslikavo priključkov na PWM kanale. Ob tem omenimo še to, da klic funkcije ledcDetachPin nad priključkom, ki ni povezan s PWM kanalom nima učinka. Zato ni bojazni, da funkcije eXdigitalWrite ne bi mogli uporabiti kadarkoli, oziroma da bi morala funkcija prej preveriti, ali je izbrani priključek povezan s PWM kanalom.
Kot zanimivosti povejmo še, da lahko različne ekvivalente funkcije analogWrite za ESP32 najdemo tudi v dodatnih programskih knjižnicah, ki jih lahko v svoje Arduino razvojno okolje prenesemo s spleta. Sam sem se odločil za lastno implementacijo zato, ker sem vnaprej vedel, katere priključke želim uporabljati za PWM modulacijo. Vseeno pa nisem želel povezav med priključki in kanali fiksno programirati v vsej programski kodi, saj bi jo bilo težko vzdrževati, če bi se v prihodnosti karkoli spremenilo. Zato sem dodal funkcijo getPWMchannel, ki za izbrani priključek na ohišju ESP32 modula vrne preslikavo na PWM kanal, ali pa vrne napako v kolikor taka preslikava ni vnaprej definirana:
uint8_t getPWMchannel(uint8_t n_pin){ uint8_t PWMch; switch(n_pin){ case _roboFW_PWMch=PWM_ch_FW;break; case _roboBW_PWMch=PWM_ch_BW;break; case _roboL_PWMch=PWM_ch_LEFT;break; case _roboR_PWMch=PWM_ch_RIGHT;break; case _roboUP_PWMch=PWM_ch_UP;break; case _roboDOWN_PWMch=PWM_ch_DOWN;break; default_PWMch=255; // error } return PWMch; }
Če ste spremljali pretekla nadaljevanja, zdaj vidite da izhodne kanale uporabljam za krmiljenje robota. Je pa res, da se mi pri pisanju programske kode ni bilo potrebno kdove kako truditi, saj za krmiljenje treh krtačnih elektromotorjev v obe smeri praviloma zadoščajo že trije PWM kanali, od katerih vsakega preklapljamo med dvema priključkoma, s čemer določimo tudi smer vrtenja motorja. No, sam sem namesto tega uporabil 6 kanalov, s čemer odpade potreba po njihovem preklapljanju med priključki, še vedno pa je potrebno kanal prej odklopiti, če želimo na izbrani priključek zapisati fiksno vrednost 0 ali 1. Slednje uporabljam pri zaustavitvi motorjev.
Popolno posnemanje analogWrite funkcije
Ni težko, kljub temu pa za to potrebujemo nekoliko več programske podpore. Najprej se moramo odločiti, ali bomo za generiranje impulzov uporabili samo strojne PWM kanale, ali bomo tem dodali še programsko implementacijo PWM kanalov. Za začetek se lotimo pisanja programske kode zgolj za 8 strojno podprtih PWM kanalov. Več kot očitno je, da lahko v tem primeru hkrati generiramo PWM le na osmih priključkih ESP32 modula. Zato potrebujemo funkcijo za dodeljevanje prostih PWM kanalov izhodnim priključkom, ki deluje s pomočjo ukazov ledcAttachPin in ledcDetachPin ter dinamične preslikovalne tabele, ki hrani seznam trenutnih povezav med PWM kanali in priključki. Pri tem klic funkcije eXdigitalWrite nad izbranim priključkom samodejno odklopi morebitno priklopljen PWM kanal in odstrani morebitno povezavo v preslikovalni tabeli. Preslikovalna tabela ima sicer 8 mest, po eno za vsak kanal. Preslikovanje deluje tako, da se najprej zapolni prvo prosto mesto itn. Torej moramo v vgrajenem programu zamenjati funkcijo digitalWrite s funkcijo eXdigitalWrite.
Naslednje vprašanje je, kaj storiti, ko je hkrati 8 PWM kanalov povezanih z 8 izhodnimi priključki. Takrat moramo dodatno uporabiti programsko podporo za generiranje PWM signalov. Vendar je vgradnja tovrstne podpore v funkcijo analogWrite lahko vprašljiva z vidika enakovrednosti programsko in strojno podprtih kanalov. Programska podpora za ustvarjanje PWM je manj učinkovita pri visokih osnovnih frekvencah PWM, hkrati pa zahteva veliko procesorskega časa. Pri nižjih osnovnih frekvencah (do 10 kHz) še nekako gre, zelo visoke pa zahtevajo preveč procesorskega časa, ne toliko zaradi merjenja časa trajanja, pri katerem si pomagamo s 64-bitni sistemskim časovnikom, temveč zaradi potrebne pogostnosti primerjanja njegove vrednost s shranjeno vrednostjo. Če uporabljamo prekinitve, je treba upoštevati, da že samo proženje prekinitvenega programa vzame ogromno procesorskega časa in zato ne more biti prav pogosto, saj se sicer ne more pravilno izvajati glavna programska zanka. Karkoli, natančno lahko nastavljamo trajanje impulza PWM modulacije le pri dovolj nizkih frekvencah.
Zamenjava Wi-Fi programskih knjižnic
Za predelavo Arduino programske kode za ESP8266 v tisto za ESP32 moramo narediti še nekaj zamenjav programskih knjižnic, med drugim tudi tistih za Wi-Fi podporo. Pri ESP8266 na primer za telnet in http strežniško funkcionalnost uporabljamo ESP8266WiFi.h, WiFiClient.h in ESP8266WebServer.h. Namesto slednjih lahko pri ESP32 uporabimo: WiFi.h, WiFiServer.h, WiFiClient.h. Razlika med ESP8266 in ESP32 je tudi pri definiciji in aktivaciji dogodkovnih filtrov. ESP8266 uporablja programsko strukturo WiFiEventHandler, ki podpira štiri vrste dogodkov, med katerimi so prijava klienta, odjava klienta in zahteva za posredovanje osnovnih podatkov dostopne točke.
Tu se programska podpora za ESP32 precej razlikuje od podpore za ESP8266, saj pri ESP32 uporabljamo povratno klicane procedure, ki jih s funkcijo WiFi.onEvent pripnemo na objekt WiFi, zadolžen za upravljanje Wi-Fi komunikacije. Podrobnosti si oglejte Arduino ESP32 primeru: File à Examples à Examples for ESP32 Dev Module: Wifi à WiFiClientEvents.
Podobne zamenjava programskih knjižnic so potrebne tudi za uporabo drugih funkcionalnosti. Še najenostavneje je, če si za vsako kompleksno funkcionalnost ogledamo primer uporabe in nato potreben del programske kode iz njega vgradimo v svoj program.
Kljub opisanim spremembam pa lahko ostane glavni del programa – procesna logika s kontrolnimi izpisi itn. – skoraj enak. Moram priznati, da sem bil tudi sam presenečen nad sorazmerno malo potrebnimi spremembami, ki omogočajo, da programsko kode ESP8266 priredimo za ESP32.
Zamenjava ESP čipa
Razporeditev priključkov na ESP8266-13 modulu se močno razlikuje od razporeditvena ESP32-WROOM modul. Sam s tem nisem imel težav, ker sem ESP8266 modul namesti »v zraku« oziroma ga pritrdil s povezovalnimi kabli, v novejših vezjih pa sem uporabil tudi kos debele bakrene žice, ki sem ga pritrdil na spodnji ozemljitveni (GND) priključek ESP8266 ali ESP32-WROOM modula. Kateri ESP32 modul izberemo namesto ESP8266, je skoraj vseeno, saj bomo v izobilju GPIO priključkov ESP32 modula (še posebej ESP32-WROVER-I) našli več kod dovolj zamenjav za priključke ESP8266. Vsekakor pa pri spajkanju ESP32 modula na tiskano vezje, prirejeno za ESP8266 module, potrebujemo adapter oziroma vmesno ploščico tiskanega vezja.
Kako se zamenjava obnese v praksi?
ESP32 se namesto ESP8266 odlično obnese. Več GPIO priključkov mu hkrati omogoča krmiljenje dodatnih naprav in enostavnejše zajemanje podatkov s senzorjev pa tudi priklop novih senzorjev. Prav zaradi slednjega sem v vsakem primeru nameraval zamenjati ESP8266 v robotskem modelu traktorja, ki ga uporabljamo za testiranje ESP modulov, a na koncu so slabi kontakti pri napajanju naredili svoje. Tako model zdaj krmilita dva ESP32 modula, ki medsebojno komunicirata prek RS-232 povezave. Več GPIO priključkov omogoča tudi priklop dodatnih senzorjev, kot so ultrazvočni merilnik razdalje. Hkrati to ne vpliva na delovanje ESP32-CAM modula, ki nima prostih priključkov, če želimo v njem uporabljati tudi SD kartico za shranjevanje podatkov. Prav slednje je zelo zanimiva možnost, ne toliko zaradi možnosti snemanja videa, temveč zaradi možnosti enostavnejše obdelav podatkov iz vseh senzorjev – tako kamere kot ultrazvočnih daljinski tipal – in možnosti sprotne izdelave zemljevida prostora, podobno kot pri robotskih sesalnikih. Slednji omogoča avtonomno delovanje robota.
Prilagajanje napetostnih nivojev in merjenje razdalj z ultrazvokom
Ceneni HC SR-04 ultrazvočni merilnik razdalje srečamo pri množici različnih projektov. Nekateri ga vgrajujejo celo v drone, da njim merijo višino do tal pri pristajanju. Vendar njegova uporaba s 3,3 V mikrokontrolerjem ni vedno samoumevna. Čeprav njegov EM78P153S mikrokontroler deluje tudi pri napetosti 3,3 V, je ostala logika na miniaturnem tiskanem vezju HC SR-04 prirejena za delovanje pri napetosti 5 V, zato so meritve slabe. Kot bomo videli v nadaljevanju, ultrazvočni senzor pravilno deluje le, ko ga napajamo s 5 V napetosti. Kljub temu ga sorazmerno enostavno uporabimo tudi z nekaterimi 3,3-voltnimi mikrokontrolerji. Na primer, s PIC32 ima precej 5,5 V tolerantnih priključkov, zato z vhodnimi signali ne bomo imeli težav. Po drugi strani, na 5 V tolerantnih priključkih doseženo 5-voltne izhodne nivoje, če jih programiramo kot izhode z odprtim kolektorjem in nanje vežemo ustrezen upor za vleko navzgor (angl. pull-up) na 5-voltni vir.
ESP32 po zagotovilih proizvajalca Espressive Systems 5 V tolerantnih priključkov nima, zato moramo sami poskrbeti za ustrezen vmesnik. Podroben pregled načrta ene od izvedb HC SR-04 senzorja in tudi pregled dveh tiskanih vezij, brez kristalnega oscilatorja in s kristalnim oscilatorjem, ki ju imam sam, razkrijeta da sta na ploščico na signalni vhod trigger in signalni izhod echo (gledano s strani HC SR-04) vezana dva 10 k ohmska upora proti napajanju (angl. pull-up). Če dobi HC SR-04 5-voltno napajanje samostojno, to gotovo ni dobro za povezani priključek ESP32, saj napetost na njem zraste prek 3,6 V, kar je najvišja dovoljena napetost na GPIO, če deluje kot vhodni priključek. No, če napajanje HC SR-04 vključimo programsko šele potem, ko se ESP32 zažene, lahko na priključku ESP32 pred priklopom napajanja nastavimo izhodni režim delovanja, kar prepreči previsoko napetost tako v stanju logične 0 kot v stanju logične 1. Vendar moramo paziti, da na priključku mikrokontrolerja za trigger signal nastavimo nizek logični nivo, ki mora biti aktiven dokler HC SR-04 ne vklopimo napajanja.
HC SR-04 ima za podporo lastnemu delovanju vgrajen 8-bitni mikrokontroler EM78P153S, ki ob 5-voltnem napajanju sprejme logično 1 pri signalih od 2 V naprej in logično 0 pri signalih, manjših od 0,8 V. To pomeni, da lahko za trigger načeloma uporabimo tudi signal iz 3,3-voltnega mikrokontrolerja, kar lahko vidimo tudi v številnih načrtih. Vendar le, če je lahko dovolj hitro »pogoltne« tok iz 5 V napajanja preko 10 k ohmskega upora v HC SR-04 vezju. Če ne, moramo upor odspajkati, ali pa dodati tranzistor, s katerim krmilimo trigger signal. V tem pogledu je pomenljivo to, da so v nekaterih referenčnih načrtih HC SR-04 vezji različnih proizvajalcev prisotni 10 k ohmski upori za vleko signalov trigger in echo navzgor (proti 5 V), v drugih pa ne.
Kaj pa izhodni echo signal? No, tudi pri tem smo v zadregi prav zaradi upora za vleko navzgor. Če na izhod echo dodamo uporovni delilnik z 1,2 k ohma in 2,2 k ohma, dobimo v nedejavnem stanju EM78P153S na njem napetost 0,16 V. Če bi v primeru, da bi izhod EM78153S deloval po principu odprtega kolektorja, bi tako na vhodu 3,3-voltnega mikrokontrolerja vselej dobili 0. K sreči se izkaže, da EM78P153S aktivno krmili izhod echo, zato je napetost okoli 4 V, na 2,2 k ohmskem uporu napetostnega delilnika pa dobimo 2,59 V, kar je pri večini 3,3 V mikrokontrolerjev zadosti pogoju, da mora biti najmanjši signal logične enice 80% od 3,3 V, kar je 2,64 V. Je pa res, da je to zelo blizu pragovne napetosti.
Druga rešitev je uporaba nekoliko zmogljivejšega pretvornika napetostnih nivojev, ki ga lahko nabavimo v čip izvedbah, ali pa ga izdelamo sami iz uporov, tranzistorjev in diod. Za prilagoditev napetosti echo signala lahko poleg omenjenega uporovnega delilnika uporabimo tudi zaporedno vezavo 1 k ohmskega upora in 3,3-voltne Zener diode. Tako napetost na vhodnem priključku mikrokontrolerja nikoli ni višja od 3,3 V. Nekoliko težje pa je izdelati izhodno prilagoditev za katero lahko uporabimo ULN2803 čip, ki je primeren tudi za krmiljenje relejev s krmilno napetostjo do 50 V, ali pa samo sestavimo par NPN tranzistorjev v Dalington vezavi, pri tem se lahko zgledujemo po načrtu notranje zgradbe ULN2803 čipa. Če pa za prilagoditev izhodnega trigger signala uporabimo pa en sam NPN tranzistor z 10 k ohmskim uporom na bazi, izhodna napetost ne bo 5 V, ampak okoli 3,3 V, saj bazo tranzistorja napajamo s to napetostjo. Kljub temu, je to dovolj za krmiljenje HC SR-04, ni pa dovolj za katerokoli 5-voltno integrirano vezje. Upoštevati moramo še, da je pri tej izvedbi izhodne prilagoditve logični nivo proženja HC SR-04 v programu ESP32 nič, stanje mirovanja pa logična 1, saj NPN tranzistor z odprtim kolektorjem hkrati deluje kot negator. Opozorimo še, da ta poenostavljena različica deluje le pri tistih HC SR-04 vezjih, ki imajo na trigger vhodu 10 k ohmski upor za vleko navzgor povezan na 5-voltno napajanje.
Arduino program za ultrazvočno merjenje razdalj
Za merjenje razdalj z ultrazvokom potrebujemo samo še program. Ta je relativno enostaven, saj začetek meritve pri HC SR-04 senzorju sprožimo z vsaj 10 mikrosekund dolgim pozitivnim impulzom na trigger priključku, ki ga lahko ustvarimo kar s pomočjo ustrezne programske zakasnitve. Nato izmerimo še čas trajanja pozitivnega signala na echo priključku, ki ni daljši od 38 milisekund, oziroma 25 milisekund, če je razdalja izmerjena. Čas trajanja pretvorimo v razdaljo do ovire z upoštevanjem hitrosti potovanja zvoka, ki je okoli 340 m/s in upoštevanjem dejstva, da mora zvok dvakrat preiti merjeno razdaljo; najprej do ovire in nato nazaj do senzorja. Večina Arduino implementacij meritve razdalj meritev izvede v enem koraku, brez uporabe prekinitev, saj je tako natančnejša, hkrati pa je mikrokontroler z njo zaposlen največ 38 milisekund (nekatere izvedba senzorjev imajo čas tudi 60 milisekund). Poglejmo še primer programske kode za izvajanje meritev:
digitalWrite(trig, LOW);delayMicroseconds(2); // start delay digitalWrite(trig, HIGH);delayMicroseconds(10); // trigger duration digitalWrite(trig, LOW); // start measurement previousMicros = micros(); while(!digitalRead(echo) && (micros() - previousMicros) <= timeout); // echo start previousMicros = micros(); while(digitalRead(echo) && (micros() - previousMicros) <= timeout); // echo end
HC SR-04 lahko povežemo tudi preko enega podatkovnega priključka. V tem primeru združimo signala trigger in echo in ju povežemo z enim samim priključkom mikrokontrolerja. Uporaba tega načina je primernejša za 5-voltne mikrokontrolerje. Poglejmo, kako moramo dopolniti programsko kodo:
pinMode(trig, OUTPUT); digitalWrite(trig, LOW);delayMicroseconds(2); // start delay digitalWrite(trig, HIGH);delayMicroseconds(10); // trigger duration digitalWrite(trig, LOW); // start measurement pinMode(trig, INPUT); previousMicros = micros(); while(!digitalRead(echo) && (micros() - previousMicros) <= timeout); // echo start previousMicros = micros(); while(digitalRead(echo) && (micros() - previousMicros) <= timeout); // echo end
Kot vidimo, je potrebno po proženju meritve način delovanja priključka iz vhodnega hitro spremeniti v vhodnega, saj lahko mikrokontroler potem iz njega prebere razdaljo do ovire.
Hekanje HC SR-04
Zakaj ne bi EM78P153S mikrokontroler HC SR-04 zamenjali s čem zmogljivejšim, recimo PIC32, ki bi obenem deloval tudi kot most med 3,3-voltno elektroniko in 5-voltno elektroniko?
Če bi povečali napajalno napetost analogne elektronike HC SR-04 senzorja ali natančneje merili odmev, bi nemara lahko razširili doseg senzorja preko 4 metre in hkrati poleg oddaljenosti izmerili še kaj. Nenazadnje, bi lahko napravo uporabili tudi za odganjanje živalskih vsiljivcev. Poglejmo!
EM78P153S mikrokontroler je odveč, zato ga odspajkamo njegove priključke povežemo z na 5 V odpornimi priključki PIC32, tako da slednji neposredno komunicira s čipi LM324 in MAX232A. LM324 ima štiri operacijske ojačevalnike, ki skupaj z še nekaj upori, kondenzatorji in izhodnim tranzistorjem tvorijo ultrazvočni detektor z 18 kHz pasovnim filtrom in nastavljivim pragom zajem signala (angl. treshold).
Sprejemnik na osnovi LM324 čipa s štirimi operacijskim ojačevalniki omogočimo prek vhoda za nastavljanje praga (angl. treshold), medtem ko signal dobimo iz izhoda operacijskega ojačevalnika, ki deluje kot napetostni primerjalnik. Ni odveč, če nekoliko podrobneje pogledamo delovanje operacijskih ojačevalnikov v LM324: Prvi operacijski ojačevalnik zvok ojači, drugi pa ga filtrira, pri čemer ima filter najvišjo propustnost pri okoli 18 kHz. Nekateri avtorji projektov na spletu trdijo, da lahko dobimo boljše rezultate, če vrednosti uporov R11 in R13 zamenjamo z 18 k ohmi in 2,2 k ohma, s čemer se največja prepustnost pasovnega filtra premakne 40 kHz. Vendar, pozor! To velja za HC SR-04 senzor, katerega zgradbo najdete na spletni strani: https://uglyduck.vajn.icu/HC-SR04E, zgradbo ostalih različic morate natančno preveriti, preden karkoli spreminjate.
Generator ultrazvoka uporablja čipa MAX232A kot ojačevalnik, ki iz signalov T1IN in T2IN z napetostnimi nivoji med 0 V (logična 0) in 5 V (logična 1) med priključki T1OUT in T2OUT ustvari izmenični sinusni signal z amplitudo +/- 24 V, s katerim krmili ultrazvočni oddajnik. Za generiranje zvoka moramo najprej vklopiti MAX232A, tako da postavimo HVoff na logično vrednost 0, nato pa ga prek priključkov T1IN, T2IN krmiliti tako, da ustvari ultrazvočni signal z želeno frekvenco in amplitudo za ultrazvočni zvočnik/mikrofon (angl. transducer). Prav ste prebrali! HC SR-04 ima vgrajena 2 ultrazvočna zvočnika/mikrofona, enega uporablja kot zvočnik, drugega pa kot mikrofon. EM78P153S ob vsakem proženju ustvari vlak osmih piskov.
Lasten algoritem za merjenje razdalje
Zdaj, ko imamo lasten mikrokontroler za merjenje razdalj z ultrazvokom, moramo uganiti še algoritem. V veliko pomoč je opis zgradbe EM78P153S, v katerem so podane osnovne karakteristike tega sorazmerno enostavnega 8-bitnega mikrokontrolerja, ki ne premore niti A/D pretvornika.
Vlak ultrazvočnih impulzov ustvarimo z nasprotnim krmiljenjem izhodov T1IN in T2IN. Dokler imata oba vhoda enako logično vrednost, razlika napetosti med T1OUT in T2OUT 0 V. Ko pa nastavimo T1IN na logično 1, T2IN pa na logično 0, je napetost med T1OUT in T2OUT +24 V. Zapleteno? MAX232A pretvori napetosti 0 in 5 V v -12 V in +12 V, kar ustreza polni implementacij standarda RS-232. Pri tem napetosti +/- 12 V ustvari kar iz napajalne napetosti 5 V. Če imamo dva izhoda za pretvorjene napetosti, T1OUT in T2OUT, lahko uporabimo tudi razliko njunih napetosti. Torej +12 – (-12 V) = + 24 V. Če logični vrednosti na priključkih T1IN in T2IN obrnemo, tako da je T1IN = 0 in T2IN = 1, dobimo – 24 V. S programom moramo torej ustvariti vlak dvobitnih podatkov za krmiljenje T1IN inT2IN, na primer: [0,0], [0,1],[1,1],[1,0], …. Tako dobimo zaporedje napetosti 0 V, – 24 V, 0 V, +24 V, …. S tem opredelimo 4 točke sinusnega signala, ki jih moramo oddati pri osnovni frekvenci 160 kHz (oz. 4x 40 kHz), vmesne pa nastanejo v MAX232A glede na izbrane vrednosti kondenzatorjev na njegovih vhodih C1-, C1+, C2-, C2+, V- in V+. Slednje sicer precej odstopajo od vrednosti, ki jih uporabljamo za implementacijo RS-232 protokola, vendar je to razumljivo, saj želimo pri prenosu podatkov hitre preklope, pri generiranju ultrazvoka pa lepe sinusne prehode.
Zdaj moramo le še poslušati odziv ultrazvočnega mikrofona. Zato najprej odklopimo napajanje MAX232A, tako da postavimo HVoff na logično 1. Nato čakamo na vlak odbitih ultrazvočnih impulzov, ki jih dobimo na izhodu signal U2A operacijskega ojačevalnika v čipu LM324, ki deluje kot primerjalnik napetosti. S signalom treshold lahko močno dvignemo prag za primerjanje napetosti in s tem dejansko izključimo zaznavo (odbitih) ultrazvočnih impulzov med generiranjem vlaka ultrazvočnih impulzov. To je še posebej koristno, če vežemo linijo signal na prekinitveni vhod mikrokontrolerja, saj tako sprejemamo prekinitve samo v časovnem oknu, namenjenem z zaznavo odmevov….
No, kakorkoli, HC SR-04 bi lahko predelali tudi tako, da bi (ultra)zvok zajemali kar z zmogljivim A/D pretvornikom v PIC32, v katerega bi vgradili algoritem za Fourierovo transformacijo, s čemer bi odpadla potreba po uporabi analognega filtra v LM324. Zajeli bi ves zvok, ki ga zajame ultrazvočni zvočnik/mikrofon in ga programsko analizirali. Vsekakor pa pri tem ne smemo pozabiti na prilagoditev nivojev za A/D pretvornik PIC32, ki zmore izmeriti največ 3,3 V.
Prihodnjič
Kot vidimo, lahko s podrobno analizo vsakdanjih vezij, ki so uporabljena v številnih (hobi) projektih, pridemo do njihovih bistvenih izboljšav in veliko zmogljivejših rešitev. Vseeno moramo v dizajn dodobra preizkusiti, preden ga uporabimo praksi.
To hitro ugotovimo tudi, če preberemo komentarje, ki so jih napisali nadobudni elektroniki potem, ko so zamenjali R11 in R13 na HC SR-04, da bi izboljšali njegovo učinkovitost. Sprememba, ki se na začetku zdi odlična, je morda uporabna samo na omejeni množici problemov, medtem ko je za ostale primere boljša serijska rešitev proizvajalca.
Če hočemo zares narediti boljši izdelek, moramo povečati njegovo splošnost in prilagodljivost. Prav s tem in še vrsto drugimi problemi s področja uporabe in zanesljivosti strojnih rešitev, kot je natančno krmiljenje smernih krtačnih motorjev s PWM modulacijo, se bomo ukvarjali prihodnjič.