Raspberry_Pi_13.pdf

(881 KB) Pobierz
Na warsztacie
SZKOŁA
Poziom tekstu: średnio trudny
To już 13-ty odcinek kursu Raspberry Pi. Numery archiwalne MT
z poprzednimi odcinkami można kupić na www.ulubionykiosk.pl
Raspberry Pi (13)
PWM dla serw
Sterowanie niektórymi elementami elektronicznymi wymaga wygenerowania
serii impulsów o specyficznym wyglądzie. Kształt przebiegu, jego częstotliwość,
stosunek stanu wysokiego do niskiego – wszystkie te parametry muszą być
odpowiednio dobrane, aby uzyskać pożądaną reakcję. Jakość generowanych
impulsów (regularność, dokładność) stanowi o stabilności odpowiedzi.
W dzisiejszym odcinku zajmiemy się modulacją szerokości impulsów
– czyli PWM (ang.
Pulse Width Modulation).
Zrozumienie jej pozwoli Wam
na sterowanie m.in. serwami modelarskimi.
Modulacja szerokości impulsu PWM jest jedną
z podstawowych metod sterowania elementami
elektronicznymi. Stosuje się ją do kontrolowania
serw modelarskich, silników czy taśm LED. W prak-
tyce sprowadza się do wygenerowania prostokątne-
go przebiegu elektrycznego o stałej częstotliwości
i amplitudzie. Częstotliwość to liczba powtórzeń,
cykli w danej jednostce czasu. W układzie SI jej
jednostką jest herc – w skrócie Hz (mnożniki to np.
1000 Hz = 1 kiloherc, 1 kHz; 1 MHz = 1000 kHz,
1 megaherc). Układ pracuje z częstotliwością 1 Hz,
jeżeli w czasie 1 s pojawia się jeden cykl. Zauważcie,
że przy częstotliwości 50 Hz, 1 cykl trwa 20 ms (tzn.
w ciągu sekundy występuje 50 cykli). Dla PWM stała
jest też amplituda, czyli różnica między poziomem
odniesienia i wartościami szczytowymi. W praktyce
taki sygnał sterujący zmienia się między poziomem
„0” – masą – a napięciem zasilania lub takim, które
komunikujące układy interpretują jako logiczną „1”
– np. ok. 3,3 V dla Raspberry (ilustracja 1; [1]).
Skoro te dwie wielkości – częstotliwość i amplitu-
da – mają pozostawać stałe, to co możemy zmieniać?
Sterowanie odbywa się za pomocą tzw. stopnia wy-
pełnienia impulsu. Stopień wypełnienia jest stosun-
kiem czasu trwania sygnału wysokiego do długości
cyklu. Jeżeli cykl ma długość 20 ms (50 Hz), z czego
sygnał wysoki trwa 10 ms (a niski przez kolejne
10 ms) – mówimy o wypełnieniu na poziomie 50%.
Przy takiej częstotliwości 1 ms sygnał wysoki to 5%
wypełnienia, 1,5 ms – 7,5%, a 2 ms – 10% (wrócimy
do tych wartości za chwilę).
Serwa modelarskie (analogowe)
1. PWM: częstotliwość, amplituda i stopień wypeł-
nienia
Analogowe serwa modelarskie zawierają niewielki
silniczek elektryczny z przekładnią. Przekładnia ma
za zadanie zwiększenie momentu obrotowego. Wał
silnika obraca potencjometrem. Pozwala to wbudo-
wanemu układowi sterującemu stwierdzić, w jakiej
pozycji się znajduje i, uruchamiając silnik, zmieniać
ją do zadanej przez użytkownika. Serwa mają trzy
wyprowadzenia: masę (kabelek o kolorze czarnym
lub brązowym), zasilanie (najczęściej w grani-
cach 4,8-6 V, kabelek czerwony – środkowy) oraz
sterowanie (kabelek biały lub pomarańczowy; zob.
ilustracja 2).
Położenie ramienia serwa zmienia się, podając
odpowiedni sygnał PWM. W zależności od parame-
trów sygnału, serwo może obracać się w lewo/prawo,
ustawić w jedną z ustalonych pozycji skrajnych
lub w neutralną. Pozycje skrajne to 0 i 180 stopni
– ograniczone przez odpowiednie blokady. Pozycja
neutralna to 90 stopni. Jeżeli sygnał się nie zmienia
(lub przestanie być dostarczany) – serwo pozostaje
nieruchome.
86
m.technik – www.mt.com.pl – nr 8/2015
Serwa oczekują sygnału PWM
o częstotliwości 50 Hz (czyli cyklu
o długości 20 ms). Układ sterujący
próbkuje długość stanu wysokie-
go. Może ona przyjmować pewne
charakterystyczne wartości, które
układ sterujący zinterpretuje jako
(ilustracja 3):
1 ms: ustaw serwo w pozycji skraj-
nej 0 stopni;
1,5 ms: ustaw serwo w pozycji
neutralnej (90 stopni);
2 ms: ustaw serwo w pozycji skraj-
nej 180 stopni.
Wielkości te mogą różnić się
dla poszczególnych modeli serw.
Szczegółowe dane na ten temat znaj-
2. Typowe serwa modelarskie: TowerPro Sg90, Redox S90 (9g) i To-
dziecie na stronie
www.servodata-
werPro SG5010 (36g)
base.com/servos/all.
Dane zebrane
doświadczalnie dla kilku wybranych
Tabela 1. Zmierzone czasy trwania sygnału wysokiego, wymuszają-
serw przedstawiłem w tabeli 1.
ce ustawienie serwa w pozycji 0, 90 i 180 stopni, dla 50 Hz
Można również zauważyć, że ser-
wo ustawi się w pozycji normalnej,
Serwo
Pozycja Pozy- Pozycja
Obrót
Obrót
dostając sygnał 1,5 ms co 10 ms (czyli
neutral- cja 0
180
w lewo
w prawo
wypełnienie 1,5 ms z 10 ms = 15%),
na [ms]
[ms]
[ms]
ale i co 40 ms (czyli wypełnienie
TowerPro SG5010 (36g) 1,5
0,600 2,5
między
między
1,5 ms z 40 ms = 3%). W tym sensie
pozycją 0
pozycją
TowerPro SG90 (9g)
1,5
0,600 2,5
nie jest to więc klasyczny PWM,
i neutralną neutralną
Redox S90 (9g)
1,4
0,600 2.2
gdzie steruje się stopniem wypełnie-
i 180
nia jako stosunkiem czasu trwania
sygnału wysokiego do okresu. Dla odróżnienia tych
dwóch sposobów sterowania dla serw używa się na-
wet terminu RC-PWM – chociaż w większości źródeł
PWM i RC-PWM są błędnie utożsamiane.
Trochę inną kategorię stanowią serwa tzw. 360
stopni. Nie mają one ograniczników i dzięki
temu mogą się kręcić „w kółko”. Sygnał sterujący
neutralny (np. 1,5 ms) zatrzymuje serwo. Impulsy
dłuższe lub krótsze niż neutralny zmieniają kie-
runek obrotów (lewo/prawo). Serwa tego typu sta-
nowią bardzo atrakcyjną alternatywę dla silników
DC (prądu stałego). Często używam ich do napę-
dzania robotów mobilnych. Na rynku znajdziecie
całkiem pokaźną ofertę modeli o różnych para-
metrach i rozmiarach, w cenach od 18 zł/sztukę
(ilustracja 4).
Zamiast kupować gotowe serwo 360, możecie
również sami zmodyfikować standardowe serwo.
Jest kilka sposobów, żeby to osiągnąć. Najczęściej
polegają one na usunięciu ograniczników i odłą-
czeniu potencjometru (ilustracja 5). W jego miej-
sce wlutowuje się dwa rezystory. Przykład modyfi-
kacji znajdziecie w [2].
Uwaga:
takie modyfikacje
oznaczają jednak utratę gwarancji i wykonujecie je
na własną odpowiedzialność. Wymagają też trochę
wprawy – są bardzo duże szanse, że pierwsza pró-
ba skończy się kompletnym zniszczeniem serwa.
Serwa 360 stopni
3. Ustawienie ramienia serwa w zależności od wy-
pełnienia sygnału
4. Serwo 360: Feetech FS90R (9g)
87
Na warsztacie
W zależności od sposobu modyfikacji zazwyczaj
dalej będziecie mogli sterować za pomocą sygnału
PWM. Często jednak występują problemy z pozycją
neutralną (czyli stop), a zakres wartości wypełnie-
nia impulsu w tej pozycji ma znacząco mniejszą
tolerancję. O ile Feetech FS90R jest nieruchome dla
zakresu 1,43-1,51 ms – przerobione przeze mnie
TowerProSG90 już jedynie 1,57-1,58 ms (długość
sygnału wysokiego).
SZKOŁA
Poziom tekstu: średnio trudny
Generowanie sygnału PWM
W warunkach laboratoryjnych do generacji takich
sygnałów można stosować urządzenia zwane
ge-
neratorami sygnału
(ilustracja 6). Są to narzędzia,
które mogą wygenerować sygnały o bardzo różnych
kształtach (prostokątny, sinusoidalny), zadanej
częstotliwości, amplitudzie, przesunięciu, stopniu
wypełnienia sygnału i innych parametrach (jak np.
czas narastania). Odpowiednio dobierając parametry,
możecie precyzyjnie wyznaczyć np. graniczne warto-
ści wypełnienia sygnału dla różnych pozycji serwa.
Niestety, są to urządzenia dość kosztowne
(od 1 tys. zł). Tańszą alternatywę stanowią generatory
w postaci płytek, np. w oparciu o projekt AVR DDS
(ilustracja 7, zob [3]).
Na szczęście, do takiej pracy można również użyć
Raspberry Pi. Wygenerowanie PWM o odpowiednich
parametrach pozwoli mu na sterowanie różnymi
urządzeniami.
5. Rozmontowane TowerPro SG90 – usunięte poten-
cjometr i ograniczniki
PWM z Raspberry: Python i RPi.GPIO
Skoro PWM jest sygnałem prostokątnym, wygenero-
wanie go za pomocą GPIO Raspberry nie powinno
być większym problemem. Wydaje się, że można go
uzyskać, odpowiednio zmieniając stan wybranego
pinu między wysokim a niskim. Metoda ta nazywana
jest
bit-banging.
Spróbujmy wygenerować PWM za
pomocą prostego programu w Pythonie z użyciem
biblioteki RPi.GPIO (dostarczanej razem z ostatnimi
wersjami Raspbiana):
$ nano test_bang.py
import RPi.GPIO as GPIO
import time
#Sygnal ma byc wygenerowany na GPIO17,
#fizyczny pin 11
PWM_PIN = 17
#Stan wysoki: 2ms, cykl: 20ms
PWM_UP = 2.
PWM_FRQ = 20.
#ustawiamy wyjscia
GPIO.setmode(GPIO.BCM)
GPIO.setup(PWM_PIN, GPIO.OUT)
print „Generuje... (przycisnij
[CTRL]+[C] zeby skonczyc)”
try:
while True:
#Pin ustawiamy w stan
wysoki
6. Badanie zakresów serwa za pomocą generatora
Siglent SDG810
7. Prosty generator sygnałów w oparciu o projekt
AVR DDS
88
m.technik – www.mt.com.pl – nr 8/2015
GPIO.HIGH)
GPIO.output(PWM_PIN,
#Czekamy 2ms; instruk-
cja sleep pobiera czas w [s] – stad
dzielenie
time.sleep(PWM_UP/1000.)
#Pin ustawiamy w stan
niski
GPIO.output(PWM_PIN,
GPIO.LOW)
#Czekamy 20-2ms
time.sleep((PWM_FRQ
- PWM_UP)/1000.)
#Elegancko konczymy po wcisnieciu
[CTRL]+[C]
except KeyboardInterrupt:
GPIO.cleanup()
print “Koniec.”
Uruchomcie skrypt:
$ sudo python test_bang.py
Powyższy kod zmienia sygnał na pinie GPIO17
(fizyczny pin 11) zgodnie z parametrami zadanymi
w zmiennych PWM_UP i PWM_FRQ. Sprawdźmy
na oscyloskopie efekty jego działania (ilustracja
8).
Niestety, w praktyce metoda – choć tak łatwa
i przejrzysta – nie da zadowalających rezulta-
tów. Zajęty poważniejszymi zadaniami, procesor
Raspberry zepchnie wykonanie poleceń naszego
skryptu na dalszy plan. W rezultacie generacja sy-
gnału może zostać poważnie zakłócona. Sprawdźcie
to sami. Stwórzcie drugi skrypt, który trochę zajmie
procesor:
$ nano work_me.py
from random import randint
while True:
z = randint(1,2000)
print z
Uruchomcie teraz obydwa skrypty:
$ sudo python work_me.py &
$ sudo python test_bang.py
Nawet odrobinę obciążony procesor spowoduje,
że otrzymacie sygnał o znacznie mniejszej regular-
ności. Długość impulsu wysokiego w niektórych
momentach może nawet przekroczyć 10 ms (ilustra-
cja 9).
Wyobraźcie sobie, jak będzie on wyglądał,
gdy dodatkowo uruchomicie inne aplikacje czy np.
środowisko graficzne.
9. Generowany programowo sygnał PWM
z Raspberry może ulec zakłóceniu
Oczywiście nie zawsze musi to być wielki pro-
blem. W niektórych zastosowaniach takie zakłócenia
nie wpłyną znacząco na sterowany obiekt. Jeżeli
jednak potrzebujecie precyzyjnego sygnału, jak przy
sterowaniu serwami, efekty tych niedokładności
mogą być bardzo dokuczliwe.
Spójrzmy jeszcze dokładniej na samą bibliotekę
RPi.GPIO. Oferuje ona bardziej „elegancki” sposób
generowania PWM poprzez klasę GPIO.PWM:
import RPi.GPIO as GPIO
import time
#Tym razem na pinie GPIO18, fizyczny 12
PWM_PIN = 18
#Korzystamy ze schematu BCM, ustawiamy
pin jako wyjscie
GPIO.setmode(GPIO.BCM)
GPIO.setup(PWM_PIN, GPIO.OUT)
#Tworzymy obiekt klasy PWM; ustawiamy
50Hz (co 20ms)
pwm = GPIO.PWM(PWM_PIN, 50)
#Inicjalizacja, wypelnienie 10% czyli
2ms (20ms/dc)
pwm.start(10)
print „Generuje... (przycisnij
[CTRL]+[C] zeby skonczyc)”
try:
while 1:
pass
except KeyboardInterrupt:
pwm.stop()
GPIO.cleanup()
print „Koniec.”
Ten program (podobnie jak poprzedni) będzie
generował impulsy do momentu, gdy nie wciśniecie
[CTRL]+[C]. Niestety, nie rozwiązuje on podstawo-
wego problemu stabilności sygnału PWM. Zgodnie
z notatkami na stronie projektu
https://pypi.python.
org/pypi/RPi.GPIO
– although
hardware PWM is
not available yet, software PWM is available to use
on all channels.
Dowiadujemy się, że PWM możemy
używać na dowolnym, wybranym pinie. Czym jest
jednak owo brakujące
hardware PWM?
Sprzętowe generowanie sygnału PWM pole-
ga na wykorzystaniu pewnych właściwości sa-
mego sprzętu (ang.
hardware)
do generowania
8. Sygnał PWM wygenerowany za pomocą Pythona
89
Na warsztacie
odpowiednich impulsów. W odróżnieniu od reali-
zacji opartych wyłącznie na oprogramowaniu, ten
sposób nie obciąża samego procesora, jest reali-
zowany przez dodatkowe układy. Nie będzie więc
zakłócany działaniem systemu operacyjnego. Jak się
zorientowaliście, RPi.GPIO nie oferuje takiej opcji.
Ale są biblioteki, dla których nie jest to problemem.
Oczywiście wymaga to pewnych dodatkowych
zabiegów.
}else{
pwmWrite (18, 500);
SZKOŁA
Lepsze PWM: wiringPi2 i C
Poziom tekstu: średnio trudny
Powyższe przykłady opierały się na generowaniu
PWM za pomocą oprogramowania. SoC napędzający
Raspberry Pi model A/B ma również dwa sprzętowe
generatory PWM, z których jeden – PWM0 – można
podłączyć do GPIO18 (fizyczny pin 12). Generator
ten jest również używany do tworzenia dźwięku
na wyjściu 3,5 mm audio.
Sprzętowe generowanie PWM może być wykorzy-
stane za pomocą popularnej biblioteki
wiringPi.
Jej
autorem jest Gordon „Drogon” Henderson. Instalacja
wymaga ściągnięcia i przekompilowania kodu źró-
dłowego z github’a:
$ git clone git://git.drogon.net/
wiringPi
$ cd wiringPi
$ sudo ./build
Biblioteka jest dostarczana z zestawem poręcznych
narzędzi wywoływanych z linii komend:
$ gpio -v
gpio version: 2.26
Copyright (c) 2012-2015 Gordon
Henderson
This is free software with ABSOLUTELY
NO WARRANTY.
...
$ gpio readall
...
Możecie również zainstalować dodatki pozwalają-
ce używać jej z poziomu Pythona (wymaga rozszerze-
nia pip):
$ sudo apt-get install python-dev
python-pip
$ sudo pip install wiringpi2
Napiszmy teraz program w C. Sygnał sterujący wy-
generujemy na GPIO18 (fizyczny pin 12) – to właśnie
na niego można przełączyć wewnętrzny generator
PWM:
$ nano pwm.c
#include <wiringPi.h>
int main (void){
if (wiringPiSetupGpio() != -1){
pinMode(18,PWM_OUTPUT);
//Wyjasnienia ponizej
pwmSetMode(PWM_MODE_MS);
pwmSetRange (1000);
pwmSetClock(384);
}
Zwróćcie uwagę na kilka szczegółów ([3]):
instrukcja
pwmSetMode()
ustawia tryb pracy ge-
neratora w bardziej przewidywalny i niezależny
od wypełnienia „mark:space”;
instrukcja
wiringPiSetupGpio()
inicjuje bibliotekę
wiringPi2.
Zakłada ona, że piny będą adresowane
jak dla BCM (GPIOxx). Możecie również zasto-
sować funkcję
wiringPiSetupPhys(),
ale wtedy
używajcie numerów fizycznych pinów w złączu
GPIO (np. 3,3v to 1, GND to 6). Kolejna funkcja
wiringPiSetup()
wymusza posługiwanie się nu-
meracją specyficzną dla tej biblioteki – innej niż
BCM i fizyczna. Upewnijcie się, której numeracji
chcecie używać;
instrukcja
pwmSetRange()
ustala liczbę prze-
działów w jednym cyklu; dla wygody programo-
wania wybrałem 1000 przedziałów. Dla 50 Hz
(cykl 20 ms) oznacza to, że każdy przedział
będzie miał szerokość 20 uS (mikrosekund
– 20 ms/1000). Przykładowy 1,5 ms sygnał wy-
maga więc 75 przedziałów (1,5 ms = 75*20 us)
– stąd
pwmWrite(18,75) – „18”
to numer GPIO.
Żeby zapewnić taką rozdzielczość, generator
układu PWM musi działać z częstotliwością
1/0.02 = 50 kHz;
instrukcja
pwmSetClock()
określa dzielnik
częstotliwości generatora PWM; dla Raspberry
działa on z częstotliwością 19,2 MHz; żeby
uzyskać 50 kHz, musimy podzielić ją na 384
(19,2 MHz/384 = 50 kHz);
Nasz nowy kod trzeba teraz skompilować i można
go uruchomić:
$ gcc -L/usr/local/lib pwm.c -lwi-
ringPi -lm -o pwm
$ sudo ./pwm
Taki sygnał będzie stabilny, ponieważ pochodzi
z przeznaczonego do tego układu. Oczywiście jeden
sprzętowy PWM to raczej niewiele. Nowsze modele A+
/B+/Pi 2 mogą wyprowadzić dodatkowy PWM1 na piny
GPIO13 i jego kopię na GPIO19 (fizyczne 33 i 35 z roz-
szerzonego zestawu). Oprócz GPIO18, kopię sygnału
PWM0 znajdziecie na GPIO12 – fizycznym pinie 32.
$ nano pwm2.c
#include <wiringPi.h>
int main (void)
{
if (wiringPiSetupGpio() != -1)
pinMode(18,
pinMode(19,
return 1;
}
return 0;
{
PWM_OUTPUT);
PWM_OUTPUT);
90
m.technik – www.mt.com.pl – nr 8/2015
Zgłoś jeśli naruszono regulamin