Spisu treści:

Nieblokująca implementacja czujnika gestów APDS9960: 5 kroków
Nieblokująca implementacja czujnika gestów APDS9960: 5 kroków

Wideo: Nieblokująca implementacja czujnika gestów APDS9960: 5 kroków

Wideo: Nieblokująca implementacja czujnika gestów APDS9960: 5 kroków
Wideo: BiteIT #57: Reaktywność nie zna kompromisów | Marcin Chrost, Łukasz Pyrkosz 2024, Listopad
Anonim
Nieblokująca implementacja czujnika gestów APDS9960
Nieblokująca implementacja czujnika gestów APDS9960
Nieblokująca implementacja czujnika gestów APDS9960
Nieblokująca implementacja czujnika gestów APDS9960
Nieblokująca implementacja czujnika gestów APDS9960
Nieblokująca implementacja czujnika gestów APDS9960

Preambuła

W tej instrukcji szczegółowo opisano sposób tworzenia nieblokującej implementacji czujnika gestów APDS9960 przy użyciu biblioteki SparkFun_APDS-9960_Sensor_Arduino_Library.

Wstęp

Więc prawdopodobnie zadajesz sobie pytanie, co to jest brak blokowania? A może nawet blokowanie z tego powodu?

Co ważniejsze, dlaczego ważne jest, aby coś nie blokowało, prawda?

Ok, więc kiedy mikroprocesor uruchamia program, sekwencyjnie wykonuje wiersze kodu, a przez to wywołuje i wraca z funkcji zgodnie z kolejnością, w jakiej je napisałeś.

Wywołanie blokujące to po prostu wywołanie dowolnego rodzaju funkcji, która powoduje zatrzymanie wykonywania, co oznacza wywołanie funkcji, w której wywołujący nie wznowi wykonywania, dopóki wywoływana funkcja nie zostanie zakończona.

Więc dlaczego jest to ważne?

W przypadku, gdy napisałeś jakiś kod, który wymaga regularnego wykonywania wielu funkcji sekwencyjnie, takich jak odczyt temperatury, odczyt przycisku i aktualizacja wyświetlacza, jeśli kod aktualizacji wyświetlacza będzie wywołaniem blokującym, twój system nie będzie odpowiadał naciska przycisk i zmienia się temperatura, ponieważ procesor będzie spędzał cały swój czas na oczekiwaniu na aktualizację wyświetlacza i nie odczytuje stanu przycisku ani ostatniej temperatury.

Ze swojej strony chcę stworzyć komputer stacjonarny IoT z obsługą MQTT przez Wi-Fi, który odczytuje zarówno lokalne, jak i zdalne wartości temperatury/wilgotności, poziomy światła otoczenia, ciśnienie barometryczne, śledzi czas, wyświetla wszystkie te parametry na ekranie LCD, loguje się do urządzenia uSD karty w czasie rzeczywistym, odczytywać wejścia przycisków, zapisywać do wyjściowych diod LED i monitorować gesty, aby kontrolować rzeczy w mojej infrastrukturze IoT, a wszystko to ma być kontrolowane przez ESP8266-12.

Niestety jedynymi dwoma źródłami biblioteki APDS9960, jakie udało mi się znaleźć, były biblioteki SparkFun i AdaFruit, z których obie zostały zgrane z kodu aplikacji firmy Avago (producent ADPS9960) i posiadają wywołanie o nazwie „readGesture”, które zawiera chwilę(1){}; pętla, która zastosowana w powyższym projekcie powoduje, że ESP8266-12E resetuje się za każdym razem, gdy czujnik ADPS9960 jest nasycony (tj. gdy obiekt pozostał w bliskiej odległości lub pojawiło się inne źródło podczerwieni oświetlające czujnik).

W związku z tym, aby rozwiązać ten problem, zdecydowałem się przenieść przetwarzanie gestów do drugiego procesora, dzięki czemu ESP8266-12E stał się głównym mikrokontrolerem, a ten system niewolnikiem, jak pokazano na rysunkach 1 i 2 powyżej, schematach przeglądu systemu i kompozycji systemu. Rysunek 3 pokazuje obwód prototypowy.

Aby ograniczyć zmiany, które musiałem wprowadzić w moim istniejącym kodzie, napisałem również klasę/bibliotekę opakowującą o nazwie „APDS9960_NonBlocking”.

Poniżej znajduje się szczegółowe wyjaśnienie rozwiązania nieblokującego.

Jakich części potrzebuję?

Jeśli chcesz skonstruować rozwiązanie I2C, które współpracuje z biblioteką APDS9960_NonBlocking, będziesz potrzebować następujących części.

  1. 1 szt. ATMega328P tutaj
  2. 1 szt. PCF8574P tutaj
  3. Tutaj 6 rezystorów 10K
  4. 4 off rezystory 1K tutaj
  5. 1 z diody 1N914 tutaj
  6. 1 szt. Tranzystor PN2222 NPN tutaj
  7. 1 off kryształ 16 MHz tutaj
  8. 2 off 0.1uF kondensatory tutaj
  9. 1 off 1000uF kondensator elektrolityczny tutaj
  10. 1 off 10uF kondensator elektrolityczny tutaj
  11. 2 kondensatory 22pF tutaj

Jeśli chcesz odczytać sygnał wyjściowy czujnika gestów przez interfejs równoległy, możesz odrzucić PCF8574P i trzy oporniki 10K.

Jakiego oprogramowania potrzebuję?

Arduino IDE 1.6.9

Jakich umiejętności potrzebuję?

Aby skonfigurować system, użyj kodu źródłowego (dostarczonego) i utwórz niezbędne obwody, których będziesz potrzebować;

  • Minimalna znajomość elektroniki,
  • Znajomość Arduino i jego IDE,
  • Zrozumienie, jak zaprogramować wbudowane Arduino (patrz instrukcja „Programowanie ATTiny85, ATTiny84 i ATMega328P: Arduino jako ISP”)
  • Trochę cierpliwości.

Omówione tematy

  • Krótki przegląd obwodu
  • Krótki przegląd oprogramowania
  • Testowanie urządzenia do wykrywania gestów APDS9960
  • Wniosek
  • Bibliografia

Krok 1: Przegląd obwodu

Przegląd obwodu
Przegląd obwodu

Obwód podzielony jest na dwie sekcje;

  • Pierwszym z nich jest konwersja szeregowego I2C do równoległego realizowana za pomocą rezystorów R8…10 i IC1. Tutaj R8…R10 ustawia adres I2C dla 8-bitowego układu ekspandera I/O IC1 i NXP PCF8574A. Prawidłowe zakresy adresów dla tego urządzenia to odpowiednio 0x38 … 0x3F. W przykładzie oprogramowania I2C 'I2C_APDS9960_TEST.ino' '#define GESTURE_SENSOR_I2C_ADDRESS' musiałby zostać zmieniony, aby pasował do tego zakresu adresów.
  • Wszystkie pozostałe komponenty tworzą wbudowaną podrzędną Arduino Uno i mają następujące funkcje;

    • R1, T1, R2 i D1 zapewniają wejście resetowania urządzenia podrzędnego. Tutaj aktywny wysoki impuls na IC1 - P7 zmusi U1 do zresetowania.
    • R3, R4 to rezystory ograniczające prąd dla wbudowanych urządzeń programujących linie TX/RX.
    • C5 i R7 umożliwiają Arduino IDE automatyczne programowanie U1 za pomocą impulsu na linii DTR podłączonego urządzenia FTDI.
    • R5 i R6 to rezystory podciągające I2C dla APDS9960 z C6 zapewniającym lokalne odsprzęganie szyny zasilającej.
    • U1, C1, C2 i Q1 tworzą odpowiednio wbudowane Arduino Uno i jego zegar.
    • Wreszcie C3 i C4 zapewniają oddzielenie lokalnej szyny zasilającej dla U1.

Krok 2: Przegląd oprogramowania

Przegląd oprogramowania
Przegląd oprogramowania
Przegląd oprogramowania
Przegląd oprogramowania
Przegląd oprogramowania
Przegląd oprogramowania

Preambuła

Aby pomyślnie skompilować ten kod źródłowy, będziesz potrzebować następujących dodatkowych bibliotek do programowania wbudowanego Arduino Uno U1;

SparkFun_APDS9960.h

  • Autor: Steve Quinn
  • Cel: Jest to rozwidlona wersja czujnika SparkFun APDS9960 rozwidlona z jonn26/SparkFun_APDS-9960_Sensor_Arduino_Library. Ma kilka modyfikacji, które pomagają w debugowaniu, i ma odczulony detektor, aby zmniejszyć fałszywe wyzwalanie.
  • Od:

APDS9960_NonBlocking.h

  • Autor: Steve Quinn
  • Cel: Zapewnia przejrzysty interfejs do osadzenia tej nieblokującej implementacji czujnika gestów APDS9960 w kodzie Arduino.
  • Od:

Zobacz poniższe instrukcje dotyczące programowania wbudowanego mikrokontrolera Arduino Uno (ATMega328P), jeśli nie wiesz, jak to osiągnąć;

PROGRAMOWANIE ATTINY85, ATTINY84 I ATMEGA328P: ARDUINO JAKO ISP

Przegląd funkcji

Wbudowany mikrokontroler podrzędny ATMega328P odpytuje linię INT z ADPS9960. Kiedy ta linia znika, mikrokontroler odczytuje rejestry ADPS9960 i określa, czy wykryto prawidłowy gest. Jeśli wykryto prawidłowy gest, kod tego gestu 0x0…0x6, 0xF jest umieszczany w porcie B, a 'nGestureAvailable' jest potwierdzany jako niski.

Gdy urządzenie Master widzi, że „nGestureAvailable” jest aktywne, odczytuje wartość na porcie B, a następnie tymczasowo wysyła impuls „nGestureClear”, aby potwierdzić odbiór danych.

Urządzenie podrzędne następnie usuwa wysoki poziom „nGestureAvailable” i usuwa dane z portu B. Rysunek 5 powyżej przedstawia zrzut ekranu pobrany z analizatora stanów logicznych podczas pełnego cyklu wykrywania/odczytu.

Przegląd kodu

Rysunek 1 powyżej przedstawia sposób działania oprogramowania w U1 wbudowanego slave'a Arduino Uno, a także rysunek 2, w jaki sposób współdziałają dwa zadania tła / pierwszego planu. Rysunek 3 to segment kodu przedstawiający sposób korzystania z biblioteki APDS9960_NonBlockinglibrary. Rysunek 4 przedstawia mapowanie między pinami cyfrowymi Arduino Uno a rzeczywistymi pinami sprzętowymi w ATMega328P.

Po zresetowaniu wbudowany mikrokontroler podrzędny inicjalizuje APDS9960, umożliwiając wykrywanie gestów w celu wyzwolenia wyjścia INT i konfiguruje swoje I/O, dołączając procedurę obsługi przerwań (ISR) „GESTURE_CLEAR()” do przerwania wektora INT0 (cyfrowy pin 2, sprzętowy pin 4), konfigurując go na wyzwalacz zbocza opadającego. Tworzy to wejście nGestureClear z urządzenia nadrzędnego.

Pin wyjścia przerwania „INT” z APDS9960 jest podłączony do cyfrowego Pin 4, Hardware IC Pin 6, który jest skonfigurowany jako wejście do U1.

Linia sygnału „nGestureAvailable” na cyfrowym pinie 7, sprzęcie na pinie 13 IC jest skonfigurowana jako wyjście i ustawiona na wysoki, nieaktywny (niepotwierdzony).

Na koniec bity 0…3 portu B są odpowiednio skonfigurowane jako wyjścia i ustawione w stan niski. Tworzą one nibble danych, który reprezentuje różne wykryte typy gestów; Brak = 0x0, Błąd = 0xF, W górę = 0x1, W dół = 0x2, W lewo = 0x3, W prawo = 0x4, Blisko = 0x5 i Daleko = 0x6.

Zaplanowane jest zadanie w tle „Pętla”, które stale odpytuje wyjście przerwania APDS9960 INT poprzez odczyt cyfrowego Pinu 4. Gdy wyjście INT z APDS9960 staje się aktywne w stanie niskim, wskazując, że czujnik został wyzwolony, mikrokontroler próbuje zinterpretować dowolny gest, wywołując „readGesture()' z it's while (1) {}; nieskończona pętla.

W przypadku wykrycia prawidłowego gestu ta wartość jest zapisywana w porcie B, następuje potwierdzenie danych wyjściowych „nGestureAvailable” i ustawiany jest semafor logiczny „bGestureAvailable”, co zapobiega rejestrowaniu dalszych gestów.

Gdy urządzenie nadrzędne wykryje aktywne wyjście „nGestureAvailable”, odczytuje tę nową wartość i wysyła impulsy „nGestureClear” w stanie niskim. To opadające zbocze powoduje, że zadanie pierwszego planu „ISR GESTURE_CLEAR()” zostanie zaplanowane, zawieszając wykonanie zadania „Pętla” w tle, czyszcząc port B, semafor „bGestureAvailable” i wyjście „nGestureAvailable”.

Zadanie pierwszego planu „GESTURE_CLEAR()” jest teraz zawieszone, a zadanie w tle „Pętla” zostało ponownie zaplanowane. Można teraz wyczuć kolejne gesty z APDS9960.

Używając w ten sposób wyzwalanych przerwaniami zadań pierwszego planu/tła, potencjalna nieskończona pętla w 'readGesture()' urządzenia podrzędnego nie wpłynie na działanie urządzenia nadrzędnego i nie będzie utrudniać wykonywania urządzenia podrzędnego. Stanowi to podstawę bardzo prostego systemu operacyjnego czasu rzeczywistego (RTOS).

Uwaga: Prefiks „n” oznacza aktywny niski lub potwierdzony, jak w „nGestureAvailable”

Krok 3: Testowanie nieblokującego urządzenia do wykrywania gestów APDS9960

Testowanie nieblokującego urządzenia do wykrywania gestów APDS9960
Testowanie nieblokującego urządzenia do wykrywania gestów APDS9960
Testowanie nieblokującego urządzenia do wykrywania gestów APDS9960
Testowanie nieblokującego urządzenia do wykrywania gestów APDS9960
Testowanie nieblokującego urządzenia do wykrywania gestów APDS9960
Testowanie nieblokującego urządzenia do wykrywania gestów APDS9960
Testowanie nieblokującego urządzenia do wykrywania gestów APDS9960
Testowanie nieblokującego urządzenia do wykrywania gestów APDS9960

Preambuła

Mimo że moduł APDS9960 jest dostarczany z +5V, używa wbudowanego regulatora +3v3, co oznacza, że jego linie I2C są zgodne z +3v3, a nie +5V. Dlatego zdecydowałem się użyć Arduino Due zgodnego z +3v3 jako testowego mikrokontrolera, aby uniknąć konieczności stosowania przełączników poziomów.

Jeśli jednak chcesz użyć rzeczywistego Arduino Uno, musisz zmienić poziom linii I2C na U1. Zobacz poniższy Instruktaż, w którym dołączyłem przydatny zestaw slajdów (I2C_LCD_With_Arduino), który zawiera wiele praktycznych wskazówek dotyczących korzystania z I2C.

Testowanie interfejsu I2C

Rysunki 1 i 2 powyżej pokazują, jak skonfigurować i zaprogramować system dla interfejsu I2C. Najpierw musisz pobrać i zainstalować bibliotekę APDS9960_NonBlocking. tutaj

Testowanie interfejsu równoległego

Zdjęcia 3 i 4 są takie same dla interfejsu równoległego!

Krok 4: Wniosek

Wniosek
Wniosek

Ogólny

Kod działa dobrze i szybko wykrywa gesty bez żadnych fałszywych alarmów. Działa już od kilku tygodni jako urządzenie podrzędne w moim następnym projekcie. Próbowałem wielu różnych trybów awarii (podobnie jak dociekliwy domowy moggie Quinn), co wcześniej spowodowało reset ESP8266-12, bez negatywnego wpływu.

Możliwe ulepszenia

  • Oczywistość. Przepisz bibliotekę APDS9960 Gesture Sensor tak, aby była nieblokująca.

    Właściwie skontaktowałem się z Broadcomem, który skierował mnie do lokalnego dystrybutora, który natychmiast zignorował moją prośbę o wsparcie, po prostu nie jestem SparkFun ani AdaFruit, jak sądzę. Więc to prawdopodobnie będzie musiało trochę poczekać

  • Przenieś kod do mniejszego mikrokontrolera podrzędnego. Używanie ATMega328P do jednego zadania to trochę przesada. Chociaż początkowo spojrzałem na ATTiny84, przestałem go używać, ponieważ czułem, że skompilowany rozmiar kodu pasuje do linii granicznej. Z dodatkowym obciążeniem konieczności modyfikowania biblioteki APDS9960 do pracy z inną biblioteką I2C.

Krok 5: Referencje

Wymagany do zaprogramowania wbudowanego arduino (ATMega328P - U1)

SparkFun_APDS9960.h

  • Autor: Steve Quinn
  • Cel: Jest to rozwidlona wersja czujnika SparkFun APDS9960 rozwidlona z jonn26/SparkFun_APDS-9960_Sensor_Arduino_Library. Ma kilka modyfikacji, które pomagają w debugowaniu, i ma odczulony detektor, aby zmniejszyć fałszywe wyzwalanie.
  • Od:

Wymagane do osadzenia tej nieblokującej funkcji w kodzie arduino i podania działających przykładów

APDS9960_NonBlocking.h

  • Autor: Steve Quinn
  • Cel: Zapewnia przejrzysty interfejs do osadzenia tej nieblokującej implementacji czujnika gestów APDS9960 w kodzie Arduino.
  • Od:

System operacyjny czasu rzeczywistego

https://en.wikipedia.org/wiki/System_operacyjny_w_czasie rzeczywistym

Arkusz danych APDS9960

https://cdn.sparkfun.com/assets/learn_tutorials/3/2/1/Avago-APDS-9960-datasheet.pdf

Zalecana: