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).

Serwomechanizm o pracy ciągłej

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
Ja podłączyłem kontroler do pinów X2, X3, X4 oraz X5, więc klasę używam tak:
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()).

Silnik krokowy

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:

Pololu DRV8833

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):

Silnik DC

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()
Przekaźnik półprzewodnikowy LAA110

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()
Zestaw zdalnego sterowania XD-YK04

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()
Czujnik zbliżeniowy

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.

Ultradźwiękowy czujnik odległości

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.

BlinkM

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:])
MinipH i PyBoard
RkBlog

Elektronika i Python, 27 September 2014

Comment article
Comment article RkBlog main page Search RSS Contact