Avtorja: Mag. Vladimir Mitrović, Robert Sedak
V tem nadaljevanju bomo pokazali, kako na razvojni sistem Shield-B sočasno vežemo enosmerni, servo in koračni motor.
Motorjev ne bomo krmilili kot v preteklih primerih preko tipk in potenciometrov na Shield-B, pač pa preko ukazov, ki jih formiramo na Shield-A in jih nato preko komunikacijske linije posredujemo v izvršitev Shield-B plošči (slika 26). Tako se bomo tudi naučili, kako lahko izmenjujemo informacije med dvema razvojnima sistemoma!
Opomba: več o razvojnem sistemu Shiled-A poiščite v Svetu elektronike 288-301.
Enosmerni motor je vezan na način, ki omogoča spremembo hitrosti in smeri vrtenja, medtem ko so servo in koračni motorji vezani preko za to predvidenih konektorjev na razvojni ploščici Shield-B. Če uporabljamo samo en servo motor, ga vežemo na priključek J5. Za enosmerni motor je preko konektorja J1 nujno zagotoviti ustrezno napajanje, primerno njegovim zahtevam.
Ta vsebina je samo za naročnike
Ukaze formiramo z interaktivnim programom, ki uporablja alfanumerični displej (LCD), tipki SW1 in SW2 in potenciometer RV1 razvojnega sistema Shield-A. Izpisi na LCD-ju prikazujejo, kateri motor je trenutno izbran in kakšni so njegovi zadani parametri (slika 27). Motorje izbiramo s kratkotrajnimi pritiski na tipko SW1.
Ko je izbran DC motor, bo v spodnji vrstici izpisana njegova trenutna relativna hitrost »v«. Hitrost izberemo z vrtenjem osi potenciometra RV1; ko je drsnik potenciometra v srednjem položaju, bo hitrost enaka 0. Z vrtenjem osi v eni smeri se bo hitrost večala do največje vrednosti, 255. Z vrtenjem osi v drugo smer bo hitrost tudi rastla do 255, vendar se bo motor sedaj vrtel v nasprotni smeri. Smer vrtenja je simbolično prikazan s simboloma ”<” in ”>” v zgornji vrstici LCD-ja.
V spodnjem desnem vogalu displeja sta prikazani oznaki ”->DA” in ”->NE”. Ko izberemo nek motor, bo začetna postavka vedno ”->NE”; kar pomeni, da se nastavitve, ki jih delamo, ne posredujejo razvojnemu sistemu Shield-B, zato bo izbrani motor deloval na predhodno postavljeni način. Oznako bomo spremenili v ”->DA” s kratkim pritiskom na tipko SW2. Od tega trenutka naprej se vse spremembe ažurno pošiljajo razvojnemu sistemu Shield-B, da bosta hitrost in smer vrtenja sledili vrtenju osi potenciometra RV1. Oznako menjamo v ”->NE” s ponovnim pritiskom na tipko SW2 ali z izbiro drugega motorja.
Kadar je izbran servo motor, se v spodnji vrstici izpisuje trajanje krmilnih impulzov v mikrosekundah. Prikazana vrednost, 1500 postavlja os servo motorja v srednji položaj. To je takrat, kadar je drsnik potenciometra v srednjem položaju. Z vrtenjem osi potenciometra od enega do drugega skrajnega položaja se bo trajanje impulzov menjalo v razponu 700-2300 µs. Postavki bodo posredovani Shieldu-B samo v primeru, ko je vključena oznaka ”->DA”.
Za koračni motor sta predvidena dva spodnja prikaza na sliki 27. Z izborom enega od njih izberemo tudi smer vrtenja motorja, s potenciometrom RV1 izberemo število korakov v razponu 0-1023. Ker koračni motor potrebuje nek čas, da ”oddela” želeno število korakov, se bo oznaka ”->DA” ko se pošlje ukaz Shieldu-B, avtomatsko spremenila v ”->NE”. Lahko menjamo motorje in njihove postavke, vendar smemo nov ukaz Shieldu-B poslati šele, ko se koračni motor zaustavi!
Struktura ukaza, ki ga Shield-A pošlje Shieldu-B, je prikazana na sliki 28. Ukaz je 16-biten: prva dva bita določata, na kateri motor se ukaz nanaša, naslednji štirje se ne uporabljajo, preostalih 10 služi branju napetosti drsnika potenciometra v razponu 0-1023. Razvojni ploščici sta povezani preko svojih I2C priključkov, zato se ukaza lahko pošiljata z I2C protokolom ali na kateri koli drugi način, kjer sta za komunikacijo dovolj dve žici.
Električni shemi na slikah 29 in 30 nam kažeta, kako so pomembne komponente razvojnih sistemov Shield-A in Shield-B povezane z mikrokontrolerjem ATmega328P na Arduino Uno ploščicah. Tukaj moramo še komentirati možne načine napajanja. Enosmerni motor (M na sliki 30) potrebuje lastni vir napajanja, UMOT. Če je ta napetost višja od 6,5 V, bo preko Schottky diode D9 napajanje dobila tudi Arduino Uno ploščica, na katero je Shield-B postavljen.
Izhodna napetost stabilizatorja na Arduino Uno ploščici je 5 V, ta napetost se uporablja za napajanje mikrokontrolerja in ostalih komponent na ploščici, in povratno tudi za napajanje servo motorja S in koračnega motorja K na Shieldu-B. Ker I2C konektorji, preko katerih sta povezana Shield-A in Shield-B vsebujejo tudi VCC priključek preko I2C povezave, bo tudi Shield-A in njegov Arduino Uno dobil potrebno napajanje. Predpogoj, da bi vse delovalo tako, kot je treba je, da vir napetosti UMOT zmore dati od sebe najmanj 1 A toka in da so spoji I2C vodil z I2C konektorji kvalitetni, brez pomembne prehodne upornosti.
Če DC motor zahteva napetost napajanja, ki je nižja od 6,5 V, moramo Shieldu-B zagotoviti lastno napajanje, npr. z osebnega računalnika preko USB kabla. Shield-A bo tudi tukaj potrebno napetost napajanja dobil preko I2C vodila. Vendar pa moramo upoštevati nekatere omejitve! Koračni motor tako v vrtenju kot v mirovanju troši okoli 350 mA. Servo motor v mirovanju troši zanemarljiv tok, vendar, pri spremembi položaja poraba kratkotrajno preseže 100 mA tudi pri malih motorjih kot je SG90. Če dodamo temu porabo Shieldov in obeh Arduino ploščic, se nahajamo na nevarni meji, pri kateri nastopi preobremenitev USB porta računalnika! Med razvojem programa se je to jasno videlo: LED-ice na Shieldu-B so pričele utripati, servo motor pa se je občasno obnašal nestabilno. Problem smo rešili tako, da smo koračni motor programsko popolnoma izključili takoj, ko smo naredili zahtevano število korakov.
- programska naloga: Napišite programe za razvojna sistema Shield-A in Shield-B, s pomočjo katerih bomo krmilili enosmerni, servo in koračni motor v skladu z uvodnim opisom!
V programu za Shield-B so pravzaprav združeni programi Shield-B_4, Shield-B_5a in Shield-B_6. Ena pomembna zamenjava je v tem, da ti programi ne berejo samostojne napetosti drsnika potenciometra, pač pa ta podatek dobijo s Shielda-A preko komunikacijske linije.
Program za Shield-A bere napetost potenciometra RV1 in nato, odvisno od trenutno izbranega motorja, formira in pošlje sporočilo Shieldu-B in izpiše ustrezne izpise na LCD-ju. To so vse običajni postopki, katere bi vsak bralec naše serije moral znati sprogramirati. To, kar je novo v obeh programih je postopek priprave sporočila in njegovega pošiljanja preko komunikacijske linije ter sprejem sporočila in njegova analiza na drugi strani komunikacijske linije. Tukaj se bomo posvetili samo tem delom programa.
Bascom-AVR rešitev za Shield-A
(program Shield-A_7.bas)
Sporočilo za Shield-B pripravimo v 16-bitni spremenljivki Podatek. Spremenljivka je dimenzionirana s pomočjo opcije Overlay, tako da lahko enostavno pristopimo njeni spodnji in zgornji polovici (Podatek_l in Podatek_h, slika 31). Uporabili bomo tudi 8-bitno spremenljivko Motor, katere vsebina je odvisna od trenutno izbranega motorja in je lahko:
&B00000000, &B01000000, &B10000000 ili
&B11000000.
V glavni zanki pogosto beremo napetost drsnika potenciometra RV1:
Podatek = Getadc(0)
Rezultat A/D pretvorbe je 10-bitno binarno število, zato bo šest najvažnejših bitov spremenljivke Podatek postavljenih v stanje ”0”. Preko najvažnejših dveh bitov bomo ”stisnili” vsebino spremenljivke Motor in tako formirali sporočilo, katere strukturo smo pokazali na sliki 28.
Podatek_h = Podatek_h Or Motor
V Bascom-AVR verziji programa bomo sporočilo poslali s pomočjo ukaza Shiftout:
Shiftout Portc.4 , Portc.5 , Podatek , 0 , 16 , 100
Waitms 20
Ukaz bo generiral 16 taktnih impulzov na priključku PC5 (SCL) in, sinhrono z njim, na priključek PC4 (SDA) postavljal bit za bitom spremenljivke Podatek. Parameter 0 določa način pošiljanja: od najbolj pomembnega proti manj pomembnim bitom, na padajoči strani taktnega impulza. Da bi bila komunikacija manj kritična, smo jo pomembno upočasnili glede na njeno najvišjo hitrost (s parametrom 100 bo pošiljanje celotnega sporočila trajalo okoli 3,5 ms). V skladu z opisom dela programa se bo pošiljanje dogodilo samo, če je omogočeno s pritiskom na tipko SW2; tega dela programa tukaj ne bomo analizirali.
Bascom-AVR rešitev za Shield-B
(program Shield-B_7.bas)
Na začetku glavne zanke pričakujemo prihod sporočila po komunikacijski liniji, preko priključka PC4 (SDA), in sinhrono s takt impulzi na priključku PC5 (SCL).
Do
…
Shiftin Pinc.4 , Pinc.5 , Podatek , 5 , 16
Ukaz Shiftin sprejeto sporočilo namesti v 16-bitni spremenljivko Podatek, parameter 5 pa je usklajen s parametrom 0 ukaza Shiftout. Iz sprejetega sporočila se izločita dva najpomembnejša bita in se preneseta v spremenljivko Motor
Motor = High(podatek)
Motor = Motor And &B11000000
nato se tudi spremenljivki Podatek zbriše celotna odvečna vsebina, razen 10 bitov, ki vsebujejo branje potenciometra RV1. Odvisno od izbranega motorja se bo ta vrednost uporabila za določanje hitrosti in smeri vrtenja DC motorja ali kota obrata osi servo motorja, na isti način, kot v programih Shield-B_4.bas in Shield-B_5a.bas.
Program za koračni motor je malo drugačen od programa Shield-B_6.bas, ker tukaj spremenljivka Podatek vsebuje želeno število korakov in te korake moramo prešteti:
If Motor = &B10000000 Then
While Podatek > 0
Step_in = Step_in + 2
Gosub Step_pomakni
Waitms 20
Podatek = Podatek – 1
Wend
EndIf
Waitms 20 zagotovi 20 ms pavze po vsakem koraku, zaradi česar se bo motor zelo počasi vrtel. Program za vrtenje v nasprotni smeri je zelo podoben, razen da smo tukaj uporabili najmanjšo zakasnitev pri kateri se motor še vedno vrti (Waitms 2, poglejte predhodni članek).
Dokler se koračni motor premika je izvrševanje programa zaprto znotraj While-Wend zanke in program ne more prejeti novega sporočila po komunikacijski liniji. Sočasno se bo DC motor vrtel s predhodno zahtevano hitrostjo, servo motor pa bo zadržal svoj predhodno postavljen položaj, ker ta motorja krmilita Timer0 in Timer1 (poglejte predhodne članke). Po zaključku While-Wend zanke, se bo koračni motor zaustavil in to je trenutek, ko ga lahko popolnoma ugasnemo s klicem podprograma Step_ugasni:
GosubStep_ugasni -> Gosub Step_ugasni
Arduino rešitev za Shield-A
(program Shield-A_7.ino)
V tem podprogramu postavljamo vse krmilne priključke koračnega motorja (PD2, PD4, PD7 in PB0) v stanje 0, zaradi česar ne bo več tekel tok niti preko enega njegovega navitja. Sočasno se bodo izklopile tudi vse modre LED-ice.
Za razliko od rešitve v Bascom-AVR v Arduino IDE uporabljamo I2C protokol.
Knjižnica Wire nam omogoča pošiljanje enega bajta ali niza bajtov. Zato poleg spremenljivke Podatek definiramo tudi niz podatek_i2c z dvema elementoma vrste bajt. Nato definiramo spremenljivko motor v katero shranimo trenutno izbrani motor na isti način kot tudi v Bascom-AVR rešitvi, in spremenljivko poslji_dane vrste bool, ki služi za definiranje pošiljanje podatka na Shield-B.
byte podatek_i2c[2];
uint16_t podatek = 0;
byte motor = 0;
bool poslji_dane = 0;
V glavni zanki pogosto beremo napetost drsnika potenciometra RV1:
podatek = analogRead(A0);
Rezultat A/D pretvorbe je 10-bitno binarno število, zato bo šest najvažnejših bitov spremenljivke podatek postavljenih v stanje ”0”. Preko najvažnejših dveh bitov bomo ”vpisali” vsebino spremenljivke motor.
podatek = (motor << 8) | podatek;
Nato bomo vrednost spremenljivke podatek ”razdelili” na dva elementa polja podatek_i2c:
podatek_i2c[0] = (podatek >> 8 ) & 0xFF;
podatek_i2c[1] = podatek & 0xFF;
Podatek pošljemo s pomočjo knjižnice Wire. Pri začetku prenosa definiramo pošiljanje podatkov na naslov 0x8, ki ga bomo definirali v programu za Shield-B.
Ukazu Wire.write() posredujemo niz podatek_i2c in informacijo, da prenašamo dva elementa polja.
Wire.beginTransmission(0x8);
Wire.write(podatek_i2c, 2);
Wire.endTransmission();
delay(20);
Pri prikazu obrata servo motorja prikazujemo stopinje obrata od 0-180 in tako pretvorjeni podatek pošljemo na Shield-B. Prikaz oznake za stopinje dobimo z uporabo numerične kode 223:
podatek = map(podatek, 0, 1023, 0, 180);
lcd.setCursor(0,1);
lcd.print(”zakret:”);
lcd.print(podatek);
lcd.print((char)223);
lcd.print(” ”);
Ostali deli programa so opisani v predhodnih člankih.
Arduino rešitev za Shield-B
(program Shield-B_7.ino)
V funkciji setup() definiramo I2C naslov 0x8 in deklariramo, da bo funkcija beri_i2c izvršena potem, ko prejmemo podatke preko I2C protokola.
void setup() {
pinMode(2,OUTPUT);
pinMode(4,OUTPUT);
pinMode(7,OUTPUT);
pinMode(8,OUTPUT);
Wire.begin(0x8);
Wire.onReceive(beri_i2c);
S1.attach(9);
S1.write(0);
} // kraj setup()
V funkciji beri_i2c() definiramo spremenljivki podatek_h in podatek_l v kateri bomo brali prejete bajte. V spremenljivko motor zapišemo samo dva najvažnejša bita iz spremenljivke podatek_h, s pomočjo katerih smo definirali izbrani motor, medtem ko podatek o obratu osi RV1 na Shield-A ”rekonstruiramo” s pomočjo obeh spremenljivk tako, da bo ”filtriral” samo bite, ki vsebujejo želeni podatek, tj. 10 najmanj važnih bitov.
void beri_i2c(inthowMany)
{
bytepodatek_h = 0;
bytepodatek_l = 0;
while(1 <Wire.available())
{
podatek_h = Wire.read();
}
podatek_l = Wire.read();
motor = podatek_h& 0b11000000;
podatek = (podatek_h<< 8);
podatek = podatek | podatek_l;
podatek = podatek & 0b1111111111;
} // kraj receiveEvent()
Del za koračni motor programiramo po Bascom-AVR rešitvi.
Pri zagonu programa za Shield-B se funkcija loop() avtomatsko izvršuje in ne čaka na sprejem podatkov preko I2C protokola. V kolikor želimo, da na začetku izvrševanja programa DC motor miruje, je potrebno definirati, da vrednost spremenljivke podatek znaša 256 in to v primeru, ko je začetna vrednost spremenljivke motor nič:
uint16_t podatek = 256;
byte motor = 0;
Kadar bi vrednost spremenljivke podatek bila nič, takrat bi se motor DC vrtel z največjo hitrostjo v eni smeri. Če želimo, da DC motor miruje dokler krmilimo druge motorje, je potrebno priključke D5 in D6 postaviti v stanje 0.
void loop() {
step_ugasni();
if (motor == 0b00000000) {
if (podatek >= 256) {
analogWrite(5, podatek – 256);
analogWrite(6, 0);
} else {
analogWrite(5, 0);
analogWrite(6, 255 – podatek);
}
} else {
analogWrite(5, 0);
analogWrite(6, 0);
}
S tem člankom smo zaključili serijo člankov, ki opisujejo krmiljenje motorjev s pomočjo razvojne ploščice Shield-B! Vse razvojne in proizvodne datoteke ploščic Shield-A in Shield-B lahko dobite na spodnjih povezavah:
https://github.com/rsedak/Shield-A
https://github.com/rsedak/Shield-A_V2.0
https://github.com/rsedak/Shield-B
Opombe: Programi, ki smo jih analizirali v tej seriji in vse reference se enako nanašajo na originalni Arduino Uno in na njegove klone. Programe Shield-A_7.bas, Shield-B_7.bas, Shield-A_7.ino in Shield-B_7.ino lahko brezplačno dobite od uredništva revije Svet elektronike! Programi za Shield-A se razlikujejo od istoimenskih programov pisanih v seriji posvečeni razvojnemu sistemu Shield-A!