Mise en fonction d'un Anémomètre

Bonjours à tous ! :)

Je possède un anémomètre Somfy et j'aimerais pouvoir récupérer la vitesse du vent en m/s sur mon port serial. J'ai pensé déduire celle-ci du nombre de changement d'état que prendrait la pin reliée à mon anémomètre. En effet, j'ai remarqué que celle-ci change 8x d'état lors d'un tour d’hélice.

Voilà mon début de code ;) :

const int Anemo = 8;

unsigned long duration; 
unsigned long impulsion;

int Anemo_Push_Counter = 0;
int Anemo_State = 0;
int Last_Anemo_State = 0;

void setup()
{
    Serial.begin(9600); // Communication serial à 9600 bauds
    pinMode(8,INPUT);   // Broche 8 en entrée
}


void loop()

{
  
  // lit l'état actuel de la pin8
  Anemo_State = digitalRead(Anemo);

  // compare l'état actuel de l'anemo à l'état précédent mémorisé
  if (Anemo_State != Last_Anemo_State)
  
  {
      Anemo_Push_Counter++;
  }
    
  
  Serial.println (Anemo_Push_Counter);
  
  delay (100);
  
}

Malheureusement, quand je vais voir dans mon serial, ma variable Anemo_Push_Counter ne s'incrémente pas quand il y a un changement d'état mais quand elle est à 1 :astonished: et ne s'incrémente pas quand elle est à 0 :sweat_smile:

Un peu d'aide serait la bienvenue ! Merci d'avance XD

C'est parce que tu ne mets pas à jour ta variable Last_Anemo_State. Elle reste toujours à sa valeur initiale. Dans ta condition if, ajoute une mise à jour de cette variable à la valeur en cours (Anemo_State).

Et si tu n’y arrives pas avec l’indication de zeni, je ne comprendrais pas. Puisque c’est connu : “It’s so easy, it’s Somfy!”

:slight_smile:

Merci zeni ! Je peux à présent compter les impulsions :)

Pour la suite je pensais regarder chaque seconde le compteur en sachant que quand le compteur est à 8 c'est que l'hélice a fait un tour. Je prendrai ensuite la valeur indiquée (exemple 1012) et je la diviserai par 8 pour obtenir le nombre de tour de l'hélice en 1 seconde (dans mon exemple 126.5).

Je mettrai ensuite cette valeur dans la formule que j'ai trouvé sur wikipedia : http://fr.wikipedia.org/wiki/An%C3%A9mom%C3%A8tre ;)

C'est à dire : V = 2*PI*F(N)*R*N donc la vitesse du vent en m/s = 2 x PI x la fonction d'étalonnage x le rayon des bras x nbr de tours / s

Donc, V sera envoyé dans mon serial et ce que je cherche à calculer sera assigné à N.

Ce qui me donnerai un code comme ça :

const int Anemo = 8;

unsigned long impulsion;
unsigned long nbr_tour;

int Anemo_Push_Counter = 0;
int Anemo_State = 0;
int Last_Anemo_State = 0;

void setup()
{
    Serial.begin(9600); // Communication serial à 9600 bauds
    pinMode(8,INPUT);   // Broche 8 en entrée
}


void loop()

{
  Anemo_Push_Counter = 0;
  
  // lit l'état actuel de la pin8
  Anemo_State = digitalRead(Anemo);

  // compare l'état actuel de l'anemo à l'état précédent mémorisé
  if (Anemo_State != Last_Anemo_State)
  
  {
      Anemo_Push_Counter++;
      Last_Anemo_State = Anemo_State;
  }
  
  delay (1000);
  
  Serial.println (2*3.1415*0.031*5*nbr_tour); 
}

Mais Anemo_Push_Counter est, dans mon cas, égal à 0 donc mon résultat aussi :P En fait, il me faudrait un moyen de réinitialiser Push_Counter correctement.

Je débute sous arduino alors n'hésitez pas si quelque chose n'est pas clair XD

Merci beaucoup !

Il ne faut pas réinitialiser ton compteur à chaque loop sinon il est toujours à 0 ou 1 avant le calcul de la vitesse du vent. De plus le delay est inutile puisque tu ne fais que mettre en pause le programme (et donc aucune variable n’est mise à jour).
Il te faut un second compteur basé sur le temps écoulé.
Ainsi, à chaque fois qu’il s’est écoulé une certaine durée (mettons appelée D, qui dépend de la vitesse de variation de la vitesse du vent), la vitesse du vent est calculée (à partir du compteur de tours et de D) et envoyée sur le port série. Dans la foulée, le compteur de tours (Anemo_Push_Counter) et de temps sont mis à 0 et à millis() respectivement. Millis() te donne le temps actuel (depuis le moment où le programme a commencé).
Dans le loop, tu as donc une condition du genre (à mettre à la place de delay et de ce qu’il y a ensuite):
if (millis()==compteur_temps+D) {
Calcul vitesse vent;
Envoie vitesse vent sur série;
Anemo_Push_Counter=0;
compteur_temps=millis();
}

Dans setup():
Anemo_Push_Counter=0;
compteur_temps=millis();

Il est préférable de déclarer compteur_temps comme un unsigned long au cas où la durée entre chaque calcul de la vitesse du vent est relativement longue.

Je ne comprends pas ce que tu considères comme la variable D.

à chaque fois qu'il s'est écoulé une certaine durée (mettons appelée D, qui dépend de la vitesse de variation de la vitesse du vent), la vitesse du vent est calculée (à partir du compteur de tours et de D)

Donc millis() c'est le temps depuis le lancement du programme, mais compteur_temps et D j'ai du mal à saisir la façon dont je dois les utiliser.

Merci de ton aide !

Tom_Auser: Je ne comprends pas ce que tu considères comme la variable D.

à chaque fois qu'il s'est écoulé une certaine durée (mettons appelée D, qui dépend de la vitesse de variation de la vitesse du vent), la vitesse du vent est calculée (à partir du compteur de tours et de D)

Donc millis() c'est le temps depuis le lancement du programme, mais compteur_temps et D j'ai du mal à saisir la façon dont je dois les utiliser.

Merci de ton aide !

bonjour regarde ici le bout de code http://arduino.cc/forum/index.php/topic,89413.msg686484.html#msg686484 la problématique est la même : comptage et restitution d'un nombre d'impulsions par secondes

Merci de votre aide !

Pour finir, j'ai décidé d'utiliser les interruptions. :P

Je poste mon code au cas où quelqu'un serait intéressé ;)

int compteurfm = 0;                                  // compteur de fronts montants
int nbrtour = 0;                                     // variable du nombre de tour
unsigned long compte_temps;                          // variable contenant le temps
int increm_temps = 1;                                // variable compteur de temps

void setup()
{
  pinMode (2, INPUT);
  attachInterrupt (0, anemometre, RISING);           // capteur de front montant
  Serial.begin(9600);                                // configuration de la transmission
}

void loop()
{
  delay(1000);
  Serial.print(2*3.1415*0.0455*5*nbrtour);            // calcul de la vitesse du vent et envoie sur serial
  Serial.println (" m/s");
  nbrtour = 0;
}

void anemometre()
{
  compteurfm++;
  if (compteurfm >4)
  {
    compteurfm = 0;
  }
  
  if (compteurfm == 4)    // car 4 fronts montants = 1 tour
  {
    nbrtour++;
  }
}

Voilà et bonne journée XD

Si je peux me permettre... tu utilises cette formule pour calculer la vitesse du vent : 2*3.1415*0.0455*5*nbrtour. Ben moi, je te fais gagner du temps :

void loop()
{
  delay(1000);
  Serial.print(2*3.1415*0.0455*5*compteurfm/4);            // calcul de la vitesse du vent et envoie sur serial
  Serial.println (" m/s");
  compteurfm = 0;
}
void anemometre()
{
  compteurfm++;
}

tu devines ma pensée? en gros, là, tu es 4 fois plus précis...

EDIT : bonne idée, les interruptions! tu peux même faire mieux, en branchant ton anemomètre sur un timer : tu n'auras rien d'autre à faire que de relever la valeur du timer...

Salut,

Je viens de faire le montage avec mon anémomètre. Le programme fonctionne, mais j'ai une précision très mauvaise et quand le vent monte, je n'ai presque pas de différence. Le matériel ne semble pas en mauvais état et j'entends un bruit qui me semble bon quand ça tourne, comme si l'aimant faisait bien son boulot...

Pensez- vous que cela soit du à un matériel de mauvaise qualité? Si oui quel genre d'anémomètre faut-il pour avoir une précision à 5 km/h près?

Merci pour le code qui m'a montré les interruptions.

Chris.

Fais un petit dump de ton compteurFM et des millis dans ton serial histoire de voir si ça augmente bien quand la vitesse du vent augmente.

Sinon j'ai pas testé, mais les cast implicites pour les opérations entre des int et des float se passent bien dans ton Serial.print(2*3.1415*0.0455*5*compteurfm/4); ? 2 est un int, 2. est un float.

J'ai eu des soucis récemment sur un overflow à cause d'une valeur qu'il considérait comme int alors que pour moi c'était un long (multiplication d'un long par 10000, stocké dans un long, me renvoyait la mauvaise valeur).

Et c'est tout con, mais optimise ton code en déclarant une variable avec le résultat du calcul : 2*3.1415*0.0455*5/4 Tu n'auras plus qu'à multiplier par compteurFM pour avoir la bonne valeur :)

Bonjour,

Je viens de terminer ma station météo qui comporte également un anémomètre. Le constructeur fournit une formule pour calculer la vitesse en m/s à partir de la fréquence des impulsions.

Je ne vois pas comment tu peux appliquer une formule autre que celle donnée par le constructeur... La vitesse de rotation d'une hélice doit dépendre de sa taille, son profil, etc.... Alors compter des impulsions et appliquer une formule quelconque me parait hasardeux..

Pour info , la formule pour mon anémomètre est : vitesseVent = (frq * 0.08669) + 0.32

J'ai utilisé une librairie de fréquencemètre, je mesure pendant 1s et j'applique la formule...

Sinon si tu veux le faire toi-même tu utilises les interruptions et un timer. Il te faudra ensuite faire une comparaison entre le nombre d'impulsions à différentes vitesses de vent afin de faire une courbe et en déduire la formule...

A vérifier également, la forme des signaux issus de ton contact. Il serait surprenant que tu n'aies pas de rebonds de ton contact qu'il te faudra éliminer par un moyen ou un autre sous peine de mesures fausses...

Moi j'ai de la chance, mon anémomètre sort des signaux issus d'un codeur optique sur un optocoupleur, c'est très propre.

Bonne réalisation,

Salut,

La formule : V = 2PIF(N)RN est tout à fait correct (formule provenant de la vitesse tangentielle d’un point en rotation), par contre celle-ci : vitesseVent = (frq * 0.08669) + 0.32 est surprenante, car même quand l’anémomètre est à l’arrêt donc fréquence = 0 , il y a quand même une vitesse du vent ???, car 0*0.086669 =0, mais +0.32 donne 0.32 surprenant .

@+

C'est bien vu pour mon anémomètre. Le constructeur précise que la vitesse minimum mesurable est 0,5 m/s.

Je maintiens que la formule dont il est fait référence ne peut pas être utilisée telle quelle, sans connaître le facteur d'étalonnage...

Je cite : "La fonction d'étalonnage (N dans la formule) traduit les propriétés aérodynamiques de l'anémomètre et les frottements qui altèrent le mouvement de rotation de l'anémomètre. Elle dépend des dimensions et matériaux de l'anémomètre et de sa vitesse de rotation. Seuls des essais en soufflerie à différents régimes de vent permettent de la déterminer précisément."

Bon, je viens de résoudre mon problème.

J'ai un peu fait le bourrin et j'ai tout démonté. C'était finalement une bonne chose car j'ai pu voir qu'à l'intérieur il y avait un capteur reed. Je l'ai changé par un capteur effet hall et toute la différence est là.

Merci pour les conseils.

Au fait totolens, j'avais oublié de dire que je l'avais essayé l'idée du compteur et que je n'obtenais rien... Vraiment merci!

Salut, je vous donne un code que je viens de faire et qui fonctionne mieux pour mon capteur.

En effet, je me suis rendu compte qu’à faible vitesse, le capteur est “lu” plusieurs fois sur le même tour et cela me donne de grandes vitesses même avec un vent très faible…

Voici donc le code (j’ai rajouté un écran LCD en plus… et il me faut encore étalonner la bête):

int hallPin=7;
unsigned long temps;
int statePin=LOW;
int t;
boolean a;

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,16,4);

void setup()
{
pinMode(hallPin,INPUT);
Serial.begin(9600);
temps=0;
t=0;
a=0;

lcd.init();
  // Print a message to the LCD.
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("test vitesse");
  lcd.setCursor(0,1);
  lcd.print("du vent");
  delay(4000);
}





void loop()
{
 
statePin=digitalRead(hallPin);


                       if( statePin==HIGH && a==0)
                                          {
                                          a=1;
                                          }
                       if(statePin==LOW && a==1)
                                          {
                                          t=t+1;
                                          Serial.println("t");
                                          Serial.println(t);
                                          a=0;
                                          }
                       
                       if (millis()-temps>1000){
                                       Serial.print("vitesse du vent");
                                       t=2*3.1415*0.0455*7*t;
                                       Serial.println(t);
                                       lcd.clear();
                                       lcd.print("vent");
                                       lcd.setCursor(0,1);
                                       lcd.print(t);
                                       lcd.setCursor(12,1);
                                       lcd.print("kts");
                                       t=0;
                                       temps=millis();
                                       }


               
}