Maszyna do automatycznego nalewania cieczy
Transkrypt
Maszyna do automatycznego nalewania cieczy
Łukasz Godziejewski MARM Projekt Temat: Maszyna do automatycznego nalewania cieczy. Opis ogólny Projekt zakładka stworzenie oprogramowania do maszyny nalewającej ciecz w dowolnej kombinacji ośmiu możliwych miejsc naczyń. Po wciśnięciu przycisku Start przez użytkownika, urządzenie automatycznie wykrywa w których z ośmiu miejsc znajdują się naczynia – dojeżdża do właściwych pozycji oraz wypełnia naczynie dostarczoną cieczą. Opis mechaniki Urządzenie posiada pompę z której poprowadzona jest silikonowa rurka do kranika. Kranik umieszczony jest na karetce prowadnicy liniowej, umiejscowionej równolegle do płytki z czujnikami. Prowadnica liniowa sterowana jest silnikiem DC z enkoderem, umożliwiającym określenie pozycji karetki prowadnicy. Na początku prowadnicy znajduje się krańcówka, dzięki której wiadome jest czy karetka znajduje się w pozycji początkowej. Na górze urządzenia znajduje się wyświetlacz wraz z dwoma przyciskami oraz przycisk z enkoderem obrotowym. Opis elektroniki Przednia płytka składa się z ośmiu czujników odległości – są to czujniki optyczne APDS-9130 z zintegrowanym układem do obróbki sygnału analogowego. Posiadają interfejs 𝐼 2 𝐶, korzystając z którego można odczytać cyfrowe wartości pomiarów w zakresie 0 − 1023. Jako że czujniki nie posiadają możliwości konfiguracji adresu 𝐼 2 𝐶 poprzez ustawienia pinów (mają fabrycznie wgrany adres) – skorzystano dodatkowo z ośmiokanałowego układu typu 𝐼 2 𝐶 𝑀𝑢𝑥, dzięki któremu możliwa jest komunikacja z każdym czujnikiem osobno. Ponadto, na przedniej płytce znajduje się osiem diod RGB, których barwy są sterowane trzema kanałami PWM. Diody są włączane i wyłączane ośmiokanałowym układem typu LED Driver, który umożliwia komunikację z głównym mikrokontrolerem poprzez interfejs 𝐼 2 𝐶. Główna płytka PCB zawiera mikrokontroler sterujący urządzeniem oraz niektóre peryferia. Można na niej znaleźć np. dwa sterowniki silników (𝐼 2 𝐶) – jeden do silnika prowadnicy liniowej, drugi do pompy. Poza tym są wyjścia do pozostałych urządzeń peryferyjnych w postaci gniazd wystawiających sygnały 𝑆𝑃𝐼, 𝐼 2 𝐶, 𝑃𝑊𝑀 lub zwyczajne podłączenie do pinu 𝐺𝑃𝐼𝑂 – schemat podłączeń poszczególnych układów znajduje się na rysunku 1. Poza wymienionymi wcześniej układami, z komunikacji 𝐼 2 𝐶 będzie jeszcze korzystał czujnik napełnienia naczynia znajdujący się na czubku kranika. Z komunikacji 𝑆𝑃𝐼 korzysta tylko wyświetlacz bazujący na sterowniku 𝑆𝑇7565 (model EA DOGL128-6). Do GPIO podłączone zostaną wszystkie przyciski(po jednym pinie), enkoder silnika(dwa piny) oraz przycisk z enkoderem obrotowym (trzy piny). Rysunek 1. Schemat podłączeń elektroniki Opis oprogramowania - założenia Oprogramowanie będzie się składać z kilku modułów realizowanych równolegle. Stany większości urządzeń peryferyjnych będą cyklicznie odczytywane i przechowywane w zmiennych do których będzie mieć dostęp pętla główna. W ten sposób zrealizowany będzie np. dostęp do tabeli pozycji 1 – 8 i ich stan, napełnienie naczynia i pozycja karetki (odczyt enkodera silnika). Pętla główna przedstawiona jest na rysunku 2. Po wciśnięciu klawisza start urządzenie upewnia się czy karetka znajduje się w pozycji początkowej (odczyt krańcówki – jeśli taka pozycja jest nie spełniona to karetka jest dosuwana do początku aż krańcówka zmieni stan). Następnie wyzerowana jest zmienna przechowująca pozycję karetki oraz sprawdzone jest czy co najmniej jedna pozycja naczynia jest zajęta. Jeśli nie – urządzenie kończy pracę, jeśli tak – uruchamiany jest cykl nalewania. W cyklu tym urządzenie pobiera pozycję następnego naczynia – dojeżdża do danej pozycji oraz nalewa ciecz dopóki nie zostanie zwrócony sygnał napełnienia naczynia. Dany cykl jest powtarzany aż skończą się pozycje naczyń – wtedy karetka wraca do krańcówki i urządzenie ponownie przechodzi w stan oczekiwania. Rysunek 2. Schemat przedstawiający główną pętlę oprogramowania. Opis rzeczy zrealizowanych W ramach projektu zrealizowano większość z założeń opisanych w poprzedniej części. Całe oprogramowanie napisano korzystając z środowiska mbed oraz biblioteki mbed RTOS. W wątki głównym na początku inicjalizowane są przerwania – enkoder prowadnicy(pozycja karetki), krańcówka, przycisk start oraz timer odpowiadający za zliczanie enkodera obrotowego(przycisku). W następnym wywołaniu konfigurowane są pozostałe wątki działające równolegle do głównego – motorsThread, sensorsThread, ledsThread i lcdThread – które, zgodnie z nazwami, odpowiadają za obsługę poszczególnych peryferiów. Przy każdym wykorzystaniu 𝐼 2 𝐶 i printf(UART) zakładany jest mutex aby wyeliminować potencjalne konflikty dostępu do zasobu. Opis wątków: sensorsThread – cyklicznie odczytuje dane pomiarowe z czujników odległości na płytce przedniej(𝐼 2 𝐶). motorsThread – obsługuje pompę (poprzez wywołania start/stop) oraz pozycjonowanie prowadnicy liniowej (z zewnątrz zadawana jest nowa pozycja, do której wątek następnie dąży – coś w rodzaju regulatora P) - 𝐼 2 𝐶. ledsThread – obsługuje sterowanie LEDami RGB w płytce przedniej – ustawia kolory poprzez trzy sygnały PWM oraz wybiera aktualnie aktywną diodę poprzez sterownik diód typu LED Driver, sterowany poprzez 𝐼 2 𝐶. lcdThread – odpowiada za odświeżanie wyświetlacza i rysowanie na nim zadanych elementów. Obecnie przez około dwie sekundy wyświetla logo, a następnie przechodzi do rysunku szklanki, wypełnionej zgodnie z wyborem użytkownika – SPI. Pętla główna została zrealizowana zgodnie z maszyną stanów przedstawioną na rysunku 2 – po wciśnięciu klawisza START dojeżdża karetką do krańcówki (jeśli już tam była odsuwa się trochę i wraca). Następnie podjeżdża do pozycji pierwszej i sprawdza czy ma w danym miejscu uruchomić proces nalewania. Później sprawdza następną pozycję którą powinna osiągnąć – jeśli takiej nie ma – wraca do krańcówki. Proces nalewania odbiega od założeń gdyż nie udało się zrealizować pomiaru wypełnienia docelowego zbiornika. Zostało to zrealizowane w formie pewnej stałej czasowej przemnożonej przez wartość wybraną przez użytkownika (teoretycznie zakres 10 – 50ml). Użytkownik może wybrać poziom napełnienia szklanek (tj. czas pracy pompy) korzystając z enkodera mechanicznego. Jest to odzwierciedlone na wyświetlaczu oraz, przy włączonych logach debugujących, wybraną wartość widać w konsoli portu szeregowego na komputerze. Oprogramowanie Kod źródłowy wraz z dokumentacją wykorzystanych klas można znaleźć pod adresem: https://developer.mbed.org/users/Sateg/code/PBMain/ Wykorzystano bibliotekę mbed oraz mbed RTOS. Dodatkowo do obsługi sterownika wyświetlacza skorzystano z programu użytkownika igorsk: https://developer.mbed.org/users/igorsk/code/DOGLCDDemo/ Został on odpowiednio odchudzony i dostosowany do potrzeb projektu. Logo wyświetlane na początku zostało wygenerowane z monochromatycznej bitmapy korzystając z programu BMP-LCD: http://www.hobbytronics.co.uk/bmp-lcd-converter Poniżej znajduje się opis funkcji w pliku main.cpp, gdyż środowisko mbed nie generuje dokumentacji do tego pliku: void limiterHit() – funkcja wykonywania w przerwaniu krańcówki. Zmienia stan maszyny stanów oraz ustawia stan prowadnicy liniowej na ustawiony (błąd pozycji = 0). void countPulses() – przerwanie z enkodera silnika – zlicza pulsy. void startCycle() – przerwanie z przycisku START – odczytuje stan sensorów i uruchamia główny algorytm. void encoderHit() – obsługa enkodera mechanicznego (przycisku obrotowego) – sprawdza stan obecny i porównuje z poprzednim. Na podstawie tabeli stanów (encoderTable) stwierdza czy obrócono w prawo czy w lewo (czy zignorować). void setupInterrupts(), void setupThreads() – dwie funkcje konfiguracyjne opisane wcześniej – konfigurują przerwania i wątki RTOSa. uint8_t getNextPosition(uint8_t currentPosition) – określenie następnej pozycji do której powinna dojechać karetka prowadnicy liniowej na podstawie obecnej i odczytu z sensorów. Dodatkowo w każdym pliku .cpp znajduje się makro debug, które domyślnie wysyła po UART’cie na konsolę komputera informacje pomagające w debugowaniu programu. Można je wyłączyć usuwając/zakomentowując linijkę #define DEBUG. Potrafi to przyspieszyć działanie programu gdyż funkcja printf->UART potrafi być czasochłonna. Wszystkie typy pól zostały nazwane w sposób opisowy oraz zgodny z przyjętymi standardami odnośnie stylu programowania. Wszystko poza plikiem main.cpp zostało zaimplementowane w formie klas – zgodnie z zaleceniami platformy mbed.