Problème de communication entre deux HC-12 : le récepteur recevant deux valeurs au lieu d'une

Bonjour,
J'ai déjà posté sur ce projet d'anémomètre qui a reçu bien de l'aide déjà.
J'utilise un NANO comme émetteur et un MEGA 2560 comme récepteur. Le HC-12 du MEGA utilise le port Serial1 et non la bibliothèque AltSoftSerial qui ne m'a pas donné de bons résultats.
L'émetteur envoie toutes les secondes le nombre d'impulsions reçues de l'anémomètre. On a ainsi la fréquence que le récepteur transforme en vitesse du vent et effectue plusieurs calculs pour un affichage sur écran I2C 20X4 (V instantanée, V moyenne sur 10 min, V max, bargraph, type de vent et type de rafales).

Le problème est le suivant :
L'émetteur envoie bien la valeur (ici 10Hz) toutes les secondes (voir écran moniteur ci-dessous). Mais le récepteur reçoit en premier lieu les 10Hz puis reçoit toujours un "0" avant les 10Hz. Ce qui fait que le "0" est toujours pris comme valeur. L'affichage final de la vitesse reste à "0". Aucune autre demande de Serial.print n'est présente côté récepteur.

Remarque, si je change la fréquence envoyée, il arrive que la valeur attendue soit prise en compte et tout fonctionne. Mais ceci est aléatoire.
Est-ce du au fonctionnement du port Serial1 ????
Je précise que la fréquence d'affichage sur l'écran LCD est d'une seconde.

Ecran du moniteur côté émetteur (fréquence de réception = 1s):

Let's start envoi!
10.00
10.00
10.00
10.00
10.00
10.00
10.00
10.00
10.00
10.00
10.00
10.00
---- Port série fermé COM7 ----

Voici le programme de l'émetteur (Arduino NANO) :

#include <Arduino.h>
#define PIN_INPUT 2                 // Pin ATACH INTERRUPT 
#define DELAI_ENTRE_DEUX_PULSE 3    // Delai doit être >= 4 ms pour fréquence 250Hz max

volatile int NB_PULSE = 0;
volatile float PRECEDENT_DEPART = 0;
volatile boolean front_descendant=0;

float FREQUENCE = 0.0;
#define TEMPORISATION 1000  //Lecture sur 1s pour avoir F avec NB_PULSE

/// DECLARATION DU HC-12    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <SoftwareSerial.h>
const byte pinTx = 10;
const byte pinRx =11;
SoftwareSerial hc12(pinTx,pinRx);     // PIN TX 10 - PIN RX 11
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


void ISR_PULSE()    // Fonction d'interruption
{
  static uint32_t precedentIT = 0;
  uint32_t  _millis = millis();     // _millis = variable temporaire
  if (precedentIT - _millis >= DELAI_ENTRE_DEUX_PULSE )
  {
    NB_PULSE++;
    front_descendant=1;
  }
  precedentIT = _millis;
}

// VOID CREATION DES CHAINES DE CARACTERES POUR ENVOI DES DONNEES  ////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void createDataString(String &data)
{
  float frequence = FREQUENCE;
  //float vitesse = v;    // le calcul de la vitesse ne doit pas être fait par lémetteur
  //data = "*" + String(frequence);   // essayer de supprimer l'*'
  data = String(frequence);   // essayer de supprimer l'*'
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void setup() 
{
  Serial.begin(9600);
  Serial.println("Let's start envoi!");
  pinMode(PIN_INPUT, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(PIN_INPUT), ISR_PULSE, FALLING);
  hc12.begin(9600);
}

void loop()
{
  if (front_descendant==1)      // Si l'ISR a été déclenchée
  {
    while ((millis() - PRECEDENT_DEPART) <= TEMPORISATION)
    {
      int _NB_PULSE;
      uint8_t oldSREG = SREG;   // Mémorisation de l'état du gestionnaire de registres 
      cli();   // ou  SREG &= ~(1<<I) ;  I étant le bit 7 du registre
                
      _NB_PULSE = NB_PULSE;
      // on redonne la main au gestionnaire des registres dans l'état de départ
      SREG = oldSREG;           
      //Serial.println(_NB_PULSE);
    }
    FREQUENCE = NB_PULSE;
    // Serial.print("FREQUENCE : ");
    // Serial.print(FREQUENCE);
    // Serial.println(" Hz");
    String dataString = "";
    createDataString(dataString);
    delay(10);
    Serial.println(dataString);
    hc12.print(dataString);

    //delay(1000);
    PRECEDENT_DEPART = millis();
    NB_PULSE = 0;
    front_descendant=0;
  }  
}

Voici l'écran du moniteur côté récepteur :

---- Ouverture du port série COM4 ----
HC-12 Ready
Received from HC-12: 
0.00
10.00
Received from HC-12: 
0.00
10.00
Received from HC-12: 
0.00
10.00

Parties de programme du récepteur :

  • Déclaration du HC-12 sur le Serial1
// Déclaratiion HC-12 sur le port Serial1 de l'Arduino MEGA 2560
#define pinTX 19        // Serial1 pour le MEGA
#define pinRX 18

Void Loop :


void loop()           
{
  
  ////////////////**************** Réception de la frequence ******************//////////////////////////
  float freq = 0;    // Déclaration de la donnée reçue

  if (Serial1.available() > 0)       // Vérifie si des données sont disponibles
  {
    String receivedData = "";         // Initialise une chaîne pour stocker les données reçues
    while (Serial1.available() > 0) // Lire toutes les données disponibles
    {
      char c = Serial1.read();
      receivedData += String(c);
      delay(10);
    }
    //Serial.println("Données reçues du HC-12 : " + receivedData); // Affiche les données reçues
    freq = receivedData.toFloat();
    Serial.print("Frequence = ");
    Serial.println(freq);
    //delay(100);
  }

    temps_precedent = micros();    // Pour la mesure d'absence d'affichage en fin de loop

    NB_PULSE_10s_INCREMENT = NB_PULSE_10s_INCREMENT + freq;     // incrémente le nombre de front descendants observés en 10s (remis à 0 après 10s dans "Calculateur 10 min)
  
    //Serial.println(NB_PULSE_10s_INCREMENT);

    memoire_vmax_zero = 0; // permet de ne mettre à 0 la v instantannée max qu'une seule fois lorsque plus de 2.5s sans signal anemomètre

    // Conversion fréquence en vitesse
    if (freq == 0.0) 
    { 	
        v = 0;
    }
    else if (freq <= 3.0)
    {
        v = 0.8 * freq ;
    }
    else
    {
        v = 3 + 0.8 * freq ;	
    }

    // Calcul v_max_inst
    if (affiche == 1)
    {                  // s'il y a eu affichage de la v_max_inst, elle est remise à zero 
      v_max_inst = 0;                   // remise à zero v_max_inst, de ce fait elle évolura entre l'affichage qui vient d'avoir lieu et le nouvel affichage à venir (toutes les 500ms)
      affiche = 0;                      // on déclare que l'affichage est à faire pour la prochaine v max inst
    }
      
    if (v == 0)
    {
      v_max_inst = 0;
    }

    if (v > v_max_inst && v < 200)
    {      
      v_max_inst = v;          // évolution de la vitesse instantannée (je prends la vitesse instantanée maximale obtenue entre 2 affichages (affichage toutes les 500ms)
    }

    if (v > v_max_inst_bargraph && v < 200)
    {      
      v_max_inst_bargraph = v;          // évolution de la vitesse instantannée (je prends la vitesse instantanée maximale obtenue entre 2 affichages (affichage toutes les 500ms)
    }

    if (v > v_max && v < 200)
    {
      v_max = v;                        // évolution vitesse max. 
    }
    //(1.8*v_precedente)) était 1.5 // calcul v max obtenue sur durée bloc de 10s, le coeff 
    //1.5 évite les aberrations de vitesse doublée qu'il y avait parfois
    if (v > v_max_bloc_10s && v < 200)
    { 
      v_max_bloc_10s = v;               // évolution vitesse max. sert AUX CALCULS DES RAFALES
    }

    // //pourcentage=(v);
    // pourcentage = (v_max_inst_bargraph);
    // percent = byte(pourcentage);

    t_ecoule_bargraph = TEMPS_milli - t_debut_bargraph;

    if (t_ecoule_bargraph > cadence_bargraph)
    { 
        //pourcentage=(v);
        pourcentage = (v_max_inst_bargraph);
        if (pourcentage > 0)          // Suppression du flash dû au "0" reçu avant la valeur
        {
          percent = byte(pourcentage);
        }
      draw_progressbar(percent);
      t_debut_bargraph = millis();
    }

//Serial.print("v prec : ");
//Serial.print(v_precedente);
//Serial.print(" | v : ");
//Serial.print(v);
//Serial.print(" | v max : ");
//Serial.print(v_max);
//Serial.print(" | nb calc : ");
//Serial.print(nb_v_calc);
//Serial.print(" | dep : ");
//Serial.println(depassement);

   if (v < 200)
   { 
      v_precedente = v;
   }


    TEMPS_milli = millis();         // instant (ms) nécessaires pour cadence d'affichage
    TEMPS_micros = micros();        // instant (µs) nécessaires remise à zero v instantanée "V_max_inst" si plus de 2 s sans signal

    CALCULATEUR_10mn();                       // appelle fonction de calcul des éléments sur 10mn d'observation
      
    t_ecoule_affichage = TEMPS_milli - t_debut_affichage;  // pour gérer cadence affichage 

    //////////////////////////////////////////////////////////////////////////////////

    if (t_ecoule_affichage > cadence_affichage)      // affichage selon cadence choisie mais au début, tant qu'il n'y a pas eu assez de front descendants, n'affiche rien
    {  
      AFFICHEUR();                              // appelle fonction d'affichage (appelée tts les 1s)
        
      duree_v_nulle = TEMPS_micros - temps_precedent;  // temps écoulé depuis le dernier front montant (sert à la mise à zero de la vitesse si pas de signal pendant plus de 2s
        
      if ((duree_v_nulle > duree_remise_zero) && memoire_vmax_zero == 0)  // si plus de 2 s sans signal anemo, v max est mise à 0 et affiche une seule fois
      {
        v_max_inst = 0;                              
        memoire_vmax_zero = 1;     // variable mémoire qui permet de ne mettre à zero la vitesse instantannée qu'une seule fois. Est remise à 0 quand nouveau front montant
        percent = 0;
        draw_progressbar(percent);
      }
    }  //// FIN IF temps d'affichage dépassé /////////////////////////////////////

}    ///// FIN LOOP ///////////// FIN LOOP ///////////// FIN LOOP ///////////// FIN LOOP ///////////// FIN LOOP ////////// FIN LOOP ///////////// FIN LOOP ///////////// FIN LOOP ///////////// FIN LOOP ///////////// FIN LOOP


Je donne ma langue au chat !
Merci à vous tous.
Bébert

1 Like

PRECEDENT_DEPART devrait un unsigned long et il n'y a aucune raison de le déclarer volatile car il n'est pas utilisé dans le gestionnaire d'interruption.

Je ne vois pas à quoi sert cette partie du code.

Pour la partie réception, le code que tu donnes ne correspond pas à ce que tu présentes comme étant "l'écran du moniteur côté récepteur :"

vous n'avez pas de section critique pour vos données traitées dans la loop et qui sont potentiellement impacté par l'ISR

pour l'émetteur, envisagez un code comme cela

#include <SoftwareSerial.h>
const byte pinTx = 10;
const byte pinRx = 11;
const byte pinAnemometre = 2;             // Pin ATACH INTERRUPT
const unsigned long deltaImpulsion = 3;   // le delai entre 2 impumsions doit être >= 3 ms pour la prendre en compte
const unsigned long periodeEmission = 1000;

SoftwareSerial hc12(pinTx, pinRx);    // PIN TX 10 - PIN RX 11
volatile unsigned long nbImpulsions = 0;
unsigned long chrono;

void ISR_PULSE() {
  static uint32_t precedentIT = 0;
  uint32_t  _millis = millis();
  if (precedentIT - _millis >= deltaImpulsion) {
    nbImpulsions++;
    precedentIT = _millis;
  }
}

void setup() {
  Serial.begin(115200);
  hc12.begin(9600);
  pinMode(pinAnemometre, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(pinAnemometre), ISR_PULSE, FALLING);
  chrono = millis();
  Serial.println("Let's start envoi!");
}

void loop() {
  if (millis() - chrono >= periodeEmission) {
    // ------- section critique ------- 
    noInterrupts();
    unsigned long copieNbImpulsions = nbImpulsions;
    nbImpulsions = 0;
    interrupts();
    // --------------------------------
    hc12.print(copieNbImpulsions);
    hc12.write('\n'); // marqueur de fin
    chrono += periodeEmission;
  }
}

on envoie la valeur du compteur en ASCII suivi d'un passage à la ligne \n pour qu'on puisse séparer les éléments côté receveur.

Pour la lecture du port série côté receveur, il faut faire cela de manière asynchrone, pas de delay etc... cf mon petit tuto sur le sujet

Bonsoir J-M-L Jackson,

C'est avec plaisir que je te retrouve ! Tes commentaires et propositions me permettent de progresser au fil des difficultés rencontrées.
Merci pour ce code affiné. Par contre, je ne comprends pas que tu initialises le Serial1 alors que j'utilise la bibliothèque "SoftwareSerial.h". Est-ce parce que ce port est utilisé par le récepteur ? Et est-il nécessaire de caler la vitesse de transmission à 115200 au lieu de 9600 ?

J'ai lu attentivement ton tuto sur la communication série et j'ai bien envie de fouiller cela plus avant. Il est très clair et fort utile pour comprendre ce qu'il se passe dans les coulisses.

Je vais intégrer la suppression du delay chez le récepteur et essayer tout cela.

A bientôt. Merci encore.

Je ne touche pas Serial1… je ne comprends pas la remarque.

Non pas nécessaire mais pourquoi aller lentement pour l’affichage sur votre terminal série?

Pardon, j'ai lu un peu vite !

Anémomètre avec HC-12, DS3231 et Carte SD : que choisir entre Mega 2560 et deux Nano pour le récepteur ?

Saison 3 ep1 :

Bonjour,

Suite de mes mises au point précédentes avec l’aide du forum :

  • (A) émetteur et récepteur avec deux HC-12 (1 et 2), deux Nanos (1 et 2) et un écran I2C LCD 20x4
  • (B) émetteur et récepteur avec deux HC-12 (1 et 2), un Nano, un Méga 2560 et un écran I2C LCD 20x4
  • (C) tests d’une horloge temps réel DS3231 et Carte SD avec Méga 2560

L’idée de passer au Méga vient de l’insuffisance de mémoire du Nano pour ajouter la DS3231 et la SD.

Cependant, deux solutions s’offrent :

  • soit j’utilise le Méga avec les deux modules I2C sur un même couple de ports SDA et SCL en pins 20 et 21. Lorsque les données sont recueillies, il me faut alors, dans la loop(), arrêter la communication avec l’écran LCD ouvrir celle de l’horloge qui me donne l’heure pour les enregistrements sur la carte SD et redonner ensuite la priorité à l’écran. Comment fonctionnera l’affichage ?
  • soit j’utilise le montage (A) et j’ajoute un 3ème circuit avec un HC-12(3), et un 3ème Nano (3) qui portera l’horloge et la Carte SD. Dans cette version, c’est le HC-12(2) du récepteur qui devra changer de canal (du 1 au 2) pour transmettre les données sur le canal 2 prédéfini du HC-12 (3) du 3ème Nano. Alors, le HC-12 (2) du récepteur ne traitera plus les impulsions reçues de l’anémomètre pendant l’envoi et l’enregistrement des données sur le circuit 3 avant de retrouver son canal de communication (canal 1).

Au vu de la lourdeur du programme récepteur actuel, quelle option choisir pour un fonctionnement optimal. That’s the question !

Merci pour vos avis.

Ci-joints les schémas des hypothèses de montages et le rappel du Loop() qui devrait recevoir les lignes de programme supplémentaires après l’appel du void « AFFICHEUR », vers la fin du Loop(). En principe du moins.

void loop()           
{
  
  ////////////////**************** Réception de la frequence ******************//////////////////////////
  float freq = 0;    // Déclaration de la donnée reçue

  String receivedData = "";

  ///////////////  VERSION OK  /////////////////  VERSION OK  //////////////   VERSION OK  //////////////
  if (Serial1.available() > 0)       // Vérifie si des données sont disponibles
  {
    String receivedData = "";         // Initialise une chaîne pour stocker les données reçues
    while (Serial1.available() > 0) // Lire toutes les données disponibles
    {
      char c = Serial1.read();
      receivedData += String(c);
      delay(10);                 // A SUPPRIMER avec l'utilisation du port Serie car communication asynchrone
                                 // Mais SANS, le bargraph ne fonctionne plus ! 
    }
    
    freq = receivedData.toFloat();
    Serial.print("Frequence = ");
    Serial.println(freq);
  }

/////////////////////////////   ESSAI NON OK  Forum   /////////////////////////////////////////
  // while (true)
  // {
  //     if (Serial1.available() > 0)       // Vérifie si des données sont disponibles
  //     {
  //         receivedData = Serial1.readStringUntil('\n');
  //         break;
  //     }
  //     freq = receivedData.toFloat();
  //     Serial.print("Frequence = ");
  //     Serial.println(freq);
  // }
  //////////////////////////////////////////////////////////////////////////////////////

    temps_precedent = micros();    // Pour la mesure d'absence d'affichage en fin de loop

    NB_PULSE_10s_INCREMENT = NB_PULSE_10s_INCREMENT + freq;     // incrémente le nombre de front descendants observés en 10s (remis à 0 après 10s dans "Calculateur 10 min)
  
    //Serial.println(NB_PULSE_10s_INCREMENT);

    memoire_vmax_zero = 0; // permet de ne mettre à 0 la v instantannée max qu'une seule fois lorsque plus de 2.5s sans signal anemomètre

    // Conversion fréquence en vitesse
    if (freq == 0.0) 
    {   
        v = 0;
    }
    else if (freq <= 3.0)
    {
        v = 0.8 * freq ;
    }
    else
    {
        v = 3 + 0.8 * freq ;  
    }

    // Calcul v_max_inst
    if (affiche == 1)
    {                  // s'il y a eu affichage de la v_max_inst, elle est remise à zero 
      v_max_inst = 0;                   // remise à zero v_max_inst, de ce fait elle évolura entre l'affichage qui vient d'avoir lieu et le nouvel affichage à venir (toutes les 500ms)
      affiche = 0;                      // on déclare que l'affichage est à faire pour la prochaine v max inst
    }
      
    if (v == 0)
    {
      v_max_inst = 0;
    }

    if (v > v_max_inst && v < 200)
    {      
      v_max_inst = v;          // évolution de la vitesse instantannée (je prends la vitesse instantanée maximale obtenue entre 2 affichages (affichage toutes les 500ms)
    }

    if (v > v_max_inst_bargraph && v < 200)
    {      
      v_max_inst_bargraph = v;          // évolution de la vitesse instantannée (je prends la vitesse instantanée maximale obtenue entre 2 affichages (affichage toutes les 500ms)
    }

    if (v > v_max && v < 200)
    {
      v_max = v;                        // évolution vitesse max. 
    }
    //(1.8*v_precedente)) était 1.5 // calcul v max obtenue sur durée bloc de 10s, le coeff 
    //1.5 évite les aberrations de vitesse doublée qu'il y avait parfois
    if (v > v_max_bloc_10s && v < 200)
    { 
      v_max_bloc_10s = v;               // évolution vitesse max. sert AUX CALCULS DES RAFALES
    }

    // //pourcentage=(v);
    // pourcentage = (v_max_inst_bargraph);
    // percent = byte(pourcentage);

    t_ecoule_bargraph = TEMPS_milli - t_debut_bargraph;

    if (t_ecoule_bargraph > cadence_bargraph)
    { 
        //pourcentage=(v);
        pourcentage = (v_max_inst_bargraph);
        if (pourcentage > 0)          // Suppression du flash dû au "0" reçu avant la valeur
        {
          percent = byte(pourcentage);
        }
      draw_progressbar(percent);
      t_debut_bargraph = millis();
    }

   if (v < 200)
   { 
      v_precedente = v;
   }

    TEMPS_milli = millis();         // instant (ms) nécessaires pour cadence d'affichage
    TEMPS_micros = micros();        // instant (µs) nécessaires remise à zero v instantanée "V_max_inst" si plus de 2 s sans signal

    CALCULATEUR_10mn();             // appelle fonction de calcul des éléments sur 10mn d'observation
      
    t_ecoule_affichage = TEMPS_milli - t_debut_affichage;  // pour gérer cadence affichage 

    //////////////////////////////////////////////////////////////////////////////////

    if (t_ecoule_affichage > cadence_affichage)      // affichage selon cadence choisie mais au début, tant qu'il n'y a pas eu assez de front descendants, n'affiche rien
    {  
      **AFFICHEUR();**                              // appelle fonction d'affichage (appelée tts les 1s)


      ///////////////////  ************** ATTENTE PROGRAMME A FAIRE POUR DS3231 ET CARTE SD ***************  ////////////////////////////////


        
      duree_v_nulle = TEMPS_micros - temps_precedent;  // temps écoulé depuis le dernier front montant (sert à la mise à zero de la vitesse si pas de signal pendant plus de 2s
        
      if ((duree_v_nulle > duree_remise_zero) && memoire_vmax_zero == 0)  // si plus de 2 s sans signal anemo, v max est mise à 0 et affiche une seule fois
      {
        v_max_inst = 0;                              
        memoire_vmax_zero = 1;     // variable mémoire qui permet de ne mettre à zero la vitesse instantannée qu'une seule fois. Est remise à 0 quand nouveau front montant
        percent = 0;
        draw_progressbar(percent);
      }
    }  //// FIN IF temps d'affichage dépassé /////////////////////////////////////

}    ///// FIN LOOP ///////////// FIN LOOP ///////////// FIN LOOP ///////////// FIN LOOP ///////////// FIN LOOP ////////// FIN LOOP ///////////// FIN LOOP /////////////

Fichier zip des motages fzz :
HC12_ANEMO_INTERRUPT_61_F-Def-1s_MEGA_ou_Nanos_DS3231_Carte-SD_Recepteur.zip (133.0 KB)

ça ne me semble pas nécessaire, les bibliothèques habituelles font le job.

Un Nano devrait aller pour un LCD 20x4, un HC-12, la carte SD et la RTC

idéalement passez vous de SoftwareSerial pour gérer le HC-12 et connectez le sur les pins 0 et 1 et utilisez Serial. Il faut que le code soit robuste bien sûr puisque vous perdez le port série pour le débug (mais vous pouvez utiliser le LCD). Il faudra penser à débrancher le HC-12 quand vous uploadez le code.

Ensuite si vous n'avez pas de souci de place, une MEGA donne plus de mémoire et plus de ports séries donc on peut faire plus de choses...

Bonjour J-M-L,
Merci pour ta répoonse.
Lorsque j'utilise le Nano, la mémoire prend 121% de RAM. Voilà pourquoi j'utilise la MEGA.
J'en suis au test avec MEGA et l'août de la DS3231 avec les begin.transmission et End.transmission pour basculer le l'écran à la DS3231. Cela marche !

if (t_ecoule_affichage > cadence_affichage)      // affichage selon cadence choisie mais au début, tant qu'il n'y a pas eu assez de front descendants, n'affiche rien
  {  
    AFFICHEUR();                              // appelle fonction d'affichage (appelée tts les 1s)



  /////////////  ************** PROGRAMME RECUPERATION DE L'HEURE SUR DS3231  ***************  //////////////////////////
  // Arrêt affichage sur LCD 20x4
  Wire.endTransmission(0x27);
      
  // Bascule sur la DS3231
  Wire.beginTransmission(0x68);
  // Affichage heure
  recuperationHeure();
  // Arrêt holrloge
  Wire.endTransmission(0x68);

  // Réactivation de l'écran
  Wire.beginTransmission(0x27);
  /////////////////// ************* FIN PROGRAMME RECUPERATION HEURE ************* ///////////////////////////////////////

J'essaierai sans cela.

Je dois intégrer maintenant la carte SD et les essais d'enregistrements à la suite du code.
Je me demande si je dois déclarer les variables recueillies dans le void AFFICHEUR(); en volatiles (vitesses, type de vent, etc...) pour les enregistrements après son excécution ?

Merci encore.
Bon dimanche.
JP

Avec quelles bibliothèques ?

Volatile ne sert pas à ça.
Volatile indique seulement que le contenu de la variable peut changer à n'importe quel moment et que le compilateur ne doit donc pas faire d'optimisation dessus et relire sa valeur à chaque fois qu'on utilise la variable.


AFFICHEUR() comme son nom semble l'indiquer ne devrait fait que de l'affichage. Dans un programme bien conçu et bien découpé, les données devrait être récupérées par une autre fonction qui pourrait passer lesdites données à une fonction d'affichage, une fonction de sauvegarde ou tout autre fonction qui pourrait faire du traitement sur celles-ci.
Au passage, AFFICHEUR() est une fonction. void (rien en anglais) indique que la fonction ne retourne aucune valeur. On pourrait aussi bien avoir int AFFICHEUR() si la fonction AFFICHEUR() retournait un entier.

Avec la SoftwareSerial.h.

Merci fdufnews pour cette précision. J'avais cru comprendre qu'il fallait utiliser volatile lorsqu'une variable affectée à une valeur était reprise dans plusieurs void différentes.

Mon AFFICHEUR() récupère en effet les valeurs du void "CALCULATEUR()", les affiche sur l'écran LCD I2C 20x4 et met à jour des variables utilisées ensuites dans la boucle LOOP().
Merci.

A retenir !
Et dans la cas de différentes variables (int, float... ou String ?) comme c'est le cas pour moi ? Quelle déclaration autre que void ?

Merci encore pour toutes ces réponses.
J'ai fini de mettre au point le programme récepteur avec le MEGA 2560. Tout marche au poil ! Cela a pris bien du temps, y compris à J-M-L et à toi que je remercie vivement pour votre disponibilité.

J'essaierai la version à deux NANO pour le récepteur. Cela me fera travailler les changements de canal pour les HC-12.

A bientôt. Et vive le forum !
JP dit BEBERT

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.