[Résolu] telecommande DTMF

Bonjour,

Je suis en train de réaliser une télécommande DTMF avec l'Arduino.

J'ai trouvé pour cela une Librairie qui fonctionne à merveille. Décodage sans problème et affichage sur l’ordinateur via serie.

Maintenant j'aimerai que, lors de la réception du code DTMF: 1234, ma Led s'allume.

J'ai essayé plusieurs méthode et fait quelques recherche, mais je n'y arrive pas.

EDIT: J'ai peut être été vite en besogne. Je n'arrive déjà pas à allumer ma Led avec 1 DTMF reçu.
Comment récupérer le chiffre "5" décodé par la librairie. le but étant d'allumer la led a la reception du code DTMF 5 correspondant au clavier de ma radio.

J'ai essayé:

if (thischar){
digitalWrite(led, HIGH);
}

La led s'allume, mais avec tous les caractères. (déjà bien, elle s'allume donc pas de soucis matériel)
et avec:

if (thischar == 5){
digitalWrite(led, HIGH);
}

ça ne fonctionne pas.

Voici la sources de la librairie: http://members.shaw.ca/el.supremo/DTMF.zip

et le code:

// The library toggles digital pin 4 in the sampling loop which allows
// measurement of the actual sampling frequency.
// If you call .sample() continuously like this:
// while(1)dtmf.sample(sensorPin);
// you can put a frequency counter on pin 4 to determine what the
// sampling frequency is on your Arduino. Note that the frequency
// counter will show half the actual rate. My meter showed 4.463kHz
// so the sampling rate is 8926Hz
#include <DTMF.h>

int sensorPin = A0;
int led = 13;


// NOTE that N MUST NOT exceed 160
// This is the number of samples which are taken in a call to
// .sample. The smaller the value of N the wider the bandwidth.
// For example, with N=128 at a sample rate of 8926Hz the tone
// detection bandwidth will be 8926/128 = 70Hz. If you make N
// smaller, the bandwidth increases which makes it harder to detect
// the tones because some of the energy of one tone can cross into
// an adjacent (in frequency) tone. But a larger value of N also means
// that it takes longer to collect the samples.
// A value of 64 works just fine, as does 128.
// NOTE that the value of N does NOT have to be a power of 2.
float n=128.0;
// sampling rate in Hz
float sampling_rate=8926.0;

// Instantiate the dtmf library with the number of samples to be taken
// and the sampling rate.
DTMF dtmf = DTMF(n,sampling_rate);

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

int nochar_count = 0;
float d_mags[8];
void loop()
{
  char thischar;
  
  // This reads N samples from sensorpin (must be an analog input)
  // and stores them in an array within the library. Use while(1)
  // to determine the actual sampling frequency as described in the
  // comment at the top of this file
  /* while(1) */dtmf.sample(sensorPin);
  
  // The first argument is the address of a user-supplied array
  // of 8 floats in which the function will return the magnitudes
  // of the eight tones.
  // The second argument is the value read by the ADC when there
  // is no signal present. A voltage divider with precisely equal
  // resistors will presumably give a value of 511 or 512.
  // My divider gives a value of 506.
  // If you aren't sure what to use, set this to 512
  dtmf.detect(d_mags,506);

  // detect the button
  // If it is recognized, returns one of 0123456789ABCD*#
  // If unrecognized, returns binary zero

  // Pass it the magnitude array used when calling .sample
  // and specify a magnitude which is used as the threshold
  // for determining whether a tone is present or not
  //
  // If N=64 magnitude needs to be around 1200
  // If N=128 the magnitude can be set to 1800
  // but you will need to play with it to get the right value
  thischar = dtmf.button(d_mags,1800.);
  if(thischar) {
    Serial.print(thischar);
    nochar_count = 0;
    // Print the magnitudes for debugging
//#define DEBUG_PRINT
#ifdef DEBUG_PRINT
    for(int i = 0;i < 8;i++) {
      Serial.print("  ");
      Serial.print(d_mags[i]);
    }
    Serial.println("");
#endif
  } else {
    // print a newline 
    if(++nochar_count == 50)Serial.println("");
    // don't let it wrap around
    if(nochar_count > 30000)nochar_count = 51;
  }
}

Merci

Bonjour,

Ça détecte bien les différentes touches (surtout celles proches) ?
J'avais fait une tentative d'implémentation de l'algorithme de Goertzel (c'est un algo de détection de fréquence utilisé pour ce genre d'application) sans grand succès.
Comme je vois que cette librairie utilise ce même algorithme ça pique ma curiosité :grin:

Bonjour,

oui, ça détecte les touches: 1 2 3 4 5 6 7 8 9 0 * # A B C D.
j'utilise pour envoyer le DTMF une radio sur le 70cm
intervalle entre 2 DTMF = 50ms
réception avec une autre radio sortie BF sur pin A0 de l'arduino. (voir schéma fourni dans le ZIP)

Ca fonctionne à merveille, pas encore essayé sur des longues distances avec du bruit.

pour utiliser la lettre correspondante pour allumer une led:

if (thischar == '5'){
digitalWrite(led, HIGH);
} //pour le chiffre 5

et ici le code complet en cour de création:

//code OK = Allume led + led2 pendant 5sec (quittance) + ouvre relais
//led3 s'allume 20ms quand DTMF détecté
//DTMF '16#' ouvre 
//DTMF '26#' ferme
//DTMF '*' reset
//Visualisation sur Moniteur Serie

#include <Password.h>

#include <DTMF.h>


Password password = Password( "16" );
Password password2 = Password( "26" );
byte currentLength = 0;
byte currentLength2 = 0;
int sensorPin = A0;
int led = 13;
int relais = 7;
int led2 = 12;
int led3 = 11;

float n=128.0;
// sampling rate in Hz
float sampling_rate=8926.0;

// Instantiate the dtmf library with the number of samples to be taken
// and the sampling rate.
DTMF dtmf = DTMF(n,sampling_rate);

void setup(){
  pinMode(led, OUTPUT);
  pinMode(relais, OUTPUT);  
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  Serial.begin(115200);
}

int nochar_count = 0;
float d_mags[8];
int val1=0;
int val2=0;

void loop()
{
  char thischar;
  
  
  /* while(1) */
  dtmf.sample(sensorPin);
  dtmf.detect(d_mags,506);
  thischar = dtmf.button(d_mags,1800.);
  
  // Code DTMF pour enclencher
  if (thischar){
    digitalWrite(led3, HIGH);
    delay(20);
    digitalWrite(led3, LOW);
    char input = thischar;
    switch (input){
      case '*': //reset password
        password.reset();
        currentLength = 0;
        Serial.println("\tCode1 reset!");
      break;
      case '#': //evaluate password
        if (password.evaluate()){
          Serial.println("\tCode1 OK!");
          digitalWrite(led, HIGH);
          digitalWrite(relais, HIGH);
          digitalWrite(led2, HIGH);
          delay(5000);
          digitalWrite(led2, LOW);
          password2.reset();
          currentLength2 = 0;
        }else{
          Serial.println("\tCode1 FAUX!");
           password.reset();
           currentLength = 0;       
        }
      break;
      default: //append any keypress that is not a '!' nor a '?' to the currently guessed password.
        password.append(input);
        currentLength++;
       } 
  }
  
  //code DTMF pour déclencher
   if (thischar){
    char input = thischar;
    switch (input){
      case '*': //reset password
        password2.reset();
        currentLength2 = 0;
        Serial.println("\tCode2 reset!");
      break;
      case '#': //evaluate password
        if (password2.evaluate()){
          Serial.println("\tCode2 OK!");
          digitalWrite(led, LOW);
          digitalWrite(relais, LOW);
           password.reset();
        currentLength = 0;
        }else{
          Serial.println("\tCode2 FAUX!");
           password2.reset();
        currentLength2 = 0;
        }
      break;
      default: //append any keypress that is not a '!' nor a '?' to the currently guessed password.
        password2.append(input);
        currentLength2++;
        
  } }
 // fin code DTMF
 
  if(thischar) {
    Serial.print(thischar);
    nochar_count = 0;
    // Print the magnitudes for debugging
//#define DEBUG_PRINT
#ifdef DEBUG_PRINT
    for(int i = 0;i < 8;i++) {
      Serial.print("  ");
      Serial.print(d_mags[i]);
    }
    Serial.println("");
#endif
  } else {
    // print a newline 
    if(++nochar_count == 50)Serial.println("");
    // don't let it wrap around
    if(nochar_count > 30000)nochar_count = 51;
  }
  
}

Bordélique mais fonctionne...

Bonne soirée