Ebyte LoRa E32 per Arduino, esp32 o esp8266: libreria – 2

Spread the love

Visto l’impiego che ne sto facendo ho voluto creare una libreria per gestire la serie LoRa EBYTE E32, basati sul Semtech sx1278/sx1276, un dispositivo molto potente, semplice ed economico.

LoRa E32-TTL-100

Puoi trovare il modulo qui AliExpress (433MHz 5Km) - AliExpress (433MHz 8Km) - AliExpress (433MHz 16Km) - AliExpress (868MHz 915MHz 5.5Km) - AliExpress (868MHz 915MHz 8Km)

Possono lavorare su una distanza dai 3000 agli 8000m e hanno molte caratteristiche e parametri.

Quindi creo questa libreria per semplificarne l’utilizzo.

Libreria

Puoi trovare la mia libreria qui.

And It’s available on Arduino IDE library manager.

EByte LoRa E22 E32 Arduino library manager
EByte LoRa E22 E32 Arduino library manager

Per scaricare.

Clicca il bottone DOWNLOADS sull’angolo in alto a destra, rinomila la cartella decompressa LoRa_E32.

Controlla che la cartella LoRa_E32 contenga LoRa_E32.cpp e LoRa_E32.h.

posizione la cartella della libreria LoRa_E32 sulla tua cartella /libraries/.

Dovrai creare la sotto cartella librarues se è la tua prima libreria.

Riavvia l’IDE.

Pinout

sx1278 sx1276 wireless lora uart module serial 3000m arduino 433 rf
Pin No.Pin itemPin directionPin application
1M0Input(weak pull-up)Lavora con M1 e decide le quattro modalità operative. Non può essere lasciato libero, può essere messo a terra.
2M1Input(weak pull-up)Lavora con M1 e decide le quattro modalità operative. Non può essere lasciato libero, può essere messo a terra.
3RXDInputIngressi UART TTL, connessione a pin di uscita TXD esterno (MCU, PC). Può essere configurato come ingresso open-drain o pull-up.
4TXDOutputUscite TTL UART, si collega all’inputpin esterno RXD (MCU, PC). Può essere configurato come uscita open-drain o push-pull

5

AUX

Output
Per indicare lo stato di funzionamento del modulo e riattivare l’MCU esterno. Durante la procedura di inizializzazione di autocontrollo, il pin emette una bassa tensione. Può essere configurato come uscita open-drain o output push-pull (è consentito non metterlo a terra, ma se hai problemi, ad esempio ti si freeze il dispositivo è preferibile mettere una restistenza di pull-up da 4.7k o meglio collegarlo al dispositivo).
6VCCAlimentazione 2.3V~5.5V DC
7GNDTerra

Come puoi vedere, puoi impostare varie modalità tramite i pin M0 e M1.

ModalitàM1M0Descrizione
Normal00UART e il canale wireless sono a attivi
Wake-Up01Come normale ma viene aggiunto un codice di preambolo ai dati trasmessi per riattivare il ricevitore.
Power-Saving10UART è disabilitato e il wireless è in modalità WOR (wake on radio), il che significa che il dispositivo si accenderà quando ci sono dati da ricevere. La trasmissione non è consentita.
Sleep11Utilizzato nell’impostazione dei parametri. Trasmissione e ricezione disabilitate.

Ci sono alcuni pin che possono essere usati in modo statico, ma se li colleghi al microcontrollore e li fai gestire alla libreria ottieni prestazioni migliori e puoi controllare tutte le modalità tramite software, ma spiegheremo meglio in seguito.

Schema di connessione completo

Come già detto, non è importante collegare tutti i pin all’uscita del microcontrollore, è possibile impostare i pin M0 e M1 su HIGH o LOW per ottenere la configurazione desiderata e, se non si collega il pin AUX, la libreria imposterà un ritardo ragionevole per essere sicuri che l’operazione sia completa, ma se hai problemi, ad esempio ti si freeze il dispositivo è preferibile mettere una restistenza di pull-up da 4.7k o meglio collegarlo al dispositivo .

AUX pin

Durante la trasmissione dei dati può essere utilizzato per riattivare l’MCU esterno e restituirà HIGH al termine del trasferimento dei dati.

LoRa E32 AUX Pin on transmission

Quando si riceve AUX viene impostato a LOW e restituisce HIGH quando il buffer è svuotato.

LoRa e32 AUX pin on reception

Viene anche utilizzato quando effettua l’autocontrollo per ripristinare il normale funzionamento (all’accensione ed in modalità sospensione/programma).

LoRa e32 AUX pin on self-check

Lo schema di connessione esp8266 è più semplice perché funziona alla stessa tensione delle comunicazioni logiche (3.3 v).

LoRa E32 TTL 100 Wemos D1 fully connected

È importante aggiungere una resistenza di pull-up (4,7Kohm) per ottenere una buona stabilità.

M0D7
M1D6
TXPIN D2 (PullUP 4,7KΩ)
RXPIN D3 (PullUP 4,7KΩ)
AUXD5 (Input)
VCC3.3v
GNDGND

La tensione di lavoro di Arduino è 5v, quindi è necessario aggiungere un partitore di tensione sul pin RX del modulo LoRa per prevenire danni, è possibile ottenere maggiori informazioni qui Partitore di tensione (voltage divider): calcolatore e applicazioni.

È possibile utilizzare una resistenza da 2Kohm su GND e 1Kohm dal segnale e poi insieme su RX.

LoRa E32 TTL 100 Arduino fully connected
M07 (Voltage divider)
M16 (Voltage divider)
TXPIN 2 (PullUP 4,7KΩ)
RXPIN 3 (PullUP 4,7KΩ & Voltage divider)
AUX5 (Input)
VCC3.3v
GNDGND
Ebyte LoRa E22 device esp32 dev kit v1 breadboard full connection
Ebyte LoRa E22 device esp32 dev kit v1 breadboard full connection
M0D21
M1D19
TXPIN RX2 (PullUP 4,7KΩ)
RXPIN TX3 (PullUP 4,7KΩ)
AUXPIN D18 (PullUP 4,7KΩ) (D15 to wake up)
VCC5V (but work with less power in 3.3v)
GNDGND
Ebyte LoRa Exx Arduino MKR WiFi 1010 Fully connected breadboard
Ebyte LoRa Exx Arduino MKR WiFi 1010 Fully connected breadboard
M02 (voltage divider)
M13 (voltage divider)
TXPIN 14 Tx (PullUP 4,7KΩ)
RXPIN 13 Rx (PullUP 4,7KΩ)
AUXPIN 1 (PullUP 4,7KΩ)
VCC5V
GNDGND

Costruttori

Ho creato una serie di costruttori abbastanza numerosi, perché possiamo avere più opzioni e situazioni da gestire.

		LoRa_E32(byte txE32pin, byte rxE32pin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);
		LoRa_E32(byte txE32pin, byte rxE32pin, byte auxPin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);
		LoRa_E32(byte txE32pin, byte rxE32pin, byte auxPin, byte m0Pin, byte m1Pin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);

Il primo set di costruttori è stato creato per delegare la gestione della seriale software e altri pin alla libreria.

  • rxPin e txPin sono i pin per connettersi all’UART e sono obbligatori.
  • auxPin è un pin che controlla lo stato delle operazioni, come la trasmissione e lo stato di ricezione (spiegheremo meglio in seguito), quel pin non è obbligatorio, se non lo si imposta applico un ritardo per consentire all’operazione di completarsi (con latenza maggiore, ma se hai problemi, ad esempio ti si freeze il dispositivo è preferibile mettere una restistenza di pull-up da 4.7k o meglio collegarlo al dispositivo ).
  • m0pin e m1Pin sono i pin per cambiare il funzionamento MODE (vedere la tabella in alto), penso che questi pin in “produzione” si collegheranno direttamente HIGH o LOW, ma per il test è utile farli gestire dalla libreria.
  • bpsRate è il baud rate della seriale normalmente è 9600 (l’unico baud rate in modalità programmin/sleep)

Un semplice esempio è:

#include "LoRa_E32.h"

LoRa_E32 e32ttl100(2, 3); // e32 TX e32 RX
// LoRa_E32 e32ttl100(2, 3, 5, 6, 7); // e32 TX e32 RX

Possiamo usare direttamente un SoftwareSerial con un altro costruttore

		LoRa_E32(HardwareSerial* serial, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);
		LoRa_E32(HardwareSerial* serial, byte auxPin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);
		LoRa_E32(HardwareSerial* serial, byte auxPin, byte m0Pin, byte m1Pin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);

L’esempio sopra può essere fatto così.

#include <SoftwareSerial.h>
#include "LoRa_E32.h"

SoftwareSerial mySerial(2, 3); // e32 TX e32 RX
LoRa_E32 e32ttl100(&mySerial);
// LoRa_E32 e32ttl100(&mySerial, 5, 7, 6);

L’ultimo set di costruttori è consente l’uso di un HardwareSerial anziché di nu SoftwareSerial.

		LoRa_E32(SoftwareSerial* serial, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);
		LoRa_E32(SoftwareSerial* serial, byte auxPin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);
		LoRa_E32(SoftwareSerial* serial, byte auxPin, byte m0Pin, byte m1Pin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);

Per gli esp32 ci sono 3 costruttori specifici in aggiunta, così da permettere di impostare i pin per l’HardWare serial

			LoRa_E32(HardwareSerial* serial, byte txE32pin, byte rxE32pin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600, uint32_t serialConfig = SERIAL_8N1);
			LoRa_E32(HardwareSerial* serial, byte txE32pin, byte rxE32pin, byte auxPin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600, uint32_t serialConfig = SERIAL_8N1);
			LoRa_E32(HardwareSerial* serial, byte txE32pin, byte rxE32pin, byte auxPin, byte m0Pin, byte m1Pin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600, uint32_t serialConfig = SERIAL_8N1);

Breaking change per i costruttori dell’esp32 per la gestione dinamica dei pin sull’HardareSerial, ora la referenza dell’HardwareSerial è dopo la dichiarazione dei pins per irmuovere l’ambiguità dei costruttori

Begin

Il comando begin viene utilizzato per avviare seriale e pin in modalità input e output.

void begin();

in esecuzione sarà:

	// Startup all pins and UART
	e32ttl100.begin();

Metodo per configurazione ed informazioni

Esiste una serie di metodi per gestire la configurazione e ottenere informazioni sul dispositivo.

		ResponseStructContainer getConfiguration();
		ResponseStatus setConfiguration(Configuration configuration, PROGRAM_COMMAND saveType = WRITE_CFG_PWR_DWN_LOSE);

		ResponseStructContainer getModuleInformation();
        void printParameters(struct Configuration configuration);
        ResponseStatus resetModule();

Response container

Per semplificare la gestione della risposta, ho creato un insieme di contenitori, per me utili per gestire gli errori e restituire dati generici.

ResponseStatus

Questo è un contenitore di stato e ha 2 semplici punti di ingresso, da qui puoi ottenere il codice di stato e la descrizione del codice di stato

	Serial.println(c.getResponseDescription()); // Description of code
	Serial.println(c.code); // 1 if Success

I codici restituiti sono:

  SUCCESS = 1,
  ERR_E32_UNKNOWN,
  ERR_E32_NOT_SUPPORT,
  ERR_E32_NOT_IMPLEMENT,
  ERR_E32_NOT_INITIAL,
  ERR_E32_INVALID_PARAM,
  ERR_E32_DATA_SIZE_NOT_MATCH,
  ERR_E32_BUF_TOO_SMALL,
  ERR_E32_TIMEOUT,
  ERR_E32_HARDWARE,
  ERR_E32_HEAD_NOT_RECOGNIZED
ResponseContainer

Questo contenitore è stato creato per gestire la risposta in formato stringa e ha 2 punti di ingresso.

data che corrisponde alla stringa ritornata dal messaggio e status un’istanza del RepsonseStatus.

		ResponseContainer rs = e32ttl.receiveMessage();
		String message = rs.data;

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

Questo è il contenitore più “complesso”, lo uso per gestire la struttura, ha lo stesso punto di ingresso di ResponseContainer ma i dati sono un puntatore void per gestire la struttura complessa.

	ResponseStructContainer c;
	c = e32ttl100.getConfiguration();
	// It's important get configuration pointer before all other operation
	Configuration configuration = *(Configuration*) c.data;
	Serial.println(c.status.getResponseDescription());
	Serial.println(c.status.code);
        c.close();

Presta attenzione, ogni volta che richiami ResponseStructContainer devi richiamare la relativa close() per liberare la memoria allocata.

getConfiguration e setConfiguration

Il primo metodo è getConfiguration, e permette di recuperare tutti i dati di configurazione memorizzati sul dispositivo.

		ResponseStructContainer getConfiguration();

Ecco un semplice esempio:

	ResponseStructContainer c;
	c = e32ttl100.getConfiguration();
	// It's important get configuration pointer before all other operation
	Configuration configuration = *(Configuration*) c.data;
	Serial.println(c.status.getResponseDescription());
	Serial.println(c.status.code);
        Serial.println(configuration.SPED.getUARTBaudRate());
        c.close();

La struttura della configurazione ha tutti i dati delle impostazioni e aggiungo una serie di funzioni per ottenere tutta la descrizione dei singoli dati.

	configuration.ADDL = 0x0; // First part of address
	configuration.ADDH = 0x1; // Second part of address
	configuration.CHAN = 0x19;// Channel

	configuration.OPTION.fec = FEC_0_OFF; // Forward error correction switch
	configuration.OPTION.fixedTransmission = FT_TRANSPARENT_TRANSMISSION; // Transmission mode
	configuration.OPTION.ioDriveMode = IO_D_MODE_PUSH_PULLS_PULL_UPS; // Pull-up management
	configuration.OPTION.transmissionPower = POWER_17; // dBm transmission power 
	configuration.OPTION.wirelessWakeupTime = WAKE_UP_1250; // Wait time for wake up

	configuration.SPED.airDataRate = AIR_DATA_RATE_011_48; // Air data rate
	configuration.SPED.uartBaudRate = UART_BPS_115200; // Communication baud rate
	configuration.SPED.uartParity = MODE_00_8N1; // Parity bit

Hai una funzione equivalente ad ogni attributo per ottenere la descrizione:

	Serial.print(F("Chan : "));  Serial.print(configuration.CHAN, DEC); Serial.print(" -> "); Serial.println(configuration.getChannelDescription());
	Serial.println(F(" "));
	Serial.print(F("SpeedParityBit     : "));  Serial.print(configuration.SPED.uartParity, BIN);Serial.print(" -> "); Serial.println(configuration.SPED.getUARTParityDescription());
	Serial.print(F("SpeedUARTDatte  : "));  Serial.print(configuration.SPED.uartBaudRate, BIN);Serial.print(" -> "); Serial.println(configuration.SPED.getUARTBaudRate());
	Serial.print(F("SpeedAirDataRate   : "));  Serial.print(configuration.SPED.airDataRate, BIN);Serial.print(" -> "); Serial.println(configuration.SPED.getAirDataRate());

	Serial.print(F("OptionTrans        : "));  Serial.print(configuration.OPTION.fixedTransmission, BIN);Serial.print(" -> "); Serial.println(configuration.OPTION.getFixedTransmissionDescription());
	Serial.print(F("OptionPullup       : "));  Serial.print(configuration.OPTION.ioDriveMode, BIN);Serial.print(" -> "); Serial.println(configuration.OPTION.getIODroveModeDescription());
	Serial.print(F("OptionWakeup       : "));  Serial.print(configuration.OPTION.wirelessWakeupTime, BIN);Serial.print(" -> "); Serial.println(configuration.OPTION.getWirelessWakeUPTimeDescription());
	Serial.print(F("OptionFEC          : "));  Serial.print(configuration.OPTION.fec, BIN);Serial.print(" -> "); Serial.println(configuration.OPTION.getFECDescription());
	Serial.print(F("OptionPower        : "));  Serial.print(configuration.OPTION.transmissionPower, BIN);Serial.print(" -> "); Serial.println(configuration.OPTION.getTransmissionPowerDescription());

Allo stesso modo setConfiguration vuole una struttura Configuration, e penso che il modo migliore per gestire la configurazione sia recuperare quella attuale, applicare l’unica modifica necessaria e reimpostarla.

		ResponseStatus setConfiguration(Configuration configuration, PROGRAM_COMMAND saveType = WRITE_CFG_PWR_DWN_LOSE);

configuration è la struttura vista prima, saveType permette di rendere persistente le scelte che tu hai fatto, in alternativa dureranno fino al riavvio.

	ResponseStructContainer c;
	c = e32ttl100.getConfiguration();
	// It's important get configuration pointer before all other operation
	Configuration configuration = *(Configuration*) c.data;
	Serial.println(c.status.getResponseDescription());
	Serial.println(c.status.code);

	printParameters(configuration);
	configuration.ADDL = 0x0;
	configuration.ADDH = 0x1;
	configuration.CHAN = 0x19;

	configuration.OPTION.fec = FEC_0_OFF;
	configuration.OPTION.fixedTransmission = FT_TRANSPARENT_TRANSMISSION;
	configuration.OPTION.ioDriveMode = IO_D_MODE_PUSH_PULLS_PULL_UPS;
	configuration.OPTION.transmissionPower = POWER_17;
	configuration.OPTION.wirelessWakeupTime = WAKE_UP_1250;

	configuration.SPED.airDataRate = AIR_DATA_RATE_011_48;
	configuration.SPED.uartBaudRate = UART_BPS_115200;
	configuration.SPED.uartParity = MODE_00_8N1;

	// Set configuration changed and set to not hold the configuration
	ResponseStatus rs = e32ttl100.setConfiguration(configuration, WRITE_CFG_PWR_DWN_LOSE);
	Serial.println(rs.getResponseDescription());
	Serial.println(rs.code);
	printParameters(configuration);

I parametri sono tutti gestiti come costanti:

Opzioni base della configurazione

ADDHIndirizzo High del modulo (impostazione predefinita 00H)00H-FFH
ADDL Indirizzo Low del modulo (impostazione predefinita 00H) 00H-FFH
SPEDInformazioni sul bit di parità della velocità dei dati e sulla velocità dei dati via etere
CHANCanale di comunicazione(410M + CHAN*1M), default 17H (433MHz), valido solo per i dispositivi a 433Mhz controlla sotto per cambiare la frequenza00H-1FH
OPTIONTipo di trasmissione, impostazioni di pull-up, tempo di sveglia, FEC, potenza di trasmissione

SPED detail

Bit di parità UART: la modalità UART può essere diversa tra le parti di comunicazione

76 UART parity bit Constant value
008N1 (default)MODE_00_8N1
018O1MODE_01_8O1
108 E1MODE_10_8E1
118N1 (equal to 00)MODE_11_8N1

Velocità di trasmissione UART: la velocità di trasmissione UART può essere diversa tra le parti di comunicazione, la velocità di trasmissione UART non ha nulla a che fare con i parametri di trasmissione wireless e non influisce sulle funzioni di trasmissione/ricezione wireless.

543 TTL UART baud rate(bps) Constant value
0001200UART_BPS_1200
0012400UART_BPS_2400
0104800UART_BPS_4800
0119600 (default)UART_BPS_9600
10019200UART_BPS_19200
10138400UART_BPS_38400
11057600UART_BPS_57600
111115200UART_BPS_115200

Air data rate: più bassa è l’Air data rate, più lunga è la distanza di trasmissione, migliori prestazioni anti-interferenza e tempo di trasmissione più lungo. L’ Air data rate deve essere la stessa per entrambe le parti di comunicazione.

210 Air data rate(bps) Constant value
0000.3kAIR_DATA_RATE_000_03
0011.2kAIR_DATA_RATE_001_12
0102.4k (default)AIR_DATA_RATE_010_24
0114.8kAIR_DATA_RATE_011_48
1009.6kAIR_DATA_RATE_100_96
10119.2kAIR_DATA_RATE_101_192
11019.2k (same to 101)AIR_DATA_RATE_110_192
11119.2k (same to 101)AIR_DATA_RATE_111_192

OPTION detail

Modalità di trasmissione: in modalità di trasmissione fissa, i primi tre byte del frame di dati di ciascun utente possono essere utilizzati come indirizzo alto/basso e canale. Il modulo cambia indirizzo e canale durante la trasmissione. E tornerà alle impostazioni originali dopo aver completato il processo.

7 Fixed transmission enabling bit(similar to MODBUS) Constant value
0Transparent transmission modeFT_TRANSPARENT_TRANSMISSION
1Fixed transmission modeFT_FIXED_TRANSMISSION

Modalità IO-Drive: questo bit viene utilizzato per la resistenza di pull-up interna del modulo. Aumenta anche l’adattabilità del livello in caso di scarico aperto. Ma in alcuni casi potrebbe essere necessario un resistore pull-up esterno.

6 IO drive mode ( default 1) Constant value
1TXD and AUX push-pull outputs, RXD pull-up inputsIO_D_MODE_PUSH_PULLS_PULL_UPS
0TXD AUX open-collector outputs, RXD open-collector inputsIO_D_MODE_OPEN_COLLECTOR

Tempo di sveglia wireless: se il modulo di trasmissione e ricezione funziona in modalità 0, il tempo di ritardo non è valido e può essere un valore arbitrario. Se il trasmettitore funziona in modalità 1 trasmetterà continuamente il codice del preambolo del tempo di wake-up corrispondente, quando il ricevitore funziona in modalità 2, il wake-up time indica l’intervallo di monitoraggio. È possibile ricevere solo i dati dal trasmettitore che funziona in modalità 1 (serve il preabolo).

543 Wireless wake-up time Constant value
000250ms (default)WAKE_UP_250
001500msWAKE_UP_500
010750msWAKE_UP_750
0111000msWAKE_UP_1000
1001250msWAKE_UP_1250
1011500msWAKE_UP_1500
1101750msWAKE_UP_1750
1112000msWAKE_UP_2000

FEC: dopo aver disattivato FEC, la velocità di trasmissione dati effettiva aumenta mentre diminuisce la capacità anti-interferenza. Inoltre, la distanza di trasmissione è relativamente breve, entrambe le parti della comunicazione devono avere gli stessi valori.

2 FEC switch Constant value
0Turn off FECFEC_0_OFF
1Turn on FEC (default)FEC_1_ON
Potenza trasmissione

È possibile modificare questo insieme di costanti applicando una definizione in questo modo:

#define E32_TTL_100 // default value without set 

Applicabile per E32-TTL-100, E32-TTL-100S1, E32-T100S2.
L’alimentazione esterna deve garantire la capacità di uscita di corrente superiore a 250 mA e garantire un’ondulazione di alimentazione entro 100 mV.
La trasmissione a bassa potenza non è consigliata a causa della sua bassa efficienza di alimentazione.

#define E32_TTL_100 // default value without set 
10 Transmission power (approximation) Constant value
0020dBm (default)POWER_20
0117dBmPOWER_17
1014dBmPOWER_14
1110dBmPOWER_10

Applicabile per E32-TTL-500.
L’alimentazione esterna deve garantire la capacità di uscita di corrente superiore a 700 mA e garantire un’ooscillazione dell’alimentazione entro i 100 mV.
La trasmissione a bassa potenza non è consigliata a causa della sua bassa efficienza di alimentazione.

#define E32_TTL_500
10 Transmission power (approximation) Constant value
0027dBm (default)POWER_27
0124dBmPOWER_24
1021dBmPOWER_21
1118dBmPOWER_18

Applicabile per E32-TTL-1W, E32 (433T30S), E32 (868T30S), E32 (915T30S)
L’alimentazione esterna deve garantire la capacità di uscita di corrente superiore a 1A e garantire un’ondulazione di alimentazione entro 100 mV.
La trasmissione a bassa potenza non è consigliata a causa della sua bassa efficienza di alimentazione.

#define E32_TTL_1W
10 Transmission power (approximation) Constant value
0030dBm (default)POWER_30
0127dBmPOWER_27
1024dBmPOWER_24
1121dBmPOWER_21

È possibile configurare la frequenza del canale anche con queste define:

// One of 
#define FREQUENCY_433 
#define FREQUENCY_170
#define FREQUENCY_470
#define FREQUENCY_868
#define FREQUENCY_915

Inviare e ricevere messaggi

Per prima cosa dobbiamo introdurre un metodo semplice ma utile per verificare se c’è qualcosa nel buffer di ricezione

int available();

Restituisce semplicemente quanti byte hai nel flusso corrente.

Normal transmission mode

La modalità di trasmissione normale / trasparente viene utilizzata per inviare messaggi a tutti i dispositivi con lo stesso indirizzo e canale.

LoRa E32 transmitting scenarios, lines are channels

Esistono molti metodi per inviare / ricevere messaggi, spiegheremo in dettaglio:

        ResponseStatus sendMessage(const String message);
        ResponseContainer receiveMessage();

Il primo metodo è sendMessage e viene utilizzato per inviare una stringa a un dispositivo in modalità trasparente.

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

L’altro dispositivo fa semplicemente sul loop

       if (e32ttl.available()  > 1){
		ResponseContainer rs = e32ttl.receiveMessage();
		String message = rs.data; // First ever get the data
		Serial.println(rs.status.getResponseDescription());
		Serial.println(message);
	}

Presta attenzione se ricevi multipli messaggi sul buffer la receiveMessage li andrà a leggere tutti in una volta, per leggerli uno ad uno dovrai usare ResponseContainer rs = e32ttl.receiveMessageUntil();

Gestire strutture

Se vuoi inviare una struttura complessa puoi usare questo metodo

        ResponseStatus sendMessage(const void *message, const uint8_t size);
        ResponseStructContainer receiveMessage(const uint8_t size);

Viene utilizzato per inviare la struttura, ad esempio:

	struct Messaggione {
		char type[5];
		char message[8];
		bool mitico;
	};
        struct Messaggione messaggione = {"TEMP", "Peple", true};
        ResponseStatus rs = e32ttl.sendMessage(&messaggione, sizeof(Messaggione));
	Serial.println(rs.getResponseDescription());

e dall’altra parte puoi ricevere il messaggio così

		ResponseStructContainer rsc = e32ttl.receiveMessage(sizeof(Messaggione));
		struct Messaggione messaggione = *(Messaggione*) rsc.data;
		Serial.println(messaggione.message);
		Serial.println(messaggione.mitico);
Leggere una parte della struttura

Se si desidera leggere la prima parte del messaggio per gestire più tipi di struttura, è possibile utilizzare questo metodo.

ResponseContainer receiveInitialMessage(const uint8_t size);

Lo creo per ricevere una stringa con tipo o altro per identificare la struttura da caricare.

		struct Messaggione { // Partial structure without type
			char message[8];
			bool mitico;
		};

		char type[5]; // first part of structure
		ResponseContainer rs = e32ttl.receiveInitialMessage(sizeof(type));
                // Put string in a char array (not needed)
		memcpy ( type, rs.data.c_str(), sizeof(type) );

		Serial.println("READ TYPE: ");
		Serial.println(rs.status.getResponseDescription());
		Serial.println(type);

                // Read the rest of structure
		ResponseStructContainer rsc = e32ttl.receiveMessage(sizeof(Messaggione));
		struct Messaggione messaggione = *(Messaggione*) rsc.data;

Fixed mode invece del normal mode

Allo stesso modo creo una serie di metodi da utilizzare con la trasmissione fissa

Fixed transmission

È necessario modificare solo il metodo di invio, poiché il dispositivo di destinazione non riceve il preambolo con Indirizzo e Canale quando impostato il fixed mode.

Così per la trasmissione di stringhe avrai:

        ResponseStatus sendFixedMessage(byte ADDH, byte ADDL, byte CHAN, const String message);
        ResponseStatus sendBroadcastFixedMessage(byte CHAN, const String message);

e per le strutture avrai:

        ResponseStatus sendFixedMessage(byte ADDH, byte ADDL, byte CHAN, const void *message, const uint8_t size);
        ResponseStatus sendBroadcastFixedMessage(byte CHAN, const void *message, const uint8_t size );

Ecco un semplice esempio:

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

La trasmissione fissa ha più scenari

LoRa E32 transmitting scenarios, lines are channels

Se si invia a un dispositivo specifico (trasmissione dei secondi scenari fissi) è necessario aggiungere ADDL, ADDH e CHAN per identificarlo direttamente.

ResponseStatus rs = e32ttl.sendFixedMessage(2, 2, 0x17, "Message to a device");

Se si desidera inviare un messaggio a tutti i dispositivi in un canale specificato, è possibile utilizzare questo metodo.

ResponseStatus rs = e32ttl.sendBroadcastFixedMessage(0x17, "Message to a devices of a channel");

Se si desidera ricevere tutti i messaggi broadcast nella rete, è necessario impostare ADDH e ADDL con BROADCAST_ADDRESS.

        ResponseStructContainer c;
	c = e32ttl100.getConfiguration();
	// It's important get configuration pointer before all other operation
	Configuration configuration = *(Configuration*) c.data;
	Serial.println(c.status.getResponseDescription());
	Serial.println(c.status.code);

	printParameters(configuration);
	configuration.ADDL = BROADCAST_ADDRESS;
	configuration.ADDH = BROADCAST_ADDRESS;

	// Set configuration changed and set to not hold the configuration
	ResponseStatus rs = e32ttl100.setConfiguration(configuration, WRITE_CFG_PWR_DWN_LOSE);
	Serial.println(rs.getResponseDescription());
	Serial.println(rs.code);
	printParameters(configuration);

Grazie

Ora hai tutte le informazioni per svolgere il tuo lavoro, ma penso sia importante mostrare alcuni esempi realistici per capire meglio tutte le possibilità.

  1. LoRa E32 per Arduino, esp32 o esp8266: specifiche ed utilizzo base
  2. LoRa E32 per Arduino, esp32 o esp8266: libreria
  3. LoRa E32 per Arduino, esp32 o esp8266: configurazione
  4. LoRa E32 per Arduino, esp32 o esp8266: trasmissione fissa
  5. LoRa E32 per Arduino, esp32 o esp8266: power saving ed invio di dati strutturati
  6. LoRa E32 per Arduino, esp32 o esp8266: WOR (wake on radio) il microcontrollore e lo shield per Arduino
  7. LoRa E32 per Arduino, esp32 o esp8266: WOR (wake on radio) il microcontrollore e lo shield per il WeMos D1 mini
  8. LoRa E32 per Arduino, esp32 o esp8266 : WOR (wake on radio) del microcontrollore e lo shield per esp32
  9. LoRa E32 per STM32: WOR (wake on radio) del microcontrollore e lo shield per STM32

Github library


Spread the love

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *