Forum Électro-Bidouilleur

Merci de vous connecter ou de vous inscrire.

Connexion avec identifiant, mot de passe et durée de la session
Recherche avancée  

Nouvelles:

Bienvenue au Forum de discussion Électro-Bidouilleur! Inscrivez-vous pour participer aux discussions!: 
https://forum.bidouilleur.ca/index.php?action=register Les demandes d'inscription sont révisées quotidiennement.

Auteur Sujet: emetteur dcf77 en Europe  (Lu 2310 fois)

ruddy

  • Newbie
  • *
  • Messages: 4
    • Voir le profil
emetteur dcf77 en Europe
« le: Octobre 29, 2023, 11:29:18 am »

Bonjour, quelqu'un a-t-il déjà  utiliser le module qui exploite le signal de l'émetteur dcf77 sur arduino? Merci
IP archivée

philchamp51

  • Full Member
  • ***
  • Messages: 247
    • Voir le profil
Re : emetteur dcf77 en Europe
« Réponse #1 le: Novembre 14, 2023, 12:33:00 pm »

Bonjour, quelqu'un a-t-il déjà  utiliser le module qui exploite le signal de l'émetteur dcf77 sur arduino? Merci

Bonjour. Oui, moi
IP archivée

philchamp51

  • Full Member
  • ***
  • Messages: 247
    • Voir le profil
Re : emetteur dcf77 en Europe
« Réponse #2 le: Novembre 14, 2023, 12:33:56 pm »

As-tu besoin de renseignements ?
IP archivée

pentahertz

  • Newbie
  • *
  • Messages: 15
    • Voir le profil
Re : emetteur dcf77 en Europe
« Réponse #3 le: Décembre 12, 2023, 02:55:28 pm »

oui j'en ai tester beaucoup
ca fonctionne mais de gros probleme pour la reception
ca fonctionne pas tous les jours j'avais utilise ce code arduino nano

#include <TimeLib.h>
#define DCF77PIN 2           // input  - DCF signal from antenna pcb. Pin must an interrupt input!
#define DCF_INTERRUPT 0         // Interrupt number associated with pin

#define LED_LEAPYEAR 31       // output - LED - Leap year
#define LED_DCFSTATUS 42      // output - LED - On when we have good DCF data


// Pulse flanks
static unsigned long leadingEdge = 0;
static unsigned long trailingEdge = 0;
unsigned long previousLeadingEdge = 0;
int bufferPosition = 0;
// used in <Int0handler>
volatile unsigned int DCFSignalState = 0; // interrupt variables ALWAYS need volatile qualifier!!
boolean errorCondition = false;
// used in <loop>
int previousSecond = 0;
unsigned int previousSignalState = 0;

// DCF Buffers and indicators
static int DCFbitBuffer[59];                         // here, the received DCFbits are stored
const int bitValue[] = {1, 2, 4, 8, 10, 20, 40, 80}; // these are the decimal values of the received DCFbits
// dcf variables to store decoded DCF time in
int dcfMinute = 0;
int dcfHour = 0;
int dcfDay = 0;
int dcfWeekDay = 0;
int dcfMonth = 0;
int dcfYear = 0;
int dcfDST = 0;
int leapYear = 0;
// variables to check if DCF bits are valid
bool dcfValidSignal = false;
int dcfP1counter = 0;
int dcfP2counter = 0;
int dcfP3counter = 0;
int dcfParityCheckP1 = 0;
int dcfParityCheckP2 = 0;
int dcfParityCheckP3 = 0;


// variables used to store weeknumber and daynumber values
int dayNumber;
int weekNumber;

// only after start on a new minute, display received bits on inner LED ring
boolean MinuteMarkerFlag = false;


void setup() {
  // put your setup code here, to run once:
 Serial.begin(115200);
 pinMode(DCF77PIN, INPUT);
 initialize();
 attachInterrupt(DCF_INTERRUPT, int0handler, CHANGE);
   
}

//================================================================================================================
//
// Function name : processDcfBit
// called from   : <scanSignal>
//
// Purpose       : after reception of one good DCF bit, do some checks and save it in the DCFbitBuffer array
// Parameters    : none
// Return value  : none
//
//================================================================================================================

void processDcfBit(int dcfBit)
{
  //--------------------------------------------------------------------
  // display incoming DCF bits on inner LED ring
  //--------------------------------------------------------------------
  // only if we have valid DCF data or after an Minute Mark (EoM) signal


  //--------------------------------------------------------------------
  //   // Fill DCFbitBuffer array with DCFbit
  //--------------------------------------------------------------------
  DCFbitBuffer[bufferPosition] = dcfBit;

  //--------------------------------------------------------------------
  // Parity check
  //--------------------------------------------------------------------
  // DURING reception of the DCF bits, calculate and display the results of the DCF parity check.
  //
  // There is a Parity bit for the minutes, the hours and for the date.
  // DCF77 works with EVEN parity, this works as follows:
  // The hours for example have 6 bits plus a paritybit. The bits with value 1 are add up including the paritybit,
  // the result must be an even number. If there is a bit wrong received, a 0 is as 1, or a 1 is as 0 received,
  // then the result is uneven.  source: http://www.picbasic.nl/frameload_uk.htm?http://www.picbasic.nl/info_dcf77_uk.htm

  if (bufferPosition == 0)
  {
 
    // reset variables
    dcfP1counter = 0;
    dcfP2counter = 0;
    dcfP3counter = 0;
    dcfParityCheckP1 = 0;
    dcfParityCheckP2 = 0;
    dcfParityCheckP3 = 0;
  }

  // ----------------------------------------
  // First parity check: minute bits
  // ----------------------------------------
  if (bufferPosition == 28)
  {
    for (int i = 21; i <= 27; i++)
    {
      // count the number of bits with the value '1'
      dcfP1counter += DCFbitBuffer;
    }

    // perform P1 parity check. Parity is OK if the sum is an EVEN value
    if ((DCFbitBuffer[28] + dcfP1counter) % 2 == 0)
    {

      // Parity P1 PASS
      dcfParityCheckP1 = 1;
    }
    else
    {

      // we have no valid data!
      dcfValidSignal = false;

    }
  }

  // ----------------------------------------
  // Second parity check: hour bits
  // ----------------------------------------
  if (bufferPosition == 35)
  {
    for (int i = 29; i <= 34; i++)
    {
      dcfP2counter += DCFbitBuffer;
    }

    // perform P2 parity check. Parity is OK if the sum is an EVEN value
    if ((DCFbitBuffer[35] + dcfP2counter) % 2 == 0)
    {

      // Parity P2 PASS
      dcfParityCheckP2 = 1;
    }
    else
    {

      // we have no valid data!
      dcfValidSignal = false;
    }
  }

  // ----------------------------------------
  // Third parity check: date bits
  // ----------------------------------------
  if (bufferPosition == 58)
  {
    for (int i = 36; i <= 57; i++)
    {
      dcfP3counter += DCFbitBuffer;
    }
    // perform P3 parity check. Parity is OK if the sum is an EVEN value
    (DCFbitBuffer[58] + dcfP3counter) % 2 == 0 ? dcfParityCheckP3 = 1 : dcfParityCheckP3 = 0;

    // Turn Parity2 'PASS' or 'FAIL' LED ON
    if (dcfParityCheckP3 == 1)
    {
      // Parity P3 PASS
      dcfParityCheckP3 = 1;
    }
    else
    {

      // we have no valid data!
      dcfValidSignal = false;
      // Turn DCF OK LED OFF
    }

    // ----------------------------------------
    // finally, check all Parity bits
    // ----------------------------------------
    dcfParityCheckP1 + dcfParityCheckP2 + dcfParityCheckP3 == 3 ? dcfValidSignal = true : dcfValidSignal = false;
  }

  //--------------------------------------------------------------------
  // before continuing with the next bit, increment counter
  //--------------------------------------------------------------------
  bufferPosition++;

  //--------------------------------------------------------------------
  // check if we have not received too many pulses?
  //--------------------------------------------------------------------
  if (bufferPosition > 59)
  {
    // Buffer Overflow ERROR - we have received more pulses before reaching
    // the 2 second 'gap' signalling the end of the minute.
    //This error may be due to a noisy signal giving addition peaks/dcfBits
    // So clear both DCFbit displays and start again.
    // Buffer Overflow ERROR - nous avons reçu plus d'impulsions avant d'atteindre
    // le 'gap' de 2 secondes signalant la fin de la minute.
    //Cette erreur peut être due à un signal bruité donnant des pics d'addition/dcfBits
    // Donc, effacez les deux affichages DCFbit et recommencez.
    // Reset buffer counter
    bufferPosition = 0;

    // turn Buffer Overflow Error LED ON

    // exit
    return;
  }

  //--------------------------------------------------------------------
  // everything OK so we wait for next incoming DCFbit
  // tout va bien donc nous attendons le prochain DCFbit entrant
  //--------------------------------------------------------------------
}

//================================================================================================================
//
// bitDecode
//
// called from <processBuffer>
//================================================================================================================
int bitDecode(int bitStart, int bitEnd)
{
  // reset 'bitValue-array' counter
  int i = 0;
  int value = 0;

  // process bitrange bitStart > bitEnd
  while (bitStart <= bitEnd)
  {
    // check if DCFbit in buffer is '1', discard when '0'
    if (DCFbitBuffer[bitStart] == 1)
    {
      // DCFbit in buffer == 1 so append its corresponding value to the variable 'value'
      // DCFbit in buffer == 1 donc ajouter sa valeur correspondante à la variable 'value'
      value = value + bitValue;
    }
    // increment 'bitValue-array' counter
    i++;
    // increment bit-range counter
    bitStart++;
  }
  return value;
}

//================================================================================================================
//
// Function name : dayWeekNumber
// called from   : <decodeBufferContents>
//
// Purpose       : calculate the WEEK number according to ISO standard, see comments in the ARCHIVE below
//                 calculer le numéro de SEMAINE selon la norme ISO, voir les commentaires dans l'ARCHIVE ci-dessous
// Parameters    : dcfYear, dcfMonth, dcfDay, dcfWeekDay
// Return value  : weekNumber   numéro de SEMAINE
//
//================================================================================================================
//Code from: http://forum.arduino.cc/index.php/topic,44476.0.html

int dayWeekNumber(int y, int m, int d, int w)
{
  // Number of days at the beginning of the month in a normal (not leap) year.
  int days[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};

  // Start to calculate the number of days of the first two months
  if (m == 1 || m == 2)
  {
    // for any type of year we calculate the number of days for January or february
    dayNumber = days[(m - 1)] + d;
  }

  // now calculate for the other months
  // first, check for a leap year
  else if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0)
  {
    // we have a leap year, so calculate in the same way but adding one day
    dayNumber = days[(m - 1)] + d + 1;
  }

  else
  {
    //no leap year, calculate in the normal way, such as January or February
    dayNumber = days[(m - 1)] + d;
  }

  // Now start to calculate Week number
  if (w == 0)
  {
    //if it is sunday (time library returns 0)
    weekNumber = (dayNumber - 7 + 10) / 7;
  }

  else
  {
    // for the other days of week
    weekNumber = (dayNumber - w + 10) / 7;
  }

  // finished! return with the week number as an INT value
  return weekNumber;
}

//================================================================================================================
//
// Function name : calculateLeapYear
// called from   : <decodeBufferContents>
//
// Purpose       : determine if a given year is a leap year
// Parameters    : year - the year to test
// Return value  : '1' if the year is a leap year, '0' otherwise
//
//================================================================================================================

int calculateLeapYear(int year)
{
  if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
  {
    return 1;
  }
  else
  {
    return 0;
  }
}





void decodeBufferContents(void)
{
  // Buffer is full and ready to be decoded
  dcfMinute = bitDecode(21, 27);
  dcfHour = bitDecode(29, 34);
  dcfDay = bitDecode(36, 41);
  dcfWeekDay = bitDecode(42, 44);
  dcfMonth = bitDecode(45, 49);
  dcfYear = bitDecode(50, 57);

  //call function to calculate day of year and weeknumber
  dayWeekNumber(dcfYear, dcfMonth, dcfDay, dcfWeekDay);

  // Get value of Summertime DCFbit. '1' = Summertime, '0' = wintertime
  dcfDST = bitDecode(17, 17);

  // determine Leap Year
  leapYear = calculateLeapYear(dcfYear);
}




//================================================================================================================
//
// Function name : finalizeBuffer
// called from   : <scanSignal>
//
// Purpose       : Process the succesfully received DCF data of one minute
// Parameters    : none
// Return value  : none
//
//================================================================================================================

void finalizeBuffer(void)
{
  //--------------------------------------------------------------------
  // We are here because of the detected 2 second 'gap'.
  // Now check if it correspondends with the buffer counter
  // 'bufferPosition' which should be value 59
  //--------------------------------------------------------------------
  if (bufferPosition == 59 && dcfValidSignal == true)
  {

    // process buffer and extract data sync the time with the RTC
    decodeBufferContents();

    setTime(dcfHour, dcfMinute, 0, dcfDay, dcfMonth, dcfYear);
    Serial.println();
    Serial.print("Time: ");
    Serial.print(dcfHour);
    Serial.print(":");
    Serial.print(dcfMinute);
    Serial.println();
    Serial.print("Date: ");
    Serial.print(dcfDay);
    Serial.print("-");
    Serial.print(dcfMonth);
    Serial.print("-");
    Serial.print(dcfYear);
    Serial.println();
 
    // Reset running buffer
    bufferPosition = 0;

    // Reset DCFbitBuffer array, positions 0-58 (=59 bits)
    for (int i = 0; i < 59; i++)
    {
      DCFbitBuffer = 0;
    }

    // reset flag
    MinuteMarkerFlag = false;

  } // if (bufferPosition == 59)

  //--------------------------------------------------------------------
  // The buffer is not yet filled although the 2 second 'gap' was detected.
  // Can be result of a noisy signal, starting in middle of receiving data etc.
  // Turn 'Minute Mark' LED ON
  //--------------------------------------------------------------------
  else
  {
     // Reset running buffer and start afresh. Now we are in sync with the incoming data
    bufferPosition = 0;

    // Reset DCFbitBuffer array, positions 0-58 (=59 bits)
    for (int i = 0; i < 59; i++)
    {
      DCFbitBuffer = 0;
    }

    // set flag so we can display incoming pulsed on the inner LED ring.
    MinuteMarkerFlag = true;
  }
}




//================================================================================================================
//
// Function name : processDcfBit
// called from   : <scanSignal>
//
// Purpose       : Evaluates the signal as it is received. Decides whether we received a "1" or a "0"
//                 and perform checks to see if the pulse timing is within limits
// Parameters    : none
// Return value  : none
//
//================================================================================================================
/*
       pulse                 pulse
       width                 width
       |- -|               |--   --|           |----- END OF MINUTE marker:2000ms -----|
        ___                 _______             ___                                     ___                 _______
       | 0 |               |   1   |           | 0 |                                   | 0 |               |   1   |
       |   |               |       |           |   |                                   |   |               |       |
       |   |               |       |           |   |                                   |   |               |       |
 ______|   |_______________|       |___________|   |___________________________________|   |_______________|       |__ _ _ _
       ^   ^               ^       ^           ^   ^               ^                   ^   ^               ^       ^
       1000 2100           2000    2200        3000 3100         NO PULSE              5000 5100           6000    6200         << example millis() value
                                                                 = end of Minute indication
       ^                   ^                   ^                                       ^                   ^
       DCFbit# 56          DCFbit# 57          DCFbit# 58                               DCFbit# 0           DCFbit# 1  etc...   << DCF bit received
       
       ^                   ^        ^
       previous            leading  trailing
       leading edge        edge     edge
       
       ^   ^
       flanktime (rising or falling)
 
 */
void twoDigitPrint(int num) {
  if (num == -1) {
    Serial.print("??");
    return;
  }
  if (num <= 9) {
    Serial.print("0");
  }
  Serial.print(num);
}



void scanSignal()
{
  //--------------------------------------------------------------------
  // Check for Rising-Edge signal and perform checks
  //--------------------------------------------------------------------
  if (DCFSignalState == 1)
  {
    // store Rising-Edge Time to check later if the time between two pulses is valid
    // stocker Rising-Edge Time pour vérifier plus tard si le temps entre deux impulsions est valide
    leadingEdge = millis();
    // not much to do now so exit.
    return;
  }

  //--------------------------------------------------------------------
  // Check for Falling-Edge signal and perform checks
  //--------------------------------------------------------------------

  if (DCFSignalState == 0)
  {
    // store Trailing-Edge Time to check later if the Pulse Width is valid
    // stocker Trailing-Edge Time pour vérifier plus tard si la largeur d'impulsion est valide
    trailingEdge = millis();

    //--------------------------------------------------------------------------------
    // Check PERIOD TIME
    //--------------------------------------------------------------------------------
    // If this flank UP is detected quickly after previous flank UP this is an incorrect
    // Period Time (should be 1000ms -or 2000ms after second 58-) that we shall reject
    if ((leadingEdge - previousLeadingEdge) < 900)
    {
      // rPW - ERROR: Periode Time (rising flank to rising flank) time is too short -> REJECTED
      // rPW - ERREUR : le temps de période (flanc montant à flanc montant) est trop court -> REJETÉ

      errorCondition = true;
    }
    //--------------------------------------------------------------------------------
    // CHECK PULSE TIME
    //--------------------------------------------------------------------------------
    // If the detected pulse is too short it will be an incorrect pulse that we shall reject
    // should be 100 and 200 ms ideally
    Serial.print("trailingEdge - leadingEdge = "); Serial.println(trailingEdge - leadingEdge);

        twoDigitPrint(hour());
        Serial.print(":");
        twoDigitPrint(minute());
        Serial.print(":");
        twoDigitPrint(second());
        Serial.println();

        Serial.print(day());
        Serial.print("/");
        Serial.print(month());
        Serial.print("/");
        Serial.println(year());
   
    if (((trailingEdge - leadingEdge) < 70) || ((trailingEdge - leadingEdge) > 230))
    {
      //rPT - ERROR: Pulse Width too short or too long -> REJECTED
      //rPT - ERREUR : Largeur d'impulsion trop courte ou trop longue -> REJETÉE
      errorCondition = true;
    }

    // if we had an error return and start over
    // si nous avons eu une erreur revenir et recommencer
    if (errorCondition == true)
    {
      errorCondition = false;
      // although we have an error, store current rising edge time to compare at the next Rising-Edge.
      previousLeadingEdge = leadingEdge;
      return;
    }

    //--------------------------------------------------------------------
    // no errors found so now we can continue
    //--------------------------------------------------------------------

    // first we turn any error Led's OFF
   

    // END OF MINUTE check, looking for a gap of approx. 2000ms
    if (leadingEdge - previousLeadingEdge > 1900 && leadingEdge - previousLeadingEdge < 2100)
    {
      // end of minute detected:
      // fin de minute détectée :
      Serial.print("leadingEdge - previousLeadingEdge 2000ms= "); Serial.println(leadingEdge - previousLeadingEdge);
     
      finalizeBuffer();
    }

    // refresh previousLeadingEdge time with the new leading edge time
    previousLeadingEdge = leadingEdge;

    //--------------------------------------------------------------------------------
    // process DCF bits
    //--------------------------------------------------------------------------------
    // distinguish between long and short pulses
    if (trailingEdge - leadingEdge < 170)
    {
      // call processDcfBit function and sent it the value '0'
      processDcfBit(0);
     
    }
    else
    {
      // call processDcfBit function and sent it the value '1'
      processDcfBit(1);
    }
  } // if (DCFSignalState == 0)
} // void scanSignal();




void initialize(void)
{
  //---------------------------------------------------
  // Initialize Variables
  //---------------------------------------------------
  leadingEdge = 0;
  trailingEdge = 0;
  previousLeadingEdge = 0;
  bufferPosition = 0;

  // Reset DCFbitBuffer array, positions 0-58 (=59 bits)
  for (int i = 0; i < 59; i++)
  {
    DCFbitBuffer = 0;
  }
}

//================================================================================================================
//
// Function name : tasksEverySecond
// called from   : <loop>
//
// Purpose       : perform tasks that must happen once every SECOND
// Parameters    : none
// Return value  : none
//
//================================================================================================================
void tasksEverySecond()
{
  // check if time is changed
  if (second() != previousSecond)
  {
    // 'reset' variable state
    previousSecond = second();

    //display the Real Time Clock Time
   // displayRtcTime();
    // display 'HI' and 'LO' temperature on specific moments
    switch (second())
    {
    case 0:
      // hourly chime output: ACTIVATE
      break;
    case 2:
      // hourly chime output: DEACTIVATE
     //digitalWrite(CHIMEPIN, LOW);
      break;
    case 30:
          break;
    case 31:
    case 32:
      // NOTE: I physically rotated digit 4 so when I activate the decimal dot, this now is the 'degrees dot' in the upper left corner
      break;
    case 33:
      break;
    case 34:
    case 35:
      break;
    case 36:
      // befor displaying the temperature in the next second,
      break;
    case 37:
      // read temperature, store in min/max memory and display current temperature
      // only once per minute this is done else things go wrong... ;)
      break;
    } // switch
  } // (second() != previousSecond)
} // void tasksEverySecond()




//================================================================================================================
//
// Function name : int0handler
// called from   :
//
// Purpose       : when a rising or falling edge is detected on pin 2, this function is called
// Parameters    : none
// Return value  : none
//
//================================================================================================================

void int0handler()
{
  DCFSignalState = digitalRead(DCF77PIN);
}

void loop() {

  // check first if pulse direction is changed (rising or falling)
  // else we would keep evaluating the same pulse
  if (DCFSignalState != previousSignalState)
  {
    // 'reset' state of variable
    previousSignalState = DCFSignalState;

    // evaluate incoming pulse
    scanSignal();
  }
}




j'ai utiliser celui la aussi
#include <TimeLib.h>

#define READPIN 2

#define ZERO_DUR_START  83L
#define ZERO_DUR_END  136L
#define ONE_DUR_START  178L
#define ONE_DUR_END  231L
#define SIGNALGAP_DUR_START 1900L
#define SIGNALGAP_DUR_END  2100L  //2100L  2.1 secondes (= 2100 millisecondes)
#define DEBUG false

int decodeMultipliers[] =  {1, 1, 2, 4, 8, 10, 20, 40, 1, 1, 2, \
                            4, 8, 10, 20, 1, 1, 2, 4, 8, 10, 20, 1, 2, 4, 1, 2, 4, \
                            8, 10, 1, 2, 4, 8, 10, 20, 40, 80, 1, 1
                           };

boolean dcf_received_date = false;
boolean dcf_received_time = false;

int last_dcf_hours = -1;
int last_dcf_mins = -1;
int last_dcf_day = -1;
int last_dcf_month = -1;
int last_dcf_year = -1;
int last_dcf_received = millis();

void dcfTimeDateReceived(int dcf_hours, int dcf_mins, int dcf_day, int dcf_month, int dcf_year) {
  Serial.println();
  Serial.print("Complete OK:  ");
  Serial.print(dcf_hours);
  Serial.print(":");
  Serial.print(dcf_mins);
  Serial.println("  ");
  Serial.print(dcf_day);
  Serial.print("-");
  Serial.print(dcf_month);
  Serial.print("-");
  Serial.print(dcf_year);
  Serial.println();
  // set the current time to 14:27:00, December 14th, 2015
  //setTime(14, 27, 00, 14, 12, 2015);
  setTime(dcf_hours, dcf_mins, 0, dcf_day, dcf_month, dcf_year);
  Serial.println("date et heure mise à jour");
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)


  dcf_received_date = true;
  dcf_received_time = true;

}

void dcfIncompleteTimeDateReceived(int dcf_hours, int dcf_mins, int dcf_day, int dcf_month, int dcf_year) {
  Serial.println();
  Serial.print("Incomplete: ");
  Serial.print(dcf_hours);
  Serial.print(":");
  Serial.print(dcf_mins);
  Serial.print("  ");
  Serial.print(dcf_day);
  Serial.print("-");
  Serial.print(dcf_month);
  Serial.print("-");
  Serial.print(dcf_year);
  Serial.println();

}

void dcfOnlyTimeReceived(int dcf_hours, int dcf_mins) {
  Serial.println();
  Serial.print("Time: ");
  Serial.print(dcf_hours);
  Serial.print(":");
  Serial.print(dcf_mins);
  Serial.println();
  dcf_received_time = true;
}


void dcfOnlyDateReceived(int dcf_day, int dcf_month, int dcf_year) {
  Serial.print("Date: ");
  Serial.print(dcf_day);
  Serial.print("-");
  Serial.print(dcf_month);
  Serial.print("-");
  Serial.print(dcf_year);
  Serial.println();
  dcf_received_date = true;
}

void setup() {
  Serial.begin(115200);
  pinMode(READPIN, INPUT_PULLUP);
   pinMode(LED_BUILTIN, OUTPUT);
}

unsigned long lastRef = millis();
boolean showTime = true;

void printTimeToLCD() {
  //450 down
  unsigned long elap = millis() - lastRef;
  if (elap > 600) {

   int val = analogRead(0);
    if (val >= 430 && val <= 495) {
      showTime = !showTime;
    }
   // Serial.clear();
 
    if (showTime)
    {
      if (dcf_received_time==true &&& dcf_received_date!=true)
      {
        Serial.println();
        twoDigitPrint(hour());
        Serial.print(":");
        twoDigitPrint(minute());
        Serial.print(":");
        twoDigitPrint(second());
        Serial.println();

        Serial.print(day());
        Serial.print("-");
        Serial.print(month());
        Serial.print("-");
        Serial.print(year());

      } else {
        Serial.println();
        Serial.print("Waiting ");
        Serial.print(millis() / 1000);
        Serial.print(" sec");
      }
    } else {
      Serial.println();
      Serial.print("DCF ");
      twoDigitPrint(last_dcf_hours);
      Serial.print(":");
      twoDigitPrint(last_dcf_mins);
      Serial.print(" (");
      Serial.print(((millis() - last_dcf_received) / 1000));
      Serial.print(")");
      Serial.println();

      oneDigitPrint(last_dcf_day);
      Serial.print("-");
      oneDigitPrint(last_dcf_month);
      Serial.print("-");
      oneDigitPrint(last_dcf_year);
    }
    lastRef = millis();
  }

}
void oneDigitPrint(int num) {
  if (num == -1) {
    Serial.print("??");
    return;
  }
  Serial.print(num);
}
void twoDigitPrint(int num) {
  if (num == -1) {
    Serial.print("??");
    return;
  }
  if (num <= 9) {
    Serial.print("0");
  }
  Serial.print(num);
}


void loop()
{
 
  unsigned long lastStartTime, signalGap, startTime, stopTime, elapsed, tmp;
  unsigned long sTimes[200];
  int bits[200];
  int i = 0;
  lastStartTime = 0;
 
  while (true)
  {
    startTime = millis();
    stopTime = startTime;
    printTimeToLCD();
 // if (  dcf_received_date != true &&  dcf_received_time!= true)
 // {
    boolean active = digitalRead(READPIN);
    if (active)
    {
      while (true) 
      {
        active = digitalRead(READPIN);
        if (active)
        {
          stopTime = millis();
        }
        else 
        {
          if (millis() < stopTime)
          {
                        Serial.println("transition entre 2 minutes, impulsion pendant 2 secondes.");
            //arduino time wrap-around, break loop bouclage du temps arduino, boucle de rupture
            break;
          }
          tmp = millis() - stopTime;
          if ( tmp > 2L) ////2000L  2 secondes (= 2000 millisecondes) La transition entre 2 minutes est manifestée par l'absence d'impulsion pour le bit 59 : on a donc une absence d'impulsion pendant 2 secondes.
          {

            break;// break est utilisé pour sortir d'une boucle for,while,do...while, en contournant la condition de boucle normale. Il est également utilisé pour sortir d'un switch case
           
          }
        }//fin else if (active)
      }//fin 2eme while (true)
      elapsed = stopTime - startTime;

      signalGap = startTime - lastStartTime;

      lastStartTime = startTime;
      if ((elapsed >= ZERO_DUR_START && elapsed <= ZERO_DUR_END) || (elapsed >= ONE_DUR_START && elapsed <= ONE_DUR_END)) {
        if (DEBUG) {
          Serial.println();
          debugPrint("ACK: ", startTime, elapsed);
        }
        sTimes[i % 100] = startTime;
        if (elapsed >= ZERO_DUR_START && elapsed <= ZERO_DUR_END) {
          bits[i % 100] = 0;
        }
        if ( elapsed >= ONE_DUR_START && elapsed <= ONE_DUR_END) {
          bits[i % 100] = 1;
        }
        i++;
        if (i == 200) {
          i = 100;
        }

      } else {
        if (DEBUG) {
          Serial.println();
          debugPrint("REJ: ", startTime, elapsed);
        }
      }
      if (signalGap >= SIGNALGAP_DUR_START && signalGap <= SIGNALGAP_DUR_END) {
        if (DEBUG) {
          Serial.println();
          debugPrint("GAP: ", startTime, elapsed);
        }
        analyseSignal(i, bits, sTimes);
      }
    }// fin if (active)
  }// fin premier while(true)
//  }//
}// fin loop

void analyseSignal(int i, int* bits, unsigned long* sTimes)
{
  if (i < 40) {
    return;
  }
  int index = i - 1;
  int signalArr[40];
  int k = 39;
  for (int i = 0; i < 40; i++) {
    signalArr = -1;
  }
  unsigned long startTime = sTimes[index % 100] - 1000L;
  index--;
  int tries = 0;
  while (k >= 0 && tries < 100) {
    tries++;
    unsigned long currTime = sTimes[index % 100];
    int bitVal = bits[(index + 1) % 100 ];

    for (int skip = 0; skip <= 4; skip++) {
      long tDiff = ((long)startTime) - ((long)currTime) - 1000L - skip * 1000L;
      if (tDiff < 0L) {
        tDiff = -tDiff;
      }
      if (tDiff < 20L + 10L * skip) {
        startTime = currTime;
        if (skip > 0) {
          for (int a = 0; a < skip; a++) {
            k--;
          }
        }
        if (k >= 0) {
          signalArr[k] = bitVal;
        }
        k--;
        break;
      }
    }


    index--;
  }
  boolean correctTimeStart = (signalArr[0] == 1);
  boolean parityMins = checkEvenParity(signalArr, 1, 8, 8);
  boolean parityHours = checkEvenParity(signalArr, 9, 15, 15);
  boolean parityDate = checkEvenParity(signalArr, 16, 38, 38);
  if (DEBUG) {
    debugSignal(signalArr, sTimes, bits, i);
  }

  for (int k = 0; k < 40; k++) {
    if (signalArr[k] != -1) {
      signalArr[k] = signalArr[k] * decodeMultipliers[k];
    }
  }

  int dcf_mins = getValue(signalArr, 1, 7);
  int dcf_hours = getValue(signalArr, 9, 14);
  int dcf_day = getValue(signalArr, 16, 21);
  int dcf_month = getValue(signalArr, 25, 29);
  int dcf_year =  getValue(signalArr, 30, 37);


  last_dcf_hours = dcf_hours;
  last_dcf_mins = dcf_mins;
  last_dcf_day = dcf_day;
  last_dcf_month = dcf_month;
  last_dcf_year = dcf_year;
  last_dcf_received = millis();

  if (correctTimeStart && parityMins && parityHours && parityDate) {
    dcfTimeDateReceived(dcf_hours, dcf_mins, dcf_day, dcf_month, dcf_year);
  }
  else if (correctTimeStart && parityMins && parityHours && !parityDate) {
                         // wait for a second
  digitalWrite(LED_BUILTIN, LOW);
    dcfOnlyTimeReceived(dcf_hours, dcf_mins);
    dcfIncompleteTimeDateReceived(dcf_hours, dcf_mins, dcf_day, dcf_month, dcf_year);
  } else if (parityDate) {
    dcfOnlyDateReceived(dcf_day, dcf_month, dcf_year);
    dcfIncompleteTimeDateReceived(dcf_hours, dcf_mins, dcf_day, dcf_month, dcf_year);
  }  else {
    dcfIncompleteTimeDateReceived(dcf_hours, dcf_mins, dcf_day, dcf_month, dcf_year);
  }

}// fin analyseSignal

boolean checkEvenParity(int* arr, int startBit, int endBit, int parityBit)
{
  int sum = 0;
  for (int k = startBit; k <= endBit; k++) {
    if (arr[k] != -1) {
      sum += arr[k];
    } else {
      sum = -1;
      break;
    }
  }
  int parity = arr[parityBit];
  if (sum == -1) {
    return false;
  }
  if (parity == -1) {
    return false;
  }
  if (sum % 2 == 0) {
    return true;
  }
  return false;

} //fin checkEvenParity

void debugPrint(String prefix, unsigned long time, unsigned long elapsed)
{
  Serial.print(prefix);
  Serial.print(time);
  Serial.print(" - ");
  Serial.print(elapsed);
  Serial.println();
} // fin debugPrint

void debugSignal(int* arr, unsigned long* st, int* bt, int i)
{
  Serial.println("RAW Data (2 lines)");
  for (int index = i - 40; index < i; index++) {
    Serial.print(st[index % 100]);
    Serial.print(",");
  }
  Serial.println();
  for (int index = i - 40; index < i; index++) {
    Serial.print(bt[index % 100]);
    Serial.print(",");
  }
  Serial.println();
  Serial.print("SIGNAL: ");
  for (int k = 0; k < 40; k++) {
    if (arr[k] == -1) {
      Serial.print("?");
    } else {
      Serial.print(arr[k]);
    }
    Serial.print(",");
  }
  Serial.println();
}// fin debugSignal

int getValue(int* arr, int startBit, int endBit)
{
  int sum = 0;
  for (int k = startBit; k <= endBit; k++) {
    if (arr[k] != -1) {
      sum += arr[k];
    } else {
      sum = -1;
      break;
    }
  }
  return sum;

}// fin getValue


« Modifié: Décembre 12, 2023, 03:01:39 pm par pentahertz »
IP archivée