Urządzenie bazuje na module ESP32-S3. Ten malutki, ale wydajny obliczeniowo mikrokontroler łączy się bezprzewodowo z innymi urządzeniami w mgnieniu oka, eliminując uciążliwe procedury parowania. Niezależnie od tego, czy znajduje się on w kieszeni, czy na breloczku, MicroMote zapewnia zdalną kontrolę nad Twoimi urządzeniami w każdym miejscu domu.
MicroMote to rewolucyjny pilot, w którym ESP32-S3 korzysta ze zintegrowanego sensora gestów Grove obrazującego w podczerwieni ruchy dłoni. To innowacyjne i kompaktowe urządzenie, mierzące zaledwie 4 cm, ma na celu zmianę sposobu, w jaki komunikujemy się z urządzeniami inteligentnego domu, takimi jak lampy, klimatyzacja itp. Mikrokontroler ESP32-S3 oferuje nie tylko wysoką wydajność obliczeniową i sprawność energetyczną, ale ma wbudowany kompletny bezprzewodowy interfejs sieciowy, dzięki czemu podłączenie systemu do Internetu jest naprawdę łatwe.
Urządzenie korzysta z protokołu ESP-NOW - jest to system do błyskawicznej i niezawodnej komunikacji z innymi urządzeniami. Użycie gotowego i szeroko aplikowanego sposobu komunikacji pozwala na prostą integrację tego modułu z innymi elementami ekosystemu, które korzystają z ESP-NOW. MicroMote został zaprojektowany do współpracy z różnymi domowymi urządzeniami Internetu Rzeczy i nie tylko. Dzięki szerokiemu zakresowi rozpoznawanych gestów układ pozwala na bardzo elastyczną konfigurację.
Dzięki niewielkim rozmiarom MicroMote jest urządzeniem przenośnym i łatwym do noszenia w kieszeni, np. jako breloczek do kluczy. Można zabrać go ze sobą, co ułatwia zachowanie ciągłej kontroli nad sterowanymi urządzeniami.
Potrzebne elementy
Do zbudowania tego prostego modułu będziemy potrzebowali zaledwie kilku komponentów elektronicznych. Całość zostanie zamknięta w wydrukowanej w 3D obudowie, która skręcona jest pojedynczym wkrętem samogwintującym M2. Ponadto potrzebne będą:
- moduł Seeed Studio XIAO ESP32-S3,
- moduł sensora gestów Seeed Studio Grove Smart IR,
- mały akumulator litowo-polimerowy 3,7 V.
Dokumentacja do wydrukowania obudowy dla modułu dostępna jest na stronie z projektem. Autor udostępnił pliki STL do druku 3D, a także cały projekt w Fusion 360.
Płaszczyzna działania sensora gestów
Dystans działania wybranego detektora gestów wynosi od 15 do 30 cm. Zasięg nie przekracza 35 cm. Sensor wyposażony jest w kamerę o polu widzenia o szerokości 78,3° (poziomej) i 62,9° (pionowej), więc obszar jego działania wynosi 48×36 cm przy odległości dłoni od sensora równej 30 cm (rysunek 1).
Oprócz odległości od czujnika, warto zwrócić uwagę na jego umieszczenie. Z przodu czujnika, w lewym górnym rogu, znajduje się mała postać ludzika (piktogram pokazany na rysunku 2). Jeśli widzimy tę figurkę stojącą wyprostowaną, to oznacza, że czujnik jest umieszczony we właściwej orientacji. Jeśli jest odwrócona, to prawdopodobnie nie uzyskamy poprawnego wyniku rozpoznania gestu.
Ponieważ tło może wpływać na dokładność rozpoznawania gestów, zaleca się unikania względnie jasnych, odbijających elementów umieszczonych za dłonią. W normalnych warunkach rozpoznawania gestów zaleca się utrzymanie odległości co najmniej 35 cm między dłonią a tłem za nią (rysunek 3).
Obsługiwane gesty
W tabeli 1 znajduje się lista wszystkich rodzajów gestów obsługiwanych przez czujnik Grove Smart IR (PAJ7660). W przypadku MicroMote autor korzysta tylko ze wzoru "Palce", który oznacza dłoń z wyprostowanymi palcami w liczbie 0...5 i "Naciśnięcie palcami", czyli przesunięcie w kierunku czujnika dłoni z wyprostowanymi palcami w liczbie 1...5. Warto zapoznać się z dokumentacją sensora w celu uwzględnienia innych gestów w MicroMote, jeśli będziemy tego potrzebowali - to tylko kwestia modyfikacji oprogramowania.
ESP-Now
Espressif Simple Protocol Now, czyli ESP-Now, to protokół komunikacji bezprzewodowej opracowany przez firmę Espressif Systems, znaną z popularnych mikrokontrolerów ESP8266 i ESP32 z obsługą Wi-Fi i Bluetooth. ESP-Now został opracowany do komunikacji typu punkt-punkt (P2P) między urządzeniami ESP8266 i ESP32. Jest szczególnie dobrze dostosowany do zastosowań związanych z Internetem Rzeczy (IoT), gdzie małe opóźnienie, wysoka niezawodność i niskie zużycie energii są wielką zaletą.
Micro Mote bazuje na protokole ESP-Now, co pozwala mu przesyłać różne sygnały i wiadomości do różnych systemów z układami ESP32. Te wiadomości mogą obejmować wiele rodzajów danych, w tym liczby i ciągi znaków. Każde urządzenie odbierające może być skonfigurowane z predefiniowanym identyfikatorem i wyzwalaczami wiadomości, co pozwala na interpretowanie przychodzących wiadomości jako sygnały do różnych działań. Te działania mogą obejmować włączanie lub wyłączanie świateł, regulowanie jasności i wiele innych funkcji dostosowanych do konkretnej aplikacji. Ważne jest, że ta sama wiadomość wysłana przez urządzenie nadawcze może służyć jako element wyzwalający dla zdefiniowanych działań na urządzeniu odbiorczym, tworząc wszechstronny i elastyczny system komunikacji.
Wiadomość wyzwalająca może być wspólna dla wielu urządzeń lub unikalna dla każdego urządzenia. Ta elastyczność pozwala kontrolować wspólne urządzenia jednocześnie. Alternatywnie, można kontrolować indywidualne urządzenia osobno, dostosowując działania do konkretnych potrzeb lub preferencji. Ta wszechstronność zapewnia potężne narzędzie do zarządzania i konfiguracji systemu IoT, aby sprostać różnym scenariuszom i wymaganiom aplikacji.
Obudowa
Obudowa dla MicroMot zaprojektowana została w programie Autodesk Fusion 360 przy użyciu arkuszy danych i skalowania do pomiaru wymiarów różnych komponentów. Pozwoliło to wygenerować model i pliki do druku 3D (fotografia 1). Pliki stl dla obudowy można pobrać i wydrukować w technologii 3D lub można dokonać modyfikacji projektu, który również załączony jest na stronie projektu. W programie Fusion 360 można wprowadzić dowolne zmiany i dostosować obudowę sensora do dowolnej aplikacji.
Konfiguracja sensora
Czujnik gestów Grove Smart IR obsługuje wiele protokołów komunikacji, w tym I²C, SPI i USB. Różne tryby wybiera się bezpośrednio za pomocą 4-pozycyjnego przełącznika DIP na odwrocie urządzenia. Diagram na rysunku 4 pokazuje, jak wybrać tryb, z którego chcesz korzystać za pomocą poczwórnego przełącznika DIP. W przypadku MicroMote autor używa protokołu I²C, więc należy ustawić przełącznik 2 w pozycji "w dół", aby włączyć odpowiedni tryb.
Podłączenie baterii i innych elementów
Montaż układu jest bardzo prosty. Całość skupia się na podłączeniu kluczowych elementów do płytki z mikrokontrolerem. Autor zastosował moduł XIAO ESP32S3, którego układ wyprowadzeń pokazano w uproszczeniu na rysunku 5. Montaż należy rozpocząć od przylutowania przewodów baterii oraz szpilek goldpin na płytce XIAO ESP32.
Ponieważ płytka XIAO ESP32 jest wyposażona we wbudowany układ ładowania akumulatora z ochroną przed nadmiernym naładowaniem, można skorzystać z portu typu C na płytce XIAO ESP32 do ładowania podłączonej baterii. Ta funkcja upraszcza konfigurację projektu. Wystarczy podłączyć kabel USB typu C, a płytka zrealizuje proces bezpiecznego ładowania podłączonej baterii.
Podłączenie czujnika gestów do ESP32 jest bardzo proste. Wystarczy włożyć płytkę XIAO ESP32 bezpośrednio do żeńskiego złącza czujnika gestów Grove, upewniając się, że port USB-C na płycie XIAO ESP32 jest skierowany na zewnątrz (fotografia 2). Taka konfiguracja ułatwia integrację czujnika gestów w dowolnym projekcie.
Są dwie opcje podłączenia czujnika gestów do innych płytek:
- Za pomocą przewodów. Jeśli chcemy podłączyć czujnik gestów do płytki, która nie ma złącza Grove, można użyć 4 przewodów. Wystarczy połączyć GND na czujniku z masą na swojej płycie, VCC z zasilaniem 3,3 V, a SCL z SCL i SDA z SDA. Ta metoda umożliwia elastyczną integrację z różnymi mikrokontrolerami.
- Za pomocą kabla Grove. Alternatywnie, jeśli wybrana płytka obsługuje złącze Grove, można użyć specjalnego kabla Grove, aby łatwo podłączyć czujnik gestów (fotografia 3). Ta metoda upraszcza proces połączenia i jest wygodna, jeśli wybrana płytka ma interfejs Grove.
Montaż urządzenia
Aby zmontować urządzenie, wystarczy wyrównać port USB-C na płytce XIAO ESP32 z odpowiednim otworem w obudowie wydrukowanej w technologii 3D i ostrożnie umieścić cały układ elektroniczny wewnątrz obudowy. Następnie przesuwamy górną pokrywę na jedną stronę obudowy, aby zamknąć elektronikę w obudowie.
Aby obudowa nie otwierała się, zastosowano małą śrubkę, która trwale mocuje górną pokrywę do obudowy i zapewnia, że cały montaż jest stabilny, a płytka nie wysunie się z obudowy (fotografia 4).
Firmware
W pierwszej kolejności należy pobrać bibliotekę czujnika gestów Grove. Po pobraniu biblioteki w formacie ZIP (link znajduje się w artykule źródłowym i w bibliografii na końcu artykułu) wystarczy otworzyć swoje środowisko Arduino IDE, kliknąć na Plik -> Dołącz bibliotekę -> Dodaj bibliotekę w formacie zip. W menu wybieramy plik ZIP, który właśnie pobraliśmy z sieci. Jeśli biblioteka zostanie poprawnie zainstalowana, wyświetlony zostanie komunikat w oknie powiadomień.
Można również zainstalować wsparcie dla płytki Arduino ESP32 w menedżerze płytek. Możesz postępować zgodnie z instrukcjami w przewodniku w celu instalacji. Po zainstalowaniu bibliotek można skopiować i wkleić kod, wybrać typ płytki, wyszukać "xiao" w zakładce Płytki po lewej stronie. Wybieramy tam "XIAO_ESP32S3", następnie wybieramy port i wgrywamy kod.
Oprogramowanie modułu pokazane jest na listingu 1. Mikrokontroler łączy się z sensorem, a następnie inicjalizuje ESP-NOW i przechodzi do pracy w pętli. Jeśli wykryty zostanie gest, uruchomiona zostanie funkcja printResultCombinedMode(), której parametrem jest wykryty gest. W funkcji printResultCombinedMode() znajduje się przełącznik (case), który w zależności od wykrytego gestu przesyła odpowiedni pakiet do sieci ESP-NOW.
#include <WiFi.h>
#include “Gesture.h”
#include <esp_now.h>
// Wykorzystuje tryb połączony (Combined)
pag7660 Gesture;
int deviceNo = 1;
// Uniwersalny adres MAC
uint8_t broadcastAddress[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
// Struktura do przesyłania danych
typedef struct messageData{
int color = 0;
} messageData;
messageData deviceData; // Dane lokalne
messageData recData; // Dane odebrane
esp_now_peer_info_t peerInfo; // Interfejs ESP NOW
// Wysyłanie danych
void OnDataSent(const uint8_t *mac_addr,
esp_now_send_status_t status){
Serial.print(“\r\nLast Packet Send Status:\t”);
Serial.println(status == ESP_NOW_SEND_SUCCESS ?
“Delivery Success” : “Delivery Fail”);
}
// Odbieranie danych
void OnDataRecv(const uint8_t * mac,
const uint8_t *incomingData, int len){
memcpy(&recData, incomingData, sizeof(recData));
Serial.print(“Bytes received: “);
Serial.println(len);
Serial.println(recData.color);
}
// Wynik operacji wysyłania danych
esp_err_t resultt;
void setup(){
Serial.begin(9600);
while(!Serial){
delay(100);
}
Serial.println(
“\nPAG7660 TEST DEMO: Gesture combined mode”.);
if(Gesture.init()){
Serial.println(
“PAG7660 initialization success”);
} else {
Serial.println(
“PAG7660 initialization failed”);
}
Serial.println(“Please input your gestures:\n”);
WiFi.mode(WIFI_STA);
if (esp_now_init() != ESP_OK) {
Serial.println(“Error initializing ESP-NOW”);
return;
}
esp_now_register_send_cb(OnDataSent);
esp_now_register_recv_cb(OnDataRecv);
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
// dodawanie urządzenia do sieci
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println(“Failed to add peer”);
return;
}
recData.color = deviceNo;
}
void loop() {
pag7660_gesture_t result;
if (Gesture.getResult(result)) {
printResultCombinedMode(result);
}
delay(100);
}
// przesyłanie pakietów do sieci ESP-Now
void printResultCombinedMode(
const pag7660_gesture_t& result) {
const char *cursor_str[] = {
NULL,
“Tap”,
“Grab”,
“Pinch”,
};
switch (result.type) {
case 0:
switch (result.cursor.type) {
case 1:
case 2:
case 3:
if (result.cursor.select)
Serial.println(cursor_str[result.cursor.type]);
break;
default:
break;
}
break;
case 1:
deviceData.color = recData.color = 1;
resultt = esp_now_send(broadcastAddress,
(uint8_t *) &deviceData, sizeof(deviceData));
delay(2000); break;
case 2:
deviceData.color = recData.color = 2;
resultt = esp_now_send(broadcastAddress,
(uint8_t *) &deviceData, sizeof(deviceData));
delay(2000); break;
case 3:
deviceData.color = recData.color = 3;
resultt = esp_now_send(broadcastAddress,
(uint8_t *) &deviceData, sizeof(deviceData));
delay(2000); break;
case 4:
deviceData.color = recData.color = 4;
resultt = esp_now_send(broadcastAddress,
(uint8_t *) &deviceData, sizeof(deviceData));
delay(2000); break;
case 5:
deviceData.color = recData.color = 5;
resultt = esp_now_send(broadcastAddress,
(uint8_t *) &deviceData, sizeof(deviceData));
break;
case 6:
break;
case 7:
break;
case 8:
break;
case 9:
break;
case 19:
deviceData.color = recData.color = 6;
resultt = esp_now_send(broadcastAddress,
(uint8_t *) &deviceData, sizeof(deviceData));
delay(2000); break;
case 20:
deviceData.color = recData.color = 7;
resultt = esp_now_send(broadcastAddress,
(uint8_t *) &deviceData, sizeof(deviceData));
delay(2000); break;
case 21:
deviceData.color = recData.color = 8;
resultt = esp_now_send(broadcastAddress,
(uint8_t *) &deviceData, sizeof(deviceData));
delay(2000); break;
case 22:
deviceData.color = recData.color = 9;
resultt = esp_now_send(broadcastAddress,
(uint8_t *) &deviceData, sizeof(deviceData));
delay(2000); break;
case 23:
deviceData.color = recData.color = 10;
resultt = esp_now_send(broadcastAddress,
(uint8_t *) &deviceData, sizeof(deviceData));
delay(2000); break;
default:
break;
}
}
Do testowania aplikacji można użyć drugiego modułu z ESP32 z załadowanym kodem z listingu 2. Odbiera on komunikaty w systemie ESP-NOW w sieci i przesyła je poprzez UART np. do komputera.
#include <esp_now.h>
#include <WiFi.h>
// Uniwersalny adres MAC
uint8_t broadcastAddress[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
// Struktura do przesyłania danych
typedef struct messageData{
int color = 0;
} messageData;
messageData deviceData; // Dane lokalne
messageData recData; // Dane odebrane
esp_now_peer_info_t peerInfo; // Interfejs ESP NOW
// Wysyłanie danych
void OnDataSent(const uint8_t *mac_addr,
esp_now_send_status_t status){
Serial.print("\r\nLast Packet Send Status:\t");
Serial.println(status == ESP_NOW_SEND_SUCCESS ?
"Delivery Success" : "Delivery Fail");
}
// Odbieranie danych
void OnDataRecv(const uint8_t * mac,
const uint8_t *incomingData, int len){
memcpy(&recData, incomingData, sizeof(recData));
Serial.print("Bytes received: ");
Serial.println(len);
Serial.println(recData.color);
}
// Wynik operacji wysyłania danych
esp_err_t resultt;
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
esp_now_register_send_cb(OnDataSent);
esp_now_register_recv_cb(OnDataRecv);
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
// dodawanie urządzenia do sieci
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add peer");
return;
}
}
void loop(){
}
Podsumowanie
Do demonstracji działania układu autor wykorzystał lampki świecące w kolorach tęczy, które wcześniej zbudował jako urządzenia odbiorcze ESP-Now (fotografia 5). Przy uruchamianiu miał on pewne problemy z zasilaniem bateryjnym, jednakże wynikały one ze złej kondycji starej baterii, a nie problemów z modułem.
W obecnej wersji programu twórca nie zdecydował się włączać/wyłączać zasilania w MicroMote, ponieważ planuje eksperymentować z trybami Deep Sleep ESP32 w przyszłości. W razie potrzeby można łatwo dodać przełącznik za pomocą prostych dodatkowych kroków.
MicroMote to interesujący i kompaktowy projekt z nieograniczonymi zastosowaniami. Jedynym ograniczeniem jest Twoja kreatywność i to, jak zdecydujesz się z niego korzystać
Nikodem Czechowski, EP
Źródła: