V preteklem nadaljevanju smo se lotili številnih težkih problemov in preučevali možnosti za izboljšanje zanesljivosti ljubiteljskih projektov na področju strojne opreme. Iskali smo tudi napake v Arduino programskih knjižnicah, še posebej tisto pri v ukazu za praznjenje izravnalnika za serijski prenos podatkov s telnet protokolom, in obenem našli ustrezne rešitve in obvode, s katerimi izboljšamo zanesljivost delovanja in se izognemo nenadnim odpovedim, pri katerih pomaga le reset mikrokontrolerja.
Avtor besedila in fotografij: dr. Simon Vavpotič
E-pošta: simon.vavpotic@gmail.com
2022-307-35
Tokrat se bomo končno lotili tehnik razvoja interaktivnih uporabniških vmesnikov, s katerimi bolje izkoristimo grafične barvne prikazovalnike. Namesto tipkovnice bomo z mikrokontrolerjem povezali preprosti enkoder, s katerim bomo vnašali številčne in črkovne znakovne nize.
Ta vsebina je samo za naročnike
Lotili se bomo tudi razvoja Arduino programske kode v okolju Arduino chipKIT, ki je prilagojeno za Microchipove mikrokontrolerje in obenem prilagodili Arduino chipKIT lastni razvojni plošči.
Enkoder s tipko namesto tipkovnice
Pri enostavnih aplikacijah, pri katerih nam ni potrebno vnašati velike količine podatkov, lahko tipkovnico in miško nadomesti enkoder s tipko, ki je tudi veliko cenejši in enostavnejši za vgradnjo v projekt razvoja strojne preme, saj ne potrebuje lastnega mikrokontrolerja.
Enkoder z mikrokontrolerjem povežemo prek treh signalnih vodnikov (SW, CLK, DTA) in mase (GND), za kar moramo rezervirati tri digitalne vhode. Čeprav se zdi preprosto, moramo zagotavljati tudi visoko odzivnost, ki jo lahko zagotovimo z uporabno prekinitev ali večnitnosti. Prekinitve lahko uporabimo, če ima mikrokontroler vgrajeno strojno logiko za njihovo proženje ob spremembi stanj izbranih vhodnih priključkov. Denimo, ESP32 take funkcionalnost za vhodne priključke GPIO34, GPIO36 in GPIO39 nima, vendar se lahko vseeno odločimo za njihovo uporabo, saj s tem prihranimo ostale GPIO priključke, ki jih lahko programiramo tudi kot digitalne izhode. Sicer pa za dvojedrni ESP32 ciklično programsko preverjanje stanja omenjenih priključkov ni problem, saj lahko ustrezno programsko nit poganjamo na drugem procesorskem jedru, medtem ko glavni program, ki teče na prvem procesorskem jedru, zgolj bere stanje enkoderja iz programskih spremenljivk, ki hranita število pritiskov na tipko in pozicijo vrtenja. Začetna pozicija enkoderja je seveda 0.
Poglejmo še, kako napišemo program za zaznavanje trenutne pozicije enkoderja ter šteje pritiskov na tipko , glej program 1.
program 1
void EncoderTask(void *parameter){
byte sw;byte cl;byte dt;byte sw_old=digitalRead(ENC_SW);
byte cl_old=digitalRead(ENC_CL);byte dt_old=digitalRead(ENC_DT);
uint32_t oldtime=0;bool sw_state;bool newstate;uint32_t newtime;
uint32_t old_state=1;int16_t locrotcount=0;
uint8_t act_state = 0;uint8_t inx;
const int8_t enc_states[]={0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
while(true){ // perpetual LOOP
sw=digitalRead(ENC_SW);cl=digitalRead(ENC_CL);dt=digitalRead(ENC_DT);
if((sw==sw_old)&&(dt==dt_old)&&(cl==cl_old)){vTaskDelay(1);}
else {
newstate=(sw==LOW);newtime=millis();
if(newtime==oldtime)return;
if(newstate!=sw_state){
sw_state=newstate;
if(!sw_state){
if((newtime-oldtime)>1000)enc_longclick=true;
else {enc_clickcount++;}
enc_inactivity=0;}}
oldtime=newtime;
act_state=(cl<<1)+dt;inx=(old_state<<2)+act_state;
locrotcount+=enc_states[inx];
if(locrotcount==4){enc_rotationcount++;locrotcount = 0;}
else if(locrotcount==-4){enc_rotationcount–;locrotcount = 0;}
old_state=act_state;}
sw_old=sw;dt_old=dt;cl_old=cl;}}
Kot vidimo, si pomagamo s tabelo enc_states, ki opredeljuje spremembo trenutne pozicije enkoderja glede na njegovo preteklo in novo stanje, pri čemer je stanje enkoderja dvobitna vrednost, sestavljena iz signalov ENC_CL in ENC_DT, pri čemer predstavlja ENC_CL bit 1, ENC_DT pa bit 0.
Koncept grafičnih oken in preklapljanje med njimi
Kot primer bomo spet uporabili vremensko postajo 3.0, ki o kateri ste lahko več prebrali v preteklih nadaljevanjih. Razumljivo je, da majhen barvni prikazovalnik z ločljivostjo 128 x 128 pik pač ne more hkrati čitljivo prikazati vseh podatkov. Zato moramo prikaz razdeliti na logične sklope oz. okna in njihove dele, ki jih lahko prikažemo.
Med okni bomo preklapljali s pomočjo enkoderja, urejanje vsebine v njih pa bomo omogočili ob prvem pritisku na tipko. Z nadaljnjimi pritiski na tipko bomo urejali vsebino znotraj izbranega okna ali podokna. Približno tak koncept je uporabljen skoraj vseh enostavnejših digitalnih napravah. A manjka mu pomembna podrobnost: odgovoriti moramo na vprašanje, kako bomo urejali številčna in črkovna polja brez miške in tipkovnice. Za ta namen si je dobro omisliti prekrivni podokni, ki bosta omogočali prosto pisanje znakov in le pisanje številk. Ker pišemo vodoravno iz leve proti desni, je morda še najenostavneje, da prekrivno izbirno okno prikažemo kot trak z mogočimi izbirami znakov oziroma cifer.
Toda, ko govorimo o prekrivnih oknih, je nujno zagotoviti shranjevanje prvotne vsebine zakrite vsebine okna, nad katerim se pojavi prekrivno okno. Slednjo moramo povrniti, ko prekrivno okno odstranimo. V ta namen moramo v RAM-u mikrokontrolerja vzpostaviti t.i. senčni pomnilnik, v katerega shranim prvotno vsebino okna, nad katerim izrišemo prekrivno okno.
Problem lahko še bolj zapletemo, če dopuščamo osveževanje vsebine glavnega okna medtem, ko se izriše prekrivno okno, saj moramo v tem primeru vsakemu od oken zagotoviti senčni pomnilnik, obenem pa ne smemo dovoliti, da bi katerikoli del programa samostojno pisal v pomnilnik prikazovalnika. Zapise v pomnilnik prikazovalnika v tem primeru izvaja izključno podprogram za njegovo osveževanje, ki vsebine senčnih pomnilnikov združi glede na to, katero okno je v ospredju, nato v prikazovalnik zapiše le spremembe. Slednje zahteva tudi uporabo vmesnega pomnilnika, ki hrani kopijo slike na prikazovalniku, saj iz njega pri večini enostavnih prikazovalnikov, povezanih prek vodila SPI, ne moremo brati.
Kaj pa če mikrokontroler za vse našteto nima dovolj RAM-a? Prva poenostavitev je, da dovolimo, da je hkrati aktivno samo okno v ospredju in del glavnega okna, kjer ni dovoljen izris prekrivnih oken (npr. zgornji rob, kjer izpisujemo tekoče podatke). S tem odpade potreba po vmesnem pomnjenju celotne vsebine pomnilnika prikazovalnika, kar vsekakor ni malo podatkov. Denimo, prikazovalnik z ločljivostjo 128 x 128 pik v 262.144 barvah ima 48 kB velik pomnilnik, saj moramo za 18-bitni zapis barv vsake pike shraniti v 3 bajte.
Druga poenostavitev je, da dovolimo spreminjanje vrednosti zgolj v alfanumeričnem ali številčnem polju, katerega vrednost spreminjamo in to od leve proti desni. Slednje je nekaj podobnega kot pisanje na zaslon starih mobilnih telefonov z enostavnimi tipkovnicami, pri katerih lahko nekatere črke dosežemo le z več zaporednimi pritiski na isto tipko.
Enostavno nastavljanje ure in datuma
Poskusimo izdelati enostaven uporabniški vmesnik, s katerim bomo lahko nastavili uro in datum ter nadmorsko višino. To so ključni podatki za pravilno delovanje vremenske postaje, ko jo priklopimo na napajanje. Doslej smo jih lahko osvežili le s PC-ja, zdaj lahko uporabimo tudi enkoder.
Prikaz novih vrednosti ure in datuma na prikazovalniku pri Vremenski postaji 3.0 je samodejen, vsaj enkrat na sekundo. Med nastavljanjem novih vrednosti ure in datuma moramo to funkcionalnost izklopiti, medtem ko lahko mikrokontroler ostali del prikazovalnika z vrednostmi temperatur, zračnega tlaka in relativne zračne vlage normalno osvežuje. Podatek o nadmorski višini ni prikazan, zato pa lahko njegov vnos izvedemo v istem polju kot nastavljamo uro in datum.
Da želimo nastaviti nove vrednosti datuma, ure in nadmorske višine sporočimo s pritiskom na tipko enkoderja, nakar mikrokontroler preneha osveževati uro in datum in dan v mesecu in omogoči urejanje podatkov, na kar uporabnika opozori z inverznim izpisom vrednosti, ki jo urejamo. Denimo, če urejamo minute, so te na primer zapisane s črno barvo na beli podlagi. Tako vemo, katero polje spreminjamo.
Vrednost v polju spremenimo z vrtenjem enkoderja v levo ali v desno, dokler ni v njem želena vrednost. Urejanje zaključimo s pritiskom na tipko, nakar se v inverzni grafiki prikaže naslednje polje, ki ga urejamo, denimo polje za ure, če smo prej urejali minute.
Omenimo še, da spreminjanje letnice ni smiselno za nazaj, torej od leta 2022 nazaj in hkrati tudi ne za več kot 100 let vnaprej. Torej, dovolimo obseg od 2022 do 2122. Tako vrednosti ni potrebno nastavljati po cifrah. Podobno nastavimo tudi ure in minute, medtem ko je pri sekundah bolje, da se začnejo šteti od nič, ko z gumbom potrdimo vnos, saj imamo tako manj dela.
Ko zaključimo urejanje ure in datuma je na vrsti urejanje nadmorske višine za preračun izmerjenega tlaka na nadmorsko višino 0 metrov. Tu se ne moremo izogniti vnosu štirimestnih številk. Zato moramo vsako cifro vnesti posebej. Najprej urejamo tisočice, nato stotice, desetice in nazadnje enice. Ko urejanje zaključimo, vremenska postaja za kratek čas prikaže vneseno vrednost, nato pa sproži redno osveževanje časa, s katerim prekrije polje za urejanje.
Dopolnitve knjižnice GFX za inverzni izpis besedil
Zanimivo, da pri Adafruitu niso pomislili na možnost inverznega izpisa besedila, ki pride še posebej prav pri izdelavi menijev, kjer želimo poudariti izbrano besedilo. Vendarle pri barvnem prikazovalniku to ni tako enostavno kot pri monokromatskem. Podati moramo barvo ozadja, kakor tudi barvo črk.
Zato sem dodal novo funkcijo Set_BgColor, s katero nastavimo barvo ozadja, medtem ko z originalno funkcijo Set_Color nastavimo barvo črt in grafičnih elementov, kot je črta med dvema točkama na prikazovalniku. Povejmo še to, da je interno barva ozadja shranjena polju s štirimi bajti, color_bg_byte, katerega vrednost uporablja smo funkcija print_StringBgColor, ki sicer sprejema enak nabor parametrov kot originalna funkcija, print_String, vendar znakom doda barvo ozadja. Denimo, če želimo izpisati črno besedilo z zeleno barvo ozadja, lahko uporabimo naslednjo kodo , glej program 2.
Kako deluje? Programska knjižnica OLED_GFX tesno sodeluje z gonilnikom OLED_Driver18, v katerem so definirane funkcije za izris znakov različnih velikosti, kot je Write_text , glej program 3.
Dodana programska koda je izpisana odebeljeno. Kot vidimo uporabo barve ozadja določa vrednost spremenljivke USE_BACKGROUND_COLOR, ki jo funkcija print_StringBgColor pred izpisom znakov postavi na vrednost TRUE, nato pa vrne na vrednost FALSE, s čemer zagotovi pravilno delovanje funkcije print_String.
program 2
oled.Set_BgColor(BLUE);oled.Set_Color(BLACK);
oled.print_StringBgColor(0, 0,(uint8_t *)« TEST », FONT_8X16);
program 3
void OLED_Driver::Write_text(uint8_t dat){
uint8_t i;
for(i=0;i<8;i++){
if (dat & 0x01){
Write_Data(color_byte[0]);Write_Data(color_byte[1]);
Write_Data(color_byte[2]);}
else{
if(!USE_BACKGROUND_COLOR){Write_Data(0x00);Write_Data(0x00);Write_Data(0x00);}
else {
Write_Data(color_bg_byte[0]);Write_Data(color_bg_byte[1]);
Write_Data(color_bg_byte[2]);}}
dat >>= 1;}}
Urejevalnik vrednosti v zgornji vrstici
Do zdaj smo v zgornji vrstici zaslona vselej prikazovali le zelen napis »WEATHER STATION«, ki se ne osvežuje, zato jo brez zadržkov lahko uporabimo za enostavno urejanje katerihkoli vrednosti, ne da bi morali kakorkoli zaustaviti ali spremeniti osveževanje trenutnih vrednosti na prikazovalniku. V prvem koraku bomo uporabniku omogočili izvor vrednosti, ki jo želi spremeniti, v drugem koraku pa splošen vnos nove vrednosti, ki ga potrdi s klikom na tipko.
Najprej bomo opredelili tabelo parametrov, ki jih lahko nastavljamo in obseg vrednostim, ki jim jih lahko priredimo. Na primer: nadmorska višina, splošno numerično polje, 4 znaki, ali: dan v mesecu, obseg 1..31, 2 znaka, itn. S tako tabelo lahko prihranimo veliko programskih vrstic, hkrati pa omogočamo enostavno dodajanje možnosti urejanja dodatnih parametrov.
Prednost omenjenega načina vnosa parametrov je tudi v tem, da nam ob vsakokratni prestavitvi ure za eno uro naprej (poletni čas) ali eno uro nazaj (zimski čas), ni potrebno vnesti ure v celoti, ampak vnesemo le spremembo. Poglejmo še, kako v programu opredelimo množico parametrov in omejitve nastavitev posameznega parametra , glej program 4.
Kot vidimo, skušamo vse nastavitve in napise na zaslonu opredeliti tabelarično, saj tako kar se da zmanjšamo količino potrebne programske kode. V tabeli param smo opredelili imena nastavitev in menijev. Pri tem je »WEATHER STATION« zgolj napis, kjer ni kaj nastavljati, zato smo v pripadajoči tabeli param_data opisali s štirimi podatki {0,0,0,0}, kar pomeni, da se samo prikaže. Pri drugih parametrih smo opredeli način nastavljanja. Nadmorsko višino nastavljamo z natančnostjo 10 metrov, v območju -200 metrov do 9000 metrov, pri čemer je prednastavljena vrednost 300 metrov. Po drugi strani, vrednost ure nastavimo med 0 in 23 s korakom 1. Vsekakor moramo za procesiranje omenjenih tabel pripraviti tudi ustrezen podprogram.
program 4
const char *param[]={»WEATHER STATION «, »ELEVATION «, »HOURS «, »MINUTES «, »DAY «, »MONTH «, »YEAR «};
int param_data[][3]={{0,0,0,0}, {300,-200,9000,10}, {0,0,23,1}, {0,0,59,1}, {1,1,31,1}, {1,1,12,1}, {2022,2022,2122,1}};
Arduino chipKIT v praksi
Programiranje Microchip mikrokontrolerjev v Arduino razvojnem okolju? Zakaj pa ne? V Arduino razvojnem okolji zaradi številnih poenostavitev pogosto veliko prej pridemo do rešitve kot, če bi se programiranja lotili v Microchip MPLAB(X), v katerem moramo določiti kopico podrobnosti. Nadobudni programerjih so že pred leti razvili chipKIT, ki je nekakšen vtičnik za Arduino razvojno okolje, podobno kot tista za ESP8266 in ESP32 module. O tem smo že pisali. Tokrat pa se bomo programiranja s pomočjo Arduino chipKIT lotili bolj s praktičnega vidika.
Lastna PIC32 Arduino chipKIT razvojna plošča
Čeprav je chipKIT odprtokoden, vsebuje celovito podporo le za nekatere (predvsem namenske) razvojne plošče z odprto arhitekturo, katerih proizvajalci navajajo združljivost s tem razvojnim okoljem. Je pa res, da je vseeno do neke mere podprta večina drugih razvojnih plošč s PIC32MX in PIC32MZ mikrokontrolerji. Če se lotevamo gradnje lastne razvojne plošče, se vsekakor splača uporabiti že izdelane rešitve na osnovi PIC32MX270F256B mikrokontrolerja, ki je enostaven za spajkanje in lahko obenem vanj novo Arduino programsko kodo naložimo kar prek USB priključka. Ima tudi 256 kB EEPROM-a in 64 kB RAM-a, kar je največ med mikrokontrolerji v SDIP ohišju, ki omogoča enostavno ročno spajkanje. Zdaj moramo le še naložiti ustrezen Arduino chipKIT-bootloader zagonski nalagalnik in mikrokontroler lahko programiramo prek USB priključka ali prek enega od serijskih RS232 priključkov (kot ESP module).
chipKIT bootloader
Izvorna kora chipKIT bootloaderjev je odprtokodna in se lahko iz nje marsikaj naučimo tudi za gradnjo aplikacij v MPLABX razvojnem okolju, a to pustimo za katero od prihodnjih nadaljevanj. Zdaj je pomembneje, da bi načeloma lahko v izvorni kodi izvedli še kako prilagoditev, denimo definirali priključek, ki ob zagonu mikrokontroler prestavi v način za vnos nove Arduino programske kode, oziroma programiranje, kot ga poznamo pri ESP modulih, a za to moramo kupiti licenco za Microchip XC32 prevajalnik, s katero odklenemo generiranje 16-bitne programske kode in vseh optimizacij. V nasprotnem je prevedena strojna kode zagonskega nalagalnika preobsežna za majhen RAM PIC32MX270F256B mikrokontrolerja. Druga možnost je namestitev že prevedene strojne kode chipKIT-bootloaderja iz *.HEX datoteke, a pri tem ne moremo spreminjati nastavitev, prirejenih za eno od podprtih razvojnih plošč. Kakorkoli, pri mikrokontrolerju z majhnim številom priključkov to še nekako gre…
Po drugi strani imajo PIC32MZ2048Exx mikrokontrolerji 512 kB RAMa in 2 MB EEPROMa, kar je za povsem dovolj, da lahko prevedemo chipKIT-bootloader v 32-bitnem načinu brez optimizacij in ga tudi namestimo. Zdaj lahko spreminjamo čisto vse, tudi način in hitrost prenosa Arduino programske kode pa tudi določimo, na katerih priključkih bodo serijska vrata. Moti le, ker pri razvojnih ploščah s PIC32MZ mikrokontrolerji (za enkrat) ni podprt način posodabljanja Arduino programske kode prek priključka USB, no vsaj jaz ga nisem našel. Zato je programiranje lahko težavno, če so povezave med vmesnikom USB-RS232 predolge (več od kakih 5 cm).
Ker sem imel pri roki PIC32MZ EC Starter Kit, se je zdel kot nalašč za testiranje Arduino programske kode, vendar je optimizem kmalu splahnel, ko iskal možnosti za čim krajšo povezavo kateregakoli od šestih vgrajenih UART-ov z doma izdelanim USB-RS232 vmesnikom na osnovi PIC32MX250F128B mikrokontrolerja. Ni enostavno! Na koncu sem se odločil, da povezave potegnem kar iz mostičnih povezav na vmesniški ploščici 168 pin to 132 pin adapter, ki starter kit povezuje s Starter kit I/O expansion boardom 16, od kjer sem potegnil PD4 (TX, potegnemo iz sredinskega priključka JP5) in PD5 (RX, potegnemo iz sredinskega priključka JP6), pri čemer sem imel maso že iz priključka USB, prek katerega je povezan vgrajeni programator starter kita. Pri tem Starter kit I/O expansion boardom 16 ni treba priključiti, vseeno pa pride prav, ko se lotevamo kakega zahtevnejšega Arduino projekta, pri katerem potrebujemo SD kartice pa tudi dodatno napajanje iz enosmernega napajalnika z od 9 V do 15 V. Podrobnosti si oglejte na fotografiji.
Kakorkoli, prilagoditev chipKIT-bootloaderja zadošča za nalaganje Arduino programske kode, a ne more delovati, če prej ne izdelamo opisa svoje razvojne plošče, ki ga dodamo v chipKIT vtičnik za Arduino razvojno okolje.
Prirejanje chipKIT vtičnika za Arduino
Ko se lotevamo različnih projektov na področju strojne oprem se pogosto težko odločimo za pravo razvojno ploščo, saj ima le malokatera natanko tiste funkcionalnosti, ki jih želimo, ali pa že imamo odlično razvojno ploščo, ki je ne moremo uporabiti, ker ni združljiva z Arduino razvojnim okoljem. No, meni se je zgodilo slednje, saj za PIC32MZ EC Starter kit s PIC32MZ2048ECH144 mikrokontrolerjem v internetu ne najdemo ustrezne podpore. Kljub temu lahko nanj naložimo zagonski nalagalnik Avrdude, združljiv z Stk500v2 protokolom. Meni sprva ni deloval in sem moral narediti še nekaj popravkov izvorne kode.
A pozor! Zagonski nalagalnik je samo to! Strojno kodo prenese iz PC-ja v EEPROM mikrokontrolerja ali jo zažene, če so za to izpolnjeni pogoji. Vendar obenem ne nudi nobene podpore glede mikrokontrolerjeve arhitekture ali zgradbe razvojne plošče, na kateri deluje. Vse to opredeli razvojno okolje Arduino chipKIT. Razvojna plošča in izbrani mikrokontroler sta natančno opredeljena v definicijah chipKIT, ki jih najdemo v imeniku <sistemski podatkovni pogon>:Users<uporabnik>AppDataLocalArduino15packageschipKIThardwarepic322.1.0. Pri tem namesto <sistemski podatkovni pogon> in <uporabnik> vnesite vaše podatke.
Osnovni podatki o razpoložljivih razvojnih ploščah z izbranimi mikrokontrolerji so v datoteki boards.txt. Če želite opredeliti svojo razvojno ploščo, predlagam, da najprej prekopirate nastavitve od najbolj podobne. V mojem primeru je bila to chipKIT Wi-Fire z mikrokontrolerjem PIC32MZ2048EFG100. Zato sem njeno definicijo najprej prekopiral in nato popravil takole , glej program 5.
Obenem sem staro definicijo pustil nedotaknjeno, ker pomeni, da sem datoteko boards.txt nekoliko podaljšal. Arduino razvojno okolje sem moral nato le še ponovno zagnati in med izbiro chipKIT razvojnih plošč se je pojavila še moja za imenom PIC32USBProj. Vendar je to šele začetek, saj ima PIC32MZ EC Starter kit razvojna plošča z PIC32MZ204ECH144 mikrokontrolerjem precej drugačno arhitekturo. Podrobne definicije podprtih razvojnih plošč s pripadajočimi mikrokontrolerji najdemo v mapi variants, kjer ima vsaka razvojna plošča svojo podmapo, katere ime mora biti enako vrednost spremenljivke chipkit_PIC32USBProj.build.variant. V podmapi sta vsaj datoteki Board_data.h in Board_data.c, lahko pa tudi dodatne, s katerimi opišemo posebnosti, kot na primer drugačno zasnovo A/D pretvornika, ki je značilna za določene mikrokontrolerje iz družine PIC32MZ.
Arduino razvojno okolje priključke na ohišju mikrokontrolerja striktno označuje s številkami, medtem ko prevajalniki za C/C++ za PIC32 te grupirajo v več portov (PORT A… PORT K), katerih število je odvisno od števila fizičnih priključkov na mikrokontrolerskem čipu. Če dodatnih portov ne podamo, ostanejo nedefinirani in jih v Arduino razvojnem okolju ne moremo uporabljati. Ker pa so svetleče diode pri PIC32MZ Starter kitu na portu H (biti 0, 1, 2), sem slednjega vseeno dodal tabele v datoteki Board_data.c. V slednji je potrebno postoriti kar nekaj stvari, saj lastnosti posameznih priključkov in njihove preslikave na funkcijske enote mikrokontrolerja niso samoumevne.
V datoteki Board_data.h so splošni podatki o razvojni plošči in mikrokontrolerju. Če dodajamo nov port, moramo spremeniti definicijo #define NUM_DIGITAL_PINS 71, ker sem dodal 3 nove priključke, sem vrednost 71 spremenil v 74. Če bi hotel dodati vse dodatne priključke PIC32MZ204ECH144, bi jih moral še bistveno več. A slednje je za začetek povsem dovolj.
Številčno oznako posameznega priključka v Arduino razvojnem okolju določimo v tabelah digital_pin_to_port_PGM in digital_pin_to_bit_mask_PGM v Board_data.c datoteki. Iz previdnosti sem priključke porta H dodal na konec obeh tabel, potem pa tudi v ostalih tabelah, ki sledijo, dodal tui ustrezne lastnosti.
program 5
# PIC32_PC_USB_PROJECTS
chipkit_PIC32USBProj.name=chipKIT PIC32USBProj
chipkit_PIC32USBProj.group=chipKIT
# new items
chipkit_PIC32USBProj.platform=pic32
chipkit_PIC32USBProj.build.board=_BOARD_WIUSBPROJ_
chipkit_PIC32USBProj.ldscript=MZ-application-32MZ2048ECX.ld
# end of new items
chipkit_PIC32USBProj.upload.protocol=stk500v2
chipkit_PIC32USBProj.upload.maximum_size=2080768
chipkit_PIC32USBProj.upload.maximum_data_size=524288
chipkit_PIC32USBProj.upload.speed=115200
chipkit_PIC32USBProj.upload.tool=pic32prog
chipkit_PIC32USBProj.build.f_cpu=200000000UL
chipkit_PIC32USBProj.build.core=pic32
chipkit_PIC32USBProj.ldcommon=chipKIT-application-COMMON-MZ.ld
chipkit_PIC32USBProj.build.variant=PIC32USBProj
chipkit_PIC32USBProj.build.ldscript.path={build.variant.path}
chipkit_PIC32USBProj.usb.enabled=true
chipkit_PIC32USBProj.usb.default=z_custom
chipkit_PIC32USBProj.menu.Version.cplus=Rev C and Newer (FPU)
chipkit_PIC32USBProj.menu.Version.cplus.build.mcu=32MZ2048ECH144
chipkit_PIC32USBProj.menu.Version.ab=Rev A or B (No FPU)
chipkit_PIC32USBProj.menu.Version.ab.build.mcu=32MZ2048ECH144
program 6
// Serial port 0 uses UART4
#define _SER0_BASE _UART4_BASE_ADDRESS
#define _SER0_IRQ _UART4_FAULT_VECTOR
#define _SER0_VECTOR _UART4_FAULT_VECTOR
#define _SER0_IPL_ISR IPL2SRS
#define _SER0_IPL 2
#define _SER0_SPL 0
#define _SER0_TX_OUT PPS_OUT_U4TX // (RPD4R = 0b0010) RD4 –> U4TX
#define _SER0_TX_PIN 43 // PD4
#define _SER0_RX_IN PPS_IN_U4RX // (U4RXR = 0b0110) RD5 -> U4RX
#define _SER0_RX_PIN 34 // PD5
Nastavitev osnovnega serijskega porta za Arduino programsko opremo
Zdaj, ko Arduino ve za PORT H, je vsekakor dobro, da mu povemo tudi, kateri UART bomo uporabili za osnovno teminalsko komunikacijo (objekt Serial), prek katere lahko spremljamo delovanje Arduino aplikacij. Nastavitev izvedemo v prej omenjeni board_data.h datoteki , glej program 6.
Kot vidimo, smo v prvih treh vrednosti nastavili UART4, prav tako pa tudi v zadnjih štirih. Pri tem povejmo, da je dovolj, da za _SER0_TX_OUT nastavimo vrednost PPS_OUT_U4TX in za _SER0_RX_IN vrednost PPS_IN_U4RX. Vse ostalo na osnovi podatkov _SER0_TX_PIN in _SER0_RX_PIN opravijo chipKIT programske knjižnice. Pri tem je pomembno vedeti, da sta preslikavi PD4 v pin 43 in PD5 v pin 34 že določeni v tabelah digital_pin_to_port_PGM in digital_pin_to_bit_mask_PGM v Board_data.c datoteki, saj moramo pri definiciji serijskega porta podati številko priključka.
Prilagoditev definicij SPI vmesnikov in SD kartice
Za tudi uporabo SPI vmesnikov v Arduino okolju moramo prilagoditi tudi nastavitve SPI vmesnikov. PIC32MZ mikrokontrolerji imajo med 4 in 6 SPI vmesnikov, za katere moramo pripraviti definicije v datoteki Board_data.h. Število SPI portov nastavimo v Board_data.h v definiciji NUM_SPI_PORTS. Nato moramo na koncu iste datoteke zapisati še preslikave signalov SPI portov na zunanje priključke mikrokontrolerja. Nastavljamo lahko priključka MISO in MOSI, medtem, ko je priključek CLK vedno preslikan na isti izhodni priključek mikrokontrolerja. Preslikava se izvede samodejno ob vklopu ustreznega SPI vmesnika. Opozorimo še, da različne Arduino chipKIT združljive razvojne plošče navadno omogočajo uporabo le nekaterih SPI vmesnikov, saj mora njihov uporabo omogočati tudi ostala strojna oprema na razvojni plošči.
V sekciji _uSD_SPI_CONFIG_ nato določimo še priključke SPI vmesnika za povezavo s SD kartico (signali SDO, SDI, SCK), kar je podobno kor pri nastavitvah SPI vmesnika, le da moramo tu podati priključek kot trojico podatkov, na primer za signal SDO (MOSI):
#define prtSDO IOPORT_C #define bnSDO BIT_4 #define SD_SDO_PPS() RPC4R = 0b0000
Prihodnjič
Z Arduino chipKIT razvojnim okoljem se bomo lotili gradnje kompleksnejših aplikacij. Prednost Microchipovih mikrokontrolerjev je bogata strojna podpora številnim komunikacijskim protokolom, kakor tudi USB povezljivosti, ki jo pri večino ESP modulov pogrešamo. Po drugi strani, večna PIC32 mikrokontrolerjev ne omogoča Wi-Fi povezljivosti, zato se moramo tu znajti drugače. Več o tem prihodnjič, ko se bomo lotili tudi problema dostopa dveh mikrokontrolerjev do skupne SD kartice. To je še posebej zanimivo v primerih, ko ima eden od mikrokontrolerjev USB povezljivost, saj lahko na ta način hitro prenašamo podatke v PC, ne da bi potrebovali Ethernet ali Wi-Fi povezavo.