Réalisation d'un anémomètre

Bonjour,
Je continue d'avancer dans ma station météo (Temp, Pression, qualité de l'air) je souhaite maintenant ajouter un anémomètre.

Pour cela j'ai un capteur à effet hall KY-003 que je souhaite brancher à mon ESP32S (https://www.amazon.fr/gp/product/B0BWLSDFY4/ref=ppx_yo_dt_b_asin_title_o07_s00?ie=UTF8&th=1

Première question est ce que ce composant vous semble pertinent?
Concernant le programme je suis parti d'un que j'ai trouvé :

unsigned long startMillis;
  unsigned long currentMillis;
  const unsigned long period = 1;

  int hall_sensor = 19;
  int magnetSense = 0;
  int counter = 0;
  boolean lastState = true;                // I changed to boolean type

  float windSpeed;
  float radius = 0.000207;
  float pi = 3.142;
  float circumference = 2 * radius * pi;
  //-----------------------------------------------------------
  void setup() {
  Serial.begin(115200);
  startMillis = millis();
  pinMode(hall_sensor, INPUT);
  }
  //-----------------------------------------------------------
  void loop() {
  currentMillis = millis();
  magnetSense = digitalRead(hall_sensor);
  if (magnetSense == 0 && lastState == true)
  {
    lastState = false;
    
    if (currentMillis - startMillis >= period)
    {
      windSpeed = circumference / (currentMillis - startMillis) * 3600000;
      startMillis = currentMillis;
      counter++;
      Serial.println(String(windSpeed) + "km/h");
    }
  }
  else
  {
    
    if (currentMillis - startMillis >= period)
    {
      startMillis = currentMillis;
      lastState = true;
    }
  }

J'ai quelques questions :

  • J'ai lu des choses sur des pb de rebond faut il modifier ce programme et ajouter des PULLUP (ou est ce surperflux) ou ajouter des résistances ou condo : en fait je suis un peu perdu
  • Je me suis gratté la tête mais je ne comprends pas la condition suivante :
if (magnetSense == 0 && lastState == true)

Et d'une façon générale pensez vous que ce programme est adapté à mon besoin.

Merci d'avance pour vos commentaires

:warning:
Post mis dans la mauvaise section, on parle anglais dans les forums généraux. déplacé vers le forum francophone.

Merci de prendre en compte les recommandations listées dans Les bonnes pratiques du Forum Francophone

Bonjour delba146

Oui, tout à fait, je n'utilise, quasiment, que ça.
Attention, il ne détecte pas que "l'aimantation", il faut faire attention au sens de l'axe nord/sud de l'aimant:
image

Avec le capteur KY-003, u ne t'inquiètes plus de tout ça.

Pour ce qui est de ton programme, si c'est le seul ensemble que tu as à contrôler avec ton Arduino, c'est bon, si ce n'est pas le cas, ça va êtte difficile à intégrer dans un autre ensemble, je pense qu'il est préférable de travailler avec une interruption, de compter les impulsions pendant 1 seconde(par ex.) et, de cette somme, en déduire la vitesse du vent.

Si tu veux un exemple, c'est volontier.

Cordialement
jpbbricole

Je suppose que ce n'est pas les conditions en soit que tu ne comprends pas, mais le principe de fonctionnement?
Tu rentre dans le IF, si les deux conditions sont vérifiées.
Je suppose que ton capteur, indique un état "positif" lorsque ça valeur est 0
Comme cela positionne lastState à false, même si ton capteur est toujours à ca valeur positif, tu ne va pas rentrer dans le IF à nouveau.
Il faudra qu'un temps correspondant à "period" ce soit écouler, pour repositionner "lastState" à True.

Par contre je ne vois pas trop pourquoi startMillis est sauvegardé lorsque l'on a attendu le temps de "period"
Il paraitrait plus logique de compter le temps entre chaque moment ou magnetSense est positif, pour savoir que l'on a fait un tour en un temps donné.
Après il semble important d'attendre un certain temps "pediod" ou 1milliseconde, je suppose pour laisser le temps à magnetSense de revenir négatif.

Meri à vous 2 pour vos premiers retours :

Effectivement Terwal je n'avais pas compris le fonctionnement désormais avec tes explications je saisis mieux la logique derrière ce programme.

Je vais intégrer cet anémomètre dans mon programme actuel qui relève déjà Temp, particules... à différents moments donc je suis preneur d'un exemple.

Si ton programme fonctionne déjà sur une machine à état, l'utilisation d'une interruption n'est pas forcément utile, même si c'est surement ce que j'aurais utilisé :slight_smile:
Surtout que cela ne résoudra pas les problèmes de rebonds que tu évoques.

A ce stade je n'ai pas encore intégré cette fonctionnalité à mon programme général je cherche la meilleure solution. donc je suis preneur de vos conseils.

Bonjour terwal

L'utilisation d'une interruption n'empêche pas le bon fonctionnement d'une machine à état, cette interruption peut même y participer.

Avec ce type de capteur, il n'y a pas à s'en inquiéter.

Cordialement
jpbbricole

Bien sûre, je ne pense pas avoir indiqué le contraire ?
J'indique juste que sauf, si il y a un risque de louper une pulsation, cela n'a pas vraiment de valeur ajoutée.

Bonsoir delba146

Voila une toute première version, essaies ça sur ta machine, ça ne fait que compter les impulsions toutes les vitesseCalculTempo millisecondes.

Le programme:

/*
    Name:       ARDFR_delba146_Anémomètre.ino
    Created:	03.01.2024
    Author:     jpbbricole/delba146

	03.01.2024	Première version #10
	https://forum.arduino.cc/t/realisation-dun-anemometre/1206599
	https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/
*/
const int hallSensorPin = 19;     // delba146 19     // jpbbricole 2
volatile int hallPulsesCompteur = 0;     // Comptage des impulsions

const unsigned long vitesseCalculTempo = 1000;     // Toutes les secondes
unsigned long vitesseCalculMillis = millis();     // Toutes les secondes, chrono

void setup()
{
	Serial.begin(115200);
	attachInterrupt(digitalPinToInterrupt(hallSensorPin), hallSensorComptage, FALLING);     // Comptage au flan descendant
}

void loop()
{
	if (millis() - vitesseCalculMillis >= vitesseCalculTempo)     // Si temps de calculer la vitesse
	{
		Serial.println("Impulsions : " + String(hallPulsesCompteur));
		hallPulsesCompteur = 0;

		vitesseCalculMillis = millis();     // Redémarrage du chrono
	}

}


void hallSensorComptage()
{
	hallPulsesCompteur ++;
}

Bonne soirée
jpbbricole

Bonsoir JPb,
J'ai effectue les tests sur une carte d'essai :

AZDelivery 3 x D1 Mini NodeMCU Lua
Que j'ai déclaré en générique ESP8266
Des infos défilent à une vitesse frénétique voici une capture prise au vol :
image

J'ai testé avec 3 wemos différents même resultat

pour info avant l'écriture j'ai le message suivant :

. Variables and constants in RAM (global, static), used 28408 / 80192 bytes (35%)
║ SEGMENT BYTES DESCRIPTION
╠══ DATA 1504 initialized variables
╠══ RODATA 952 constants
╚══ BSS 25952 zeroed variables
. Instruction RAM (IRAM_ATTR, ICACHE_RAM_ATTR), used 60095 / 65536 bytes (91%)
║ SEGMENT BYTES DESCRIPTION
╠══ ICACHE 32768 reserved space for flash instruction cache
╚══ IRAM 27327 code in IRAM
. Code in flash (default, ICACHE_FLASH_ATTR), used 237396 / 1048576 bytes (22%)
║ SEGMENT BYTES DESCRIPTION
╚══ IROM 237396 code in flash

Merci.

Bonsoir delba146

Je n'arrive pas à trouver ta carte dans l'IDE Arduino :woozy_face: pour essayer la compilation.

A+
jpbbricole

Je viens d'essayer avec ce programme basique et j'ai bien le message :

void setup() {
  
    Serial.begin(115200);
}

void loop() {
  Serial.println("Hello World.");
   delay(500);                                   
}

Donc je me dis que la config de la carte doit fonctionner??

Bonsoir delba146

Je pense que cela provient du fait que ta carte d'essai n'a pas de GPIO 19, comme ta carte d'origine
int hall_sensor = 19;
Essaies avec un autre port.

Cordialement
jpbbricole

J'avais déjà essayé avec d'autres ports mais sans succès

Qu'as tu choisi comme carte dans l'IDE?
Je vais refaire des test demain.

Bonne nuit
jpbbricole

Bonjour delba146

Essaies:
image

Je n'ai malheureusement pas cette carte pour pousser plus loin :woozy_face:

Bonne journée
jpbbricole

Bonjour jbbricole,
J'avais mis mon projet en stand by je viens de m'y remettre, cette fois je me suis connecté sur mon ESP définitif un espressif wroom 32.

J'ai reprise les lignes que tu avais proposé :

// variables anémométre
const int hallSensorPin = 2;     
volatile int hallPulsesCompteur = 0;     // Comptage des impulsions
const unsigned long vitesseCalculTempo = 5000;     // Toutes les 5 secondes
unsigned long vitesseCalculMillis = millis();   
void hallSensorComptage()
{
	hallPulsesCompteur ++;
  Serial.println("Detection hall");
}

set up

attachInterrupt(digitalPinToInterrupt(hallSensorPin), hallSensorComptage, FALLING);

loop

if (millis() - vitesseCalculMillis >= vitesseCalculTempo){  // Si temps de calculer la vitesse
			Serial.println("Impulsions : " + String(hallPulsesCompteur));
	  	hallPulsesCompteur = 0;
  		vitesseCalculMillis = millis();    

Et là c'est un festival de messages :



15:31:58.687 -> Impulsions : 14245
15:32:03.682 -> Impulsions : 233
15:32:22.776 -> Detection hall
15:32:22.776 -> Detection hall
15:32:22.776 -> Detection hall
15:32:22.776 -> Detection hall
15:32:22.794 -> Detection hall
15:32:22.794 -> Detection hall
15:32:22.794 -> Detection hall
15:32:22.794 -> Detection hall
15:32:22.794 -> Detection hall
15:32:22.794 -> Detection hall
15:32:22.794 -> Detection hall
15:32:22.794 -> Detection hall
15:32:22.794 -> Detection hall
 DeteGuru Meditation Error: Core  1 panic'ed (Interrupt wdt timeout on CPU1). 
15:32:23.045 -> 
15:32:23.045 -> Core  1 register dump:
15:32:23.045 -> PC      : 0x40090f56  PS      : 0x00060e35  A0      : 0x8008fbf6  A1      : 0x3ffbf3cc  
15:32:23.045 -> A2      : 0x3ffb897c  A3      : 0x3ffbd320  A4      : 0x00000004  A5      : 0x00060e23  
15:32:23.045 -> A6      : 0x00060e23  A7      : 0x00000001  A8      : 0x3ffbd320  A9      : 0x00000019  
15:32:23.076 -> A10     : 0x3ffbd320  A11     : 0x00000019  A12     : 0x3ffc55cc  A13     : 0x00060e23  
15:32:23.076 -> A14     : 0x007bf5f8  A15     : 0x003fffff  SAR     : 0x0000001e  EXCCAUSE: 0x00000006  
15:32:23.076 -> EXCVADDR: 0x00000000  LBEG    : 0x4008af39  LEND    : 0x4008af49  LCOUNT  : 0xfffffffc  
15:32:23.076 -> Core  1 was running in ISR context:
15:32:23.076 -> EPC1    : 0x400e8f13  EPC2    : 0x00000000  EPC3    : 0x00000000  EPC4    : 0x00000000
15:32:23.076 -> 
15:32:23.076 -> 
15:32:23.076 -> Backtrace: 0x40090f53:0x3ffbf3cc |<-CORRUPTED
15:32:23.076 -> 
15:32:23.108 -> 
15:32:23.108 -> Core  0 register dump:
15:32:23.108 -> PC      : 0x400910ef  PS      : 0x00060035  A0      : 0x8008f81f  A1      : 0x3ffbed1c  
15:32:23.108 -> A2      : 0x3ffbf5f8  A3      : 0xb33fffff  A4      : 0x0000abab  A5      : 0x00060023  
15:32:23.108 -> A6      : 0x00060021  A7      : 0x0000cdcd  A8

Bonsoir delba146

J'ai fait des essais avec un ESP32 et il ne supporte pas ça (c'est susceptibles ces petites bêtes :wink: ):

dans la routine d'interruption. Contente toi d'y mettre le minimum.

Si tu veux afficher l'activité du hall, fait une variable globale booléenne:
volatile boolean hallDetection = false;

Dans la routin d'interruption, tu mets:

void hallSensorComptage()
{
	hallPulsesCompteur ++;
	hallDetection = true;
}

et dans loop():

	if (hallDetection)
	{
		Serial.println("Detection hall\t" + String(hallPulsesCompteur));
		hallDetection = false;
	}

Bonne soirée
jpbbricole

Bonsoir,

J'ai un peu cherché il y a des articles sur ce sujet mais bon compliqué pour moi :
Pour info :
https://lastminuteengineers.com/handling-esp32-gpio-interrupts-tutorial/?utm_content=cmp-true

Sinon tu aurais proposé quel type de cartes pour supporter : DHT, SDS011 (mesures de particules) anémométre, pluviométre... selon mes idées, est ce trop juste un ESP32 vroom??

Je reviens à ta proposition qu'est ce qui détecte le changement de champ du capteur, auparavant c'était le attachInterrupt(digitalPinToInterrupt(hallSensorPin), hallSensorComptage, FALLING);mais dans ta proposition je ne vois pas.

Merci.