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:

Le Forum est maintenant chiffré (préambule https). Bien sûr, des liens externes insérés dans les sujets vont demeurer inchangés. Mais la composition des pages du Forum est désormais sécurisée. Si des problèmes d'affichage surviennent, veillez à vider votre cache pour ce site.

Auteur Sujet: emetteur dcf77 en Europe  (Lu 2172 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