Détection tonalité téléphonique fin de communication 440Hz [Résolu]

Bonjour,

Mes essais de conception détecteur 440 hz à base de LM 567 restent infructueux malgré la simplicité du concept. Les divers montages proposés sur internet ne donnent rien, malgré avoir contrôlé à l'oscilloscope, l'exactitude des fréquences, tant d'entrée que générée par le Lm567.
Peut-être parce que c'est un LM567cn ( origine Chine)! En ayant commandé 10, j'en ai essayé plusieurs bien entendu. Malheureusement, on ne trouve pas de micro module tout prêt assurant cette fonction.

Sinon, l'un de vous a peut-être procédé par un programme Arduino directement, assurant la même fonction sur cette fréquence , comme tout autre pouvant intéresser plusieurs d'entre nous .

Bonjour

Prendre connaissance des Règles du Forum pour découvrir et comment présenter ses demandes.

Ce message n'a pas sa place dans la zone réservée aux projets F I N I S omme l'indique son titre (c'est en somme la 'vitrine d'exposition' , le détecteut de tonalité y aura sa place ... le moment venu !!)

Demandes rapidement au Modérateur le déplacement, pour cela utiliser le lien 'Report to Moderator'

A+

Bonjour

Mes essais de NE567 ou LM567 remontent loin .... et à l'époque il ne s'agissait pas de puces 'low cost' venant d'Asie
Pas de soucis une fois définies la fréquence centrale et la bande passante.... mais l'amplitude du signal d'entrée était importante (une centaine de mV environ ) pour l'accrochage de la PLL

Les divers montages proposés sur internet ne donnent rien.....

As-tu exploité ce site ? Electronique - Realisations - Decodeur tonalite 001

Pour la détection de tonalité logicielle sur Arduino chercher une librairie faisant tourner l'agorithme de Goertzel. C'est plus efficace qu'une FFT lorsqu'il s'agit de détecter la présence d'une fréquence particulière .

Reste a bien gérer la liaison entre ligne téléphonique et entre Arduino

Içi une application de cet algorithme pour faire un décodage DTMF

Merci al1fch,

Sonelec est le premier essai effectué, bien commenté, il est d’une parfaite évidence, et pourtant!
j’ai également bien fait attention à l’amplitude d’entrée, dont le site attire également l’attention sur ce point critique. il apparaît donc que le maillon faible provienne des LM 567 eux même.

Aussi m’ orienterais-je plutôt sur la piste que tu me proposes, basée sur l’algorithme de Goertzel.
il me suffit apparemment d’appliquer le principe du décodage DTMF, adapté à la seule fréquence qui m’intéresse, et de supprimer les 7 autres dont je n’ai pas besoin.
Ensuite filtrer les déclenchements intempestifs par une temporisation d’impulsion longue, voir 1 seconde, car le signal 440 hz est maintenu 1,5 seconde par impulsion issue du réseau. Ainsi, les quelques pics courts au travers de la voix des interlocuteurs devraient être sans conséquences.
Et enfin, activer une sortie disponible à l’état haut activée uniquement par le 440hz si présent 1 seconde sans discontinuer.

Je ferai des essais en ce sens dans les jours prochains et reviendrai ici en commenter la suite.

Vu la météo, je m’y suis remis finalement de suite.

Premier constat, ce n’est pas la librairie Groetzel.h mais la Groetzel-master que j’ai trouvé.
Correspondraient-elles?
Je n’ai rien obtenu de concluant avec le code DTMF complet, histoire de voir si ça fonctionne sans modifier quoi que ce soit. Je précise utiliser une Nano atmega 328 , mon smartphone sur Szynalski.com/tone en générateur 440hz, et un pont diviseur 2 x 10 k sur l’entrée A0 pour l’entrée signal d’amplitude maxi 1,2 volts derrière un condo de découplage.
Les choses ont été légèrement différentes en modifiant le programme, soit en éliminant les lignes de codes des 7 fréquences non retenues, et en adaptant celle conservée au 440 hz souhaité.
Sauf que , signal au max, en scannant les fréquences sur le générateur, la led 13 semblait réagir dans des plages très proches des fréquences déterminées initialement en dtmf.
Et encore, rien de fiable et surtout rien côté 440hz.
J’en déduis que la librairie verrouille bien l’application vers le dtmf, et qu’il va me falloir m’y prendre autrement.
Le Shield dtmf arduino ne me sera pas d’un grand secours, testé et bien que très efficace, il ne correspond pas à ma quête d’une fréquence précise autre que celles auxquelles il est affecté.
Ou je m’y suis mal pris, ou un conseil avisé me remettra sur le bon chemin… merci d’avance.

Bonjour

Premier constat, ce n'est pas la librairie Groetzel.h mais la Groetzel-master que j'ai trouvé.

Goetzel.h est l'un des fichiers de la librairie Goetzel alias Goetzel-master

Pljutôt que simplifier DTMF, essayer plutôt l'exemple simple detect.ino venant avec la librairie, en changeant la valeur de la fréquence à détecter.

Le signal appliquer à l'entrée A0 doit être centré sur 2,5V, utilser un pont diviseur R/R et relier la sortie audio au point milieu du pont à travers un condensateur. Le signal audio injecté est alors décalé de la masse. Une note de guitare était détectée pas le demi ton au dessus ou en dessous !

Dans mon cas ce petit code detect.ino a été testé avec succès en reliant à la carte Arduino un petit module microphone d'Adafruit dont la sortie est centrée sur 2,5V....
J'ai un faible pour les bons vieux circuits analogiques mais il me faut reconnaaître que l'algo de Goertzel avec une petite carte Arduino ça "le fait" aussi !!

Merci pour ton suivi régulier Al1fch,

Après lecture de ton dernier post, je suis retourné sur le site Github de Goetzel.

Ainsi, ais-je retrouvé le code dont tu me parles, et il est vrai qu’il s’approche au mieux de ce dont j’ai besoin. D’autant que s’il fonctionne chez toi, il est donc exploitable.
Je vais donc m’y remettre sans tarder.

Entre temps, j’ai persisté sur le 567, n’abandonnant pas comme ça.
Si tous les sites francophones recommandent un signal d’entrée entre 25 et 200mv, il en est un autre,Anglophone, qui fait une liaison directe depuis la sortie d’un 555.
C’est ce dernier qui visait juste, de plus le 555 rétabli un signal carré parfait de 3.4 volts si alimenté sous 5,1 volts. Autant dire qu’à 10 hz près, le 567 obtempère presto en présence de 440hz.
Le o volts n’est pas absolu en sortie 8 en pullup, soit 0.21 à 0.60 au pire, en logique ça vaut tout de même 0.
Le mystère plane toutefois autour de l’application du Lm567, vraisemblablement différent du Ne567, dont on dit qu’il sont pourtant équivalents.

je reprendrai mes investigations selon ton dernier conseil, toujours intéressant d’en apprendre plus et de persister dans l’étude d’un code qui serait utile au delà d’une seule et unique application.

Al1ch, j'ai tenté téléverser directement le code detect.ino vers ma carte Nano, sans aucune modification, mais l'IDE Arduino m'indique une erreur de compilation vers carte Nano.

Erreur de librairie Goertzel semble-t-il!
bien que l'ayant supprimé et ré-installé depuis le site officiel, même résultat.

Le terme "permissives" apparait dans la très longue liste d'erreur détaillée, laquelle si cela peut te mettre sur la voie, je pourrai copier et coller ici si besoin.

Ou peut-être, le code est spécifique à la carte Uno.

Bonsoir

Aucune erreur, aucun warning quand je compile l'exemple detect.ino que ce soit vers Uno, Nano, Pro Mini...

Mon IDE Arduino est en version 1.8.13, je l'ai installé sous Linux à partir du fichier fourni sur le site Arduino

Goertzel est un physicien qui a publié en 1958 l'algorithme qui porte son nom.
On trouve pour Arduino plusieurs librairies voisines qui exécutent cet algorithme..
Il me semble que j'utilise celle-çi :

L'erreur provenait de mon code où le non report de " Void Setup" bloquait la compilation.
Il ne suffisait pas simplement de copier/coller detect.ino

Mais , même correctement compilé et téléversé, reste à redéfinir plus précisément les bons paramètres.
Tel quel, je n'obtiens pas de détection 440Hz.

Target fréquency me semble correspondre à la fréquence recherchée, est-ce correct?

N=100 me semble être l'écart de fréquence toléré autour de la fréquence recherchée

Threshold, semble être le niveau de déclenchement de détection. Que veut dire 4000, par contre?
A0 étant une entrée analogique, je m'attendais à un nombre entre 0 et 1024!
La base de calcul est peut-être calculée autrement.

De plus, hormis la fréquence, est-ce l'amplitude du signal qui importe soit 1,8 volts, ou la tension crête. Laquelle, dans mon cas, fait 2,5 volts + 1,8 volts de signal, soit 4,3 volts.

je n'ai pas modifié Sampling fréquency, La Nano étant cadencée à 16 Mhz, et 8900 étant recommandé comme fréquence d'échantillonnage en l'occurence.

Al1fch, sauf erreur, je dois pêcher surement côté Threshold! Modifié à la valeur 500 ne m'a rien apporté de nouveau.

voici mon code actuel

code]

#include "Goertzel.h"


int sensorPin = A0;
int led = 13;
 
const float TARGET_FREQUENCY = 440; 

const int N = 100;   

const float THRESHOLD = 4000; 


const float SAMPLING_FREQUENCY = 8900; 

Goertzel goertzel = Goertzel(TARGET_FREQUENCY, N, SAMPLING_FREQUENCY);

void setup()
{
  pinMode (A0,INPUT);
  pinMode(13,OUTPUT);
}

 void loop()
{    digitalWrite(led, LOW); //if not found, or lost, disable led

}

Bonsoir

laisser tel quel le setup() detect.ino,
ajouter la ligne suivante n'arrange rien est est contradictoire avec l'utilisation de A0 en entrée analogique, c'est une ligne qui vise a utilser en entrée numérique A0 (c'est possible !)

pinMode (A0,INPUT);

Paramètres :

Mettre 440 pour target frequency et conserver les valeurs initiales de N et de Threshold (elles convienent à une carte Arduino basique)

Par analogie avec une transformée de Fourrier numérique :
N (nombre 'd'échantillons prélevés ) influe sur la 'finesse' des raies, la résolution.
Threshold est le seuil d'amplitde de la raie principale (fréquence cible) à partir duquel la DEL est allumée . Il ne s'agit pas de l'amplitude du signal injecté mais de l'amplitude du résultat du calcul effectué.

Amplitude du signal injecté : de mémoire 1 volt va bien , ce qui donne en entrée une tension dont le creux est vers 1,5V et le sommet vers 3,5V, tension centrée sur Vcc/2, tension d evaleur moyenne Vcc/2

Merci pour ces précisions Al1fch,

Malheureusement, j'ai beau supprimer mes 2 lignes dans "Void setup", je ne peux pas supprimer la ligne de code " void setup" elle-même, sinon la compilation est refusée, elle passe en défault.

Et le signal d'entrée sinusoîdal correspondant tout à fait aux données que tu m'as conseillé, toujours pas de led allumée en présence 440Hz. mon dernier code testé est le suivant:

int sensorPin = A0;
int led = 13;
 
const float TARGET_FREQUENCY = 440; 

const int N = 100;   

const float THRESHOLD = 4000; 


const float SAMPLING_FREQUENCY = 8900; 

 Goertzel goertzel = Goertzel(TARGET_FREQUENCY, N, SAMPLING_FREQUENCY);


 void setup () {
 
 }
 void loop()

 
{    digitalWrite(led, LOW); //if not found, or lost, disable led

}

D'où vient l'idée d'amputer le programme detect.ino de sa fonction Setup() présente aux lignes 72 à 75 ??

void setup(){
  pinMode(led, OUTPUT);     
  Serial.begin(9600); 
}

Testes le programme detect.ino ENTIER (89 lignes) en ne changeant que la fréquence cible et en conservant TOUT le reste.

Rien dans ton code ne produit de changement d'état de la DEL !!
Son état invariable dans ton code est fixé une fois pour toutes par cette ligne

digitalWrite(led, LOW); //if not found, or lost, disable led

Le coeur du programme detect.ino c'est sa fonction loop(), si t évacues la quasi totalité des lignes il ne se passe plus rien en matière de détection de tonalité !!

-> Notre échange me fait penser qu'un détour pas les tutoriels d'initiation ne serait pas superflu ...
https://zestedesavoir.com/tutoriels/686/arduino-premiers-pas-en-informatique-embarquee/

Loin de moi l’idée d’être à l’aise avec les codes, c’est vrai.

Je reprends à zéro mes expérimentations, peut-être mal commentées auparavant.

En faisant un copier collé de detect.ino, ne modifiant que la fréquence, LA COMPILATION N’EST PAS POSSIBLE.

j’ai l’inscription suivante:

C:\Users\Pierre\AppData\Local\Temp\ccCHFilr.ltrans0.ltrans.o: In function `main’:

C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/main.cpp:43: undefined reference to `setup’

collect2.exe: error: ld returned 1 exit status

Utilisation de la bibliothèque Goertzel-master prise dans le dossier : C:\Users\Pierre\Documents\Arduino\libraries\Goertzel-master (legacy)
exit status 1
Erreur de compilation pour la carte Arduino Nano

En faisant des recherches, il apparait que la fonction Setup soit manquante ou mal définie.

Le code tel quel ne fonctionne pas, sauf si je rajoute " void setup" dans le code.

Je comprends qu’ainsi inséré, ce peut être n’importe quoi, de plus, même si avec " void setup", la compilation fonctionne, “magnitude” is not in this scope me bloque plus loin.

En faisant un copier collé de detect.ino, ne modifiant que la fréquence, LA COMPILATION N’EST PAS POSSIBLE.

Sans copié collé, en ouvrant directement l’exemple fourni : Fichier/Exemple/Goertzel-master/detect (pas de ‘legacy’ pour la bibilothèque utilisée de mon côté)

On se trouve en présence d’un fichier .ino de 89 lignes qui comporte sa fonction setup() et passe chez moi, tel quel, la compilation sans le moindre souci, quelque soit la carte cible Arduino quelconque, ESP diverses)
Fonctionnel, il joue son rôle d’exemple.

je joins ce programme detect.ino

Il y a peut être de votre côté un problème d’installation de la librairie

detect.ino (3.98 KB)

Autant pour moi Al1fch, et avec toutes mes excuses, il me manquait une partie du code, n’ayant pas développer le code complet en cliquant sur la flèche dédiée à cette fonction.
Effectivement, il y avait de quoi coincer irrémédiablement.

Ton code complet est sans faille, fonctionnant indiscutablement au premier essai. Magique!

A vrai dire, mieux qu’avec le LM567, soit, plus incisif.
Je pense donc adopter ta solution, d’autant que derrière, j’ai une suite de quelques commandes à écrire pour finaliser mon projet.

Merci encore pour ta contribution sans laquelle j’errerais encore.

Ayant pratiqué l’analogique durant des années, il a encore ma préférence, mais j’avoue le digital forcément grandement le supplanter, tant il offre de perspectives. Nous nous rejoignons sur ce point de vue.

Au plaisir d’une autre rencontre sur ce Forum et encore Mille remerciements.

Le code final:

#include <Goertzel.h>

int sensorPin = A0;
int led = 13;

const float TARGET_FREQUENCY = 440; 

const int N = 100; 	

const float THRESHOLD = 4000;	

const float SAMPLING_FREQUENCY = 8900; 

Goertzel goertzel = Goertzel(TARGET_FREQUENCY, N, SAMPLING_FREQUENCY);

void setup(){
  pinMode(led, OUTPUT);     
  Serial.begin(9600); 
}
void loop()
{
  goertzel.sample(sensorPin); 
  
  float magnitude = goertzel.detect();  
  
  if(magnitude>THRESHOLD) 
    digitalWrite(led, HIGH); 
  else
    digitalWrite(led, LOW);     
  Serial.println(magnitude);
}

Ton code complet est sans faille.....

Ce n'est pas mon code !! je me contente içi de 'promouvoir' cet algorithme performant de détection de fréquences pérticulières dans un signal.

Content de voir un nouvel adepte !!

Retour sur le sujet a fin d'amélioration résultat obtention d'un signal débarrassé d'imperfections.

Non, concernant le code communiqué par Al1fch, qui fonctionne à merveille.

Mais,comme je m'y attendais, une conversation téléphonique génère elle aussi des impulsions transitoires de et autour des 440hz. D'où nécessité de filtrer autant en entrée qu'en sortie.

En premier lieu, j'ai récupéré un shield micro arduino letmeknow lm1281, sur lequel j'ai viré le micro electred, remplacé par le condensateur d'isolement d'entrée ligne téléphonique.
Le potentiomètre me permet d'ajuster la sensibilité d'entrée; a bas niveau audio la sortie est à zéro.
A réception d'une tonalité 440 hz issue d'un générateur ou ligne téléphone, la sortie du lmk 1281 génère un parfait signal carré de 5 volts, instantanément reconnu par le code Goertzel.
En dehors de ce signal, le " mute " du lmK 1281 agi sur faible signal audio, rien en sortie.( en fait un comparateur). Lorsque l'audio dépasse un certain seuil, effectivement quelques impulsions issues de la conversation arrivent à faire basculer le détecteur de la carte Nano.

C'est là qu'intervient une suite de filtres " numériques ", à base de temporisations et d'un compteur.

L' impulsion de sortie générée lors d'une détection 440hz est d'abord validée si elle dure au minimum 490 ms , sachant qu'une tonalité téléphonique en fait 500. Toute impulsion inférieure n'est pas prise en compte.
Ensuite, une tempo remet à zéro la sortie tonalité afin qu'un compteur puisse être opérationnel derrière.
Et enfin, un compteur positionné sur 5 tonalités active la sortie finale,une commande reset, en l’occurrence l'arrêt enregistrement dans mon cas.

j'avoue avoir été séduit par le résultat, ma femme m'ayant pris pour un fou, tant j'ai parlé dans le portable appelant mon fixe, sans que le reset ne s'active. Par contre, dès fin d'appel depuis le portable et dès les 5 tonalités, le rest s'enclenche bel et bien.

Des leds sur les différentes sorties m'ont permis de suivre l'évolution du signal, c'est pratique et permet de voir les différentes réactions.
Le code suivant donne un aperçu, notamment concernant les tempos et le compteur, sans le code GoertzeL ( mon code test tempo et compteur avant application avec Goertzel)

Si vous avez mieux, je suis preneur. Certainement qu'un code plus simple puisse se faire, notamment en utilisant mieux les variables, boutonA étant la simulation par bouton de la sortie impulsion 440hz de la carte Nano.
BoutonB celle de la sortie tonalité validée car supérieure aux 490ms imposées.
Pas encore à l'aise avec les variables, mon test final avec Goertzel, nécessite 2 transistors entre entrées-sorties en remplacement des boutons ci dessous.

Merci à Bricoleau pour la librairie simple bouton très pratique.

#include "simpleBouton.h"

simpleBouton boutonA(3);                                     // simulation détection signal 440hz       
simpleBouton boutonB_plus(2);                                // simulation sortie activée par une tonalité supérieure à 490ms
int compteur=0;
const int Btn = 9;                                           // Sortie activée par une tonalité supérieure à 490ms 
int tempoActive = 0;
unsigned long tempoDepart = 0;

void setup()
{  
  pinMode(boutonA,INPUT_PULLUP);  
  pinMode(Btn,OUTPUT);
  pinMode(boutonB_plus,INPUT_PULLUP);
  pinMode(7,OUTPUT);
}

void loop(){
    

  //Lecture de la durée d'appui AVANT d'actualiser
  uint32_t duree = boutonA.dureeEnfonce();
 
  boutonA.actualiser();  
  boutonB_plus.actualiser();
  if (duree >= 490)
  { digitalWrite(Btn,HIGH);   // pas de DELAY - transformer tempo en millis            // si plus de 490ms, sortie active
  tempoActive = 1;
  tempoDepart = millis();
  }
  if (tempoActive){
  if((millis() - tempoDepart ) >= 500){                      // sans cette tempo et la ligne suivante, le compteur ne peut fonctionnerb
    digitalWrite(Btn,LOW);
  }
 
     
if(boutonB_plus.vientDEtreEnfonce())                         // en fait, si une tonalité > 490ms  active le bouton simulé
{
  compteur++;
  if(compteur>=5) {                                          // on compte 5 tonalités
    digitalWrite(7,HIGH);                                    // activation du RESET enregistrement - objet de ce code                        
    delay(2000);                    // usage d'un delay pour alléger le code, ici millis ne s'impose pas vraiment 
    digitalWrite(7,LOW);                                     // remise à zéro pour une prochaine utilisation                                

    compteur=0;                                              // remise à zéro compteur
 

  }
}
  }
  }