Go Down

Topic: DCF77 impossible d'utiliser autre chose que A5 (Read 1 time) previous topic - next topic

Whaouu

Bonjour,

Il y a quelque temps, j'ai décidé de faire une horloge DCF pour faire un cadeau à mes parents.

J'ai donc acheté un module de réception chez HKW, un afficheur 7 segments I2C chez Adafruit.

J'ai téléchargé un Sketch sur le GIT de Blinkenlight.

J'ai fait un montage sur un Arduino UNO pour faire des tests (le montage final ne se feras pas sur un UNO à cause du résonateur. Le Sktech à besoin d'un vrai cristal).

Si je branche mon récepteur sur le A5 et que je lance le Sketch SCOPE pour analyser la qualité de réception ça fonctionne. En revanche si j'utilise une autre PIN, et que je modifie le paramétrage du Sketch en conséquence, je ne reçois rien.

Je ne comprends pas pourquoi je ne peux pas utiliser autre chose que le A5 ?

Merci, par avant, pour vos conseils.

trimarco232

Bonjour,

cela doit fonctionner avec toute autre pin analogique ...

Whaouu

#2
Jun 13, 2016, 07:06 pm Last Edit: Jun 13, 2016, 07:19 pm by Whaouu
Merci pour ta réponse Trimarco232.

Je suis tout à fait d'accord avec toi et c'est ce qu'a confirmé l'auteur du Sketch.

J'en déduis que je dois faire mal quelque chose, mais quoi ?...

Actuellement, j'utilise le branchement préconisé par l'auteur :

LP1 -> GND,
LP2 -> GND,
LP3 -> A5,
LP4 -> 5V

À noter que je n'utilise aucune résistance pull-up.

trimarco232

le branchement est correct, forcément ...
quelle autre pin as-tu essayé et comment as-tu fait la déclaration de la modif ?

Whaouu

Bonjour Pepe et Trimarco232,

Désoler pour cette réponse tardive, mais j'ai fait beaucoup de tests de mon côté et j'ai, un petit peut, avancer dans le diagnostique.

J'ai récupéré un programme DCF proposer par Thijs Elenbaas. Il est moins perfectionné que celui que je voudrais utiliser (n'y as pas de correction via le cristal dans les environnements qui perturbent le signal), mais lui fonctionne correctement sur la Pin A5 et D2.

Donc ça m'a permis de valider la partie hardware du montage.

Du coup, j'ai repris mes échanges avec Uno sur son site pour tenter de faire fonctionner son programme (pour rappe,l il fonctionne, pour moi, en A5 seulement).

Il m'a demandé de faire quelques tests avec le DCF77_Scope, mais pour le moment, mis à part en A5, je n'obtiens aucun signal sur D2.

Je ne suis pas du tout bon en programmation Arduino, j'ai donc du mal à investiguer en profondeur dans son code, mais au vu de mes tests, j'ai l'impression que le problème est logiciel.

Vous en pensez quoi ?

bricoleau

A5 vs D2 c'est plus que louche ton affaire.

Est-ce que tu as regardé le tuto complet DCF77 que j'ai mis en ligne ici sur le forum?


Tutoriels arduino : http://forum.arduino.cc/index.php?topic=398112.0

Whaouu

@Bricoleau :

Si je prends ton exemple "Demo_decodeurDCF77" et que je paramètre la Pin D2 (const uint8_t PIN_DCF77 = 2;) cela fonctionne parfaitement chez moi avec mon module.

@_Pepe_ :

Voila le code qui fonctionne, chez moi, avec le A5 et le D2 (en fonction du paramètrage) :

Code: [Select]
/*
 * InternalClockSync.pde
 * example code illustrating time synced from a DCF77 receiver
 * Thijs Elenbaas, 2012
 * This example code is in the public domain.
 
  This example shows how to fetch a DCF77 time and synchronize
  the internal clock. In order for this example to give clear output,
  make sure that you disable logging  from the DCF library. You can
  do this by commenting out   #define VERBOSE_DEBUG 1   in Utils.cpp.
 */

#include "DCF77.h"
#include "Time.h"

#define DCF_PIN 2          // Connection pin to DCF 77 device
#define DCF_INTERRUPT 0 // Interrupt number associated with pin

time_t time;
DCF77 DCF = DCF77(DCF_PIN,DCF_INTERRUPT);


void setup() {
  Serial.begin(9600);
  DCF.Start();
  Serial.println("Waiting for DCF77 time ... ");
  Serial.println("It will take at least 2 minutes until a first update can be processed.");
}

void loop() {
  delay(1000);
  time_t DCFtime = DCF.getTime(); // Check if new DCF77 time is available
  if (DCFtime!=0)
  {
    Serial.println("Time is updated");
    setTime(DCFtime);
  }
  digitalClockDisplay(); 
}

void digitalClockDisplay(){
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(" ");
  Serial.print(day());
  Serial.print(" ");
  Serial.print(month());
  Serial.print(" ");
  Serial.print(year());
  Serial.println();
}

void printDigits(int digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

Whaouu

Voila le code qui ne fonctionne, chez moi, qu'avec le A5 :

Code: [Select]
//
//  www.blinkenlight.net
//
//  Copyright 2015 Udo Klein
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program. If not, see http://www.gnu.org/licenses/

namespace {
    // workaround to convince the Arduino IDE to not mess with the macros
}

#if defined(__AVR__)
// pin settings for AVR based Arduino like Blinkenlighty, Uno or Nano
const uint8_t dcf77_analog_sample_pin = 5;
const uint8_t dcf77_sample_pin = 19;  // A5 == D19 for standard Arduinos
const uint8_t dcf77_inverted_samples = 1;
const uint8_t dcf77_analog_samples = 1;
const uint8_t dcf77_pull_up = 1;

const uint8_t dcf77_monitor_led = 18; // A4 == D18 for standard Arduinos

const uint8_t lower_output_led = 2;
const uint8_t upper_output_led = 17;

uint8_t ledpin(const int8_t led) {
    return led;
}

#else
// Pin settings for Arduino Due
// No support for "analog samples", the "analog samples".
// is only required for the Blinkenlighty or Arduino Uno + Blinkenlight Shield.
// For the Due any free pin may be used in digital mode.

const uint8_t dcf77_sample_pin = 53;
const uint8_t dcf77_inverted_samples = 0;
const uint8_t dcf77_pull_up = 1;

const uint8_t dcf77_monitor_led = 18;

const uint8_t lower_output_led = 2;
const uint8_t upper_output_led = 17;

uint8_t ledpin(const int8_t led) {
    return led<14? led: led+(54-14);
}

// Sine the DUE has so many pins it may be convenient to power
// some pins in a way that fits some specific DCF77 module.

// As an example these are pin settings for the "Pollin Module".
#define dedicated_module_support 1
const uint8_t gnd_pin  = 51;
const uint8_t pon_pin  = 51;  // connect pon to ground !!!
const uint8_t data_pin = dcf77_sample_pin;  // 53
const uint8_t vcc_pin  = 49;
#endif

// CRITICAL_SECTION macro definition depending on architecture
#if defined(__AVR__)
    #include <avr/eeprom.h>

    #include <util/atomic.h>
    #define CRITICAL_SECTION ATOMIC_BLOCK(ATOMIC_RESTORESTATE)

#elif defined(__arm__)
    // Workaround as suggested by Stackoverflow user "Notlikethat"
    // http://stackoverflow.com/questions/27998059/atomic-block-for-reading-vs-arm-systicks

    static inline int __int_disable_irq(void) {
        int primask;
        asm volatile("mrs %0, PRIMASK\n" :: "r"(primask));
        asm volatile("cpsid i\n");
        return primask & 1;
    }

    static inline void __int_restore_irq(int *primask) {
        if (!(*primask)) {
            asm volatile ("" ::: "memory");
            asm volatile("cpsie i\n");
        }
    }
    // This critical section macro borrows heavily from
    // avr-libc util/atomic.h
    // --> http://www.nongnu.org/avr-libc/user-manual/atomic_8h_source.html
    #define CRITICAL_SECTION for (int primask_save __attribute__((__cleanup__(__int_restore_irq))) = __int_disable_irq(), __n = 1; __n; __n = 0)

#else
    #error Unsupported controller architecture
#endif

#define sprint(...)   Serial.print(__VA_ARGS__)
#define sprintln(...) Serial.println(__VA_ARGS__)


uint8_t sample_input_pin() {
    const uint8_t sampled_data =
    #if defined(__AVR__)
        dcf77_inverted_samples ^ (dcf77_analog_samples? (analogRead(dcf77_analog_sample_pin) > 200):
                                                        digitalRead(dcf77_sample_pin));
    #else
        dcf77_inverted_samples ^ digitalRead(dcf77_sample_pin);
    #endif

    digitalWrite(ledpin(dcf77_monitor_led), sampled_data);
    return sampled_data;
}

void led_display_signal(const uint8_t sample) {
    static uint8_t ticks_per_cycle = 12;
    static uint8_t rolling_led = lower_output_led;
    static uint8_t counter = 0;

    digitalWrite(ledpin(rolling_led), sample);

    if (counter < ticks_per_cycle) {
        ++counter;
    } else {
        rolling_led = rolling_led < upper_output_led? rolling_led + 1: lower_output_led;
        counter = 1;
        // toggle between 12 and 13 to get 12.5 on average
        ticks_per_cycle = 25-ticks_per_cycle;
    }
}

const uint16_t samples_per_second = 1000;
const uint8_t bins                = 100;
const uint8_t samples_per_bin     = samples_per_second / bins;

volatile uint8_t gbin[bins];
boolean samples_pending = false;

void process_one_sample() {
    static uint8_t sbin[bins];

    const uint8_t sample = sample_input_pin();
    led_display_signal(sample);

    static uint16_t ticks = 999;  // first pass will init the bins
    ++ticks;

    if (ticks == 1000) {
        ticks = 0;
        memcpy((void *)gbin, sbin, bins);
        memset(sbin, 0, bins);
        samples_pending = true;
    }

    sbin[ticks/samples_per_bin] += sample;
}

void setup() {
    Serial.begin(115200);
    sprintln();

    #if defined(dedicated_module_support)
    pinMode(gnd_pin, OUTPUT);
    digitalWrite(gnd_pin, LOW);
    pinMode(pon_pin, OUTPUT);
    digitalWrite(pon_pin, LOW);
    pinMode(vcc_pin, OUTPUT);
    digitalWrite(vcc_pin, HIGH);
    #endif

    pinMode(dcf77_sample_pin, INPUT);
    digitalWrite(dcf77_sample_pin, dcf77_pull_up);

    pinMode(dcf77_monitor_led, OUTPUT);
    for (uint8_t led = lower_output_led; led <= upper_output_led; ++led) {
        pinMode(ledpin(led), OUTPUT);
        digitalWrite(ledpin(led), LOW);
    }

    setupTimer();
}

void loop() {
    static int64_t count = 0;
    uint8_t lbin[bins];

    if (samples_pending) {
        CRITICAL_SECTION {
            memcpy(lbin, (void *)gbin, bins);
            samples_pending = false;
        }

        ++count;
        // ensure the count values will be aligned to the right
        for (int32_t val=count; val < 100000000; val *= 10) {
            sprint(' ');
        }
        sprint((int32_t)count);
        sprint(", ");
        for (uint8_t bin=0; bin<bins; ++bin) {
            switch (lbin[bin]) {
                case  0: sprint(bin%10? '-': '+'); break;
                case 10: sprint('X'); break;
                default: sprint(lbin[bin]);
            }
        }
        sprintln();
     }
}

// timer handling depending on architecture
#if defined(__AVR_ATmega168__)  || \
    defined(__AVR_ATmega48__)   || \
    defined(__AVR_ATmega88__)   || \
    defined(__AVR_ATmega328P__) || \
    defined(__AVR_ATmega1280__) || \
    defined(__AVR_ATmega2560__) || \
    defined(__AVR_AT90USB646__) || \
    defined(__AVR_AT90USB1286__)
ISR(TIMER2_COMPA_vect) {
    process_one_sample();
}

void stopTimer0() {
    // ensure that the standard timer interrupts will not
    // mess with msTimer2
    TIMSK0 = 0;
}

void initTimer2() {
    // Timer 2 CTC mode, prescaler 64
    TCCR2B = (0<<WGM22) | (1<<CS22);
    TCCR2A = (1<<WGM21) | (0<<WGM20);

    // 249 + 1 == 250 == 250 000 / 1000 =  (16 000 000 / 64) / 1000
    OCR2A = 249;

    // enable Timer 2 interrupts
    TIMSK2 = (1<<OCIE2A);
}

void setupTimer() {
    initTimer2();
    stopTimer0();
}
#endif

#if defined(__SAM3X8E__)
extern "C" {
    // sysTicks will be triggered once per 1 ms
    int sysTickHook(void) {
        process_one_sample();
        return 0;
    }
}

void setupTimer() {}
#endif

bricoleau

Idem pour ma lib decodeurDCF1

Elle fait tout le boulot en arrière plan grâce à des interruptions.
Le module doit être branché sur D2 ou D3.

Et après il y a juste une collection de variables globales mises à jour de manière automatique, dont il suffit de lire les valeurs.

Rappel du header :
Code: [Select]
/***************************************************************************************************
/*
/* 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
Tutoriels arduino : http://forum.arduino.cc/index.php?topic=398112.0

Whaouu

#9
Nov 26, 2016, 11:28 am Last Edit: Nov 26, 2016, 11:36 am by Whaouu
Bonjour à tous,

Désolé pour mon absence de réponse, mais suite à la perte de mon père je n'avais plus le coeur à continuer, d'autant plus que c'était un cadeau dessiné à mes parents.

Bref, je vais essayer de le terminer...

Donc, si un de vous a l'envie et le temps pourrait-il essayer sur un Arduino Uno le Sketch SCOPE mis à disposition sur le GIT de Blinkenlight ?

Si ça fonctionne pour vous sur une autre PIN que A5 c'est que je fais quelque chose de mal de mon côté.

Je pourrais certes utiliser une des nombreuses librairies DFC disponibles (qui fonctionnent parfaitement chez moi), mais je n'aurais pas compris d'où venait mon problème et intellectuellement ça n'apporterait pas grand-chose du coup.

Voilà, encore désolé de reprendre si tard ce topique et encore merci pour votre aide.

Whaouu

Bonjour,

Personne ne dispose d'un module DCF77 pour faire le test ?

Whaouu

#11
Apr 07, 2017, 02:50 pm Last Edit: Apr 07, 2017, 04:13 pm by Whaouu
Bonjour,

J'essaye de terminer ce projet.

Si je prends la lib decodeurDCF1 de Bricoleau que je branche mon module DCF en D3 sur le Uno cela fonctionne parfaitement.

J'en déduis que sur le plan hardware il n'y a pas de soucis.

L'un d'entre vous aurait-il la possibilité de tester le Sketch SCOPE disponible sur le GIT de Blinkenlight avec un module DCF brancher sur D3 ?

Je pourrais certes utiliser une des nombreuses librairies DFC disponibles (qui fonctionnent parfaitement chez moi), mais je n'aurais pas compris d'où venait mon problème et intellectuellement ça n'apporterait pas grand-chose du coup.

Merci par avance pour votre aide.

68tjs

Si tu veux modifier la bibliothèque pour progresser s'attaquer à une grosse biblio n'est pas le meilleurs moyen.

Commence par modifier une bibliothèque rudimentaire et apprendre à créér de zéro une tout aussi rudimentaire.
Avec un sujet rudimentaire cela te permettra de comprendre les mécanismes mis en jeux.

Une fois ce travail réalisé tu pourra t'attaquer (avec succès) à la biblio DCF77.
Le travail sera plus facile et beaucoup plus rapide.

Whaouu

Je n'envisage pas du tout de modifier la bibliothèque mais simplement de l'utiliser en l'état. :)

Il me suffit de respecter le bon cablage et fonction du paramètrage de la bibliothèque, en théorie ça devais être super simple.

Avec toutes les bibliothèques DCF que je teste, cela fonctionne parfaitement sauf avec celle qui m'intéresse...

Je pense que son auteur a fait un très bon travail et que très certainement elle fonctionne, mais je ne parviens pas à m'en servir sur autre chose que A5.

C'est pour cette raison que j'aurais aimé avoir confirmation.

68tjs

Il se peut que la pin A5 a été déclarée à l'intérieur de la bibliothèque "en dur" et que la bibliothèque ne peut utiliser que cette pin, du moins telle qu'elle a été écrite ?

Go Up