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.

Voir les contributions

Cette section vous permet de consulter les contributions (messages, sujets et fichiers joints) d'un utilisateur. Vous ne pourrez voir que les contributions des zones auxquelles vous avez accès.

Messages - pentahertz

Pages: [1]
1
Discussion Générale d'Électronique / Re : emetteur dcf77 en Europe
« le: décembre 12, 2023, 09:55:28 am »
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



2
bonjour  a tous,
je reviens vers vous pour essayer de modifier une alim de labo dont le plan est en piece jointe
a la place du 24v AC  je souhaite mettre du 12V AC pensez vous que l'alim fonctionnera encore ou faut-il faire des modification pour adapté
je vous met le lien du site ou j'ai trouver des informations : https://www.qsl.net/z33t/dc_0-30v_0-3A_eng.html

3
merci pour le lien

4
merci pour la réponse qui me convient,

aprés test en 3v j'ai mis un mofset IRL3303 et cela fonctionne correctement en 3v
merci beaucoup

Bonjour.

Un petit circuit simple à  base de MOSFET et basé sur le temps de charge d’un condensateur. Ce temps peut être diminué ou augmenté en jouant sur les valeurs du condensateur ou de la résistance.

https://www.elcircuit.com/2017/07/mosfet-timer-circuit-simple-and-easy-to.html

5
Trucs et Astuces d'Électronique / économiseur de batterie
« le: août 06, 2023, 03:59:32 am »
bonjour tout le monde
je cherche a construire un economiseur de batterie ressemblant a celui des multimètres qui s'arrete automatiquement apres un certain temps
l'utilité serais pour un jouet electronique afin de l'arreter automatiquement
je ne veux pas de relais il consomme 200ma
avez vous des shémas ?

6
Discussion Générale d'Électronique / Tachymètre compte tours scooter
« le: novembre 21, 2022, 08:22:00 am »
bonjour,
j'ai une question je cherche a faire un tachymetre sur un scooter 50cc,
j'ai vu des modeles qui fonctionne en faisant 5 tours de fils sur le cable qui va a la bougie
voir photos en pieces jointe
pouvez vous me dire avec ces 5 tours de fils autour du fils de bougie quelle tension il pourrait y avoir
pour que je puisse le tester sans risquer de problème
je compte enregister les RPM sur une carte sd avec un arduino
merci de vos conseil
cordialement

7
 :)
bonjour,
j'ai regardé toutes les vidéos sur les mosfets je n'ai vu aucune vidéo qui proposer un montage avec une tension d'entrée identique a la tension de sortie

je voulez utiliser un mosfet pour remplacer un relais 3.3v
avez vous un montage pour du 3.3v en entrée et sortie avait vous le numéro de modèle du mosfet que je pourrait utiliser ?

j'ai vu des modules su Aliexpress mais je ne connais pas ca consommation a vide
 merci de votre réponse
ps je viens de m'offrir un chauvin arnoux amperemetre 401 et un CA 402 voltmetre et un oscilloscope hameg 303.4 30mhz 2 voix mais pour le moment je visualise les videos avant de m'en servir

8
avez vous un montage qui permet d'alimenter le esp8266 par un port du attiny85 en 3.3v ou il faut mettre un relais ?

9
Discussion Générale d'Électronique / transistors darlington ULN2803A
« le: juillet 30, 2022, 07:05:21 am »
bonjour pensez vous qu'il est possible d'utiliser le circuit  transistors darlington ULN2803A
pour alimenter un esp8266 avec tiny85 en 3.3v
après test le microcontrôleur ne s'allume pas

breadbord  3.3v
                 5.0v       
                 gnd
l'uln2803a est alimenter en 5v
la pin 1 de uln2803 est sur le +3.3v
la pin 18 sort 4.42v
je test entre le +5v et la sortie 16 gnd



10
bonjour
j'ai fabriquer une horloge avec des afficheurs de 5 pouces c'est tres grand
le pb il y a plusieur leds en serie donc la tension et pres de 9.6v
il faut un controleur genre uln 2803

11
bonjour,
j'en ai acheter 2 modeles avec 3 canal et 2 canal jamais eu ce probleme
tu utilise alexa ?

12
bonjour j'ai creer plusieurs horloges
avec 60 leds commander par un Circuit intégré Maxim MAX7219, Controleur 64 Leds, DIP-24, DIY, Arduino, Pi.

maintenant j'ai un écran de led 64x64 

13
Discussion Générale d'Électronique / Re : DEEPSLEEP RESET HARD
« le: juin 16, 2022, 02:01:23 pm »
bonjour papiblue
je vais test ta solution

j'ai essaye avec ltspice et un astable par 2 transistor en supprimant une résistance pour ne pas faire un astable
tu peux me dire ce que tu en pense ?
2 fichiers joints
merci



14
Discussion Générale d'Électronique / Re : DEEPSLEEP RESET HARD
« le: juin 16, 2022, 01:56:02 am »
bonjour a tous
bonjour papyblue
pourrait tu me transmettre le fichier ltspice SVP
je pensais qu'il était possible de faire encore plus simple avec un condensateur ou un inverseur
j'avais penser faire ca avec un microcontroleur ATtiny
qu"en pensez vous ?
papytony

15
Discussion Générale d'Électronique / DEEPSLEEP RESET HARD
« le: juin 15, 2022, 09:18:23 am »
Bonjour,

je cherche un plan electronique pour faire un reset etat bas puis haut depuis un signal haut
je veux pourvoir faire un reset de esp8266 broche RST par un signal externe, le niveau haut declenchera le reset c'est a dire
il y aura un état bas puis un état haut , il restera a l'état haut ensuite.
ceci me permettra de relancer le wemos aprés ESP.deepsleep(0)

Pages: [1]