Communication pair-à-pair entre deux modules LoRa-E5
Ce tutoriel explique comment mettre en œuvre une communication “directe” entre deux modules LoRa-E5 avec STM32duino. Il est constitué de deux parties :
- Partie 1 : Piloter un module Grove LoRa-E5 avec des commandes AT.
- Partie 2 : Liaison LoRa entre deux cartes NUCLEO-L476RG équipées de modules LoRa-E5.
Voici à quoi ressemble le module Grove LoRa-E5 :
Crédit image : Seeed Studio
Le matériel radiofréquence LoRa est essentiellement destiné à la création de réseaux étendus et très basse consommation d’objets connectés (LoRaWAN, voir cette référence ou encore la page dédiée sur notre site).
Cependant, il est aussi possible de créer une liaison directe entre deux modules en utilisant un mode test prévu par la spécification LoRa. Nous faisons ici la démonstration de cette possibilité, intéressante dans le cas d’applications nécessitant de très faibles flux de données (quelques octets de temps en temps), comme par exemple en domotique. Et les performances des petits modules Grove LoRa-E5 sont étonnantes compte-tenu de leur antenne minimaliste : nous avons pu les faire communiquer approximativement à 190 mètres de distance, alors que deux murs occultaient le trajet de leur signal radio !
Matériel requis et montage
Pour l’ensemble de ce tutoriel, nous utiliserons le matériel suivant :
- Deux cartes NUCLEO-L476RG de STMicroelectronics.
- Deux modules Grove LoRa-E5, basé sur un système sur puce (SoC) STM32WLE5JC de STMicroelectronics.
- Deux câbles Grove - Dupont mâles.
Les deux montages que nous allons utiliser sont donc strictement identiques. La seule difficulté consiste à connecter correctement le module LoRa-E5 à l’UART4 de la carte NUCLEO-L476RG, conformément aux indications données sur cette page :
Broche du module LoRa-E5 | Broche (Arduino) de la NUCLEO-L476RG |
---|---|
GND | GND |
VCC | 3V3 |
RX | A0 (TX de l’UART4) |
TX | A1 (RX de l’UART4) |
Partie 1 : Piloter un module Grove LoRa-E5 avec des commandes AT
Dans un premier temps, nous allons tester différentes commandes “AT” reconnues par les modules LoRa-E5, pour nous assurer de leur bonne connexion mais aussi pour expliquer les modes émission et réception dont nous aurons besoin par la suite. Un sketch s’impose, pour échanger “interactivement” avec le module LoRa-E5 depuis le terminal série de l’IDE Arduino. La documentation complète des commandes AT du module LoRa-E5 est disponible ici.
Bibliothèque(s) requise(s)
Aucune bibliothèque n’est nécessaire pour cet exemple, le sketch qui suit est suffisant.
Le sketch Arduino
Le sketch pour cet exemple (et tous les autres) peut être téléchargé en cliquant ici. Vous le trouverez dans le dossier “\LoRa - Ping-pong LoRa-E5\LoRa_E5_AT”.
Lancez l’IDE Arduino, ouvrez un nouveau sketch vide et copiez-y le code qui suit :
/*------------------------------------------------------------------------------*/
// Programme pour échanger des commandes avec le module LoRa-E5 via le terminal
// série de l'IDE Arduino.
// Dans celui-ci, sélectionnez "Both NR & CL" et "9600" bauds.
/*------------------------------------------------------------------------------*/
#define RX_PIN PA1 // Broche A1 Arduino, brancher dessus la ligne TX du module LoRA-E5
#define TX_PIN PA0 // Broche A0 Arduino, brancher dessus la ligne RX du module LoRA-E5
HardwareSerial LoRa(RX_PIN, TX_PIN); // Initialisation de l'UART4 de la NUCLEO-L476RG
#define STLK_BDRATE 9600 // Débit (bauds) du port série du au ST-LINK
#define LORA_BDRATE 9600 // Débit (bauds) du port série du module LoRa
// Configuration des périphériques et initialisations
void setup() {
// Démarrage du port série du ST-LINK
Serial.begin(STLK_BDRATE);
// Démarrage du port série du module LoRa-E5
LoRa.begin(LORA_BDRATE);
Serial.println("Setup completed !");
}
// Boucle principale
void loop() {
// Lecture des commandes en provenance du terminal série Arduino
// Envoi de ces commandes au module LoRa-E5
while (Serial.available() > 0) {
LoRa.write(Serial.read());
}
// Lecture des réponses du module LoRa-E5
// Ecriture de ces réponses sur le terminal série Arduino
while (LoRa.available() > 0) {
Serial.write(LoRa.read());
}
}
Après avoir vérifié que l’IDE Arduino est correctement configurée, notamment qu’elle est connectée au port COM attribué au ST-LINK de votre carte (sous Windows), cliquez sur “Téléverser”.
Utilisation du sketch Arduino
1. La première étape consiste à vous assurer que le module est correctement connecté. Tapez AT
dans la boite de saisie du terminal série, qui doit par ailleurs être paramétré en “Both NL & CR” et “9600 bauds”.
Sa réponse, +AT: OK
confirmera que tout va bien.
2. Ensuite, nous utilisons la commande AT qui permet de configurer le module en mode émetteur (ou en mode test, c’est équivalent) :
Pour passer en mode émetteur :
AT+MODE=TEST
La réponse du module devrait être simplement :
+MODE: TEST
3. Ensuite, nous configurons le module en mode récepteur, en lui adressant la séquence de commandes AT qui suit :
Pour passer en mode test :
AT+MODE=TEST
Pour passer en mode réception :AT+TEST=RXLRPKT
Le module devrait vous envoyer les deux accusés de réception qui suivent et qui confirment que tout s’est bien passé :
+MODE: TEST
+TEST: RXLRPKT
4. Nous pouvons à présent réaliser un échange de messages à distance entre deux modules. Configurez une carte NUCLEO + module LoRa-E5 en émetteur (point 2) et une autre carte NUCLEO + module LoRa-E5 en récepteur (point 3). Attention, ces configurations seront perdues si vous arrêtez l’alimentation électrique des cartes/modules !.
Rendez-vous dans le terminal série de l’émetteur et validez :
-
Ceci pour envoyer un message en mode “chaîne de caractères hexadécimaux” :
AT+TEST=TXLRPKT, "0123456789ABCDEF0123456789ABCDEF"
Cette commande ne peut envoyer que des messages rédigés avec les 16 caractères de la base hexadécimale. -
Ceci pour envoyer un message en mode “chaîne de caractères ASCII” :
AT+TEST=TXLRSTR, "Je suis un novice pardi !"
Cette commande peut envoyer n’importe quelle chaîne de caractère ASCII.
Les accusés de réception du module dans le terminal série de l’émetteur sont :
+TEST: TXLRPKT "0123456789ABCDEF0123456789ABCDEF"
+TEST: TX DONE
+TEST: TXLRSTR "Je suis un novice pardi !"
+TEST: TX DONE
Et les messages sont bien transmis, on le vérifie avec le terminal série du récepteur :
+TEST: LEN:16, RSSI:-43, SNR:12
+TEST: RX "0123456789ABCDEF0123456789ABCDEF"
+TEST: LEN:25, RSSI:-45, SNR:12
+TEST: RX "4A65207375697320756E206E6F766963652070617264692021"
On remarque que, du côté récepteur, les messages sont toujours décodés avec les symboles de la base hexadécimale. Donc, pour le deuxième message envoyé en mode texte, un peu de (dé)codage sera nécessaire afin de transformer “4A65207375697320756E206E6F766963652070617264692021” en “Je suis un novice pardi !” dans une éventuelle application.
Partie 2 : Communication LoRa directe entre deux modules LoRa-E5
Cette deuxième partie met en œuvre les commandes AT que nous venons de voir pour faire communiquer deux modules LoRa-E5 en mode “ping-pong”, en leur donnant alternativement les rôles d’émetteur et de récepteur. Entre deux échnages, nous prenons le soin d’optimiser la consommation énergétique en mettant en veille le MCU STM32L476 de la carte NUCLEO et le MCU SMT32WL55 du module LoRa-E5.
Bibliothèque(s) requise(s)
Pour ce sketch, nous utilisons la bibliothèque STM32LowPower qui servira à mettre en sommeil le MCU STM32L476RG de la carte NUCLEO et à le réveiller chaque fois que des octets seront reçus par le module LoRa-E5, ou bien chaque fois que l’on appuiera sur le bouton utilisateur, géré en mode interruption.
Important : Cette bibliothèque ne fonctionne pas avec le LPUART1 (UART basse consommation) de la carte NUCLEO-L476RG (ou de toute autre carte NUCLEO en fait). Aucun problème en revanche avec l’UART4 que nous utilisons.
Le sketch Arduino
Le sketch pour cet exemple (et tous les autres) peut être téléchargé en cliquant ici. Vous le trouverez dans le dossier “\LoRa - Ping-pong LoRa-E5\LoRa_E5_P2P_Station”.
/*-----------------------------------------------------------------------------------------------*/
// Mise en oeuvre d'une communication LoRa directe entre deux cartes NUCLEO-L476RG équippées
// de modules Grove LoRa-E5.
// On désigne par "station" le système "carte NUCLEO-L476RG + module LoRa-E5".
// Au démarrage, la station est configurée en mode "récepteur" en adressant les commandes AT
// qui conviennent à son module LoRa, connecté à l'UART4 du MCU STM32L476RG.
// Si on appuie sur le bouton utilisateur de la station, celle-ci passe en mode émetteur, puis
// elle envoie un message donné, avant de revenir en mode récepteur.
// La réception des messages sur l'UART4 est gérée par interruption, en utilisant la fonction
// "LowPower.enableWakeupFrom()" de la bibliothèque "STM32LowPower.h".
// L'envoi de messages est également géré par une interruption associée au bouton bleu de la
// carte NUCLEO-L476RG.
/*-----------------------------------------------------------------------------------------------*/
// Clef d'apairage, pour s'assurer que le système ne traite que les messages des stations
// partageant celle-ci.
const String PAIRING_KEY = "4587933521";
// Bibliothèque "low power"
#include "STM32LowPower.h"
#define RX_PIN PA1 // Broche A1 Arduino, brancher dessus la ligne TX du module LoRa-E5
#define TX_PIN PA0 // Broche A0 Arduino, brancher dessus la ligne RX du module LoRa-E5
HardwareSerial LoRa(RX_PIN, TX_PIN); // Initialisation de l'UART4 de la NUCLEO-L476RG
#define STLK_BDRATE 9600 // Débit, en bauds, du port série associé au ST-LINK
#define LORA_BDRATE 9600 // Débit, en bauds, du port série associé au module LoRa
#define TIMEOUT_MS 1000 // Timeout pour la réception des réponses du module LoRa
#define DELAY_200_MS 200 // Petit délai en millisecondes
#define RX_BUF_SIZE 512 // Taille, en caractères, du buffer de réception
char rx_buffer[RX_BUF_SIZE]; // Buffer de réception du module LoRa-E5
#define TX_BUF_SIZE 128 // Taille, en caractères, du buffer d'émission
char tx_buffer[TX_BUF_SIZE]; // Buffer d'émission du module LoRa-E5
// Différentes commandes AT et leurs accusés de réception
#define CMD_AT "AT\r\n"
#define CMD_AT_ACK "+AT: OK"
#define CMD_TEST "AT+MODE=TEST\r\n"
#define CMD_TEST_ACK "+MODE: TEST"
#define CMD_RECV "AT+TEST=RXLRPKT\r\n"
#define CMD_RECV_ACK "+TEST: RXLRPKT"
#define RECV_ACK "+TEST: RX"
#define CMD_SEND "AT+TEST=TXLRSTR"
#define CMD_SEND_ACK "+TEST: TXLRSTR"
#define CMD_SLEEP "AT+LOWPOWER\r\n"
// Variable globale signalant qu'un message est en cours d'émission
volatile uint8_t send_msg = 0;
// Variable globale signalant que des octets arrivent sur la ligne RX du module LoRa
volatile uint8_t data_received = 0;
// Configuration des périphériques et initialisations
void setup() {
// Initialise le bouton utilisateur de la carte NUCLEO
pinMode(USER_BTN, INPUT_PULLUP);
// On attache une interruption au bouton pour gérer son appui
attachInterrupt(digitalPinToInterrupt(USER_BTN), Button_Down_ISR, LOW);
// Active la LED de la carte NUCLEO
pinMode(LED_BUILTIN, OUTPUT);
// Allume la LED
digitalWrite(LED_BUILTIN, HIGH);
// Démarrage du port série du ST-LINK
Serial.begin(STLK_BDRATE);
// Démarrage du port série du module LoRa-E5
LoRa.begin(LORA_BDRATE);
// Teste le bon fonctionnement du module
test_module();
// Configure le module en mode réception
set_receiver_mode();
// Configure low power
LowPower.begin();
//Active le mode "wake-up" de l'UART4
LowPower.enableWakeupFrom(&LoRa, Serial_Wakeup_ISR);
// Eteint la LED
digitalWrite(LED_BUILTIN, LOW);
Serial.println("Setup completed !");
delay(DELAY_200_MS);
}
// Boucle principale
void loop() {
if (send_msg) {
// Configure le module en mode émission
set_emitter_mode();
// Envoie un message
String Message = String(PAIRING_KEY) + String("_Hello");
send_message(Message);
// Configure le module en mode réception
set_receiver_mode();
send_msg = 0;
data_received = 0;
}
// A chaque interruption de réception
if (data_received) {
// Ecoute le port série du module LoRa-E5
if (at_check_response(RECV_ACK)) {
Serial.println("Raw data : ");
Serial.print(rx_buffer);
// Parsing du message reçu
recv_parse(rx_buffer);
// Si le message reçu commence par le code d'apairage
String rxmessage = String(rx_buffer);
if (rxmessage.indexOf(PAIRING_KEY) == 0) {
Serial.println("Receiver - emitter keys maching.");
Serial.print("Decoded data : ");
Serial.println(rxmessage.substring(PAIRING_KEY.length()+1));
}
delay(DELAY_200_MS);
data_received = 0;
}
}
// Place le module LoRa-E5 en mode économies d'énergie
LoRa.print(CMD_SLEEP);
// Place le microcontrôleur en mode économies d'énergie
LowPower.deepSleep();
}
/*----------------------------------------------------------------------------*/
// Routine de service de l'interruption de réception de l'UART4 (module)
/*----------------------------------------------------------------------------*/
void Serial_Wakeup_ISR() {
data_received = 1; // On signale que des octets sont arrivés dans la file RX
}
/*----------------------------------------------------------------------------*/
// Envoie un message avec le module LoRa-E5 au format texte / ASCII
/*----------------------------------------------------------------------------*/
void send_message(String message) {
char p_message[TX_BUF_SIZE];
message.toCharArray(p_message, TX_BUF_SIZE);
sprintf(tx_buffer, "%s,\"%s\"\r\n", CMD_SEND, p_message);
LoRa.print(tx_buffer);
Serial.print("Module sending message : ");
Serial.print(tx_buffer);
if (at_check_response(CMD_SEND_ACK)) {
Serial.print("Lora module feedback : ");
Serial.print(rx_buffer);
Serial.println("CMD_SEND success !");
} else {
Serial.println("CMD_SEND failure !");
while (1)
;
}
}
/*----------------------------------------------------------------------------*/
// Configure le module en mode émission
/*----------------------------------------------------------------------------*/
void set_emitter_mode(void) {
Serial.println("---- Setting emitter mode ----");
Serial.print("Command sent to LoRa Module : ");
Serial.print(CMD_TEST);
// Envoie la commande AT au module
LoRa.print(CMD_TEST);
delay(DELAY_200_MS);
if (at_check_response(CMD_TEST_ACK)) {
Serial.print("Lora module feedback : ");
Serial.print(rx_buffer);
Serial.println("CMD_TEST success !");
} else {
Serial.println("CMD_TEST failure !");
blocking_blink();
}
Serial.println("---- Emitter mode set ----\r\n");
delay(DELAY_200_MS);
}
/*----------------------------------------------------------------------------*/
// Configure le module LoRa-E5 en mode réception
/*----------------------------------------------------------------------------*/
void set_receiver_mode(void) {
Serial.println("---- Setting receiver mode ----");
Serial.print("Command sent to LoRa Module : ");
Serial.print(CMD_TEST);
// Envoie la commande AT "TEST" au module
LoRa.print(CMD_TEST);
delay(DELAY_200_MS);
if (at_check_response(CMD_TEST_ACK)) {
Serial.print("LoRa module feedback : ");
Serial.print(rx_buffer);
Serial.println("CMD_TEST success !");
} else {
Serial.println("CMD_TEST failure !");
blocking_blink();
}
Serial.print("Command sent to LoRa Module : ");
Serial.print(CMD_RECV);
// Envoie la commande AT "RECEPTION" au module
LoRa.print(CMD_RECV);
delay(DELAY_200_MS);
if (at_check_response(CMD_RECV_ACK)) {
Serial.print("LoRa module feedback : ");
Serial.print(rx_buffer);
Serial.println("CMD_RECV success !");
} else {
Serial.println("CMD_RECV failure !");
blocking_blink();
}
Serial.println("---- Receiver mode set ----\r\n");
delay(DELAY_200_MS);
}
/*----------------------------------------------------------------------------*/
// Vérifie que le module répond aux commandes AT qu'on lui adresse
/*----------------------------------------------------------------------------*/
void test_module(void) {
Serial.println("---- Testing module ----");
Serial.print("Command sent to LoRa Module : ");
Serial.print(CMD_AT);
// Envoie la commande AT au module
LoRa.print(CMD_AT);
delay(DELAY_200_MS);
if (at_check_response(CMD_AT_ACK)) {
Serial.print("LoRa module feedback : ");
Serial.print(rx_buffer);
Serial.println("CMD_AT success !");
} else {
Serial.println("CMD_AT failure !");
blocking_blink();
}
Serial.println("---- Module is online ----\r\n");
}
/*----------------------------------------------------------------------------*/
// Attend la réponse du module LoRa-E5 pendant TIMEOUT_MS millisecondes
// p_ack : Message retour de validation attendu de la part du module
/*----------------------------------------------------------------------------*/
uint8_t at_check_response(char *p_ack) {
char ch;
uint16_t index = 0;
unsigned long startMillis = 0;
// Efface le buffer de réception
memset(rx_buffer, 0, sizeof(rx_buffer));
startMillis = millis();
if (p_ack == NULL)
return 0;
do { // Aussi longtemps qu'on n'a pas dépassé le délai de timeout
while (LoRa.available() > 0) {
// Capture les caractères qui arrivent sur le port série du module
ch = LoRa.read();
rx_buffer[index++] = ch;
// Serial.print((char)ch);
delay(2);
}
// Vérifie que le message reçu contient l'accusé de la commande AT adressée au module
if (strstr(rx_buffer, p_ack) != NULL)
return 1;
} while (millis() - startMillis < TIMEOUT_MS); // Temporisation non bloquante
return 0;
}
/*----------------------------------------------------------------------------*/
// Parcours la réponse du module LoRa-E5 et la transforme en chaîne de caractères
// p_msg : Message reçu en entrée, remplacé par le message décodé en sortie
/*----------------------------------------------------------------------------*/
void recv_parse(char *p_msg) {
if (p_msg == NULL) {
Serial.println("Received null");
return;
}
char *p_start = NULL;
char data[RX_BUF_SIZE];
// Recherche les octets correspondant au message utile dans la chaîne reçue
uint32_t bytes_len = 0;
p_start = strstr(p_msg, "RX");
if (p_start && (1 == sscanf(p_start, "RX \"%s\"", &data))) {
for (uint32_t i = 0; i < sizeof(data); i++) {
if (int(data[i + 1]) == 0) {
bytes_len = i;
break;
}
}
// Conversion des caractères en une chaîne d'octets
uint32_t message_len = bytes_len / 2 + 1;
auto getNum = [](char c) {
return c > '9' ? c - 'A' + 10 : c - '0';
};
uint32_t x, y;
for (x = 0, y = 0; x < bytes_len; ++x, ++y)
p_msg[y] = (getNum(data[x++]) << 4) + getNum(data[x]);
p_msg[y] = '\0'; // Caractère de terminaison de chaîne
}
}
/*----------------------------------------------------------------------------*/
/* Gestion de l'interruption du bouton */
/*----------------------------------------------------------------------------*/
void Button_Down_ISR(void) {
// Gestion anti-rebond du bouton (délai non bloquant)
static unsigned long prevMillis;
unsigned long currMillis = millis();
if (currMillis - prevMillis > DELAY_200_MS) {
prevMillis = currMillis;
// Si aucun message n'est déjà en cours de réception ou d'émission,
// envoie une requête d'émission
send_msg = 1;
}
}
/*----------------------------------------------------------------------------*/
/* Gestion du clignotement de la LED (blocante) */
/* Signale un échec de l'une des commandes AT */
/*----------------------------------------------------------------------------*/
void blocking_blink(void) {
while (1) {
// Allume la LED
digitalWrite(LED_BUILTIN, HIGH);
delay(DELAY_200_MS);
// Eteint la LED
digitalWrite(LED_BUILTIN, LOW);
delay(DELAY_200_MS);
}
}
Bien qu’il soit un peu long, vous ne devriez pas avoir de difficultés à comprendre son fonctionnement en le lisant attentivement. Ses portions les plus délicates sont celles chargées de la réception des messages octet par octet, de leur “parsing” et du “décodage” des chaînes hexadécimales en ASCII :
- La fonction
at_check_response(...)
- La fonction
recv_parse(...)
Ces fonctions sont directement adaptées de l’exemple donné ici par Seeed Studio et nécessitent un bon niveau de compétence en c++ pour être comprises.
Mise en œuvre du sketch Arduino
Chargez le sketch dans l’IDE Arduino puis “téléversez” le dans vos deux “stations”, constituées chacune d’une carte NUCLEO-L476RG et d’un module LoRa-E5. Votre système communiquant est résumé par la figure suivante :
L’usage du sketch ne devrait poser aucune difficulté s’il a été compilé et téléchargé sans erreur.
Lorsque la station 1 démarre, vous devriez avoir les logs suivants dans le terminal série de l’IDE Arduino qui lui correspond :
---- Testing module ----
Command sent to LoRa Module : AT
LoRa module feedback : +AT: OK
CMD_AT success !
---- Module is online ----
---- Setting receiver mode ----
Command sent to LoRa Module : AT+MODE=TEST
LoRa module feedback : +MODE: TEST
CMD_TEST success !
Command sent to LoRa Module : AT+TEST=RXLRPKT
LoRa module feedback : +TEST: RXLRPKT
CMD_RECV success !
---- Receiver mode set ----
Setup completed !
La station 1 a donc bien démarré en mode réception.
Si vous appuyez sur le bouton bleu de la carte NUCLEO-L476RG de la station 1 celle-ci passe en mode émission, envoie un message puis repasse en mode réception :
---- Setting emitter mode ----
Command sent to LoRa Module : AT+MODE=TEST
Lora module feedback : +MODE: TEST
CMD_TEST success !
---- Emitter mode set ----
Module sending message : AT+TEST=TXLRSTR,"4587933521_Hello"
Lora module feedback : +TEST: TXLRSTR "4587933521_Hello"
+TEST: TX DONE
CMD_SEND success !
---- Setting receiver mode ----
Command sent to LoRa Module : AT+MODE=TEST
LoRa module feedback : +MODE: TEST
CMD_TEST success !
Command sent to LoRa Module : AT+TEST=RXLRPKT
LoRa module feedback : +TEST: RXLRPKT
CMD_RECV success !
---- Receiver mode set ----
Le message envoyé est donc “4587933521_Hello”.
Et voici les logs que vous obtenez pour la station 2 dans le terminal série de l’IDE Arduino qui lui correspond :
Raw data :
+TEST: LEN:16, RSSI:-37, SNR:12
+TEST: RX "343538373933333532315F48656C6C6F"
Receiver - emitter keys maching !
Decoded data : Hello
Le message “utile” de la station 1, à savoir “Hello”, a donc bien été reçu et décodé par la station 2.
Pour aller plus loin
Nous avons limité notre exemple à deux stations, mais absolument rien n’interdit d’en utiliser 3, 4, 10, 40 … La communication entre les modules se fait en “broadcast” (diffusion), ce qui signifie que tous les modules configurés en mode récepteur vont effectivement recevoir une bonne partie des messages LoRa susceptibles de les atteindre, en provenance également d’un nombre arbitraire d’émetteurs.
Ce tutoriel est donc une base intéressante pour réfléchir à des protocoles de communication plus complexes entre un grand nombre d’objets connectés ; par exemple en construisant un réseau maillé dans lequel chaque station se comporterait comme un relai capable de propager certains messages sur de longue distances en extérieur.
Liens et ressources
Sur LoRa (et LoRaWAN) en général :
Une revue du module LoRa-E5 sur le blog disk91.com : c’est ici.
Pour de la communication point à point (P2P) avec un/des module(s) LoRa-E5 :