Wykorzystanie Raspberry Pi do detekcji obrazu i sterowania napędem
Wykorzystanie Raspberry Pi do detekcji obrazu i sterowania napędem
Przeglądając fora techniczne, można natrafić na różne publikacje prezentujące możliwości detekcji obrazu realizowane na platformie Raspberry Pi. Komunikacja pomiędzy maliną a sterownikami SIMATIC może być realizowana na wiele sposobów. Jednym z prostszych jest biblioteka Snap7. Postanowiłem przetestować jakość detekcji gestów dłoni w połączeniu ze sterowaniem funkcją EPOS napędu SINAMICS S210.
W moim minimalistycznym projekcie zastosowałem:
– odnaleziony w szufladzie mocno zakurzony i nie najnowszy model Raspberry Pi 3b + dedykowana kamera
– sterownik SIMATIC S7-1511F
– napęd servo SINAMICS S210 nowej generacji z FW 6.3 (obsługujący funkcjonalność prostego pozycjonera EPOS)
Projekt TIA V18 zawierający konfigurację oraz sterowanie napędem SINAMICS S210 w trybie EPOS zrealizowałem w jednym ze wcześniejszych wpisów – link.
Pierwszym etapem będzie skomunikowanie oraz wymiana danych pomiędzy Raspberry Pi a sterownikiem.
W tym celu posłużę się biblioteką Snap7 – link.
Dokładny proces instalacji biblioteki dla malinki znajdziemy pod tym linkiem.
Jedną z bardziej istotnych informacji związanych z konfiguracją Raspberry jest system operacyjny – pracuje na starszej wersji Raspbiana “Buster”, najnowsza wersja, czyli “Bullseye”, uniemożliwia instalację modułu OpenCV (detekcji obrazu).
Dodatkowo warto przenieść system maliny z karty SD na zewnętrzny dysk SSD – praca jest nieco szybsza.
W projekcie TIA tworzę nowy blok danych, dedykowany do obsługi komunikacji:
Po stworzeniu bloku danych i kompilacji projektu – pojawi się zakres przestrzeni adresowej w kolumnie “offset”.
W widoku właściwości bloku danych wyłączamy optymalizację:
Następnie łączymy zmienne bloku danych z sina_pos_tel112:
Przykładowy skrypt w języku Python 3.7:
#importuję bibliotekę snap7
import snap7
#nawiązanie komunikacji ze sterownikiem PLC - adres PN
plc = snap7.client.Client()
plc.connect('192.168.0.1', 0, 1)
#deklaracja odczytu danych z bloku DB
read = 0
#CTW - aktywacja słowa sterującego
CTW = 0
#wartość DEC - bitów słowa sterującego
cvalue = 0
#stop = 0
#enable = 1
#execute = 3
#jog1 = 5
#jog2 = 9
#ackF = 16
#c_mode - aktywacja sina_pos mode
c_mode = 0
#wybór trybu pracy:
mode = 0
#0 - no selection
#1 - relative
#2 - absolut
#7 - jog speed
#8 - jog relative
#5 - set home position
#setpoint - velocity, position, acceleration, deceleration, overspeed control
setpoint = 0
###############
velocity = 10
position = 100
acceleration = 100.0
deceleration = 100.0
overspeed = 100.0
#odczyt danych z bloku DB sterownika
if read == 1:
DB_snap7 = plc.db_read(3,0,22)
control = snap7.util.get_byte(DB_snap7,0)
velocity = snap7.util.get_real(DB_snap7,2)
position = snap7.util.get_real(DB_snap7,6)
acceleration = snap7.util.get_real(DB_snap7,10)
deceleration = snap7.util.get_real(DB_snap7,14)
overspeed = snap7.util.get_int(DB_snap7,18)
mode = snap7.util.get_int(DB_snap7,20)
print (control)
print (velocity)
print (position)
print (acceleration)
print (deceleration)
print (overspeed)
print (mode)
#sterowanie
if CTW == 1:
#enable = 1
#execute = 3
#jog1 = 5
#jog2 = 9
#ackF = 16
control = plc.db_read(3,0,2)
snap7.util.set_byte(control,0,cvalue)
print (control)
plc.db_write(3,0,control)
#wybór trybu pracy
if c_mode == 1:
#mode of operation:
#1 - relative
#2 - absolut
#7 - jog speed
#8 - jog relative
#5 - set home position
#mode = 7
mode_plc = plc.db_read(3,20,2)
snap7.util.set_int(mode_plc,0,mode)
print (mode_plc)
plc.db_write(3,20,mode_plc)
#deklaracja wartości zadanej dla profilu ruchu
if setpoint == 1:
values = plc.db_read(3,2,18)
snap7.util.set_real(values,0,velocity)
snap7.util.set_real(values,4,position)
snap7.util.set_real(values,8,acceleration)
snap7.util.set_real(values,12,deceleration)
snap7.util.set_int(values,16,overspeed)
print (values)
plc.db_write(3,2,values) Dla funkcji plc.db.read oraz plc.db.write deklarujemy argumenty związane z numerem bloku danych oraz zakresem odczytywanych/modyfikowanych danych.
Pierwszym argumentem funkcji jest numer bloku danych – w moim przypadku jest to blok DB3.
Następnie deklarujemy zakres danych podając liczbę bajtów.
Polecenia snap7.util.set/get_(typ zmiennej –> bool, byte, real, int) konwertuje odczytane bajty do odpowiedniego formatu.
Wprowadziłem własne zmienne w postaci CTW oraz c_mode
Zmienna CTW – control word steruje tagami wejściowymi bloku sina_pos takimi jak:
– załączenie napędu (enable),
– wykonanie operacji bazowania lub przejazdu absolutnego/relatywnego (execute),
– funkcjami JOG 1 oraz 2,
– kwitowaniem błędów napędu ackF,
– przejazdem
Zmienna c_mode definiuje tryb pracy sina_pos – mode:
– przejazd relatywny,
– przejazd absolutny,
– JOG w trybie relatywnym,
– JOG w trybie
Jeżeli chcemy modyfikować wartość zadaną prędkości, pozycję lub dynamikę profilu ruchu, ustawiamy zmienną “setpoint”=1, następnie deklarujemy odpowiednie parametry(velocity, position, acceleration, deceleration oraz overspeed).
Kolejnym krokiem jest instalacja modułu OpenCV oraz MediaPipe.
Pełen opis wraz z przykładowymi projektami detekcji można znaleźć na stronie link.
Najważniejsze pytanie – jak to działa?
Moja malinka ma już swoje lata co uwidacznia się podczas procesu instalacji pakietów programowych, kompilacji a następnie obsługi. Działanie jest po prostu wolne.
Układ działa, ale detekcja jest niestabilna mocno opóźniona względem czasu rzeczywistego. Przejście na nową generację RP prawdopodobnie poprawi sytuację.
W celu odcięcia się od ograniczeń sprzętowych, koncepcję przeniosłem się na stację PC z zainstalowanym systemem Ubuntu.
Po takiej modyfikacji działanie systemu jest płynne a jakość detekcji więcej niż zadawalająca.
Porównanie implementacji Raspberry PI vs Ubuntu poniżej.
Zastosowanie prostego mikrokomputera jakim jest Raspberry Pi oferuje sporo nowych możliwości, których implementacja nie jest specjalnie trudna. Zastosowań może być tu naprawdę wiele – od gromadzenia danych, wizualizacji, dostępu zdalnego, po detekcję obrazu.