PyBoard i MicroPython w przykładach - skryptujemy elektronikę
Kontynuujemy naszą przygodę z PyBoard i MicroPythonem. W tym artykule pokażę jak skryptować różne części elektroniczne i elektryczne jak serwa, silniki, przekaźniki, urządzenia z interfejsem I2C i inne.
Zaprezentowane poniżej klasy dostępne są też w repozytorium na githubie.
Serwo o pracy ciągłej
Większość serwomechanizmów posiada ograniczony zakres ruchu, np. 180 stopni. Są też jednak serwomechanizmy o pracy ciągłej. Modulacja impulsowa mówi
serwomechanizmowi jak szybko i w którym kierunku ma się poruszać (a nie na jaką pozycję).
Podłączając serwo o pracy ciągłej do pyboard tak jak w poprzednim artykule wykorzystujemy klasę Servo by sterować serwem, np.:
import pyb
servo = pyb.Servo(1)
servo.speed(10)
Metoda speed nie ustawia kąta jak metoda angle, ale wpływa na prędkość poruszania się silnika w serwomechanizmie (-100 do 100).

Silnik krokowy
Sterownik silników krokowych ULN2003 posiada cztery piny do kontroli pracy silnika. Żeby przesunąć silnik o jeden krok należy ustawić odpowiednie piny w stan wysoki (kolejny zestaw pinów z sekwencji np. 8 kroków). Inne kontrolery mogą nieco się różnić np. sekwencją, ale ogólna zasada jest taka sama.
W przypadku MicroPythona i pyboard do dyspozycji mamy wiele pinów i wystarczy podłączyć kontroler silników do czterech z nich i skonfigurować te piny jako cyfrowe wyjście, po czym można ustawiać je w stan wysoki i niski. Oto klasa obsługująca cały proces:
import pyb
class Stepper:
"""
Handles common 4-pin ULN2003 stepper motor controllers
"""
steps = [
[1],
[1, 2],
[2],
[2, 3],
[3],
[3, 4],
[4],
[1, 4]
]
step_delay_ms = 5
def __init__(self, pins):
self.pins = [pyb.Pin(pin, pyb.Pin.OUT_PP) for pin in pins]
self.current_step = 0
def do_step(self):
self._low_on_all()
self._high_on_step_pins()
self._record_step()
pyb.delay(self.step_delay_ms)
def _low_on_all(self):
for pin in self.pins:
pin.low()
def _high_on_step_pins(self):
high_pins = self.steps[self.current_step]
for pin_number in high_pins:
self.pins[pin_number - 1].high()
def _record_step(self):
self.current_step += 1
if self.current_step == len(self.steps):
self.current_step = 0
from stepper_motor import *
motor = Stepper(['X2', 'X3', 'X4', 'X5'])
for _ in range(2000):
motor.do_step()
Metoda do_step wykonuje całą pracę. Ustawia piny w stan niski, a później ustawia w stan wysoki piny obecnego kroku i przekręca licznik kroków. W konstruktorze piny podane jako lista łańcuchów zamieniane są na listę obiektów - pinów skonfigurowanych jako cyfrowe wyjście. Po odpaleniu pętli silnik wykona 2000 kroków. Żeby silnik działał w przeciwnym kierunku należy odwrócić kolejność kroków (motor.steps.reverse()).

Silniki DC
Do sterowania prędkością i kierunkiem obrotu silnika DC stosuje się układy z mostkiem H. W najprostszej postaci będzie to mała płytka z przylutowanym scalakiem. Do testów użyłem płytki ze sterownikiem DRV8833, który wcześniej testowałem z PyMCU. Schemat płytki wygląda następująco:

Po jednej stronie podłączamy GND oraz dwa piny PWM, po drugiej zasilanie silnika oraz sam silnik (4 piny). Jako że do testów użyłem mały silniczek o małej mocy zasilanie szło z pinów 5V pyboard (a GND było wspólne):

Jeżeli pin X1 (Servo 1) jest podłączony jako BIN1, to wystarczy ustawić długość impulsu by kontrolować prędkość obrotów, np:
s = pyb.Servo(1)
s.pulse_width(2500)
...
s.pulse_width(0)
W moim przypadku znaczenie miały wartości między 2000 a 2600. Przy niższych silnik nadal się obracał, ale bardzo powoli. Klasa Servo jak na razie nie pozwala wyłączyć
modulacji. Żeby wymusić wyłączenie pinu należy wykonać:
pyb.Pin('X1', pyb.Pin.OUT_PP).low()
W nowszej wersji firmware pyboard klasa Timer ma dostęp do czystego PWM co powinno pozwolić sterować modulacją aż do zera.
Przekaźniki
Przekaźniki to podstawa automatyzacji. Mogą włączać lub wyłączać zasilanie urządzeń, w tym tych zasilanych z sieci 230V. Na rynku dostępnych jest wiele przekaźników cewkowych, w tym na ładnych i poręcznych płytkach. Oznaczone są jako kompatybilne z Arduino
i do pracy wymagają 5V (czasami 12V). Wiele płytek Arduino stosuje właśnie 5V na pinach, dzięki czemu mogą przełączać 5V przekaźniki. Pyboard jak i Raspberry Pi używają 3.3V na pinach GPIO. Mimo 5V zasilania nie udało mi się przełączyć przekaźnika na płytce z wydzielonym zasilaniem cewki. Dioda LED zapala się, ale cewka nie przełącza zasilania. Jeżeli uda Ci się znaleźć płytkę kompatybilną z 3.3V na pinach sterujących to powinno działać. Jak nie - trzeba przełączać 5V poprzez np. tranzystor.
Płytka z przekaźnikie, którą użyłem do testów posiada cztery piny: dwa na zasilanie i dwa na sterowanie (jeden musi być w stanie niski, drugi w wysokim). Przełączenie przekaźnika z poziomu pyboard jest proste, np:
pin_high = pyb.Pin('X2', pyb.Pin.OUT_PP)
pin_low = pyb.Pin('X3', pyb.Pin.OUT_PP)
pin_low.low()
pin_high.high()
Bezproblemowo powinno działać przełączanie przełączników półprzewodnikowych, czy przekaźników SSR (o ile obsługują niskie napięcia sterowania, co w ich przypadku jest raczej dość powszechne).
Przekaźnik półprzewodnikowy LAA110
Z tym przekaźnikiem sterowałem kamerką cyfrowo przyciskając przyciski w jakie została wyposażona.
Pyboard radzi sobie z tym przekaźnikiem bez problemów. Wystarczy ustawić pin w stan wysoki i kontrolowany obwód zostanie zamknięty. Od strony mikrokontrolera potrzebujemy pinu cyfrowego (np. X1) oraz GND. Od strony kontrolowanej jakiś układ, który zostanie zamknięty gdy pin ustawimy na stan wysoki.
p = pyb.Pin('X1', pyb.Pin.OUT_PP)
p.high()

Zdalnie sterowany moduł XD-YK04
W chińskich sklepach (jak i polskich) coraz częściej można spotkać zestawy pilot + płytka z odbiornikiem. Prosty gotowy zestaw do automatyzacji. W zależności od zestawu pilot może ustawiać piny w stan wysoki albo przełączać przekaźnik. Omawiany model robi to pierwsze. Na pilocie ma cztery przyciski, które po wciśnięciu ustawiają w stan wysoki jeden z czterech pinów cyfrowych na płytce. Żeby pin spadł do wartości niskiej trzeba... wcisnąć inny przycisk. Pomocny może być pin VT, który jest w stanie wysokim tylko wtedy, gdy wciśnięty jest jakiś przycisk.
Zestaw z przekaźnikami może działać nawet i bez mikrokontrolera. Zestaw taki jak ten musi współpracować z innym układem, który wykorzysta informację o zmianie stanu pinów. Jeżeli podłączymy wyjście D0 do pinu X1 na pyboard to odczytanie stanu jest bardzo proste:
x = pyb.Pin('X1', pyb.Pin.IN)
x.value()

Czujnik zbliżeniowy
Tak samo odczytamy stan czujnika zbliżeniowego, którego stan przejdzie w stan niski jeżeli będzie dostatecznie blisko przeszkody. Czerwony pin to VCC, zielony to GND a żółty to pin sygnałowy, którego stan musimy odczytać:
x = pyb.Pin('X1', pyb.Pin.IN)
x.value()

Ultradźwiękowy czujnik odległości
Czujniki odległości tego typu popularne są w robotyce. Służą do wykrywania i omijania przeszkód (choć można też stosować prostsze czujniki zbliżeniowe). Czujniki ultradźwiękowe wysyłają impuls i nasłuchują kiedy powróci. Im więcej czasu upłynie do powrotu echa tym większą odległość impuls przebył.
Dla MicroPythona mamy już gotową bibliotekę. Wystarczy zaimportować klasę, podać w konstruktorze nazwy pinów podłączonych do pinów Trig
i Echo
i gotowe. Metoda distance_in_cm dokona pomiaru i zwróci wynik.

BlinkM - sterowanie diodą LED po I2C
Pisałem o BlinkM wcześniej przy okazji PyMCU. Prosty układ pozwalający sterować wielokolorową diodą LED poprzez I2C. Czasami bywa oporna w użyciu, ale pozwala sprawdzić działanie komunikacji I2C.
Do komunikacji poprzez I2C wykorzystywane są dwa piny. Na pyboard są dwa interfejsy I2C po bokach płytki SDA1/SCL1 i SDA2/SCL2. W zależności gdzie podepniemy BlinkM lub inne urządzenie używające tego samego mechanizmu komunikacji trzeba aktywować odpowiedni interfejs 1 lub 2. Klasa I2C ma przydatną metodę scan, która wykrywa urządzenia oraz is_ready pozwalającą sprawdzić czy urządzenie jest już gotowe.
W przypadku BlinkM możemy nieco pobawić się kolorami:
from pyb import I2C
i2c = I2C(2, I2C.MASTER)
i2c.send('c x00 0x00 0xff', 0x09)
0x09 to domyślny adres BlinkM, a dane które wysyłamy to według dokumentacji zaświecić jasnoniebiesko
.

Pehametr MinipH
Kolejnym urządzeniem wykorzystującym komunikację po I2C jest pehametr minipH. Tak jak w przypadku pyMCU obsługa jest dość prosta. Trzeba odczytać dwa bajty. Pierwszy to cyfra przed, a drugi to cyfra po przecinku pomiaru (np. 4,15):
from pyb import I2C
i2c = I2C(2, I2C.MASTER)
ord(i2c.recv(2, 0x4D)[0:1])
ord(i2c.recv(2, 0x4D)[1:])

Comment article