Go Down

Topic: [conseil] Réalisation d'un anémomètre/girouette pour un voilier (Read 449 times) previous topic - next topic

lesept

Comment stocker dans un tableau ?
On définit un tableau comme on définit une variable, en ajoutant une dimension, une taille. Par exemple, voici une variable :
Code: [Select]
int var = 0;et voici un tableau :
Code: [Select]
int tablo[10];
Pour initialiser c'est un peu plus compliqué :
Code: [Select]
int tablo[10] = {0};met tout à 0.
Code: [Select]
int tablo[10] = {0,1,2,3,4,5,6,7,8,9};fait une autre initialisation. Tu peux affecter une valeur à un élément du tableau comme ceci :
Code: [Select]
tablo[5] = 4;ou lire un élément comme cela
Code: [Select]
var = tablo[5];
Une dernière chose  savoir : le premier élément d'un tableau porte l'indice 0.


Sur 10 minutes car on peut :
- faire une moyenne des valeurs (vent moyen)
-les rafales : valeur max de vent sur 10min dépassant de 10nds le vent moyen
Il faut donc faire une moyenne glissante pour vérifier à chaque mesure si elle dépasse le max + 10 kt sur les 10 minutes précédentes. Il te reste à définir combien de mesures tu stockeras sur ta période de 10 minutes, ce sera la taille de ton tableau.
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

Sayber

Je suis en train de me perdre complètement dans le code, j'ai l'impression de partir dans tous les sens :/

Alors j'ai essayé PulseIn() à la place de FreqMeasure, et ca a l'air de faire à peu près la même chose

Code: [Select]
void anemo() {
  if ((millis() - timeold) > 1000) { //Timer 1 secondes

    // Mesure la durée de l'impulsion haute
    //noInterrupts();
    unsigned long etat_haut = pulseIn(signal_anemo, HIGH);
    //interrupts();

    // Mesure la durée de l'impulsion basse
    //noInterrupts();
    unsigned long etat_bas = pulseIn(signal_anemo, LOW);
    //interrupts();

    // Calcul de la periode = etat haut + etat bas
    long periode = (etat_bas + etat_haut);
    // Calcul de la frequence = 1 / periode
    frequence = (1 / (periode * 0.000001));
    vit_kmh = (((frequence * 0.75) + 0.35) * 3.6);
     
    if (periode <= 0 ) {
      frequence = 0;
      vit_kmh = 0;
    }
   
    z = 0;
    n++;
    sensorValue2 = 0 ;

    while (z < 1000){
      z++;
      sensorValue = vit_kmh ;
      sensorValue2 = sensorValue2 + sensorValue ;
    }
    sensorValue = (sensorValue2/ z);
   
    timeold = millis();
  }
}


J'ai ajouté la calculatrice à la fin, mais évidemment il me calcule la moyenne sur la loop apparement (donc 1 seconde), et non pas sur une durée de x secondes.

J'ai commencé à mettre les mains dans les tableaux (array) avec l'exemple smoothing, mais j'ai les neurones qui fument entre tous les codes que j'essaie à taton...

Comment définit-on la période de mesure de 10min, avec mettons 60 mesures par minute (donc 600 mesures) ?
Code: [Select]
int tablo [600] pour 601 mesures (de 0 à 600)
Et surtout comment exprimer :
- Arduino tu affiches la vitesse instantané
- Pendant ce temps là, tu récupères une mesure de vitesse instantané/seconde pendant 10mn et tu me sors la moyenne

je rame grave !

lesept

Code: [Select]
int tablo [600];
définit un tableau de 600 valeurs, indexées de 0 à 599.

Il faut que tu fasses des fonctions simples, quitte à en écrire plus. L'avantage, c'est que tu peux valider plus facilement une fonction simple et passer à autre chose sereinement, plutôt que chercher dans les multiples lignes commentées ou modifiées l'endroit où se trouve une erreur. Ensuite, c'est la loop qui va orchestrer le déroulement de ton code.

Par exemple, tu fais une fonction qui renvoie la direction indiquée par la girouette. Dès qu'elle fonctionne correctement, tu n'y touches plus. Une autre fonction renvoie la vitesse instantanée mesurée par l'anémomètre. Idem, une fois que ça marche, tu n'y touches plus. Une autre fonction va faire une moyenne sur un tableau de données.

Ensuite, tu écris la loop pour faire ce que tu veux : mesures de direction et de vitesse toutes les X millisecondes et stockage de la vitesse dans le tableau, calcul de la moyenne toutes les Y millisecondes, affichage toutes les secondes, etc.

Pour faire une action toutes les X millisecondes, tu sais faire il me semble :
Code: [Select]
if (millis()_chronoAction > X) {
  chronoAction = millis();
// Ici appel de la fonction qui lance l'action
}

Certains mettent le bloc if dans la fonction appelée, d'autres dans la loop, à toi de voir ce que tu préfères. L'important est de simplifier au maximum afin de valider sereinement et ne plus toucher à ce qui est validé...
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

jc_buntu

Bonjour.
Je lis ce topic un peu tardivement ... mais je rentre de croisière !
Amateur de DIY et de navigation, je transfère progressivement toute l'électronique du bord sur des montages perso.
Je suis en phase de développement de l'anémo-girouette en utilisant un capteur Advansea ( moderne) envoyant ses données sur un répétiteur Autohelm ( très vieux) et un module perso portable à base de MKRZ.

L'anémomètre émet 8 impulsions par tour. Il suffit de compter le nombre d'impulsions durant une durée précise pour obtenir directement la vitesse du vent, sans calculs. Utilisation d'une interruption pour capture des impulsions :
     attachInterrupt(digitalPinToInterrupt(ANEMO_IN), INT_Anemo, RISING);
     Contenu de l'interruption -> void INT_Anemo() { ComptAnemo ++;}

Pour une vitesse en noeuds, je compte les impulsions durant 280ms. Les mesures sont affichées toutes les 0,5s.
La vitesse est aussi intégrée ( moyennée) sur 2s selon la méthode du tableau ( post n°13 de lesept). Ca fonctionne parfaitement.

La girouette ne fonctionne pas comme la tienne ( la mienne fait varier le rapport cyclique d'un signal de 1KHz). Je ne surcharge donc pas ce topic. Par contre là se pose un réel problème d'intégration ( moyenne)  : Lorsque l'angle indiqué oscille entre 350 et 10 degrés, nous sommes face au vent, soit au 0. Or la moyenne de (350+10) / 2 = 180, soit plein vent arrière !!!



MarsaMatruh

Pour la moyenne de la direction,  il faut convertir en x et y, faire la moyenne sur x et y puis retourner à la direction avec un arctangente (voir un atan2).

jc_buntu

MarsaMatruh -> Merci pour la réponse, mais les calculs de trigonométrie sont peu compatibles avec les mesures en temps réel basées sur les interruptions. Cette méthode est, bien sûr, la plus rigoureuse mais je ne l'utiliserai pas. J'ai préféré assurer quelques test simples ( if) et, selon leur valeur, ajouter/retirer 360° (ou 2*PI !).

Mais j'arrête là cette divagation hors sujet par rapport au fil initié par Sayber.

Go Up