Extraire les données des packets lora

Bonsoir,

j'utilise depuis peu un module esp32 TTGO lora. Aucun souci pour dialoguer et transmettre des messages ou des données. Le problème est que je ne sais pas extraire les données numériques des données transmises :

en gros, la partie de code est la suivante :

// read packet
    while (LoRa.available()) {
     Serial.print((char)LoRa.read());

    }

    // print RSSI of packet
    Serial.print("Kg with RSSI ");
    Serial.println(LoRa.packetRssi());

j'obtiens bien mes données sur le terminal :

LoRa Receiver
1.76Kg with RSSI -66
...
... (etc)

A part une donnée apparente de temps en temps, tout va bien mais ...

j'aimerais récupérer la donnée "poids" (et RSSI) pour la stocker sous influxdb et ThingSpeak. Mais je ne sais pas l'extraire. Quand j'essaie de la lire j'obtiens des données incompréhensibles.

Une idée ?

Cordialement

Bonsoir,

essayer toFloat()

oui ça ne marche pas, avec ou sans toFloat, en fait, il me retourne la deuxième décimale, si le poids est de 1.76 kg (affiché par lora) , la donnée extraite est 6, si le poids est 1.75 la donnée est 5...

Preuve par l'image :

Sending UDP packet...
Received packet '1.77' with RSSI -65
poids value=   7
Sending UDP packet...
localport :8191
temperature value=
Sending UDP packet...

Je manipule très mal les données binaires et autres...

a plus

Lacuzon:
oui ça ne marche pas, avec ou sans toFloat, en fait, il me retourne la deuxième décimale, si le poids est de 1.76 kg (affiché par lora) , la donnée extraite est 6, si le poids est 1.75 la donnée est 5...

il faut d'abord stocker les données dans la string, regardes l'ex dans le lien que je t'ai donné

Bonsoir,

J'ai étudié l'exemple et ai compris la structure, je l'ai fait tourner ça marche super mais je suis pas foutu de l'adapter à mon cas :confused:

Voilà le bout de code concerné avant tentative:

void loop() {
  // try to parse packet
  int packetSize = LoRa.parsePacket();
  if (packetSize) {
    // received a packet
    Serial.print("Received packet '");
    // read packet
    while (LoRa.available()) {
      Serial.print((char)LoRa.read());
    }
    // print RSSI of packet
    Serial.print("' with RSSI ");
    Serial.println(LoRa.packetRssi());
    Serial.println(rssi2);

    
  udp.begin(localport);

  String line, Ruches; // définit le nom de la série de données
  line = String("poids value=" + "le poids sous forme d'un string");
  Serial.println(line);
  // send the packet    
  Serial.println("Sending UDP packet...");
  Serial.print("localport :");
  Serial.println(localport);
  udp.beginPacket(host, localport);
  udp.print(line);
  udp.endPacket();
  delay(500);

  }
}

Voilà ci-dessous mon bricolage qui ne marche pas :
Les variables citées sont définies dans l'entête.

void loop() {
  // try to parse packet
  int packetSize = LoRa.parsePacket();
  if (packetSize) {
    // received a packet
    Serial.print("Received packet '");
    // read packet
    while (LoRa.available()) {
      Serial.print((char)LoRa.read());
    }
    // print RSSI of packet
    Serial.print("' with RSSI ");
    Serial.println(LoRa.packetRssi());
    Serial.println(rssi2);

    int inChar = LoRa.read();
        if (inChar != '\n') {
          StrPoids += (char)inChar;
          
        }
        else {
    
    poids = StrPoids.toFloat();
     // clear the string for new input:
    StrPoids = "";
  }
  udp.begin(localport);
  String line, Ruches; // définit le nom de la série de données
  line = String("poids value=" + poids); // ça plante ici
  Serial.println(line);
  // send the packet
  Serial.println("Sending UDP packet...");
  Serial.print("localport :");
  Serial.println(localport);
  udp.beginPacket(host, localport);
  udp.print(line);
  udp.endPacket();
  delay(500);

  }
}

Ce que je comprends pas c'est que la transmission via udp est effectuée en string or quand j'envoie directement le string issu de lora ça ne marche pas. Converti en float c'est pareil. L'erreur doit être grossière.

Help please...

A ce sujet que me conseillez-vous comme bon bouquin sur le langage C ?

Bonjour,

essayes ceci sans garantie …

void loop() {

  // try to parse packet
  int packetSize = LoRa.parsePacket();
  if (packetSize) {
    // received a packet
    Serial.print("Received packet '");
    // read packet
    int inChar;
    while (LoRa.available()) {
      int inChar = LoRa.read();
      Serial.print(inChar);
      if (inChar != '\n') {
        StrPoids += (char)inChar;
      }
      else {

        poids = StrPoids.toFloat();
        // clear the string for new input:
        StrPoids = "";
      }
    }
    // print RSSI of packet
    Serial.print("' with RSSI ");
    Serial.println(LoRa.packetRssi());
    Serial.println(rssi2);

    udp.begin(localport);
    String line, Ruches; // définit le nom de la série de données
    line = "poids value=" + String(poids); // 
    Serial.println(line);
    // send the packet
    Serial.println("Sending UDP packet...");
    Serial.print("localport :");
    Serial.println(localport);
    udp.beginPacket(host, localport);
    udp.print(line);
    udp.endPacket();
    delay(500);

  }
}

merci du coup de main, l'avancée est l'introduction de la fonction String dans la ligne :

line = String("poids value=" + String(poids)); mais ça ne me donnait toujours que la valeur introduite dans l'entête. (poids = 0.1). J'en ai déduit que le programme ne lisait pas la ligne :

poids = StrPoids.toFloat();

en fait c'est la condition if/else qui bloquait. La condition "if" semble toujours vérifiée donc la conséquence "else" n'est jamais appelée. J'ai viré la condition et ça m'a donné mes premiers résultats cohérents.

Tout n'est pas réglé, j'ai aussi quelques soucis de contacts électriques plus ou moins fiables qui viennent compliquer la tâche mais ça devient bon.

Encore merci de l'aide

Bonjour,
de toute manière tu auras certainement plusieurs mesures a transmettre, il faut que tu implémente un protocole entre émetteur et récepteur
je te conseil le tuto de JML écouter le port série et un ex de transmission d’une structure en Lora
salutations apicoles :wink:

Merci du conseil,

je vais lire tout ça

Cordialement

Bonjour,

j'ai lu et appris... Un bon prof c'est quand l'élève a l'impression d'être plus intelligent qu'il ne le pensait :slight_smile:

j'ai compris un peu mieux la logique des char, string et autres.

Cela dit il y a encore du boulot. :confused:

Pour en revenir à mon programme, ça y est, il tourne et donne les bons résultats (udp --> influxdb --> grafana), excepté qu'il s'arrête au bout d'un certain nombre d'acquisitions (une dizaine) sans que je comprenne pourquoi.

Ce n'est pas l'émetteur qui lui fonctionne sans problème. Est-ce un problème matériel, de bibliothèque pas trop compatible, de mémoire. Pour l'instant je n'en sais rien. Je creuse...

J'ajoute que le module esp32 ttgo est alimenté simplement par la prise usb (soit alim ordinateur soit alim type smartphone/tablette). Il n'y a aucune connexion sur les broches.

Voilà mon bout de programme qui fonctionne, l'envoi des données par UDP sur la base influxdb est conditionné à la détection d'un paquet lora :

void loop() {
StrPoids = "";
  // try to parse packet
  int packetSize = LoRa.parsePacket();
  if (packetSize) {
    // received a packet
    Serial.print("Received packet '");
    // read packet
    while (LoRa.available()) {
      StrPoids += (char)LoRa.read();
      poids = StrPoids.toFloat();
    }
    // print RSSI of packet
    Serial.print("' with RSSI ");
    Serial.println(LoRa.packetRssi());
    Serial.println(rssi2);

    //Transmission UDP
    udp.begin(localport);
    String line, Ruches; // définit le nom de la série de données
    line = String("poids value=" + String(poids));
    Serial.println(line);
    // send the packet
    Serial.println("Sending UDP packet...");
    Serial.print("localport :");
    Serial.println(localport);
    udp.beginPacket(host, localport);
    udp.print(line);
    udp.endPacket();
    delay(1000);
  }
}

Bonjour,

des nouvelles du front :

le dispo émetteur composé du pèse ruche, du module RTC Ds3231 et du module esp32 ttgo lora fonctionne sans problème et sans interruption en définissant la carte comme "DOIT ESP32 Devkit V1". Le module RTC est reconnu et l'heure est actualisée.
A noter que si la carte est vue comme Heltec_lora_WIFI, le module RTC n'est semble-t-il pas reconnu et donne des valeurs incohérentes 165/165/165. Semble venir du bus I2C. Cela dit les sketches d'exemples lorasender et lora receiver fonctionnent normalement.

Du côté récepteur, tout fonctionne aussi en définissant la carte indifféremment comme DOIT ESP32 ou comme Heltec. Les données sont maintenant envoyées proprement par UDP dans ma base influxdb installée dans mon serveur Raspberry.

Mais, le programme stoppe après un "certain" temps variable, un quart d'heure, une heure, 3 heures. Le dispo n'envoie sur le terminal aucun message d'erreur. Il suffit d'un hard reset pour que tout reparte.

J'ai éloigné l'émetteur, rien n'a changé, j'ai alimenté avec une source extérieure kifkif.

Comme l'émetteur fonctionne sans interruption (avec le même module esp32 TTGO LoRa, j'en déduis que ce problème est sans doute lié au programme lui-même.

J'ai aussi noté que la puce SX1276 chauffe (quoique raisonnablement, 29*C) ainsi que le chip esp32 DOWdQ6 (35 degrés) alors que du côté émetteur tout reste à température ambainte.

J'ai scruté la toile et je ne suis pas le seul à connaitre ce type de problème. Certains préconisent l'introduction de delay() d'autres mettent en cause l'alim mais tout semble encore très confus.

Pour moi c'est décevant surtout que le dispo émetteur fonctionne sans problème et que la fiabilité est une condition incontournable. Je ne vais pas faire un reset toutes les demi-heures à 50 cm de la ruche. :confused:

Edit :

Concernant l'envoi de données multiples, je pensais procéder comme avec les nrf24 : c'est-à-dire écrire mes données dans un tableau et envoyer le tableau. A la réception, je recevais mes données également dans un tableau de même dimension. Pour l'instant la bête transposition ne marche pas...

Cordialement

Bonsoir,

il faudrait que tu postes ton code en entier pour que les spécialistes puissent t’aider
je n’en suis pas un, mais je te propose de rajouter dans ton code

unsigned long boucletest = 0;
const int dureetest = 60000;

.....

void loop() {
  StrPoids = "";
  // try to parse packet
  int packetSize = LoRa.parsePacket();
  if (packetSize) {
    // received a packet
    Serial.print("Received packet '");
    // read packet
    while (LoRa.available()) {
      StrPoids += (char)LoRa.read();
      poids = StrPoids.toFloat();
    }
    // print RSSI of packet
    Serial.print("' with RSSI ");
    Serial.println(LoRa.packetRssi());
    Serial.println(rssi2);

    //Transmission UDP
    udp.begin(localport);
    String line, Ruches; // définit le nom de la série de données
    line = String("poids value=" + String(poids));
    Serial.println(line);
    // send the packet
    Serial.println("Sending UDP packet...");
    Serial.print("localport :");
    Serial.println(localport);
    udp.beginPacket(host, localport);
    udp.print(line);
    udp.endPacket();
    delay(1000);
  }
  else {
    if (millis() - boucletest > dureetest) {
      Serial.println("en attente packet Lora ...");
      stats(stat);
      boucletest = millis();
    }
  }
}

void stats(const char* what) {
  // we could use getFreeHeap() getMaxFreeBlockSize() and getHeapFragmentation()
  // or all at once:
  uint32_t free;
  uint16_t max;
  uint8_t frag;
  ESP.getHeapStats(&free, &max, &frag);
  Serial.printf("free: %5d - max: %5d - frag: %3d%% <- ", free, max, frag);
  Serial.println(what);
}

sans garantie …

et de suivre ce qu’il se passe dans la console jusqu’au moment du plantage

ensuite il faut essayer sans la partie udp, sans émetteur, …

Edit :
Concernant l’envoi de données multiples, je pensais procéder comme avec les nrf24 : c’est-à-dire écrire mes données dans un tableau et envoyer le tableau. A la réception, je recevais mes données également dans un tableau de même dimension. Pour l’instant la bête transposition ne marche pas…

dans le deuxieme lien que je t’ai donné il y a un ex de transmission de structure qui devrait te convenir

merci pour la réponse rapide.

J’ai tenté d’intégrer ta partie de code mais ça ne compile pas ça me retourne le message d’erreur suivant :

cannot convert ‘int ()(const char, stat*)’ to ‘const char*’ for argument ‘1’ to ‘void stats(const char*)’

j’avoue que j’atteins mes limites de compétences (pour l’instant :confused: )

Voici mon code global :

#include <SPI.h>
#include <WiFiUdp.h>
#include <WiFi.h>
//#include <Wire.h>
#include <LoRa.h>

// GPIO5  -- SX1278's SCK
// GPIO19 -- SX1278's MISO
// GPIO27 -- SX1278's MOSI
// GPIO18 -- SX1278's CS
// GPIO14 -- SX1278's RESET
// GPIO26 -- SX1278's IRQ(Interrupt Request)

#define SS      18
#define RST     14
#define DI0     26
#define BAND    868E6

//Parametrage du WiFi, le mot de passe est la cle WIFI
const char* ssid = "xxxxxxx"; // Le nom de votre box
const char* password = "xxxxxxxxxxxx"; // Le mot de passe

// the IP address of your InfluxDB host
byte host[] = {192, 168, 1, 45};
// the port that the InfluxDB UDP plugin is listening on
int localport = 8191;

WiFiUDP udp;
WiFiClient client;

String StrPoids = "";
float poids = 1.0;
char inChar;
int rssi2;


void setup() {
  Serial.begin(57600);
  while (!Serial); //if just  the basic function, must connect to a computer
  delay(1000);
  Serial.println("LoRa Receiver");
  SPI.begin(5, 19, 27, 18);
  LoRa.setPins(SS, RST, DI0);
  LoRa.setSyncWord(0xF3);
  if (!LoRa.begin(BAND)) {
    Serial.println("Starting LoRa failed!");
    while (1);
  }
  //WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
}
void loop() {
  StrPoids = "";
  float poidsPrecedent;
  poidsPrecedent = poids;
  // try to parse packet
  int packetSize = LoRa.parsePacket();
  if (packetSize) {
    // received a packet
    Serial.print("Received packet '");
    // read packet
    while (LoRa.available()) {
      StrPoids += (char)LoRa.read();
      poids = StrPoids.toFloat();
    }
    // print RSSI of packet
    Serial.print("' with RSSI ");
    Serial.println(LoRa.packetRssi());
    Serial.println(rssi2);

    //Transmission UDP
    udp.begin(localport);
    String line, Ruches; // définit le nom de la série de données
    line = String("poids value=" + String(poids));
    Serial.println(line);
    // send the packet
    Serial.println("Sending UDP packet...");
    Serial.print("localport :");
    Serial.println(localport);
    udp.beginPacket(host, localport);
    udp.print(line);
    udp.endPacket();
    delay(1000);

  }
}

Je viens de rejeter un oeil sur le deuxième lien oui oui c’est la solution. Je vais creuser merci!

j'ai oublié "const char stat = "?";"

Ok,

je récidive...

et ça résiste, j'ai rajouté dans l'entête la déclaration : const char stat = "?"; il me retourne :

'const char stat ' redeclared as different kind of symbol'

Quand je le mets dans la boucle il me retourne :

'class EspClass' has no member named 'getHeapStats'

je n’arrive pas à compiler ton code car mes cartes Heltec n’utilisent pas les même lib

pour l’outil de mesure mémoire il est normalement inclus dans le core de l’IDE mais peut être que tu n’utilises pas l’IDE. Il m’a servi a voir que j’avais une fuite mémoire qui plantait l’ESP au bout d’un certain temps
tu peux supprimer cette partie et garder la sortie moniteur dans le else pour vérifier si ton programme continu de tourner lorsqu’il parait planté … peut être que c’est la partie réception Lora qui ne reçoit plus rien ?

pour ma part, j’ai abandonné la liaison Lora entre mon rucher et mon domicile car je n’arrive pas à avoir une communication fiable malgré qu’ils sont seulement à 1 km à vol d’oiseau en campagne mais il y a quelques obstacles (arbres, maisons, …) il y a souvent une différence entre la théorie (on peut lire 10kms) et la pratique …

désolé de ne pouvoir t’aider plus

Bonjour,

merci encore pour le coup de main, bien précieux.

Je compile indifféremment avec l’IDE arduino et platformio. Je déclare ma carte comme DOIT esp32 ou Heltec_esp32_loRa. Dans ce dernier cas, ça plante au niveau émetteur, l’IDE ne me tpas à l’heure le DS3231 qui rythme mes envois.

En principe, mes bibliothèques sont à jour. Je note aussi pour l’instant l’impossibilité d’obtenir mes données dans thingspeak alors qu’avec esp8266 c’est immédiat.

Question distance, j’ai fait un test avec lorareceiver et lorasender, je n’ai pas de souci de distance, ma ruche concernée étant à moins de 100 m de la maison, ça transmet bien. Avec les nrf24 je n’avais pas de connexion.

Tout ça pour quelques kg de miel (mais quel miel…)

bon dimanche

getHeapStats sur ESP8266 uniquement.

Sur ESP32 :

    uint32_t getHeapSize(); //total heap size
    uint32_t getFreeHeap(); //available heap
    uint32_t getMinFreeHeap(); //lowest level of free heap since boot
    uint32_t getMaxAllocHeap(); //largest block of heap that can be allocated at once

OK

Merci,

cordialement

Bonjour,

j'ai tenté d'utiliser les fonctions ci-dessus sans succès, ça me retournait chaque fois une erreur du type "erreur de compilation pour la carte XXX".

Donc, j'ai continué à explorer et j'ai modifié mon sketch de la manière suivante :

j'ai séparé l'acquisition de données lora du renvoi sur le serveur via udp comme on le voit sur le bout de programme ci-dessous. (En effet, tout fonctionnait bien dans les exemples lorasender et lorareciever, très dépouillés) :

void loop() {
  if ( millis() - previousReset >= Reset) {
    previousReset = millis();
    esp_restart();
  }
  StrPoids = "";
  // try to parse packet
  int packetSize = LoRa.parsePacket();
  if (packetSize) {
    // received a packet
    Serial.print("Received packet '");
    // read packet
    while (LoRa.available()) {
      StrPoids += (char)LoRa.read();
      poids = StrPoids.toFloat();
    }
    // print RSSI of packet
    Serial.print("' with RSSI ");
    Serial.println(LoRa.packetRssi());
    //Serial.println(rssi);
  }
  //Transmission UDP
  if ( millis() - previousMillis >= interval) {
    previousMillis = millis();
    sendUdp();
  }
}
void sendUdp() {
  udp.begin(localport);
  String line, Ruches; // définit le nom de la série de données
  if (poids != 0) { //pour éliminer les valeurs aberrantes
    line = String("poids value=" + String(poids));
    Serial.println(line);
    // send the packet
    Serial.println("Sending UDP packet...");
    Serial.print("localport :");
    Serial.println(localport);
    udp.beginPacket(host, localport);
    udp.print(line);
    udp.endPacket();
  }
}
  • Comme udp n'est plus dans la boucle "if packetSize..." qui donne le tempo, j'ai ajouté une temporisation pour l'envoi des données par udp en utilisant millis et non delay qui plantait. Donc la réception des données et leur réenvoi sont indépendants.

  • d'autre part, mes plantages aléatoires étaient dus (semble-t-il, il faut être prudent dans les conclusions) à deux causes, l'une due à l'ESP32 (bug peut-être) et l'autre à la transmission wifi. Celle-ci se fait via une antenne composée d'un petit bout de tôle repliée censée améliorer l'émission. Le problème est que j'avais enfiché mon module sur une planche d'essai qui devait jouer le rôle de cage de faraday et diminuait fortement l'émissivité de l'antenne. J'ai galéré car j'ai mélangé les deux problèmes...

Donc attention quand on fait une montage définitif bien propre sur un circuit imprimé.

Enfin pour la première cause, non réellement identifiée, j'ai tenté beaucoup de choses pour finalement utiliser une méthode de bourrin : toutes les heures, je lance un restart via la commande esp_restart() (ou une autre un peu plus explicite, piquée sur la toile) :

void hard_restart() {
  esp_task_wdt_init(1, true);
  esp_task_wdt_add(NULL);
  while (true);
}

Pour l'instant, ça semble fonctionner en continu. Je ne marque pas encore [RESOLU}, je teste encore quelques jours pour m'assurer que tout fonctionne comme souhaité.

Je ne désespère pas de comprendre pourquoi ttgo lora plante de temps en temps :frowning:

Cordialement