[TUTO] DCF77

Tuto DCF77

Le signal DCF77 est un message radio qui donne en permanence l’heure exacte, diffusé depuis un émetteur située en Allemagne.

La trame fait 59 bits. Sa transmission dure une minute. Tout est très bien expliqué ici : DCF77 — Wikipédia

Dans le commerce, il existe des appareils dits "radio pilotés" qui exploitent ce signal DCF77 : montres, horloges, réveils, stations météo, etc.

On trouve également des modules électroniques permettant de lire ce signal.
Ce tuto est basé sur le module DCF1 disponible sur le site http://www.pollin.de

DCF1.JPG

Intérêt pour un montage à base d'arduino : un module DCF1 ne remplace pas un module horloge temps réelle de type DS1307 ou DS3231, mais il permet de le mettre à l'heure régulièrement, de manière automatique, dans les montages où l'arduino ne dispose pas d'un autre moyen pour récupérer l'heure exacte (accès internet, module GPS, etc.).

La première chose à savoir sur une réception DCF77, c'est que cela ne marche pas à tous les coups.
En conditions optimales, on arrive à décoder une trame chaque minute.
Mais plusieurs facteurs viennent réduire le taux de réussite :

  • la distance à l'émetteur
  • la qualité de réception du signal radio : interférences, bâtiments, relief, orientation de l'antenne, etc.
    Par exemple, la réception est souvent meilleure la nuit.

Dans notre cas, l'objectif n'est pas super ambitieux, puisqu'il s'agit de remettre à l'heure un module RTC au moins une fois par jour.
Sauf conditions particulières, cet objectif doit pouvoir être atteint depuis n'importe où en France métropolitaine.

Pour les arduinautes compulsifs, toujours pressés :

  1. Installer la librairie decodeurDCF77 en pièce jointe ci-dessous
  2. Ouvrir l'exemple demo_decodeurDCF1 via l'IDE Arduino
  3. Brancher une carte arduino et son module DCF1, tel qu'indiqué dans l'exemple
  4. Téléverser et ouvrir le terminal série à 115200 bauds
  5. Et là youpi ça marche. Ranger le DCF1 dans un tiroir et passer au projet suivant :smiling_imp:

Pour les autres arduinautes un peu moins compulsifs, l'exemple demo_decodeurDCF1 contient tout ce qu'il y a à savoir pour récuperer l'heure sans se poser de questions.

La librairie utilisée tourne en tâche de fond, via une interruption, et fournit en permanence la dernière heure captée (avec la référence millis() associée), ainsi que les informations sur la qualité de réception du signal.

photo montage.jpg

Aperçu du terminal série :

Programme de test reception DCF77 pour module DCF1
avec lectures automatiques de la pin DATA via des interruptions

Cablage pour module DCF1 (www.pollin.de) : 
DCF1(PON)-----------(GND)Arduino
DCF1(DATA)---------(PIN3)Arduino
DCF1(GND)-----------(GND)Arduino
DCF1(VCC)-----------(3V3)Arduino

L'antenne doit etre perpendiculaire a la direction de l'emetteur (Allemagne)

SIGNAL: FAIBLE        <-OK---BON-------PARASITES------>
>>>>>>>>>>>>>>>>>>>>                                   Reception 04/59
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>                    Reception 09/59
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>                         Reception 14/59
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>                         Reception 19/59
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>                    Reception 24/59
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>                         Reception 29/59
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>                         Reception 34/59
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>                         Reception 38/59
>>>>>>>>>>>>>>>>>>>>>>>>>                              Reception 04/59
>>>>>>>>>>>>>>>>>>>>>>>>>                              Reception 09/59
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>                         Reception 14/59
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>                         Reception 19/59
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>                         Reception 24/59
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>                         Reception 29/59
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>                         Reception 34/59
>>>>>>>>>>>>>>>>>>>>>>>>>                              Reception 39/59
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>                         Reception 44/59
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>                         Reception 49/59
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>                         Reception 54/59
>>>>>>>>>>>>>>>>>>>>>>>>>                              Reception 58/59
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>                         Mercredi 28/10/2015 22:26 (heure d'hiver)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>                         Reception 09/59
>>>>>>>>>>>>>>>>>>>>>>>>>                              Reception 14/59

decodeurDCF77.zip (118 KB)

Pour les arduinautes curieux :

Le module DCF1 n'assure aucun décodage de la trame. Il se contente de fournir l'état instantané 0 ou 1 du signal.
Charge ensuite au logiciel d'effectuer le suivi de ce signal dans le temps, et d'appliquer le modèle théorique de trame DCF77 pour en déduire la valeur des bits reçus.

Pas clair ? Illustration : quand on a de la chance, le signal observé en sortie du module DCF1 ressemble à ceci


Là le signal est parfait : une impulsion par seconde, dont la durée est de 100 ms pour un bit à 0 et 200 ms pour un bit à 1. L'écriture d'une fonction de décodage des bits de la trame est alors triviale.

Mais bien souvent, le signal observé est plus ou moins éloigné du modèle théorique.
Par exemple, en cas de réception affaiblie, on observe ceci :

Ou alors il peut carrément y avoir des parasites :
<désolé pas d'image : j'en ai eu j'vous jure, mais pas ce soir et pas enregistrés :-* >

Et là, on voit mieux le travail à réaliser pour pondre un algorithme capable de repérer l'information utile dans un tel fouillis.
La qualité du logiciel utilisé est donc un élément essentiel à l'obtention d'un résultat satisfaisant, pour tous ceux qui n'ont pas la chance de vivre au pied de l'émetteur.

NB : ces courbes ont été obtenues grâce au sketch trace_DCF77, également fourni avec la librairie.
Ce sketch est un stand-alone rudimentaire, qui n'utilise aucune librairie.
Il se contente de lire en boucle l'état de la pin à raison d'un échantillon par milliseconde puis, lorsque son buffer en RAM est plein, de vider le tout sur le terminal série.
Une arduino de base peut ainsi mémoriser jusqu'à 10 secondes de signal.
Ensuite, un copier/coller vers un tableur de type excel, permet d'obtenir la courbe (CTRL-A dans le terminal série pour tout sélectionner...)
C'est artisanal, mais facile. Un genre d'oscillo du pauvre.

A ce stade, je vois déjà les matheux, férus de théorie du signal et autres algorithmes de filtrage numérique, se pencher plus attentivement sur le sujet. :smiling_imp:
Mais halte-là : 99 fois sur 100, notre arduino aura autre chose à faire que passer son temps à lire le signal DCF77 et appliquer des filtres savants, coûteux en RAM et en CPU.

Mon objectif était plutôt de bâtir une solution capable de décoder une trame DCF77 avec une certaine tolérance aux parasites, tout en ayant une empreinte RAM/CPU raisonnable.
Là, on est seulement à une soixantaine d'octets de RAM alloués de manière permanente.

A mon sens, pour aller significativement plus loin dans la résistance aux parasites, l'alternative serait de dédier une arduino pro mini à ce travail. Celle-ci pourrait consacrer 99% de ses resources au décodage permanent du signal, et fonctionner comme un périphérique esclave I2C qui donne l'heure exacte quand on lui demande.

Mais si vous pensez pouvoir développer une fonction de décodage meilleure et moins coûteuse en RAM / CPU, je suis preneur !
Celle que je vous propose est entièrement le fruit de mes propres neurones, donc largement perfectible.

Pour les arduinautes désireux de soulever le capôt et mettre les mains dans le cambouis logiciel :

La librairie proposée contient en réalité 4 headers distincts.

trameDCF77.h

Une librairie permettant la mise en buffer et manipulation des bits d'une trame DCF77.

Sa fonction de décodage logique d'une trame complète, effectue des contrôles de validité sur tout ce qu'il est possible de vérifier.
Ainsi par exemple, si le jour de la semaine ne correspond pas à la date reçue, la trame est considérée comme invalide.
Idem pour l'indicateur heure d'été / heure d'hiver, au regard de la date/heure.

Cette petite lib aurait sa place comme composant de base de tout développement autour du signal DCF77.

/***************************************************************************************************
/*
/* Librairie de manipulation d'une trame DCF77
/*
/* Code générique multi-plateforme, non spécifique à Arduino.
/* (2015) Bricoleau
/*
/***************************************************************************************************/
#ifndef trameDCF77_h
#define trameDCF77_h

#include <stdint.h>

const uint8_t NB_BITS_TRAME_DCF77 = 59;
const uint8_t NB_OCTETS_TRAME_DCF77 = (NB_BITS_TRAME_DCF77 + 7) / 8;

class trameDCF77_c
{
  public :
    trameDCF77_c();

    void raz();
    void ajouterBit(uint8_t bit);
    uint8_t lireBit(uint8_t rang);

    const uint8_t longueur();
    const bool estVide();
    const bool estComplete();

    const bool decoder(uint8_t *annee, uint8_t *mois, uint8_t *jour, uint8_t *joursem,
                       uint8_t *heure, uint8_t *minute, bool *heure_ete);
    //retourne false si trame invalide, avec date/heure inchangées
    //retourne true  si trame valide, avec date/heure chargées et certifiées cohérentes.
    //nb : joursem = 1 Lundi .... 7 Dimanche

  private : //Données : 9 octets
    uint8_t _longueur;
    uint8_t _valeur[NB_OCTETS_TRAME_DCF77];

    void localiserBit(uint8_t rang, uint8_t *num_octet, uint8_t *num_bit);
    void ecrireBit(uint8_t bit, uint8_t rang);
    uint8_t calculerParite(uint8_t debut, uint8_t fin);
    uint8_t extraireValeurDCB(uint8_t debut, uint8_t fin);
};

extern trameDCF77_c trameDCF77;

#endif

tunerDCF77.h

Une librairie permettant d'évaluer la qualité du signal reçu.

C'est aussi un stand alone logiciel en cpp standard, indépendant des primitives hardware de lecture du signal.

Elle contient un buffer dans lequel on enregistre les fronts montants / descendants observés, avec une référence temporelle.
Le buffer est géré sur une période de 5 secondes glissantes.
Une méthode de calcul exploite ce buffer pour fournir un indicateur de qualité du signal reçu.
Celui-ci ne considère pas la validité des données de la trame DCF77, mais seulement la bonne fréquence statistiques des fronts.

Cette librairie permet donc de savoir si le signal observé a "une bonne bouille de signal DCF77", avec une actualisation à chaque seconde.

Elle n'est pas strictement nécessaire au décodage des trames, mais bien utile pour suivre la réception et ajuster la position de l'antenne.

Peut-être que le calcul de l'indicateur de qualité pourrait être amélioré, afin d'être encore plus pertinent.

/***************************************************************************************************
/*
/* Tuner pour signal DCF77 - Permet de qualifier le niveau de réception du signal
/* Actualisation à la seconde
/*
/* Code générique multi-plateforme, non spécifique à Arduino.
/* (2015) Bricoleau
/*
/***************************************************************************************************/
#ifndef tunerDCF77_h
#define tunerDCF77_h

#include <stdint.h>

const uint8_t PERIODE_MESURE_DCF77 = 5; //secondes glissantes

const uint32_t DUREE_MINIMUM_NIVEAU_BAS_DCF77 = 700; //millisecondes

class tunerDCF77_c
{
  public :
    tunerDCF77_c();

    void enregistrerFrontMontant(uint32_t millis_front);
    void enregistrerFrontDescendant(uint32_t millis_front);

    const uint8_t qualiteReception(uint32_t millis_maintenant);
  //valeurs renvoyées :
  //  0    : signal inexistant
  //1 à 4  : signal trop faible, pas de décodage possible
  //  5    : signal parfait, décodage probable
  //  6    : signal correct, décodage probable
  //7 à 11 : signal parasité, décodage incertain selon algo

  private : //Données : 25 octets
    uint8_t  qualite;
    uint32_t ref_chrono;
    uint32_t ref_blanc;
    uint32_t ref_trou;
    uint8_t  nb_pics[PERIODE_MESURE_DCF77 + 1];
    uint8_t  nb_blancs[PERIODE_MESURE_DCF77 + 1];

    void     glisser(uint32_t jusqua);
    void     glisser(uint8_t combien);
    void     comblerTrou();
    uint8_t  calculerQualite();
};

extern tunerDCF77_c tunerDCF77;

#endif

Le programme exemple demo_tunerDCF77 montre une utilisation isolée de cette librairie :

Tuner pour signal DCF77

SIGNAL: FAIBLE        <-OK---BON-------PARASITES------>
                                                       00 Signal inexistant
>>>>>                                                  01 Signal trop faible
>>>>>>>>>>                                             02 Signal trop faible
>>>>>>>>>>>>>>>                                        03 Signal trop faible
>>>>>>>>>>>>>>>>>>>>                                   04 Signal trop faible
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>               08 Signal avec parasites
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>               08 Signal avec parasites
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>               08 Signal avec parasites
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>                    07 Signal avec parasites
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>                    07 Signal avec parasites
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>                         06 Signal correct
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>                         06 Signal correct
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>                         06 Signal correct
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>                         06 Signal correct

decodeurDCF77.h

C'est la librairie principale, qui utilise les deux précédentes en y ajoutant les fameuses règles d'analyse du signal, pour déterminer si on a reçu un bit 1 ou à 0.
Le traitement du signal repose sur plusieurs points, dont une analyse statistique des fronts montants, pour repérer la pulsation principale du signal DCF77.

C'est là que se concentrent les macérations neuronales, avec très certainement des possibilités d'amélioration.

A noter que cette librairie est encore du cpp standard non lié à l'environnement arduino, pour une meilleure portabilité.

/***************************************************************************************************
/*
/* Décodeur DCF77
/*
/* Code générique multi-plateforme, non spécifique à Arduino.
/* (2015) Bricoleau
/*
/***************************************************************************************************/
#ifndef decodeurDCF77_h
#define decodeurDCF77_h

#include <stdint.h>

class decodeurDCF77_c
{
  public :
    decodeurDCF77_c();

    bool traiterSignal(uint8_t signal_0_ou_1, uint32_t millis_signal);
    //retourne true si une trame est décodée, false sinon

    //Les donnees ci-dessous sont mises à jour par la fonction traiterSignal()
    //Utilisation en lecture seule

    //HORLOGE
    const uint32_t millis_derniere_trame_ok();
    const uint8_t  annee();
    const uint8_t  mois();
    const uint8_t  jour();
    const uint8_t  joursem(); //1 = lundi, ... 7 = dimanche
    const uint8_t  heure();
    const uint8_t  minute();
    const bool     heure_ete();

    //SIGNAL
    const uint8_t  qualiteReception(uint32_t millis_maintenant);
          //valeurs renvoyées :
          //  0    : signal inexistant
          //1 à 4  : signal trop faible, pas de décodage possible
          //  5    : signal parfait, décodage probable
          //  6    : signal correct, décodage probable
          //7 à 11 : signal parasité, décodage incertain
    const uint8_t  longueur_trame_en_cours(); //pour suivre la réception
    const uint8_t  bit_trame(uint8_t rang);   //pour suivre la réception

  private :
    uint32_t _millis_derniere_trame_ok;
    uint8_t  _annee;
    uint8_t  _mois;
    uint8_t  _jour;
    uint8_t  _joursem;
    uint8_t  _heure;
    uint8_t  _minute;
    bool     _heure_ete;

    uint32_t ref_synchro_pulsation;
    void     decalerPulsation(uint32_t millis_reference);
};

extern decodeurDCF77_c decodeurDCF77;

#endif

Les digitalRead() et millis() doivent être effectués en amont, et leurs valeurs fournies aux primitives d'entrée de la librairie

Le programme exemple demo_decodeurDCF77 montre une utilisation de cette librairie, avec visualisation de la trame en cours de réception :

Demo decodage signal DCF77

Recherche pulsation...
0000000
00000110101000
0011111101100010001011000110101000100001011100000110101000 Mercredi 28/10/2015 22:31 (heure d'hiver)
0110111100011010001010100110101000100001011100000110101000 Mercredi 28/10/2015 22:32 (heure d'hiver)
0111000111000000001011100110001000100001011100000110101000 Mercredi 28/10/2015 22:33 (heure d'hiver)
0011101100010010001010010110101000100001011100000110101000 Mercredi 28/10/2015 22:34 (heure d'hiver)
0010111010110010001011010110001000100001011100000110101000 Mercredi 28/10/2015 22:35 (heure d'hiver)
0101001000110000001010110110001000100001011100000110101000 Mercredi 28/10/2015 22:36 (heure d'hiver)
0000111100100000001011110110101000100001011100000110101000 Mercredi 28/10/2015 22:37 (heure d'hiver)
0001010000010010001010001110101000100001011100000110101000 Mercredi 28/10/2015 22:38 (heure d'hiver)
00100101000110100010110011100010

decodeurDCF1.h

Ca c'est le vrai driver hardware de module DCF1, pour arduino.

Cette librairie est une surcouche du decodeurDCF77.h
Elle met en place une interruption associée au changement d'état de la pin DATA du module DCF1.
La routine d'interruption lit l'état du signal et déclenche les primitives du decodeurDCF77.

Le programme exemple demo_decodeurDCF1 déjà évoqué au début du toto, montre une utilisation de cette librairie.
C'est cette librairie qu'il convient d'inclure dans vos programmes arduino

/***************************************************************************************************
/*
/* Driver de récepteur DCF77, modèle DCF1 (www.polllin.de)
/* Librairie spécifique Arduino
/*
/* (2015) Bricoleau
/*
/***************************************************************************************************/
#ifndef decodeurDCF1_h
#define decodeurDCF1_h

#include <Arduino.h>

class decodeurDCF1_c
{
  public :
    void begin(uint8_t pin); //obligatoirement une pin avec interruption

    void start(); //activer le traitement de l'interruption (non inclus dans begin)
    void stop();  //desactiver le traitement de l'interruption

    //A partir de là, les donnees ci-dessous sont automatiquement mises à jour par l'interruption
    //Utilisation en lecture seule

    //HORLOGE
    const uint32_t millis_derniere_trame_ok(); //Suivre la valeur de cette zone
          //pour savoir si une nouvelle date/heure est disponible ci-dessous
    const uint8_t  annee();
    const uint8_t  mois();
    const uint8_t  jour();
    const uint8_t  joursem(); //1 = lundi, ... 7 = dimanche
    const uint8_t  heure();
    const uint8_t  minute();
    const bool     heure_ete();

    //SIGNAL
    const uint8_t  qualiteReception();
          //valeurs renvoyées :
          //  0    : signal inexistant
          //1 à 4  : signal trop faible, pas de décodage possible
          //  5    : signal parfait, décodage probable
          //  6    : signal correct, décodage probable
          //7 à 11 : signal parasité, décodage incertain
    const uint8_t  longueur_trame_en_cours(); //pour suivre la réception
    const uint8_t  bit_trame(uint8_t rang);   //pour suivre la réception

    //DIVERS
    const bool started(); //interruption activee
    const uint8_t pin();

  private :
    uint8_t _pin;
};

extern decodeurDCF1_c decodeurDCF1;

#endif

Le programme principal ne se soucie alors plus du tout de la gestion du DCF1.
Il se contente de lire les variables d'état du décodeur, pour connaître la date exacte ou encore la qualité du signal reçu.

C'est uniquement cette librairie qu'il faudra adapter, pour gérer la réception DCF77 avec un module autre qu'un DCF1, ou sur un système autre qu'arduino.

Au vu des programmes exemples fournis, on pourrait penser qu'il y a peu de différences d'utilisation entre les librairies decodeurDCF77 et decodeurDCF1.

Pourtant, la différence est fondamentale.

Si vous essayez d'intégrer la librairie decodeurDCF77 dans un programme qui fait déjà autre chose, vous risquez de rater des impulsions du signal, dès lors qu'une partie annexe du programme dure plus de 50 ms.
La librairie decodeurDCF1 vous garantit de ne perdre aucune impulsion, même si votre programme principal fait déjà beaucoup de choses.

Elle a toutefois son inconvénient : la routine d'interruption est un poil lourde, puisqu'elle inclut l'exécution des fonctions de décodage du signal. Elle peut durer jusqu'à 600µs (temps moyen 80µs) sur une arduino standard à 16 Mhz. Votre programme principal doit dont être compatible avec ces petits freeze.

Si ce n'est pas le cas, il vous faudra envisager de restructurer le driver DCF1 (séparer acquisition et traitement du signal), ou bien de simplifier le traitement du signal dans le decodeurDCF77, quitte à perdre en capacité de filtrage des parasites.

Voilou, on est au bout du tuto

Enfin presque, juste un dernier conseil :

Lorsqu'on altère un signal brut reçu parasité, pour arriver à le faire coller à un modèle théorique, il y a toujours un risque de récupération d'une vraie fausse valeur.

Là, le risque est amplifié par les faibles protections techniques du format DCF77 : les quelques bits de parité de la trame n'offrent pas une protection suffisante. Statistiquement, on finit par passer au travers.

D'un autre côté, les contrôles ajoutés sur la validité des données décodées et sur la cohérence entre elles, limitent un peu le risque.

Mais si la prise en compte d'une date/heure erronée devait avoir un effet désastreux sur votre montage, je vous suggère d'attendre d'avoir reçu plusieurs trames cohérentes entre elles, avant de les exploiter.

Merci au courageux qui auront tout lu jusqu'ici.

N'hésitez pas à réagir ci-dessous, pour toute remarque / question / critique / proposition d'amélioration.

a+

Service après-vente :smiley:

Suite à une demande d'aide reçue en MP

Si vous essayez d'utiliser cette librairie avec une vieille version de l'IDE Arduino, vous risquez d'avoir le message d'erreur ci-dessous à la compilation :

...arduino\libraries\decodeurDCF77\decodeurDCF1.cpp: In member function 'void decodeurDCF1_c::start()':
...arduino\libraries\decodeurDCF77\decodeurDCF1.cpp:38: error: 'digitalPinToInterrupt' was not declared in this scope
...arduino\libraries\decodeurDCF77\decodeurDCF1.cpp: In member function 'void decodeurDCF1_c::stop()':
...arduino\libraries\decodeurDCF77\decodeurDCF1.cpp:51: error: 'digitalPinToInterrupt' was not declared in this scope

La cause est l'absence de définition de la macro digitalPinToInterrupt()

Deux solutions :

  1. Mettre à niveau votre IDE

  2. Ajouter manuellement le code ci-dessous au début du fichier decodeurDCF1.cpp

#ifndef digitalPinToInterrupt
  #if defined(__AVR_ATmega168__)
    // Arduino Diecimila and older
    #define digitalPinToInterrupt(p)  ((p) == 2 ? 0 : ((p) == 3 ? 1 : -1))
  #endif

  #if defined(__AVR_ATmega328P__)
    // Arduino Duemilanove and Uno
    #define digitalPinToInterrupt(p)  ((p) == 2 ? 0 : ((p) == 3 ? 1 : -1))
  #endif

  #if defined(__AVR_ATmega2560__)
    // Arduino Mega 2560
    #define digitalPinToInterrupt(p) ((p) == 2 ? 0 : ((p) == 3 ? 1 : ((p) >= 18 && (p) <= 21 ? 23 - (p) : -1)))
  #endif

  #if defined(__AVR_ATmega1280__)
    // Arduino Mega
    #define digitalPinToInterrupt(p) ((p) == 2 ? 0 : ((p) == 3 ? 1 : ((p) >= 18 && (p) <= 21 ? 23 - (p) : -1)))
  #endif

  #if defined(__AVR_ATmega32U4__)
    // Arduino Leonardo
    #define digitalPinToInterrupt(p) ((p) == 0 ? 2 : ((p) == 1 ? 3 : ((p) == 2 ? 1 : ((p) == 3 ? 0 : ((p) == 7 ? 4 : -1)))))
  #endif

  #if defined(__SAM3X8E__)
    // Arduino Due
    #define digitalPinToInterrupt(p)  ((p) < 54 ? (p) : -1)
  #endif
#endif

Bonjour Bricoleau,

merci pour le partage, je testerais dès que j' en aurais un à disposition.

Ca c'est du tuto comme je les aime!!

Intéressant, complet... et nécessitant quelques tasses de café et un ou deux dolipranes :slight_smile:

Merci.

Bonjour Bricoleau,

Pourrait-on envisager de filtrer le signal sortant du DCF1 avec un filtre passe bas analogique(RC)?
Cela simplifierait les choses. De cette manière on enlèverait les rapides changements d'état, mais cels rendrait peut être les flancs significatifs trop "diagonaux" ou plus assez verticaux..

merci! joli tuto

Bonjour et merci pour le compliment

Oui c'est certainement possible de faire un filtre passe bas hardware entre le DCF1 et l'arduino.
Après, "cela simplifierait les choses" est une question de point de vue :smiley:

Pour ma part, informaticien pur souche, j'ai tendance à tout faire au niveau logiciel pour minimiser le hardware.
En plus là il faut de toute manière traiter le signal de manière numérique. avec des règles de gestion temporelles sur les changements d'état.
L'ajout d'un équivalent de filtre passe bas logiciel était "plus simple" vu de ma paroisse :wink:

Calculer un R et C, trouver les composants, les souder est moins dans mes cordes que d'utiliser un clavier :smiley:

Salut,

Merci pour le Tuto.
Je vais le mettre en oeuvre prochainement car j'ai récupéré un module DCF77 pour pas cher (5,99 €).
Pour ceux qui en cherchent, il y a actuellement en vente à LIDL (désolé pour la pub) des petits radio-réveils AURIOL pilotés à 5,99€ pièce.

Comme celui-çi :

Je l'ai démonté et trouvé le tout petit module DCF77 soudé sur la carte principale, ainsi que son antenne sur ferrite. Le tout alimenté en 3V (2 x 1,5V). Il y a les pinoches : PON, OUT, VCCet GND.

A+
Blocos27

Bonjour,
Je viens de tomber sur cette discussion, tout d'abord, toutes mes félicitations à l'auteur, un travail remarquable.
Je reviendrai pour tout lire à tête reposée.
J'ai une première question, est ce qu'une UNO est suffisante pour une application d'horloge avec ce soft?
Merci d'avance pour toute réponse.

Bonjour et merci

Oui bien sur une uno ou nano ou micro ou mini est suffisante.
Faut juste ajouter des afficheurs 7 segments ou un lcd

Bonjour,
OK, ma UNO fera l'affaire. Je n'ai pas encore tout lu et j'ai une question : que se passe-t-il en cas de non réception ou de mauvaise réception? Est ce que l'horloge fonctionne avec un quartz?

Merci pour tes explications.

Bonjour,

J'ai acheté 2 modules cités plus haut (DCF1 de chez Pollin.de).
J'ai voulu les tester avec l'exemple ''demo_decodeurDCF1 ''.
Branchement à l'arduino (uno) tel que dans l'exemple et conforme à la data sheet du module.

Rien, aucun des 2 ne fonctionne, même après 30min.
Comme je sais que le signal dcf77 est parfois difficile à capter j'ai essayé à différents endroits de la maison, mais rien n'y fait

Mon oscilloscope étant fichu, impossible de tester le signal data du module.

Ci joint copies d'écran du moniteur série.

Une idée ?
Merci

Bonjour

Pour vérifier le signal brut en sortie du récepteur, utiliser le sketch trace_DCF77

bricoleau:
...
Mais bien souvent, le signal observé est plus ou moins éloigné du modèle théorique.
Par exemple, en cas de réception affaiblie, on observe ceci :

...

Et là, on voit mieux le travail à réaliser pour pondre un algorithme capable de repérer l'information utile dans un tel fouillis.
La qualité du logiciel utilisé est donc un élément essentiel à l'obtention d'un résultat satisfaisant, pour tous ceux qui n'ont pas la chance de vivre au pied de l'émetteur.

NB : ces courbes ont été obtenues grâce au sketch trace_DCF77, également fourni avec la librairie.
Ce sketch est un stand-alone rudimentaire, qui n'utilise aucune librairie.
Il se contente de lire en boucle l'état de la pin à raison d'un échantillon par milliseconde puis, lorsque son buffer en RAM est plein, de vider le tout sur le terminal série.
Une arduino de base peut ainsi mémoriser jusqu'à 10 secondes de signal.
Ensuite, un copier/coller vers un tableur de type excel, permet d'obtenir la courbe (CTRL-A dans le terminal série pour tout sélectionner...)
C'est artisanal, mais facile. Un genre d'oscillo du pauvre.

electronn2002:
Comme je sais que le signal dcf77 est parfois difficile à capter j'ai essayé à différents endroits de la maison, mais rien n'y fait

Plutôt que sa position, c'est surtout l'orientation de l'antenne qui est critique

j'ai récupéré 2 module DCF77 dans un réveil et une horloge, les 2 fonctionnent mais uniquement le soir entre 18 et 19h.
apres avoir orienté l'antenne correctement grâce a demo_tunerDCF77, cela marche bien a ces heures la, le signal doit etre plus fort sans doute car dans la journée et sans rien changer de la position de mon module c'est signal avec parasites...

Ce qui est étonnant c'est que les horloges radio-pilotées trouve en 10mn, quelque soit l'heure.

Et quand le signal est OK, c'est bon avec demo_decodeurDCF77 et aussi avec avec une autre lib Funkhur.

sur un module pas besoin de résistance pullup elle est deja sur le module, sur l'autre il en faut une, j'ai mis 1k
c'est bon.

me reste plus qu'a envoyer le résultat dans la RTC.

Bonjour et un grand merci pour ce tuto qui ne semble très bien rédigé, car je pense avoir tout compris.

Il m'est quand même venue une question :

bricoleau:
Pour les arduinautes désireux de soulever le capôt et mettre les mains dans le cambouis logiciel :

La librairie proposée contient en réalité 4 headers distincts.

trameDCF77.h

Une librairie permettant la mise en buffer et manipulation des bits d'une trame DCF77.

Sa fonction de décodage logique d'une trame complète, effectue des contrôles de validité sur tout ce qu'il est possible de vérifier.
Ainsi par exemple, si le jour de la semaine ne correspond pas à la date reçue, la trame est considérée comme invalide.

Idem pour l'indicateur heure d'été / heure d'hiver, au regard de la date/heure.

Une directive européenne pourrait bien mettre fin aux changements d'horaires saisonniers dans l'Union Européenne. Si le système est effectivement abandonné, cela rentrerait en vigueur en 2021, date sur laquelle les ministres des transports européens se sont mis d'accord lors d'un sommet en décembre 2018.

(source France Inter : Heure d'été, heure d'hiver ou les deux ? Vous avez jusqu'à dimanche pour choisir... )

Est-ce qu'en 2021 cette librairie détectera une erreur 6 mois sur 12 ?