Fórum témák

» Több friss téma
Cikkek » Tényleg nincs királyi út? I. rész
Tényleg nincs királyi út? I. rész
Szerző: icserny, idő: Jún 22, 2013, Olvasva: 26939, Oldal olvasási idő: kb. 5 perc
Lapozás: OK   4 / 8

"Analóg" vezérlések: PWM és szervó

Folytassuk az ismerkedést az Energai fejlesztői könytárainak további lehetőségeivel! Az első példánkban az analóg vezérléssel ismerkedünk meg. Analóg vezérlés? De hiszen a Launchpad kártyához kapott mikrovezérlőinken nincs is analóg kimenet! Hogyan valósíthatjuk meg akkor az analóg vezérlést?  Nos, sok esetben élhetünk azzal a lehetőséggel, hogy az analóg vezérlést  digitális impulzussorozat-jelekkel valósítjuk meg, amelyek hosszabb időtartamra vonatkoztatott átlagfeszültsége egyenértékű a számunkra szükséges analóg feszültségjellel. Lámpák fényerejének vezérlése, ventilátorok, vagy egyéb villanymotorok fordulatszáma, egy fűtőtest fűtőteljesítménye könnyen vezérelhető ilyen módon. A digitális impulzussorozat frekvenciáját úgy kell (elegendően nagyra) megválasztani, hogy az a vezérelt vagy szabályozott eszköz megfelelő működését biztosítsa. Például a szabályozott fényforrás folyamatos működésűnek látsszon (a szemünk ne vegyen észre villogást), vagy egy egyenáramú motor ne lökésszerűen változó szögsebességgel forogjon.

A digitális jelsorozattal történő vezérlés egyik jól használható változatai az impulzus-szélesség moduláció (PWM = Pulse Width Modulation), amelynél olyan állandó periódusidejű (frekvenciájú) jeleket keltünk, ahol az a szabályozás a jel kitöltési tényezőjének változtatásával történik. Néhány különböző kitöltési tényezőjű PWM jelet mutat be a következő ábra:

pwm_example.png

4_1. ábra: Azonos periódusú, de különböző kitöltésű impulzus-sorozatok

 Az analogWrite() függvény

Az Energia perifériakönyvtárak analogWrite() függvénye a fentiekhez hasonló módon impulzusszélesség-modulációt (PWM) valósít meg, amely a következő paraméterekkel jellemezhető:

  • A PWM frekvencia az Arduino-hoz hasonlóan 490 Hz körüli érték.
  • A PWM jel kitöltési tényezője 0 és 255 közötti egész számmal adható meg (255 felel meg a 100 %-os kitöltésnek).
  • Az analogWrite() függvény csak az előző oldalon bemutatott lábkiosztáson lilával megjelölt lábakra vonatkozóan használható, de további megkötések is vannak.

Mivel a PWM jel előállítása a Timer0 vagy Timer1 időzítőket használja, melyeknek 0. capture/Compare csatornája a jel frekvenciáját állítja be, így a Launchpad kártya MSP430G2553 mikrovezérlőjével egyidejűleg legfeljebb 3 db PWM jelet állíthatunk elő, az alábbi táblázat szerint (lásd: MSP430G2553 adatlap, Table12 és Table13).

Időzítő Csatorna Választható kivezetés
Timer0 TA0.1 P1_2, P1_6 vagy P2_6
Timer1 TA1.1 P2_1 vagy P2_2
Timer1 TA1.2 P2_4 vagy P2_5

Megjegyzés: az analogWrite() függvény lefoglalja az adott lábhoz rendelt Timer időzítőt, ezért nem használható egyidejűleg olyan könyvtári függvénnyel, amely ugyanazt az időzítőt használná.

Mintaprogram: Fade

A mintaprogramok között található Fade program a Launchpad kártya zöld LED-jének fényességét változtatja, periodikusan, az analogWrite() függvény segítségével. Azért éppen ezt a LED-et használjuk, mert ez a P1_6 lábra van kötve, amelyen használható az analogWrite() függvény.

Hardver követelmény: Launchpad kártya

 

4_1. lista: A Fade mintaprogram listája

  1. int brightness = 0; // ilyen fényesen világítson a LED (0-255)
  2. int fadeAmount = 5; // ekkora legyen a fényerősség változása
  3.  
  4. void setup() {
  5.   // a zöld LED-hez tartozó kivezetést digitális kimenetnek állítjuk
  6.   pinMode(GREEN_LED, OUTPUT);
  7. }
  8.  
  9. void loop() {
  10.   // a zöld LED fényerejének beállítása:
  11.   analogWrite(GREEN_LED, brightness);
  12.   // változtassuk meg a fényerőt a következő ciklushoz:
  13.   brightness = brightness + fadeAmount;
  14.   // fordítsuk meg a fényerősségváltoztatás irányát a határoknál:
  15.   if (brightness == 0 || brightness == 255) {
  16.     fadeAmount = -fadeAmount ;
  17.   }
  18.   // várunk 30 miliszekundumot, hogy a változás érvényesüljön
  19.   delay(30);
  20. }

A programban a brightness nevű változóban állítjuk elő a kitöltési tényezőt, azaz a LED fényerejét szabályozó, 0 - 255 közötti értéket. A loop() végtelen ciklusban minden alkalommal az előre megadott fadeAmount értékkel növeljük. Amikor valamelyik határértéket elértük, akkor a fadeAmount változó értékének előjelét ellenkezőjére változtatjuk, így felváltva növekedő, illetve csökkenő számsorozatot állítunk elő (a LED fokozatosan fényesedik, majd elhalványul).

Minden ciklusba egy 30 ms-os késleltetést is beiktatunk, hogy addig ne kerülön sor újabb változtatásra, amíg a beállított kitöltési tényezővel néhány PWM periódus le nem zajlik.  

Szervó motorok vezérlése

Az impulzusszélesség-moduláció egy speciális esete a szervó motorok vezérlőjele. Mivel főleg a rádiótávirányítású modellekben terjedt el  a használatuk, ezeket többnyire "RC servo" néven emlegeti az angol nyelvű szakirodalom. A szervó motorok felépítése és tipikus jelalakja az alábbi ábrákon látható (a képek forrása a ServoCity honlapja).

servo_motor_components.jpg 

4_2. ábra: A szervó motor "robbantott képe

A szervó egy kisméretű egyenáramú motort tartalmaz, amely a fogaskerék áttételen keresztül mechanikai összeköttetésben áll egy potméter tengelyével. A beérkező vezérlőjelet feldolgozó beépített elektronika úgy irányítja a motor forgását előre vagy hátra, hogy a potméterrel összekötött tengely mindig az adott szögállásba kerüljön. A különböző gyártmányú szervók vezérlőjele nem egységes, de a bejövő jel általában 50 Hz-es ismétlődési frekvenciájú, 5 - 10 %-os kitöltésű impulzus, amelynél az impulzus szélessége szabja meg a kívánt szögállást. Az 1,5 ms szélességű jel tartozik a középső, úgynevezett nyugalmi helyzethez, s 0,5-1 ms szélességű jel felel meg a bal szélső helyzetnek, valamint 2 - 2,5 ms szélességű jel felel meg a jobb szélső véghelyzetnek.

 sevo_jelalak.jpg

4_3. ábra: Tipikus jelalakok szervó motor vezérléséhez

Az Energia IDE hardware\msp430\libraries\Servo mappájában a Servo.h fejléc állomány makróinak módosításával szoftveresen korlátozhatjuk a minimális és maximális impulzusszélességet (erre azért van szükség, mert a szervó meghibásodhat, ha a gyártó által előírt határértékeket túllépjük!), az ismétlődési időt és a maximálisan kezelhető szervók számát.

  1. #define MIN_PULSE_WIDTH       544     // the shortest pulse sent to a servo [uS]
  2. #define MAX_PULSE_WIDTH      2400     // the longest pulse sent to a servo [uS]
  3. #define DEFAULT_PULSE_WIDTH  1500     // default pulse width when servo is attached
  4. #define REFRESH_INTERVAL    20000     // servos refresh period in microseconds
  5. #define MAX_SERVOS              8

Mintapélda: Servo Knob

Az alábbi mintapélda eredetije az Energia hardware\msp430\libraries\Servo\examples mappájában található. A lábkiosztást azonban megváltoztattam. A programban ciklikusan ismételve beolvassuk egy potméter állását, majd a Launchpad kártyához kötött szervót a potméter állásával arányos szögállásba állítjuk.

Hardver követelmények:

  • MSP430 Launchpad kártya
  • Egy 10 kΩ-os potméter, melynek csúszkáját az A4 analóg bemenetre (P1_4 láb) kötjük.
  • Szervó, amelyet a P1_5 digitális kimenet vezérel

A lábkiosztás természetesen megváltoztatható, de a programot ennek megfelelően módosítani kell.

 

servo_knob_schema.png

4_4. ábra: A Servo_Knob programban használt áramköri elrendezés

 

4_2. lista: A Servo_Knob program listája

  1. // Szervó vezérlése potenciométerrel
  2. // Szerző: Michal Rinott <http://people.interaction-ivrea.it/m.rinott>
  3.  
  4. #include
  5.  
  6. Servo myservo;                       // Szervó objektum példányosítása
  7. int potpin = 4;                      // A potmétert az A4 (P1.4) lábra kötjük
  8. int val;                             // Változó az analóg feszültség beolvasásához
  9.  
  10. void setup() {
  11.   myservo.attach(7);                 // A szervó vezérlése a 7. lábon (P1.5) történik
  12. }
  13.  
  14. void loop() {
  15.   val = analogRead(potpin);          // a potméter állásának beolvasása (0-1023)
  16.   val = map(val, 0, 1023, 0, 179);   // a kapott szám átskálázása a szervóhoz (0-180)
  17.   myservo.write(val);                // a szervó beállítása a fenti érték szerint
  18.   delay(100);                        // várunk, hogy a szervó beálljon
  19. }

 

Megjegyzés: Figyeljünk rá, hogy az analóg és a digitális lábszámozás nem konzisztens. A P1_4 láb analóg bemenetként 4-es sorszámú, de a szomszádos P1_5 láb már 7-es sorszámú lesz, mert digitális módban van, s ott a sorszám a fizikai lábszámmal egyezik meg!

A szervó kezelése három lépésből áll:

Példányosítjuk a Servo objektumot (a Servo myservo; deklarációval).

A setup() függvényben hozzárendelünk egy digitális kimenetet a szervóhoz (a myservo.attach(7); függvényhívással). A portlábat nem kell külön kimenetnek definiálnunk, azt megteszi helyettünk a meghívott függvény!

A loop() függvényben (végtelen ciklus) a myservo.write() függvényhívással beállítjuk a szervót vezérlő  impulzus szélességét. Ha MIN_PULSE_WIDTH és MAX_PULSE_WIDTH közé eső értéket adunk meg, akkor mikroszekundumban adhatjuk meg az impulzusszélességet. Ha pedig 0 - 180 közé eső értéket adunk meg, akkor fokokban adhatjuk meg a szervó beállítandó pozícióját.

A mintaprogramban a 10 bites ADC-vel mérjük meg a potméterrel leosztott feszültséget a VCC tápfeszültséghez képest, így a konverzió értéke 0- 1023 közötti szám lesz. Ezt átt kell skáláznunk a 0 - 180 közötti tartományra. Ehhez az y = map(x, minA, maxA, minB, maxB) függvényt használjuk, ahol x az átszámítandó érték, minA és maxA a bejövő érték alsó és felső határa, minB és maxB pedig az átszámított eredmény alsó és felső határa. Az átskálázás az alábbi képlettel írható fel:

y = minB + (x - minA) * (maxB - minB)/(maxA - minA)

 


A cikk még nem ért véget, lapozz!
Következő: »»   4 / 8
Értékeléshez bejelentkezés szükséges!
Bejelentkezés

Belépés

Hirdetés
XDT.hu
Az oldalon sütiket használunk a helyes működéshez. Bővebb információt az adatvédelmi szabályzatban olvashatsz. Megértettem