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.
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.
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
Pin No. | Pin item | Pin direction | Pin application |
---|---|---|---|
1 | M0 | Input(weak pull-up) | Lavora con M1 e decide le quattro modalità operative. Non può essere lasciato libero, può essere messo a terra. |
2 | M1 | Input(weak pull-up) | Lavora con M1 e decide le quattro modalità operative. Non può essere lasciato libero, può essere messo a terra. |
3 | RXD | Input | Ingressi UART TTL, connessione a pin di uscita TXD esterno (MCU, PC). Può essere configurato come ingresso open-drain o pull-up. |
4 | TXD | Output | Uscite 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). |
6 | VCC | Alimentazione 2.3V~5.5V DC | |
7 | GND | Terra |
Come puoi vedere, puoi impostare varie modalità tramite i pin M0 e M1.
Modalità | M1 | M0 | Descrizione |
---|---|---|---|
Normal | 0 | 0 | UART e il canale wireless sono a attivi |
Wake-Up | 0 | 1 | Come normale ma viene aggiunto un codice di preambolo ai dati trasmessi per riattivare il ricevitore. |
Power-Saving | 1 | 0 | UART è 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. |
Sleep | 1 | 1 | Utilizzato 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.
Quando si riceve AUX viene impostato a LOW e restituisce HIGH quando il buffer è svuotato.
Viene anche utilizzato quando effettua l’autocontrollo per ripristinare il normale funzionamento (all’accensione ed in modalità sospensione/programma).
Lo schema di connessione esp8266 è più semplice perché funziona alla stessa tensione delle comunicazioni logiche (3.3 v).
È importante aggiungere una resistenza di pull-up (4,7Kohm) per ottenere una buona stabilità.
M0 | D7 |
M1 | D6 |
TX | PIN D2 (PullUP 4,7KΩ) |
RX | PIN D3 (PullUP 4,7KΩ) |
AUX | D5 (Input) |
VCC | 3.3v |
GND | GND |
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.
M0 | 7 (Voltage divider) |
M1 | 6 (Voltage divider) |
TX | PIN 2 (PullUP 4,7KΩ) |
RX | PIN 3 (PullUP 4,7KΩ & Voltage divider) |
AUX | 5 (Input) |
VCC | 3.3v |
GND | GND |
M0 | D21 |
M1 | D19 |
TX | PIN RX2 (PullUP 4,7KΩ) |
RX | PIN TX3 (PullUP 4,7KΩ) |
AUX | PIN D18 (PullUP 4,7KΩ) (D15 to wake up) |
VCC | 5V (but work with less power in 3.3v) |
GND | GND |
M0 | 2 (voltage divider) |
M1 | 3 (voltage divider) |
TX | PIN 14 Tx (PullUP 4,7KΩ) |
RX | PIN 13 Rx (PullUP 4,7KΩ) |
AUX | PIN 1 (PullUP 4,7KΩ) |
VCC | 5V |
GND | GND |
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
etxPin
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
em1Pin
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
ADDH | Indirizzo High del modulo (impostazione predefinita 00H) | 00H-FFH |
ADDL | Indirizzo Low del modulo (impostazione predefinita 00H) | 00H-FFH |
SPED | Informazioni sul bit di parità della velocità dei dati e sulla velocità dei dati via etere | |
CHAN | Canale di comunicazione(410M + CHAN*1M), default 17H (433MHz), valido solo per i dispositivi a 433Mhz controlla sotto per cambiare la frequenza | 00H-1FH |
OPTION | Tipo 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
7 | 6 | UART parity bit | Constant value |
---|---|---|---|
0 | 0 | 8N1 (default) | MODE_00_8N1 |
0 | 1 | 8O1 | MODE_01_8O1 |
1 | 0 | 8 E1 | MODE_10_8E1 |
1 | 1 | 8N1 (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.
5 | 4 | 3 | TTL UART baud rate(bps) | Constant value |
---|---|---|---|---|
0 | 0 | 0 | 1200 | UART_BPS_1200 |
0 | 0 | 1 | 2400 | UART_BPS_2400 |
0 | 1 | 0 | 4800 | UART_BPS_4800 |
0 | 1 | 1 | 9600 (default) | UART_BPS_9600 |
1 | 0 | 0 | 19200 | UART_BPS_19200 |
1 | 0 | 1 | 38400 | UART_BPS_38400 |
1 | 1 | 0 | 57600 | UART_BPS_57600 |
1 | 1 | 1 | 115200 | UART_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.
2 | 1 | 0 | Air data rate(bps) | Constant value |
---|---|---|---|---|
0 | 0 | 0 | 0.3k | AIR_DATA_RATE_000_03 |
0 | 0 | 1 | 1.2k | AIR_DATA_RATE_001_12 |
0 | 1 | 0 | 2.4k (default) | AIR_DATA_RATE_010_24 |
0 | 1 | 1 | 4.8k | AIR_DATA_RATE_011_48 |
1 | 0 | 0 | 9.6k | AIR_DATA_RATE_100_96 |
1 | 0 | 1 | 19.2k | AIR_DATA_RATE_101_192 |
1 | 1 | 0 | 19.2k (same to 101) | AIR_DATA_RATE_110_192 |
1 | 1 | 1 | 19.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 |
---|---|---|
0 | Transparent transmission mode | FT_TRANSPARENT_TRANSMISSION |
1 | Fixed transmission mode | FT_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 |
---|---|---|
1 | TXD and AUX push-pull outputs, RXD pull-up inputs | IO_D_MODE_PUSH_PULLS_PULL_UPS |
0 | TXD AUX open-collector outputs, RXD open-collector inputs | IO_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).
5 | 4 | 3 | Wireless wake-up time | Constant value |
---|---|---|---|---|
0 | 0 | 0 | 250ms (default) | WAKE_UP_250 |
0 | 0 | 1 | 500ms | WAKE_UP_500 |
0 | 1 | 0 | 750ms | WAKE_UP_750 |
0 | 1 | 1 | 1000ms | WAKE_UP_1000 |
1 | 0 | 0 | 1250ms | WAKE_UP_1250 |
1 | 0 | 1 | 1500ms | WAKE_UP_1500 |
1 | 1 | 0 | 1750ms | WAKE_UP_1750 |
1 | 1 | 1 | 2000ms | WAKE_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 |
---|---|---|
0 | Turn off FEC | FEC_0_OFF |
1 | Turn 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
1 | 0 | Transmission power (approximation) | Constant value |
---|---|---|---|
0 | 0 | 20dBm (default) | POWER_20 |
0 | 1 | 17dBm | POWER_17 |
1 | 0 | 14dBm | POWER_14 |
1 | 1 | 10dBm | POWER_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
1 | 0 | Transmission power (approximation) | Constant value |
---|---|---|---|
0 | 0 | 27dBm (default) | POWER_27 |
0 | 1 | 24dBm | POWER_24 |
1 | 0 | 21dBm | POWER_21 |
1 | 1 | 18dBm | POWER_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
1 | 0 | Transmission power (approximation) | Constant value |
---|---|---|---|
0 | 0 | 30dBm (default) | POWER_30 |
0 | 1 | 27dBm | POWER_27 |
1 | 0 | 24dBm | POWER_24 |
1 | 1 | 21dBm | POWER_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.
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
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à.
- LoRa E32 per Arduino, esp32 o esp8266: specifiche ed utilizzo base
- LoRa E32 per Arduino, esp32 o esp8266: libreria
- LoRa E32 per Arduino, esp32 o esp8266: configurazione
- LoRa E32 per Arduino, esp32 o esp8266: trasmissione fissa
- LoRa E32 per Arduino, esp32 o esp8266: power saving ed invio di dati strutturati
- LoRa E32 per Arduino, esp32 o esp8266: WOR (wake on radio) il microcontrollore e lo shield per Arduino
- LoRa E32 per Arduino, esp32 o esp8266: WOR (wake on radio) il microcontrollore e lo shield per il WeMos D1 mini
- LoRa E32 per Arduino, esp32 o esp8266 : WOR (wake on radio) del microcontrollore e lo shield per esp32
- LoRa E32 per STM32: WOR (wake on radio) del microcontrollore e lo shield per STM32
- Mischianti Arduino LoRa shield (Open source)
- Mischianti WeMos LoRa shield (Open source)
- Mischianti ESP32 DOIT DEV KIT v1 LoRa shield (Open source)