Lire fréquence avec arduino

Bonjour, dans le cadre de mon tipe, j'aimerais que la carte arduino me renvoie la fréquence 440hz d'un signal sinusoidal, malheuresement mon code marche mais renvoie des fréquences aberrantes et qui changent constamment de valeur. Pourriez vous m'aider ?

const int sensorPin = A0;  // Pin analogique où le signal du GBF est connecté
int signalValue = 0;       // Valeur lue par la broche analogique
int threshold = 512;       // Seuil de détection (au centre de la plage de lecture analogique)
unsigned long startTime, endTime;
float frequency;

void setup() {
  Serial.begin(9600);  // Initialisation de la communication série
}

void loop() {
  // Trouver la crête montante du signal
  signalValue = analogRead(sensorPin);
  if (signalValue > threshold) {
    startTime = micros();  // Capturer le temps du début du cycle sinusoïdal

    // Attendre la prochaine crête descendante
    while (analogRead(sensorPin) > threshold) {
      // Attend que le signal redescende en dessous du seuil
    }

    endTime = micros();  // Capturer le temps du cycle complet

    // Calculer la période du signal
    unsigned long period = endTime - startTime;
    
    // Calculer la fréquence en Hertz
    frequency = 1000000.0 / period;  // Conversion microsecondes en Hertz

    // Afficher la fréquence
    Serial.print("Fréquence : ");
    Serial.print(frequency);
    Serial.println(" Hz");

    // Attendre un peu avant de recommencer
    delay(500);
  }  }

Ton algo prend le temps, n'importe où dans l'alternance haute, puis mesure à partir de cette position plus haut moi aléatoire.
Il faudrait mieux commencer le chronométre après que le signal redescende au dessous du seuil. puis le stop lorsque tu dépasse au nouveau le seuil.
Tu peux aussi inversé la logique si ton premier échantillion est en dessous.

Merci pour ta réponse, mais sinon j'avais une alternative plus simple peut etre en comptant le nombre de passe ou la courbe passe par zéro, ce qui correspondrait à la mesure de la demi période, mais je ne sais pas tres bien comment le coder, j'ai quelque chose comme ça :

const int signalPin = A0;  // Pin analogique où le signal sinusoïdal est connecté
unsigned long lastZeroCrossingTime = 0;  // Temps du dernier passage par zéro
unsigned long currentZeroCrossingTime = 0;  // Temps du passage actuel par zéro
float period = 0.0;  // Période du signal sinusoïdal en microsecondes

int lastSignalValue = 0;  // Dernière valeur lue du signal

void setup() {
  Serial.begin(9600);  // Initialiser la communication série
  pinMode(signalPin, INPUT);  // Définir la pin comme entrée
}

void loop() {
  int signalValue = analogRead(signalPin);  // Lire la valeur du signal sinusoïdal

  // Détection des passages par zéro
  if ((lastSignalValue <= 512 && signalValue > 512) || (lastSignalValue >= 512 && signalValue < 512)) {
    currentZeroCrossingTime = micros();  // Temps actuel en microsecondes
    
    if (lastZeroCrossingTime > 0) {
      period = currentZeroCrossingTime - lastZeroCrossingTime;  // Calculer la période
      Serial.print("Période: ");
      Serial.print(period);  // Afficher la période
      Serial.println(" microsecondes");
    }

    lastZeroCrossingTime = currentZeroCrossingTime;  // Sauvegarder le temps du dernier passage par zéro
  }

  lastSignalValue = signalValue;  // Mettre à jour la dernière valeur lue
}

Ton code ne compte pas le nombre de fois ou cela passe le zéro relatif.
Ton code prend le temps entre deux passages à zéro.

Je ne sais pas si c'est vraiment plus simple.
Attention sur l'alternance montante par exemple, tu peux très bien avoir la premiére acquisition qui est plus grande que la deuxiéme.

D'accord merci je vais donc rester sur ma première idée je pense, mais je ne vois pas comment coder pour que le chronomètre commence lorsque le signal est au dessous du seuil.

Cela dépend de ce que tu appels coder.
Le code n'est pas l'application d'un algorithme, donc il faut d'abords établir celui-ci, puis après essayer de traduire cet algorithme en code, puis une fois cela fait, tu pourrais essayer d'optimiser tout ça.

Donc quel est ta première idée en mots et essaye de voir les limites ou problèmes de celle-ci.

Si sinon tu peux aussi nous décrire précisément ce qui te pose problème à coder ton idée.

Merci pour ta réponse mais finalement j'ai changé de code, j'en ai trouvé un plus efficace, toutefois j'ai quand même un problème de masse: mon gbf a une masse de 50 ohm tandis que celle de l'arduino est bcp plus élevée, j'ai donc essayé de mettre un ali suiveur dans mon circuit mais je ne comprend pas comment alimenter l'ali

Non, ton géné BF à une impédance de sortie de 50Ω et il faut adapter la ligne en impédance.
Pour cela il suffit juste de placer une résistance de 50Ω entre l'entrée de l'Arduino et le GND pour fermer la ligne sur son impédance caractéristique. C'est vrai seulement si tu utilises un câble adapté entre le géné BF et ton Arduino. Les géné BF sortant généralement sur une embase BNC, si tu utilises un cordon coaxial entre le deux c'est bon.


Attention, les générateur BF sortent généralement un signal symétrique autour de 0 et l'Arduino ne tolère pas de tension négative sur ses entrées.
Pour mesurer précisément la fréquence du signal il faut tester le franchissement d'un seuil mais aussi le sens de franchissement de celui-ci sinon ta mesure sera fausse. La courbe rouge c'est ce que tu mesures si tu ne mesures que pendant le temps ou le signal est supérieur au seuil. Tu vois clairement que tu ne mesures même pas la demi période.

La courbe jaune c'est lorsque tu mesures entre deux franchissements du seuil, le sens du franchissement étant positif. Ici tu mesures exactement la fréquence.

Merci pour ta réponse

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