Spisu treści:

Komunikacja bezprzewodowa LoRa 3Km do 8Km z tanim urządzeniem E32 (sx1278/sx1276) dla Arduino, Esp8266 lub Esp32: 15 kroków
Komunikacja bezprzewodowa LoRa 3Km do 8Km z tanim urządzeniem E32 (sx1278/sx1276) dla Arduino, Esp8266 lub Esp32: 15 kroków

Wideo: Komunikacja bezprzewodowa LoRa 3Km do 8Km z tanim urządzeniem E32 (sx1278/sx1276) dla Arduino, Esp8266 lub Esp32: 15 kroków

Wideo: Komunikacja bezprzewodowa LoRa 3Km do 8Km z tanim urządzeniem E32 (sx1278/sx1276) dla Arduino, Esp8266 lub Esp32: 15 kroków
Wideo: Bezprzewodowy pilot 8km moduły LoRa 🗼SX1278 LoRa 433 MHz 30dBm1W 2024, Lipiec
Anonim
Komunikacja bezprzewodowa LoRa 3Km do 8Km z tanim urządzeniem E32 (sx1278/sx1276) dla Arduino, Esp8266 lub Esp32
Komunikacja bezprzewodowa LoRa 3Km do 8Km z tanim urządzeniem E32 (sx1278/sx1276) dla Arduino, Esp8266 lub Esp32

Tworzę bibliotekę do zarządzania EBYTE E32 w oparciu o urządzenie LoRa serii Semtech, bardzo wydajne, proste i tanie urządzenie.

Wersję 3Km znajdziesz tutaj, wersję 8Km tutaj

Mogą pracować na dystansie od 3000m do 8000m, posiadają wiele funkcji i parametrów. Więc tworzę tę bibliotekę, aby uprościć użytkowanie.

To rozwiązanie do pobierania danych z czujników miejskich lub sterowania dronem.

Kieszonkowe dzieci

Arduino UNO

Wemos D1 mini

Wersja LoRa E32 TTL 100 3Km

Wersja LoRa E32 TTL 1W 8Km

Krok 1: Biblioteka

Biblioteka
Biblioteka

Moją bibliotekę znajdziesz tutaj.

Pobrać.

Kliknij przycisk POBIERZ w prawym górnym rogu, zmień nazwę nieskompresowanego folderu LoRa_E32.

Sprawdź, czy folder LoRa_E32 zawiera LoRa_E32.cpp i LoRa_E32.h.

Umieść folder biblioteki LoRa_E32 w folderze /libraries/. Może być konieczne utworzenie podfolderu biblioteki, jeśli jest to Twoja pierwsza biblioteka.

Uruchom ponownie środowisko IDE.

Krok 2: Pinout

Pinout
Pinout
Pinout
Pinout
Pinout
Pinout

Jak widać, możesz ustawić różne tryby za pomocą pinów M0 i M1.

Istnieje kilka pinów, których można używać w sposób statyczny, ale jeśli podłączysz go do mikrokontrolera i skonfigurujesz je w bibliotece, zyskujesz na wydajności i możesz sterować wszystkimi trybami za pomocą oprogramowania, ale dokładniej wyjaśnimy to w dalszej części.

Krok 3: pin AUX

Styk AUX
Styk AUX
Styk AUX
Styk AUX
Styk AUX
Styk AUX

Jak już pisałem Nie jest ważne, aby podłączyć wszystkie piny do wyjścia mikrokontrolera, można ustawić piny M0 i M1 na HIGH lub LOW, aby uzyskać pożądaną konfigurację, a jeśli nie podłączysz AUX biblioteka ustaw rozsądną zwłokę dla pewności że operacja została zakończona.

Styk AUX

Podczas transmisji danych można użyć do wybudzenia zewnętrznego MCU i powrotu do stanu HIGH po zakończeniu przesyłania danych.

Po odebraniu AUX przechodzi w LOW i zwraca HIGH, gdy bufor jest pusty.

Służy również do samokontroli w celu przywrócenia normalnej pracy (w trybie włączenia i uśpienia/programu).

Krok 4: W pełni połączony schemat Esp8266

W pełni połączony schemat Esp8266
W pełni połączony schemat Esp8266
W pełni połączony schemat Esp8266
W pełni połączony schemat Esp8266

Schemat podłączenia esp8266 jest prostszy, ponieważ działa na tym samym napięciu komunikacji logicznej (3,3v).

Ważne jest, aby dodać rezystor podciągający (4, 7Kohm), aby uzyskać dobrą stabilność.

Krok 5: W pełni połączony schemat Arduino

W pełni połączony schemat Arduino
W pełni połączony schemat Arduino
W pełni połączony schemat Arduino
W pełni połączony schemat Arduino

Napięcie pracy Arduino wynosi 5V, dlatego musimy dodać dzielnik napięcia na pinie RX M0 i M1 modułu LoRa, aby zapobiec uszkodzeniom, więcej informacji znajdziesz tutaj Dzielnik napięcia: kalkulator i aplikacja.

Możesz użyć rezystora 2Kohm do GND i 1Kohm z sygnału niż połączone na RX.

Krok 6: Biblioteka: Konstruktor

Zrobiłem zestaw dość licznych konstruktorów, ponieważ możemy mieć więcej opcji i sytuacji do zarządzania.

LoRa_E32 (bajt rxPin, bajt txPin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);

LoRa_E32 (bajt rxPin, bajt txPin, bajt auxPin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600); LoRa_E32(bajt rxPin, bajt txPin, bajt auxPin, bajt m0Pin, bajt m1Pin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);

Tworzony jest pierwszy zestaw konstruktorów do delegowania zarządzania pinami Serial i innymi pinami do biblioteki.

rxPin i txPin to pin do podłączenia do UART i są one obowiązkowe.

auxPin to pin, który sprawdza stan operacji, transmisji i odbioru (będziemy wyjaśniać dokładniej dalej), ten pin Nie jest obowiązkowy, jeśli nie ustawisz. z opóźnieniem).

m0pin i m1Pin to piny do zmiany TRYBU pracy (patrz tabela u góry), myślę, że te piny w „produkcji” będą łączyć bezpośrednio WYSOKI lub NISKI, ale do testu przydatne są do zarządzania przez bibliotekę.

bpsRate to szybkość transmisji oprogramowania SoftwareSerial, która zwykle wynosi 9600 (jedyna szybkość transmisji w trybie programowania/uśpienia)

Prostym przykładem jest

#include "LoRa_E32.h"LoRa_E32 e32ttl100(2, 3); // RX, TX // LoRa_E32 e32ttl100(2, 3, 5, 6, 7); // RX, TX

Możemy użyć bezpośrednio SoftwareSerial z innym konstruktorem

LoRa_E32 (szeregowy sprzęt szeregowy*, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);

LoRa_E32 (Szeregowy sprzęt szeregowy*, bajt auxPin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);

LoRa_E32 (Szeregowy sprzęt szeregowy*, bajt auxPin, bajt m0Pin, bajt m1Pin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);

Przykład górny z tym konstruktorem można zrobić w ten sposób.

#include #include "LoRa_E32.h"

SoftwareSerial mySerial(2, 3); // RX, TX

LoRa_E32 e32ttl100(&mySerial);

// LoRa_E32 e32ttl100(&mySerial, 5, 7, 6);

Ostatnim zestawem konstruktorów jest zezwolenie na użycie HardwareSerial zamiast SoftwareSerial.

LoRa_E32 (szeregowy SoftwareSerial*, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);

LoRa_E32 (szeregowy SoftwareSerial*, bajt auxPin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);

LoRa_E32 (Serial SoftwareSerial*, bajt auxPin, bajt m0Pin, bajt m1Pin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);

Krok 7: Rozpocznij

Polecenie begin służy do uruchamiania portu szeregowego i pinów w trybie wejścia i wyjścia.

nieważny początek();

w wykonaniu jest

// Uruchom wszystkie piny i UART

e32ttl100.begin();

Krok 8: Metoda konfiguracji i informacji

Istnieje zestaw metod zarządzania konfiguracją i uzyskiwania informacji o urządzeniu.

ResponseStructContainer getConfiguration();

ResponseStatus setConfiguration(Konfiguracja konfiguracji, PROGRAM_COMMAND saveType = WRITE_CFG_PWR_DWN_LOSE);

ResponseStructContainer getModuleInformation();

void printParameters(struktura konfiguracji konfiguracji);

ResponseStatus resetModule();

Krok 9: Kontener odpowiedzi

Aby uprościć zarządzanie odpowiedziami, tworzę zestaw kontenerów, które są dla mnie bardzo przydatne do zarządzania błędami i zwracania danych generycznych.

Stan odpowiedzi

Jest to kontener statusu i ma 2 proste punkty wejścia, dzięki czemu możesz uzyskać kod statusu i opis kodu statusu

Serial.println(c.getResponseDescription()); // Opis kodu

Serial.println(c.kod); // 1 jeśli sukces

Kod są

SUKCES = 1, ERR_UNKNOWN, ERR_NOT_SUPPORT, ERR_NOT_IMPLEMENT, ERR_NOT_INITIAL, ERR_INVALID_PARAM, ERR_DATA_SIZE_NOT_MATCH, ERR_BUF_TOO_SMALL, ERR_TIMEOUT, ERR_HARDWARE, ERR_HEAD_NOT_RECOGNIZED

Kontener odpowiedzi

Ten kontener jest tworzony do zarządzania odpowiedzią ciągu i ma 2 punkty wejścia.

dane z ciągiem zwróconym z komunikatu i statusem wystąpienia RepsonseStatus.

Kontener Odpowiedzi rs = e32ttl.receiveMessage();

Wiadomość ciąg = rs.data;

Serial.println(rs.status.getResponseDescription());

Serial.println(wiadomość);

Kontener struktury odpowiedzi

Jest to bardziej „złożony” kontener, używam go do zarządzania strukturą. Ma ten sam punkt wejścia co ResponseContainer, ale dane są pustym wskaźnikiem do zarządzania złożoną strukturą.

ResponseStructContainer c;

c = e32ttl100.getConfiguration();// Ważne jest, aby uzyskać wskaźnik konfiguracji przed wszystkimi innymi operacjami

Konfiguracja konfiguracji = *(Konfiguracja*) c.data;

Serial.println(c.status.getResponseDescription());

Serial.println(c.status.kod);

getConfiguration i setConfiguration

Pierwsza metoda to getConfiguration, możesz jej użyć do odzyskania wszystkich danych przechowywanych na urządzeniu.

ResponseStructContainer getConfiguration();

Oto przykład użycia.

ResponseStructContainer c;

c = e32ttl100.getConfiguration();// Ważne jest, aby uzyskać wskaźnik konfiguracji przed wszystkimi innymi operacjami

Konfiguracja konfiguracji = *(Konfiguracja*) c.data;

Serial.println(c.status.getResponseDescription());

Serial.println(c.status.kod);

Serial.println(konfiguracja. SPED.getUARTBaudRate());

Struktura konfiguracji zawiera wszystkie dane ustawień i dodaję szereg funkcji, aby uzyskać cały opis pojedynczych danych.

konfiguracja. ADDL = 0x0; // Pierwsza część adresuconfiguration. ADDH = 0x1; // Druga część konfiguracji adresu. CHAN = 0x19;// Konfiguracja kanału. OPTION.fec = FEC_0_OFF; // Przekaż konfigurację przełącznika korekcji błędów. OPTION.fixedTransmission = FT_TRANSPARENT_TRANSMISSION; // Konfiguracja trybu transmisji. OPTION.ioDriveMode = IO_D_MODE_PUSH_PULLS_PULL_UPS; // Konfiguracja zarządzania pull-up. OPTION.transmissionPower = POWER_17; // konfiguracja mocy transmisji dBm. OPTION.wirelessWakeupTime = WAKE_UP_1250; // Czas oczekiwania na wybudzenie configuration. SPED.airDataRate = AIR_DATA_RATE_011_48; // Konfiguracja szybkości transmisji danych. SPED.uartBaudRate = UART_BPS_115200; // Konfiguracja szybkości transmisji komunikacji. SPED.uartParity = MODE_00_8N1; // Bit parzystości

Masz równoważną funkcję dla wszystkich atrybutów, aby uzyskać cały opis:

Serial.print(F("Chan: ")); Serial.print(konfiguracja. CHAN, DEC); Serial.print(" -> "); Serial.println(configuration.getChannelDescription());Serial.println(F(" ")); Serial.print(F("SpeedParityBit: ")); Serial.print(konfiguracja. SPED.uartParity, BIN);Serial.print("->"); Serial.println(konfiguracja. SPED.getUARTParityDescription()); Serial.print(F("DataPrędkościUART: ")); Serial.print(konfiguracja. SPED.uartBaudRate, BIN);Serial.print("->"); Serial.println(konfiguracja. SPED.getUARTBaudRate()); Serial.print(F("SpeedAirDataRate: ")); Serial.print(konfiguracja. SPED.airDataRate, BIN);Serial.print("->"); Serial.println(konfiguracja. SPED.getAirDataRate()); Serial.print(F("OptionTrans: ")); Serial.print(konfiguracja. OPCJA.fixedTransmission, BIN);Serial.print("->"); Serial.println(konfiguracja. OPCJA.getFixedTransmissionDescription()); Serial.print(F("OptionPullup: ")); Serial.print(konfiguracja. OPCJA.ioDriveMode, BIN);Serial.print("->"); Serial.println(konfiguracja. OPCJA.getIODroveModeDescription()); Serial.print(F("OpcjaWakeup: ")); Serial.print(konfiguracja. OPCJA.wirelessWakeupTime, BIN);Serial.print(" -> "); Serial.println(konfiguracja. OPCJA.getWirelessWakeUPTimeDescription()); Serial.print(F("OpcjaFEC: ")); Serial.print(konfiguracja. OPCJA.fec, BIN);Serial.print("->"); Serial.println(konfiguracja. OPCJA.getFECDescription()); Serial.print(F("OpcjaMoc: ")); Serial.print(konfiguracja. OPCJA.transmissionPower, BIN);Serial.print("->"); Serial.println(konfiguracja. OPCJA.getTransmissionPowerDescription());

W ten sam sposób setConfiguration chce struktury konfiguracji, więc myślę, że lepszym sposobem zarządzania konfiguracją jest pobranie bieżącej, zastosowanie jedynej potrzebnej zmiany i ponowne ustawienie.

ResponseStatus setConfiguration(Konfiguracja konfiguracji, PROGRAM_COMMAND saveType = WRITE_CFG_PWR_DWN_LOSE);

Konfiguracja jest strukturą pokazaną wcześniej, saveType pozwala wybrać, czy zmiana zostanie trwale ustawiona tylko na bieżącą sesję.

ResponseStructContainer c;c = e32ttl100.getConfiguration(); // Ważne jest, aby uzyskać wskaźnik konfiguracji przed wszystkimi innymi operacjami Configuration configuration = *(Configuration*) c.data; Serial.println(c.status.getResponseDescription()); Serial.println(c.status.kod); printParameters(konfiguracja); konfiguracja. ADDL = 0x0; konfiguracja. ADDH = 0x1; konfiguracja. KANAŁ = 0x19; konfiguracja. OPCJA.fec = FEC_0_OFF; configuration. OPTION.fixedTransmission = FT_TRANSPARENT_TRANSMISSION; konfiguracja. OPTION.ioDriveMode = IO_D_MODE_PUSH_PULLS_PULL_UPS; konfiguracja. OPCJA.moc transmisji = MOC_17; configuration. OPTION.wirelessWakeupTime = WAKE_UP_1250; configuration. SPED.airDataRate = AIR_DATA_RATE_011_48; konfiguracja. SPED.uartBaudRate = UART_BPS_115200; konfiguracja. SPED.uartParity = MODE_00_8N1; // Ustaw konfigurację zmienioną i ustaw, aby nie przechowywać konfiguracji ResponseStatus rs = e32ttl100.setConfiguration(configuration, WRITE_CFG_PWR_DWN_LOSE); Serial.println(rs.getResponseDescription()); Serial.println(rs.kod); printParameters(konfiguracja);

Wszystkie parametry są zarządzane jako stałe:

Krok 10: Podstawowa opcja konfiguracji

Podstawowa opcja konfiguracji
Podstawowa opcja konfiguracji

Krok 11: Wyślij wiadomość do odbioru

Najpierw musimy wprowadzić prostą, ale użyteczną metodę sprawdzania, czy coś jest w buforze odbiorczym

dostępne();

Po prostu zwraca, ile bajtów masz w bieżącym strumieniu.

Krok 12: Normalny tryb transmisji

Normalny tryb transmisji
Normalny tryb transmisji

Tryb transmisji Normal/Transparent służy do wysyłania wiadomości do wszystkich urządzeń o tym samym adresie i kanale.

Istnieje wiele metod wysyłania/odbierania wiadomości, wyjaśnimy szczegółowo:

ResponseStatus sendMessage(const String wiadomość);

ResponseContainer odbierzMessage();

Pierwsza metoda to sendMessage i służy do wysyłania ciągu do urządzenia w trybie normalnym.

ResponseStatus rs = e32ttl.sendMessage("Prova");Serial.println(rs.getResponseDescription());

Drugie urządzenie po prostu działa w pętli

if (e32ttl.available() > 1){ResponseContainer rs = e32ttl.receiveMessage(); Wiadomość ciąg = rs.data; // Najpierw pobierz dane Serial.println(rs.status.getResponseDescription()); Serial.println(wiadomość); }

Krok 13: Zarządzaj strukturą

Jeśli chcesz wysłać złożoną strukturę, możesz skorzystać z tej metody

ResponseStatus sendMessage(const void *wiadomość, const uint8_t rozmiar);ResponseStructContainer odbiór wiadomości(const uint8_t rozmiar);

Służy do wysyłania struktur, na przykład:

struct Messaggione {typ znaku[5]; wiadomość znakowa[8]; bool mitico; }; struct Messaggione messaggione = {"TEMP", "Peple", prawda}; ResponseStatus rs = e32ttl.sendMessage(&messaggione, sizeof(Messaggione)); Serial.println(rs.getResponseDescription());

a po drugiej stronie możesz otrzymać wiadomość, więc

ResponseStructContainer rsc = e32ttl.receiveMessage(sizeof(Messaggione));struct Messaggione messaggione = *(Messaggione*) rsc.data; Serial.println(wiadomość.wiadomość); Serial.println(messaggione.mitico);

Przeczytaj częściową strukturę

Jeśli chcesz przeczytać pierwszą część wiadomości, aby zarządzać większą ilością struktur, możesz skorzystać z tej metody.

ResponseContainer odbierzInitialMessage(const uint8_t size);

Tworzę go, aby otrzymać ciąg z typem lub innym w celu identyfikacji struktury do załadowania.

struct Messaggione { // Częściowa struktura bez typechar message[8]; bool mitico; }; typ znaku[5]; // pierwsza część struktury ResponseContainer rs = e32ttl.receiveInitialMessage(sizeof(type)); // Wstaw ciąg znaków do tablicy znaków (niepotrzebne) memcpy (type, rs.data.c_str(), sizeof(type)); Serial.println("TYP ODCZYTU: "); Serial.println(rs.status.getResponseDescription()); Serial.println(typ); // Odczytaj resztę struktury ResponseStructContainer rsc = e32ttl.receiveMessage(sizeof(Messaggione)); struct Messaggione messaggione = *(Messaggione*) rsc.data;

Krok 14: Tryb stały zamiast trybu normalnego

W ten sam sposób tworzę zestaw metod do użycia ze stałą transmisją

Transmisja stała

Należy zmienić tylko metodę wysyłania, ponieważ urządzenie docelowe nie otrzymuje preambuły w trybie Adres i Kanał quando settato il fixed.

Więc dla wiadomości String masz

ResponseStatus sendFixedMessage(bajt ADDL, bajt ADDH, bajt CHAN, const String komunikat);ResponseStatus sendBroadcastFixedMessage(bajt CHAN, const String komunikat);

i za strukturę, którą masz

ResponseStatus sendFixedMessage(bajt ADDL, bajt ADDH, bajt CHAN, const void *wiadomość, const uint8_t rozmiar);Status odpowiedzi sendBroadcastFixedMessage(bajt CHAN, const void *wiadomość, const uint8_t rozmiar);

Oto prosty przykład

ResponseStatus rs = e32ttl.sendFixedMessage(0, 0, 0x17, &messaggione, sizeof(Messaggione));// ResponseStatus rs = e32ttl.sendFixedMessage(0, 0, 0x17, "Ciao");

Transmisja stała ma więcej scenariuszy

Jeśli wysyłasz do konkretnego urządzenia (scenariusze drugie Transmisja stała) musisz dodać ADDL, ADDH i CHAN, aby bezpośrednio je zidentyfikować.

ResponseStatus rs = e32ttl.sendFixedMessage(2, 2, 0x17, "Wiadomość do urządzenia");

Jeśli chcesz wysłać wiadomość do wszystkich urządzeń w określonym kanale, możesz użyć tej metody.

ResponseStatus rs = e32ttl.sendBroadcastFixedMessage(0x17, "Wiadomość do urządzeń kanału");

Jeśli chcesz otrzymywać wszystkie wiadomości rozgłoszeniowe w sieci, musisz ustawić ADDH i ADDL z BROADCAST_ADDRESS.

ResponseStructContainer c;c = e32ttl100.getConfiguration(); // Ważne jest, aby uzyskać wskaźnik konfiguracji przed wszystkimi innymi operacjami Configuration configuration = *(Configuration*) c.data; Serial.println(c.status.getResponseDescription()); Serial.println(c.status.kod); printParameters(konfiguracja); konfiguracja. ADDL = BROADCAST_ADDRESS; konfiguracja. ADDH = BROADCAST_ADDRESS; // Ustaw konfigurację zmienioną i ustaw, aby nie przechowywać konfiguracji ResponseStatus rs = e32ttl100.setConfiguration(configuration, WRITE_CFG_PWR_DWN_LOSE); Serial.println(rs.getResponseDescription()); Serial.println(rs.kod); printParameters(konfiguracja);

Krok 15: Dzięki

Teraz masz wszystkie informacje do wykonania swojej pracy, ale myślę, że ważne jest, aby pokazać kilka realistycznych przykładów, aby lepiej zrozumieć wszystkie możliwości.

  1. Urządzenie LoRa E32 dla Arduino, esp32 lub esp8266: ustawienia i podstawowe użytkowanie
  2. Urządzenie LoRa E32 dla Arduino, esp32 lub esp8266: biblioteka
  3. Urządzenie LoRa E32 dla Arduino, esp32 lub esp8266: konfiguracja
  4. Urządzenie LoRa E32 dla Arduino, esp32 lub esp8266: poprawiona transmisja
  5. Urządzenie LoRa E32 dla Arduino, esp32 lub esp8266: oszczędzanie energii i wysyłanie uporządkowanych danych

Zalecana: