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