e-Nurse - elektroniczny dyspenser leków (2)

e-Nurse - elektroniczny dyspenser leków (2)

W poprzednim numerze EP zaprezentowaliśmy konstrukcję układu elektronicznego oraz szczegóły dotyczące sterowania i zasilania adresowalnych diod LED, stanowiących prosty i intuicyjny interfejs użytkownika dyspensera e-Nurse. Tym razem zajmiemy się architekturą programu sterującego oraz opiszemy sposób montażu i obsługi urządzenia. Dla Czytelników zainteresowanych odtworzeniem urządzenia dla siebie lub bliskiej osoby udostępniamy także szczegóły dotyczące drukowalnego panelu przegródek, opracowanego przez autora na potrzeby projektu.

Podstawowe parametry:
  • liczba przegródek: 16,
  • maksymalna liczba dziennych dawek: 5,
  • źródło napięcia zasilającego: bateria alkaliczna typu AAA,
  • prąd pobierany ze źródła zasilania (maksymalny/tryb uśpienia): 55 mA/80 μA (szczegóły w tekście artykułu).

 

Autor składa podziękowania firmie Artronic za dostarczenie wyświetlacza LCD zastosowanego w projekcie urządzenia e-Nurse.

Program sterujący

Zaczniemy od pliku nagłówkowego do obsługi diod LED RGB upraszczającego i porządkującego późniejszy kod, który to plik pokazano na listingu 1.

Listing 1. Plik nagłówkowy modułu obsługi diod WS2812B-V5

#define LED_PORT PORTA
#define LED_DDR DDRA
#define LED_PIN_NR PA3
#define LED_SET LED_PORT |= (1<<LED_PIN_NR)
#define LED_RESET LED_PORT &= ~(1<<LED_PIN_NR)
#define LED_PIN_AS_OUTPUT LED_DDR |= (1<<LED_PIN_NR)

Dalej, na listingu 2, pokazano ciało funkcji odpowiedzialnej za przesłanie jednego bitu danych przy udziale wspomnianego wcześniej asynchronicznego interfejsu komunikacyjnego. Warto zauważyć, że stosowną funkcję zdefiniowano, używając atrybutu __always_inline__, który instruuje kompilator, by ZAWSZE wstawiał rozwinięcie funkcji w miejscu wywołania, nie zaś skok do jej ciała. Jest to o tyle istotne, że operujemy na dość rygorystycznych timingach rzędu setek nanosekund, gdzie, przy częstotliwości taktowania mikrokontrolera rzędu 8 MHz (okres 125 ns), niepotrzebne (z punktu widzenia programisty, nie kompilatora) wykonanie jakiegoś rozkazu asemblera może rozłożyć całą transmisję danych, uniemożliwiając jakiekolwiek sterowanie wspomnianymi elementami.

Listing 2. Funkcja odpowiedzialna za przesłanie jednego bitu danych interfejsu diod WS2812B-V5

__inline__ void __attribute__((__always_inline__))
ledSendBit(uint8_t Bit) {
if(Bit) {
LED_SET;
_delay_us(0.65);
LED_RESET;
_delay_us(0.65);
} else {
LED_SET;
_delay_us(0.25);
LED_RESET;
_delay_us(0.65);
}
}

Skoro mamy już funkcję umożliwiającą przesłanie jednego bitu informacji, to pora na funkcję (także odpowiednio zadeklarowaną) umożliwiającą przesłanie kompletnego bajta danych, przy udziale wspomnianego wcześniej interfejsu danych, której ciało pokazano na listingu 3.

Listing 3. Funkcja odpowiedzialna za przesłanie jednego bajta danych interfejsu diod WS2812B-V5

__inline__ void __attribute__((__always_inline__))
ledSendByte(uint8_t Byte){
ledSendBit(Byte & 0x80);
ledSendBit(Byte & 0x40);
ledSendBit(Byte & 0x20);
ledSendBit(Byte & 0x10);
ledSendBit(Byte & 0x08);
ledSendBit(Byte & 0x04);
ledSendBit(Byte & 0x02);
ledSendBit(Byte & 0x01);
}

Dalej, by uprościć zapis danych do adresowalnych diod LED RGB, przewidziano funkcję pozwalającą na przesłanie kompletnej informacji o kolorze tejże diody LED, której ciało pokazano na listingu 4.

Listing 4. Funkcja pozwalającą na przesłanie kompletnej informacji o kolorze diody LED typu WS2812B-V5

__inline__ void __attribute__((__always_inline__))
ledSendColor(uint8_t R, uint8_t G, uint8_t B){
ledSendByte(G);
ledSendByte(R);
ledSendByte(B);
}

Zapewne pamiętacie, że asynchroniczny interfejs komunikacyjny diod LED typu WS2812B-V5 przewiduje transmisję jeszcze jednego sygnału, a mianowicie sygnału RESET. Ciało funkcji odpowiedzialnej za transmisję sygnału RESET interfejsu diod WS2812B-V5 pokazano na listingu 5.

Listing 5. Funkcja odpowiedzialna za transmisję sygnału RESET interfejsu diod WS2812B-V5

inline void ledReset(void){
LED_RESET;
_delay_us(300);
}

Normalnie w tym miejscu zakończyłbym opis obsługi naszych ciekawych diod LED RGB, ale nie tym razem. Prawdę mówiąc, funkcje pokazane powyżej będą działać bez problemów wyłącznie na szybszych mikroprocesorach, dla których jeden cykl zegarowy jest najlepiej o rząd wielkości krótszy niż timingi odpowiedzialne za wysłanie poszczególnych bitów koloru diod LED. W innym przypadku, czyli jak u nas, gdzie takt zegara trwa 125 ns (dla częstotliwości taktowania 8 MHz), wykonanie każdego dodatkowego rozkazu (jak na przykład sprawdzenie wartości każdego bitu zmiennej przeznaczonej do wysłania) może dość skutecznie rozłożyć całą transmisję danych, gdyż niezachowane są wówczas rygorystyczne timingi kodujące bity informacji.

Jak sobie z tym poradzić? Dość prosto, choć nie nazbyt optymalnie. Ja utworzyłem osobne funkcje dla każdego rodzaju bitu (0 i 1) i każdego koloru, który zamierzałem przesyłać, a wszelkie warunki zastąpiłem "gotowym" do wykonania kodem bez zbędnych (z punktu widzenia transmisji) rozkazów. Spowodowało to powstanie wielu funkcji o bardzo prostym (i w gruncie rzeczy podobnym), acz długim kodzie, który zachował niezbędne timingi. Te uproszczone funkcje, o których mowa powyżej, pokazałem na listingu 6, gdzie zamieszczono odrębne funkcje dla każdego z bitów informacji (0 i 1), jak i przykładową funkcję wysyłającą dane dla koloru czerwonego. Dzięki takiemu rozwiązaniu bez problemu możemy transmitować dane do naszych diod LED, korzystając z mikrokontrolera taktowanego zegarem 8 MHz.

Listing 6. Uproszczone funkcje umożliwiające poprawną transmisję sygnałów sterujących interfejsu diod WS2812B-V5 dla mikrokontrolera taktowanego zegarem 8 MHz

#define NOP() __asm__ __volatile__ (“nop”)

__inline__ void __attribute__((__always_inline__))
ledSendBit0(void) { //Dla zegara 8MHz (NOP = 125ns)
LED_SET;
NOP();
LED_RESET;
NOP();
NOP();
NOP();
NOP();
NOP();
}

__inline__ void __attribute__((__always_inline__))
ledSendBit1(void) { //Dla zegara 8MHz (NOP = 125ns)
LED_SET;
NOP();
NOP();
NOP();
NOP();
NOP();
LED_RESET;
NOP();
NOP();
NOP();
NOP();
NOP();
}

__inline__ void __attribute__((__always_inline__))
ledRed(void) {
ledSendBit0();
ledSendBit0();
ledSendBit0();
ledSendBit0();
ledSendBit0();
ledSendBit0();
ledSendBit0();
ledSendBit0();

ledSendBit1();
ledSendBit0();
ledSendBit0();
ledSendBit0();
ledSendBit0();
ledSendBit0();
ledSendBit0();
ledSendBit0();

ledSendBit0();
ledSendBit0();
ledSendBit0();
ledSendBit0();
ledSendBit0();
ledSendBit0();
ledSendBit0();
ledSendBit0();
}

Oczywiście, i czego się zapewne domyślacie, w czasie takiej transmisji należy blokować możliwość obsługi przerwań systemowych. Można również poradzić sobie w prostszy sposób, zwyczajnie zwiększając prędkość zegara taktującego mikrokontroler (najlepiej co najmniej dwukrotnie), lecz ja nie chciałem iść tą drogą, gdyż wydatnie zwiększa się wtedy zapotrzebowanie systemu mikroprocesorowego na energię. Inną sprawą jest to, że w przypadku naszego mikrokontrolera nie mam już wolnych portów I/O, by podłączyć niezbędny rezonator kwarcowy, w związku z czym należałoby zastosować element o większej liczbie wyprowadzeń, co z kolei nie jest pożądane z uwagi na wymiary obwodu drukowanego. Kolejną możliwością jest użycie jakiegoś sprzętowego, szeregowego medium transmisyjnego wbudowanego w mikrokontroler (USART lub SPI), ale i w takim przypadku nie uciekniemy od konieczności zwiększenia częstotliwości taktowania mikrokontrolera. Tyle w kwestiach implementacyjnych, w zawiązku z czym przejdźmy do zagadnień montażowych.

Montaż i uruchomienie

Schemat płytki PCB naszego urządzenia pokazano na rysunku 5. Jak widać, zaprojektowano bardzo zgrabną, dwustronną płytkę drukowaną ze zdecydowaną przewagą elementów THT montowanych po obu stronach laminatu (po stronie BOTTOM montowane są wyłącznie elementy SMD). Montaż urządzenia rozpoczynamy od warstwy BOTTOM, gdzie w pierwszej kolejności montujemy półprzewodniki, zaś w kolejnym kroku elementy bierne. W tym momencie przechodzimy na warstwę TOP, gdzie, podobnie jak poprzednio, w pierwszej kolejności montujemy diody LED RGB, następnie pozostałe elementy półprzewodnikowe (z wyłączeniem wyświetlacza), a na końcu elementy bierne (z wyłączeniem buzzera piezoelektrycznego) oraz elementy mechaniczne w postaci koszyczka baterii AAA czy przycisków funkcyjnych. Na koniec, do tak przygotowanego obwodu drukowanego, montujemy wyświetlacz LCD, lutując jego wyprowadzenia w przeznaczone do tego celu punkty lutownicze, co zapewni mu zarówno niezbędne połączenia elektryczne, jak i pożądaną stabilizację mechaniczną.

Rysunek 5. Schemat montażowy urządzenia e-Nurse

Na fotografii 1 pokazano zmontowane urządzenie od strony warstwy TOP tuż przed przylutowaniem wyświetlacza LCD (wersja prototypowa, przed niewielkimi modyfikacjami), zaś na fotografii 2 to samo urządzenie od strony warstwy BOTTOM (pokazano wyłącznie ten obszar obwodu drukowanego, gdzie montowane są elementy SMD i to przed niewielkimi modyfikacjami sekcji zasilania).

Fotografia 1. Zmontowane urządzenie e-Nurse od strony warstwy TOP tuż przed przylutowaniem wyświetlacza LCD
Fotografia 2. Zmontowane urządzenie e-Nurse od strony warstwy BOTTOM

Obsługa

Projektując system Menu urządzenia e-Nurse oraz sposób jego obsługi, przyjąłem, że ergonomia i prostota jego użytkowania i czytelność interfejsu użytkownika powinny być najważniejszym kryterium przy konstruowaniu stosownych procedur sterujących. Zgodnie z tymi podstawowymi założeniami, na płytce sterownika przewidziano wyłącznie 4 przyciski funkcyjne pozwalające na poruszanie się po dostępnych ekranach Menu. Mówiąc zupełnie ogólnikowo, przyciski oznaczone jako NEXT, PREV (symbolizowane przez stosowne symbole strzałek) służą do zmiany typu edytowanego elementu, zaś przyciski oznaczone jako UP, DOWN (symbolizowane przez stosowne symbole strzałek) służą do zmiany wartości edytowanego elementu oraz poruszania się po kolejnych opcjach Menu urządzenia.

Rysunek 6. Ekran Menu głównego urządzenia e-Nurse

W ramach systemu Menu dostępne są 2 ekrany użytkownika: ekran Menu głównego oraz ekran Menu ustawień. Poniżej, na rysunku 6, pokazano ekran Menu głównego urządzenia e-Nurse, zaś na rysunku 7 pokazano ekran Menu ustawień naszego urządzenia. Jak widać, w ramach Menu głównego dostępna jest informacja o bieżącej dacie i godzinie systemowej oraz informacja o aktywnych alarmach (aktywność alarmu pokazywana jest w postaci wypełnienia wybranego symbolu "przegródki"). Z tego poziomu dokonujemy potwierdzenia przyjęcia dawki leku, co skutkuje skasowaniem alarmu, posiłkując się przy tym przyciskami funkcyjnymi umożliwiającymi poruszanie się po liście ikonek alarmów (przesuwającymi podkreślenie konkretnego symbolu "przegródki") oraz ich kasowanie. Kasowanie może przebiegać w dwojaki sposób: długie przyciśnięcie przycisku DOWN kasuje jeden alarm dla danej "przegródki", zaś długie przyciśnięcie przycisku UP kasuje wszystkie alarmy dla tejże "przegródki". Dodatkowo, długie przyciśniecie przycisku NEXT wprowadza nas w tryb Menu ustawień.

Rysunek 7. Ekran Menu ustawień urządzenia e-Nurse

Tryb Menu ustawień pozwala nam na dokonanie ustawień zarówno bieżącej godziny i dnia tygodnia, jak i skonfigurowanie ustawień dla każdej "przegródki" oznaczonej tu jako "Slot". Ustawienia, o których mowa powyżej, to: aktywność "przegródki" (gdyż można ją wstępnie skonfigurować, ale jeszcze nie aktywować), dzienna liczba dawek leku (1…5), godziny przyjmowania leku (dowolne z zakresu 0…23) oraz dni tygodnia przyjmowania leku. Poruszanie się pomiędzy elementami poddawanymi edycji, jak i ich edycję umożliwiają krótkie naciśnięcia przycisków funkcyjnych, zaś poruszanie się pomiędzy wierszami opcji Menu ustawień umożliwiają długie naciśnięcia przycisków UP i DOWN.

Wyjście z Menu ustawień i przejście do Menu głównego dokonywane jest poprzez długie naciśnięcie przycisku NEXT. Procesowi temu towarzyszy zapisanie bieżących ustawień urządzenia (ustawień "przegródek") w nieulotnej pamięci EEPROM mikrokontrolera oraz aktualizacja czasu zegara RTC. Do czasu wyjścia z Menu ustawień niemożliwe jest automatyczne przejście urządzenia do stanu uśpienia w przypadku braku aktywnych alarmów. Z kolei, proces sprawdzania alarmów i sygnalizacja ich wystąpienia (za pomocą wbudowanych diod LED RGB oraz buzzera) dokonywana jest również w czasie konfiguracji urządzenia (w Menu ustawień). Na rysunku 8 pokazano kompletny diagram systemu Menu urządzenia e-Nurse wraz ze sposobem jego obsługi.

Rysunek 8. Kompletny diagram systemu Menu urządzenia e-Nurse wraz ze sposobem jego obsługi

Obudowa

I na sam koniec obiecany "ekstras". Gotowy panel obudowy "przegródek" wykonany w aplikacji do projektowania 3D przez mojego, zawsze niezawodnego, Kolegę Bartłomieja Wawrzyszko. Element ten zaprojektowany został w taki sposób, by po jego przykręceniu do obwodu drukowanego (4 śruby ∅ 3 mm maks.) stanowił kompletne rozwiązanie dozownika leków zbliżone swoim wyglądem do prostych kasetek na leki dostępnych w aptekach czy drogeriach. Co więcej, w bocznych ściankach elementu (trzech z czterech) przygotowano specjalne wcięcia do wsunięcia w nie przezroczystej pleksi o grubości do 1,5 mm i wymiarach 68×80 mm tak, by stanowiła ona pokrywę dozownika uniemożliwiającą wypadnięcie leków ze swoich "przegródek". Prawda, że fajne?

Rysunek 9. Rysunek techniczny panelu "przegródek" (z zaznaczeniem ważniejszych wymiarów)

Na rysunku 9 pokazano rysunek techniczny panelu "przegródek" (z zaznaczeniem ważniejszych wymiarów), zaś na rysunku 10 pokazano z kolei model 3D tegoż elementu.

Rysunek 10. Model 3D panelu "przegródek"

Plik produkcyjny do wykonania wyżej wymienionej obudowy udostępniony jest w materiałach dodatkowych do artykułu.

Robert Wołgajew, EP

Artykuł ukazał się w
Elektronika Praktyczna
styczeń 2024
DO POBRANIA
Materiały dodatkowe

Elektronika Praktyczna Plus lipiec - grudzień 2012

Elektronika Praktyczna Plus

Monograficzne wydania specjalne

Elektronik czerwiec 2024

Elektronik

Magazyn elektroniki profesjonalnej

Raspberry Pi 2015

Raspberry Pi

Wykorzystaj wszystkie możliwości wyjątkowego minikomputera

Świat Radio maj - czerwiec 2024

Świat Radio

Magazyn krótkofalowców i amatorów CB

Automatyka, Podzespoły, Aplikacje maj 2024

Automatyka, Podzespoły, Aplikacje

Technika i rynek systemów automatyki

Elektronika Praktyczna czerwiec 2024

Elektronika Praktyczna

Międzynarodowy magazyn elektroników konstruktorów

Elektronika dla Wszystkich czerwiec 2024

Elektronika dla Wszystkich

Interesująca elektronika dla pasjonatów