Skip to main content
Linked shield referenced in question; changed code quoting on enable syntax highlighting.
Source Link
timemage
  • 5.7k
  • 1
  • 15
  • 27

I'm revisiting my Arduino stuff (I want to revive Teleinfo shield to monitor closely my power consumption). I just cannot get the thing to work (Teleinfo ShieldTeleinfo Shield + Uno Wifi).

The code is the following Teleinfo_Arduino_V0_3E.ino (just added some lines writing to serial to follow progress; and modified Serial.beginSerial.begin accordingly and "shortened" to stay within size limits but it's sending wrong characters ate beginning))

/*
              Datalogger Téléinfo 2 compteurs sur Arduino

              Compteur 1: consommation
              Compteur 2: production solaire en tarif BASE

              Juin 2011:
              v0.2  * passage automatique à l'heure d'été
                      correctif erreur abo BBR
                      modification ecriture sur SD (utilisation de teleinfoFile.print à la place s'une variable STRING
                      qui plante l'Arduino avec les abonnements BBR
              v0.2a * ajout mode sans puissance apparente pour ancien compteur et calcul de celle-ci pour les logiciels d'analyse
              v0.2b * pour Arduino 1.0 (mise à jour de la RTC et utilisation de la librairie SD livrée avec la 1.0)
              v0.2c * modif type de variable pour éviter d'avoir 2 enregistrements à la même minute (surtout sur des proc + rapide)
              v0.3  * détection automatique du type d'abonnement sur le compteur 1
              v0.3a * Fonction de mise à l'heure par l'usb (interface série) en 1200 bauds 7 bits parité pair
                      Procédure:
                      1- carte débranchée, enlevez la pile de son support (pour réinitialiser l'horloge)
                      2- enlevez le cavalier du shield téléinfo
                      3- configurer votre logiciel émulateur de terminal (termite,Hyperterminale...) en 1200 bauds 7 bits parité pair
                      4- mettre sous tension la carte.
                      -- Le programme détectera le reset de l'horloge et vous demandera de rentrer l'heure et la date. --

              v0.3b * Correction bug calcul PAP compteur 2, enregistrement journalier compteur 2
              v0.3c * Triphasé sur compteur 2
              v0.3d * correction bug retour ligne sur compteur 2 (entête fichier)
              v0.3e * Correction bug si pas de compteur 2
*/

#include <SD.h>
#include <SPI.h>
#include <Wire.h>
#include <RTClib.h>

const char version_logiciel[6] = "V0.3e";

// #define echo_USB            //envoie toutes les trames téléinfo sur l'USB
#define message_systeme_USB  //envoie des messages sur l'USB (init SD, heure au demarrage, et echo des erreures)

//*****************************************************************************************
byte inByte = 0;  // caractère entrant téléinfo
char buffteleinfo[21] = "";
byte bufflen = 0;
byte mem_sauv_minute = 1;
byte mem_sauv_journee = 1;
byte num_abo = 0;
byte type_mono_tri[2] = { 0, 0 };
uint8_t presence_teleinfo = 0;  // si signal teleinfo présent
byte presence_PAP = 0;          // si PAP présent
boolean cpt2_present = true;    // mémorisation de la présence du compteur 2
boolean compteursluOK = false;  // pour autoriser l'écriture de valeur sur la SD
boolean mem_affichage_cpt2_present = true;

int ReceptionOctet = 0;            // variable de stockage des octets reçus par port série
unsigned int ReceptionNombre = 0;  // variable de calcul du nombre reçu par port série
byte reg_horloge = 1;
boolean mem_reg_horloge = false;
const uint8_t val_max[6] = { 24, 59, 59, 31, 12, 99 };

// declarations Teleinfo
unsigned int papp = 0;  // Puissance apparente, VA

uint8_t IINST[2][3] = { { 0, 0, 0 }, { 0, 0, 0 } };  // Intensité Instantanée Phase 1, A  (intensité efficace instantanée) ou 1 phase en monophasé

unsigned long INDEX1 = 0;  // Index option Tempo - Heures Creuses Jours Bleus, Wh
unsigned long INDEX2 = 0;  // Index option Tempo - Heures Pleines Jours Bleus, Wh
unsigned long INDEX3 = 0;  // Index option Tempo - Heures Creuses Jours Blancs, Wh
unsigned long INDEX4 = 0;  // Index option Tempo - Heures Pleines Jours Blancs, Wh
unsigned long INDEX5 = 0;  // Index option Tempo - Heures Creuses Jours Rouges, Wh
unsigned long INDEX6 = 0;  // Index option Tempo - Heures Pleines Jours Rouges, Wh

// compteur 2 (solaire configuré en tarif BASE par ERDF)
unsigned long cpt2index = 0;     // Index option Base compteur production solaire, Wh
unsigned int cpt2puissance = 0;  // Puissance apparente compteur production solaire, VA

#define debtrame 0x02
#define debligne 0x0A
#define finligne 0x0D

// *************** déclaration carte micro SD ******************
const byte chipSelect = 4;

// *************** déclaration activation compteur 1 ou 2 ******
#define LEC_CPT1 5  // lecture compteur 1
#define LEC_CPT2 6  // lecture compteur 2
//
byte verif_cpt_lu = 0;
//

byte compteur_actif = 1;           // numero du compteur en cours de lecture
byte donnee_ok_cpt[2] = { 0, 0 };  // pour vérifier que les donnees sont bien en memoire avant ecriture dans fichier
byte donnee_ok_cpt_ph[2] = { 0, 0 };

// *************** variables RTC ************************************
byte minute, heure, seconde, jour, mois, jour_semaine;
unsigned int annee;
char date_heure[18];
char mois_jour[7];
byte mem_chg_heure = 0;  //pour pas passer perpetuellement de 3h à 2h du matin le dernier dimanche d'octobre
RTC_DS1307 RTC;

// ************** initialisation *******************************
void setup() {
  // initialisation du port 0-1 lecture Téléinfo
  Serial.begin(1200);
  // parité paire E
  // 7 bits data
  UCSR0C = B00100100;
#ifdef message_systeme_USB
  Serial.print(F("-- Teleinfo USB Arduino "));
  Serial.print(version_logiciel);
  Serial.println(F(" --"));
#endif
  // initialisation des sorties selection compteur
  pinMode(LEC_CPT1, OUTPUT);
  pinMode(LEC_CPT2, OUTPUT);
  digitalWrite(LEC_CPT1, HIGH);
  digitalWrite(LEC_CPT2, LOW);

  // verification de la présence de la microSD et si elle est initialisée:
#ifdef message_systeme_USB
  if (!SD.begin(chipSelect)) {
    Serial.println(F("> Erreur carte, ou carte absente !"));
    return;
  }
  Serial.println(F("> microSD initialisee !"));
#endif

  // initialisation RTC16

  Wire.begin();
  RTC.begin();

  if (!RTC.isrunning()) {
#ifdef message_systeme_USB
    Serial.println(F("RTC non configure !"));
#endif
  }

  DateTime now = RTC.now();  // lecture de l'horloge
  annee = now.year();
  mois = now.month();
  jour = now.day();
  heure = now.hour();
  minute = now.minute();
  jour_semaine = now.dayOfTheWeek();

  format_date_heure();
#ifdef message_systeme_USB
  Serial.println(date_heure);
#endif
}

// ************** boucle principale *******************************

void loop()  // Programme en boucle
{

  if (!(RTC.isrunning()) && (reg_horloge < 7)) {  // si l'horloge n'est pas configurée
    digitalWrite(LEC_CPT1, LOW);

    if (!mem_reg_horloge) {
      switch (reg_horloge) {  // debut de la structure
        case 1:
          Serial.print(F("Entrer Heure: "));
          break;
        case 2:
          Serial.print(F("Entrer Minute: "));
          break;
        case 3:
          Serial.print(F("Entrer Seconde: "));
          break;
        case 4:
          Serial.print(F("Entrer Jour: "));
          break;
        case 5:
          Serial.print(F("Entrer Mois: "));
          break;
        case 6:
          Serial.print(F("Entrer Annee 20xx: "));
          break;
      }
      mem_reg_horloge = true;
    }
    if (Serial.available() > 0) {  // si caractère dans la file d'attente

      Serial.print(F("un nombre a ete recu")); //---- lecture du nombre reçu
      while (Serial.available() > 0) {
        // tant que buffer pas vide pour lire d'une traite tous les caractères reçus
        inByte = Serial.read();         // renvoie le 1er octet présent dans la file attente série (-1 si aucun)
        Serial.println(inByte);
        if (((inByte > 47) && (inByte < 58)) || (inByte == 13)) {
          ReceptionOctet = inByte - 48;  // transforme valeur ASCII en valeur décimale
          if ((ReceptionOctet >= 0) && (ReceptionOctet <= 9)) ReceptionNombre = (ReceptionNombre * 10) + ReceptionOctet;
          // si valeur reçue correspond à un chiffre on calcule nombre
          Serial.print(ReceptionNombre);
          Serial.print(reg_horloge);
        } else
          presence_teleinfo = -1;
      }  // fin while
      if (inByte == 13) {
        if ((ReceptionNombre > val_max[reg_horloge - 1]) || (ReceptionNombre == -1)) {
          Serial.println(F("Erreur horaire"));
          ReceptionNombre = 0;
          mem_reg_horloge = true;
        } else {
          Serial.print("cela bugge");
          switch (reg_horloge) {  // debut de la structure
            case 1:
              heure = ReceptionNombre;
              Serial.print("heure:");
              Serial.println(heure);
            case 2:
              minute = ReceptionNombre;
              break;
            case 3:
              seconde = ReceptionNombre;
              break;
            case 4:
              jour = ReceptionNombre;
              break;
            case 5:
              mois = ReceptionNombre;
              break;
            case 6:
              annee = 2000 + ReceptionNombre;
              break;
          }

          mem_reg_horloge = false;
          ReceptionNombre = 0;
          ++reg_horloge;

          if (reg_horloge > 6) {
            RTCsetTime();
            Serial.println(F("Reglage heure OK - installer le cavalier pour la teleinfo"));
            digitalWrite(LEC_CPT1, HIGH);
          }
        }
      }
    }
  }

  else {

    DateTime now = RTC.now();  // lecture de l'horloge
    minute = now.minute();
    heure = now.hour();
    seconde = now.second();

    if ((heure == 0) && (minute == 0) && (seconde == 0)) {
      annee = now.year();
      mois = now.month();
      jour = now.day();
      jour_semaine = now.dayOfTheWeek();
    }

    // passage à l'heure d'été +1 heure
    // la lib RTC a une fonction: dayOfWeek qui donne le jour de la semaine (la DS1307 se charge de tout !)
    // réponse: 0 -> dimanche, 1 -> lundi etc...
    //
    if ((heure == 2) && (minute == 0) && (seconde == 0) && (jour_semaine == 0) && (mois == 3) && (jour > 24)) {
      heure = 3;
      RTCsetTime();
    }

    // passage à l'heure d'hiver -1 heure
    if ((heure == 3) && (minute == 0) && (seconde == 0) && (jour_semaine == 0) && (mois == 10) && (jour > 24) && (mem_chg_heure == 0)) {
      heure = 2;
      RTCsetTime();
      mem_chg_heure = 1;
    }

    if ((heure == 23) && (minute == 59) && (seconde == 10))  // pour être sur de pas tomber pendant l'enregistrement toutes les minutes
    {
      if ((mem_sauv_journee == 0) && (compteursluOK))  // un seul enregistrement par jour !
      {
        fichier_annee();
        mem_sauv_journee = 1;
        mem_chg_heure = 0;
      }
    } else
      mem_sauv_journee = 0;

    if (seconde == 1) {
      if ((mem_sauv_minute == 0) && (compteursluOK))  // un seul enregistrement par minute !
      {
        enregistre();
        mem_sauv_minute = 1;
      }
    } else
      mem_sauv_minute = 0;

#ifdef message_systeme_USB
    if ((donnee_ok_cpt[1] == B00000111) && (mem_affichage_cpt2_present)) {
      if (mem_affichage_cpt2_present) Serial.println(F("- Compteur 2 detecte"));
      mem_affichage_cpt2_present = false;
    } else if ((!cpt2_present) && (mem_affichage_cpt2_present)) {
      if (mem_affichage_cpt2_present) Serial.println(F("- Compteur 2 non present !"));
      mem_affichage_cpt2_present = false;
    }
#endif

    if ((donnee_ok_cpt[0] == verif_cpt_lu) and (cpt2_present)) {
      if ((type_mono_tri[0] == 1) && (donnee_ok_cpt_ph[0] == B10000001)) bascule_compteur();
      else if ((type_mono_tri[0] == 3) && (donnee_ok_cpt_ph[0] == B10000111))
        bascule_compteur();
    } else if ((donnee_ok_cpt[1] == B00000001) or ((compteur_actif == 2) and (!cpt2_present))) {
      if ((type_mono_tri[1] == 1) && (donnee_ok_cpt_ph[1] == B10000001)) bascule_compteur();
      else if ((type_mono_tri[1] == 3) && (donnee_ok_cpt_ph[1] == B10000111))
        bascule_compteur();
      compteursluOK = true;
    }

    if (compteur_actif == 2) {
      if (presence_teleinfo > 200) {
        cpt2_present = false;
        compteursluOK = true;
        bascule_compteur();
      } else
        cpt2_present = true;
    }

    read_teleinfo();
  }
}

///////////////////////////////////////////////////////////////////
// Calcul Checksum teleinfo
///////////////////////////////////////////////////////////////////
char chksum(char *buff, uint8_t len) {
  int i;
  char sum = 0;
  for (i = 1; i < (len - 2); i++) sum = sum + buff[i];
  sum = (sum & 0x3F) + 0x20;
  return (sum);
}

///////////////////////////////////////////////////////////////////
// mise en forme Date & heure pour affichage ou enregistrement
///////////////////////////////////////////////////////////////////
void format_mois_jour() {
  sprintf(mois_jour, "%02d,%02d,", mois, jour);
}

// Convert normal decimal numbers to binary coded decimal
static uint8_t bin2bcd(uint8_t val) {
  return val + 6 * (val / 10);
}

///////////////////////////////////////////////////////////////////
// mise à l'heure de la RTC (DS1307)
///////////////////////////////////////////////////////////////////
void RTCsetTime(void) {
  Wire.beginTransmission(104);  // 104 is DS1307 device address (0x68)
  Wire.write(bin2bcd(0));       // start at register 0

  Wire.write(bin2bcd(seconde));       //Send seconds as BCD
  Wire.write(bin2bcd(minute));        //Send minutes as BCD
  Wire.write(bin2bcd(heure));         //Send hours as BCD
  Wire.write(bin2bcd(jour_semaine));  // dow
  Wire.write(bin2bcd(jour));          //Send day as BCD
  Wire.write(bin2bcd(mois));          //Send month as BCD
  Wire.write(bin2bcd(annee % 1000));  //Send year as BCD

  Wire.endTransmission();
}
/*
              Datalogger Téléinfo 2 compteurs sur Arduino

              Compteur 1: consommation
              Compteur 2: production solaire en tarif BASE

              Juin 2011:
              v0.2  * passage automatique à l'heure d'été
                      correctif erreur abo BBR
                      modification ecriture sur SD (utilisation de teleinfoFile.print à la place s'une variable STRING
                      qui plante l'Arduino avec les abonnements BBR
              v0.2a * ajout mode sans puissance apparente pour ancien compteur et calcul de celle-ci pour les logiciels d'analyse
              v0.2b * pour Arduino 1.0 (mise à jour de la RTC et utilisation de la librairie SD livrée avec la 1.0)
              v0.2c * modif type de variable pour éviter d'avoir 2 enregistrements à la même minute (surtout sur des proc + rapide)
              v0.3  * détection automatique du type d'abonnement sur le compteur 1
              v0.3a * Fonction de mise à l'heure par l'usb (interface série) en 1200 bauds 7 bits parité pair
                      Procédure:
                      1- carte débranchée, enlevez la pile de son support (pour réinitialiser l'horloge)
                      2- enlevez le cavalier du shield téléinfo
                      3- configurer votre logiciel émulateur de terminal (termite,Hyperterminale...) en 1200 bauds 7 bits parité pair
                      4- mettre sous tension la carte.
                      -- Le programme détectera le reset de l'horloge et vous demandera de rentrer l'heure et la date. --

              v0.3b * Correction bug calcul PAP compteur 2, enregistrement journalier compteur 2
              v0.3c * Triphasé sur compteur 2
              v0.3d * correction bug retour ligne sur compteur 2 (entête fichier)
              v0.3e * Correction bug si pas de compteur 2
*/

#include <SD.h>
#include <SPI.h>
#include <Wire.h>
#include <RTClib.h>

const char version_logiciel[6] = "V0.3e";

// #define echo_USB            //envoie toutes les trames téléinfo sur l'USB
#define message_systeme_USB  //envoie des messages sur l'USB (init SD, heure au demarrage, et echo des erreures)

//*****************************************************************************************
byte inByte = 0;  // caractère entrant téléinfo
char buffteleinfo[21] = "";
byte bufflen = 0;
byte mem_sauv_minute = 1;
byte mem_sauv_journee = 1;
byte num_abo = 0;
byte type_mono_tri[2] = { 0, 0 };
uint8_t presence_teleinfo = 0;  // si signal teleinfo présent
byte presence_PAP = 0;          // si PAP présent
boolean cpt2_present = true;    // mémorisation de la présence du compteur 2
boolean compteursluOK = false;  // pour autoriser l'écriture de valeur sur la SD
boolean mem_affichage_cpt2_present = true;

int ReceptionOctet = 0;            // variable de stockage des octets reçus par port série
unsigned int ReceptionNombre = 0;  // variable de calcul du nombre reçu par port série
byte reg_horloge = 1;
boolean mem_reg_horloge = false;
const uint8_t val_max[6] = { 24, 59, 59, 31, 12, 99 };

// declarations Teleinfo
unsigned int papp = 0;  // Puissance apparente, VA

uint8_t IINST[2][3] = { { 0, 0, 0 }, { 0, 0, 0 } };  // Intensité Instantanée Phase 1, A  (intensité efficace instantanée) ou 1 phase en monophasé

unsigned long INDEX1 = 0;  // Index option Tempo - Heures Creuses Jours Bleus, Wh
unsigned long INDEX2 = 0;  // Index option Tempo - Heures Pleines Jours Bleus, Wh
unsigned long INDEX3 = 0;  // Index option Tempo - Heures Creuses Jours Blancs, Wh
unsigned long INDEX4 = 0;  // Index option Tempo - Heures Pleines Jours Blancs, Wh
unsigned long INDEX5 = 0;  // Index option Tempo - Heures Creuses Jours Rouges, Wh
unsigned long INDEX6 = 0;  // Index option Tempo - Heures Pleines Jours Rouges, Wh

// compteur 2 (solaire configuré en tarif BASE par ERDF)
unsigned long cpt2index = 0;     // Index option Base compteur production solaire, Wh
unsigned int cpt2puissance = 0;  // Puissance apparente compteur production solaire, VA

#define debtrame 0x02
#define debligne 0x0A
#define finligne 0x0D

// *************** déclaration carte micro SD ******************
const byte chipSelect = 4;

// *************** déclaration activation compteur 1 ou 2 ******
#define LEC_CPT1 5  // lecture compteur 1
#define LEC_CPT2 6  // lecture compteur 2
//
byte verif_cpt_lu = 0;
//

byte compteur_actif = 1;           // numero du compteur en cours de lecture
byte donnee_ok_cpt[2] = { 0, 0 };  // pour vérifier que les donnees sont bien en memoire avant ecriture dans fichier
byte donnee_ok_cpt_ph[2] = { 0, 0 };

// *************** variables RTC ************************************
byte minute, heure, seconde, jour, mois, jour_semaine;
unsigned int annee;
char date_heure[18];
char mois_jour[7];
byte mem_chg_heure = 0;  //pour pas passer perpetuellement de 3h à 2h du matin le dernier dimanche d'octobre
RTC_DS1307 RTC;

// ************** initialisation *******************************
void setup() {
  // initialisation du port 0-1 lecture Téléinfo
  Serial.begin(1200);
  // parité paire E
  // 7 bits data
  UCSR0C = B00100100;
#ifdef message_systeme_USB
  Serial.print(F("-- Teleinfo USB Arduino "));
  Serial.print(version_logiciel);
  Serial.println(F(" --"));
#endif
  // initialisation des sorties selection compteur
  pinMode(LEC_CPT1, OUTPUT);
  pinMode(LEC_CPT2, OUTPUT);
  digitalWrite(LEC_CPT1, HIGH);
  digitalWrite(LEC_CPT2, LOW);

  // verification de la présence de la microSD et si elle est initialisée:
#ifdef message_systeme_USB
  if (!SD.begin(chipSelect)) {
    Serial.println(F("> Erreur carte, ou carte absente !"));
    return;
  }
  Serial.println(F("> microSD initialisee !"));
#endif

  // initialisation RTC16

  Wire.begin();
  RTC.begin();

  if (!RTC.isrunning()) {
#ifdef message_systeme_USB
    Serial.println(F("RTC non configure !"));
#endif
  }

  DateTime now = RTC.now();  // lecture de l'horloge
  annee = now.year();
  mois = now.month();
  jour = now.day();
  heure = now.hour();
  minute = now.minute();
  jour_semaine = now.dayOfTheWeek();

  format_date_heure();
#ifdef message_systeme_USB
  Serial.println(date_heure);
#endif
}

// ************** boucle principale *******************************

void loop()  // Programme en boucle
{

  if (!(RTC.isrunning()) && (reg_horloge < 7)) {  // si l'horloge n'est pas configurée
    digitalWrite(LEC_CPT1, LOW);

    if (!mem_reg_horloge) {
      switch (reg_horloge) {  // debut de la structure
        case 1:
          Serial.print(F("Entrer Heure: "));
          break;
        case 2:
          Serial.print(F("Entrer Minute: "));
          break;
        case 3:
          Serial.print(F("Entrer Seconde: "));
          break;
        case 4:
          Serial.print(F("Entrer Jour: "));
          break;
        case 5:
          Serial.print(F("Entrer Mois: "));
          break;
        case 6:
          Serial.print(F("Entrer Annee 20xx: "));
          break;
      }
      mem_reg_horloge = true;
    }
    if (Serial.available() > 0) {  // si caractère dans la file d'attente

      Serial.print(F("un nombre a ete recu")); //---- lecture du nombre reçu
      while (Serial.available() > 0) {
        // tant que buffer pas vide pour lire d'une traite tous les caractères reçus
        inByte = Serial.read();         // renvoie le 1er octet présent dans la file attente série (-1 si aucun)
        Serial.println(inByte);
        if (((inByte > 47) && (inByte < 58)) || (inByte == 13)) {
          ReceptionOctet = inByte - 48;  // transforme valeur ASCII en valeur décimale
          if ((ReceptionOctet >= 0) && (ReceptionOctet <= 9)) ReceptionNombre = (ReceptionNombre * 10) + ReceptionOctet;
          // si valeur reçue correspond à un chiffre on calcule nombre
          Serial.print(ReceptionNombre);
          Serial.print(reg_horloge);
        } else
          presence_teleinfo = -1;
      }  // fin while
      if (inByte == 13) {
        if ((ReceptionNombre > val_max[reg_horloge - 1]) || (ReceptionNombre == -1)) {
          Serial.println(F("Erreur horaire"));
          ReceptionNombre = 0;
          mem_reg_horloge = true;
        } else {
          Serial.print("cela bugge");
          switch (reg_horloge) {  // debut de la structure
            case 1:
              heure = ReceptionNombre;
              Serial.print("heure:");
              Serial.println(heure);
            case 2:
              minute = ReceptionNombre;
              break;
            case 3:
              seconde = ReceptionNombre;
              break;
            case 4:
              jour = ReceptionNombre;
              break;
            case 5:
              mois = ReceptionNombre;
              break;
            case 6:
              annee = 2000 + ReceptionNombre;
              break;
          }

          mem_reg_horloge = false;
          ReceptionNombre = 0;
          ++reg_horloge;

          if (reg_horloge > 6) {
            RTCsetTime();
            Serial.println(F("Reglage heure OK - installer le cavalier pour la teleinfo"));
            digitalWrite(LEC_CPT1, HIGH);
          }
        }
      }
    }
  }

  else {

    DateTime now = RTC.now();  // lecture de l'horloge
    minute = now.minute();
    heure = now.hour();
    seconde = now.second();

    if ((heure == 0) && (minute == 0) && (seconde == 0)) {
      annee = now.year();
      mois = now.month();
      jour = now.day();
      jour_semaine = now.dayOfTheWeek();
    }

    // passage à l'heure d'été +1 heure
    // la lib RTC a une fonction: dayOfWeek qui donne le jour de la semaine (la DS1307 se charge de tout !)
    // réponse: 0 -> dimanche, 1 -> lundi etc...
    //
    if ((heure == 2) && (minute == 0) && (seconde == 0) && (jour_semaine == 0) && (mois == 3) && (jour > 24)) {
      heure = 3;
      RTCsetTime();
    }

    // passage à l'heure d'hiver -1 heure
    if ((heure == 3) && (minute == 0) && (seconde == 0) && (jour_semaine == 0) && (mois == 10) && (jour > 24) && (mem_chg_heure == 0)) {
      heure = 2;
      RTCsetTime();
      mem_chg_heure = 1;
    }

    if ((heure == 23) && (minute == 59) && (seconde == 10))  // pour être sur de pas tomber pendant l'enregistrement toutes les minutes
    {
      if ((mem_sauv_journee == 0) && (compteursluOK))  // un seul enregistrement par jour !
      {
        fichier_annee();
        mem_sauv_journee = 1;
        mem_chg_heure = 0;
      }
    } else
      mem_sauv_journee = 0;

    if (seconde == 1) {
      if ((mem_sauv_minute == 0) && (compteursluOK))  // un seul enregistrement par minute !
      {
        enregistre();
        mem_sauv_minute = 1;
      }
    } else
      mem_sauv_minute = 0;

#ifdef message_systeme_USB
    if ((donnee_ok_cpt[1] == B00000111) && (mem_affichage_cpt2_present)) {
      if (mem_affichage_cpt2_present) Serial.println(F("- Compteur 2 detecte"));
      mem_affichage_cpt2_present = false;
    } else if ((!cpt2_present) && (mem_affichage_cpt2_present)) {
      if (mem_affichage_cpt2_present) Serial.println(F("- Compteur 2 non present !"));
      mem_affichage_cpt2_present = false;
    }
#endif

    if ((donnee_ok_cpt[0] == verif_cpt_lu) and (cpt2_present)) {
      if ((type_mono_tri[0] == 1) && (donnee_ok_cpt_ph[0] == B10000001)) bascule_compteur();
      else if ((type_mono_tri[0] == 3) && (donnee_ok_cpt_ph[0] == B10000111))
        bascule_compteur();
    } else if ((donnee_ok_cpt[1] == B00000001) or ((compteur_actif == 2) and (!cpt2_present))) {
      if ((type_mono_tri[1] == 1) && (donnee_ok_cpt_ph[1] == B10000001)) bascule_compteur();
      else if ((type_mono_tri[1] == 3) && (donnee_ok_cpt_ph[1] == B10000111))
        bascule_compteur();
      compteursluOK = true;
    }

    if (compteur_actif == 2) {
      if (presence_teleinfo > 200) {
        cpt2_present = false;
        compteursluOK = true;
        bascule_compteur();
      } else
        cpt2_present = true;
    }

    read_teleinfo();
  }
}

///////////////////////////////////////////////////////////////////
// Calcul Checksum teleinfo
///////////////////////////////////////////////////////////////////
char chksum(char *buff, uint8_t len) {
  int i;
  char sum = 0;
  for (i = 1; i < (len - 2); i++) sum = sum + buff[i];
  sum = (sum & 0x3F) + 0x20;
  return (sum);
}

///////////////////////////////////////////////////////////////////
// mise en forme Date & heure pour affichage ou enregistrement
///////////////////////////////////////////////////////////////////
void format_mois_jour() {
  sprintf(mois_jour, "%02d,%02d,", mois, jour);
}

// Convert normal decimal numbers to binary coded decimal
static uint8_t bin2bcd(uint8_t val) {
  return val + 6 * (val / 10);
}

///////////////////////////////////////////////////////////////////
// mise à l'heure de la RTC (DS1307)
///////////////////////////////////////////////////////////////////
void RTCsetTime(void) {
  Wire.beginTransmission(104);  // 104 is DS1307 device address (0x68)
  Wire.write(bin2bcd(0));       // start at register 0

  Wire.write(bin2bcd(seconde));       //Send seconds as BCD
  Wire.write(bin2bcd(minute));        //Send minutes as BCD
  Wire.write(bin2bcd(heure));         //Send hours as BCD
  Wire.write(bin2bcd(jour_semaine));  // dow
  Wire.write(bin2bcd(jour));          //Send day as BCD
  Wire.write(bin2bcd(mois));          //Send month as BCD
  Wire.write(bin2bcd(annee % 1000));  //Send year as BCD

  Wire.endTransmission();
}

enter image description hereExample output on Serial Monitor

I'm revisiting my Arduino stuff (I want to revive Teleinfo shield to monitor closely my power consumption). I just cannot get the thing to work (Teleinfo Shield + Uno Wifi).

The code is the following Teleinfo_Arduino_V0_3E.ino (just added some lines writing to serial to follow progress; and modified Serial.begin accordingly and "shortened" to stay within size limits but it's sending wrong characters ate beginning))

/*
              Datalogger Téléinfo 2 compteurs sur Arduino

              Compteur 1: consommation
              Compteur 2: production solaire en tarif BASE

              Juin 2011:
              v0.2  * passage automatique à l'heure d'été
                      correctif erreur abo BBR
                      modification ecriture sur SD (utilisation de teleinfoFile.print à la place s'une variable STRING
                      qui plante l'Arduino avec les abonnements BBR
              v0.2a * ajout mode sans puissance apparente pour ancien compteur et calcul de celle-ci pour les logiciels d'analyse
              v0.2b * pour Arduino 1.0 (mise à jour de la RTC et utilisation de la librairie SD livrée avec la 1.0)
              v0.2c * modif type de variable pour éviter d'avoir 2 enregistrements à la même minute (surtout sur des proc + rapide)
              v0.3  * détection automatique du type d'abonnement sur le compteur 1
              v0.3a * Fonction de mise à l'heure par l'usb (interface série) en 1200 bauds 7 bits parité pair
                      Procédure:
                      1- carte débranchée, enlevez la pile de son support (pour réinitialiser l'horloge)
                      2- enlevez le cavalier du shield téléinfo
                      3- configurer votre logiciel émulateur de terminal (termite,Hyperterminale...) en 1200 bauds 7 bits parité pair
                      4- mettre sous tension la carte.
                      -- Le programme détectera le reset de l'horloge et vous demandera de rentrer l'heure et la date. --

              v0.3b * Correction bug calcul PAP compteur 2, enregistrement journalier compteur 2
              v0.3c * Triphasé sur compteur 2
              v0.3d * correction bug retour ligne sur compteur 2 (entête fichier)
              v0.3e * Correction bug si pas de compteur 2
*/

#include <SD.h>
#include <SPI.h>
#include <Wire.h>
#include <RTClib.h>

const char version_logiciel[6] = "V0.3e";

// #define echo_USB            //envoie toutes les trames téléinfo sur l'USB
#define message_systeme_USB  //envoie des messages sur l'USB (init SD, heure au demarrage, et echo des erreures)

//*****************************************************************************************
byte inByte = 0;  // caractère entrant téléinfo
char buffteleinfo[21] = "";
byte bufflen = 0;
byte mem_sauv_minute = 1;
byte mem_sauv_journee = 1;
byte num_abo = 0;
byte type_mono_tri[2] = { 0, 0 };
uint8_t presence_teleinfo = 0;  // si signal teleinfo présent
byte presence_PAP = 0;          // si PAP présent
boolean cpt2_present = true;    // mémorisation de la présence du compteur 2
boolean compteursluOK = false;  // pour autoriser l'écriture de valeur sur la SD
boolean mem_affichage_cpt2_present = true;

int ReceptionOctet = 0;            // variable de stockage des octets reçus par port série
unsigned int ReceptionNombre = 0;  // variable de calcul du nombre reçu par port série
byte reg_horloge = 1;
boolean mem_reg_horloge = false;
const uint8_t val_max[6] = { 24, 59, 59, 31, 12, 99 };

// declarations Teleinfo
unsigned int papp = 0;  // Puissance apparente, VA

uint8_t IINST[2][3] = { { 0, 0, 0 }, { 0, 0, 0 } };  // Intensité Instantanée Phase 1, A  (intensité efficace instantanée) ou 1 phase en monophasé

unsigned long INDEX1 = 0;  // Index option Tempo - Heures Creuses Jours Bleus, Wh
unsigned long INDEX2 = 0;  // Index option Tempo - Heures Pleines Jours Bleus, Wh
unsigned long INDEX3 = 0;  // Index option Tempo - Heures Creuses Jours Blancs, Wh
unsigned long INDEX4 = 0;  // Index option Tempo - Heures Pleines Jours Blancs, Wh
unsigned long INDEX5 = 0;  // Index option Tempo - Heures Creuses Jours Rouges, Wh
unsigned long INDEX6 = 0;  // Index option Tempo - Heures Pleines Jours Rouges, Wh

// compteur 2 (solaire configuré en tarif BASE par ERDF)
unsigned long cpt2index = 0;     // Index option Base compteur production solaire, Wh
unsigned int cpt2puissance = 0;  // Puissance apparente compteur production solaire, VA

#define debtrame 0x02
#define debligne 0x0A
#define finligne 0x0D

// *************** déclaration carte micro SD ******************
const byte chipSelect = 4;

// *************** déclaration activation compteur 1 ou 2 ******
#define LEC_CPT1 5  // lecture compteur 1
#define LEC_CPT2 6  // lecture compteur 2
//
byte verif_cpt_lu = 0;
//

byte compteur_actif = 1;           // numero du compteur en cours de lecture
byte donnee_ok_cpt[2] = { 0, 0 };  // pour vérifier que les donnees sont bien en memoire avant ecriture dans fichier
byte donnee_ok_cpt_ph[2] = { 0, 0 };

// *************** variables RTC ************************************
byte minute, heure, seconde, jour, mois, jour_semaine;
unsigned int annee;
char date_heure[18];
char mois_jour[7];
byte mem_chg_heure = 0;  //pour pas passer perpetuellement de 3h à 2h du matin le dernier dimanche d'octobre
RTC_DS1307 RTC;

// ************** initialisation *******************************
void setup() {
  // initialisation du port 0-1 lecture Téléinfo
  Serial.begin(1200);
  // parité paire E
  // 7 bits data
  UCSR0C = B00100100;
#ifdef message_systeme_USB
  Serial.print(F("-- Teleinfo USB Arduino "));
  Serial.print(version_logiciel);
  Serial.println(F(" --"));
#endif
  // initialisation des sorties selection compteur
  pinMode(LEC_CPT1, OUTPUT);
  pinMode(LEC_CPT2, OUTPUT);
  digitalWrite(LEC_CPT1, HIGH);
  digitalWrite(LEC_CPT2, LOW);

  // verification de la présence de la microSD et si elle est initialisée:
#ifdef message_systeme_USB
  if (!SD.begin(chipSelect)) {
    Serial.println(F("> Erreur carte, ou carte absente !"));
    return;
  }
  Serial.println(F("> microSD initialisee !"));
#endif

  // initialisation RTC16

  Wire.begin();
  RTC.begin();

  if (!RTC.isrunning()) {
#ifdef message_systeme_USB
    Serial.println(F("RTC non configure !"));
#endif
  }

  DateTime now = RTC.now();  // lecture de l'horloge
  annee = now.year();
  mois = now.month();
  jour = now.day();
  heure = now.hour();
  minute = now.minute();
  jour_semaine = now.dayOfTheWeek();

  format_date_heure();
#ifdef message_systeme_USB
  Serial.println(date_heure);
#endif
}

// ************** boucle principale *******************************

void loop()  // Programme en boucle
{

  if (!(RTC.isrunning()) && (reg_horloge < 7)) {  // si l'horloge n'est pas configurée
    digitalWrite(LEC_CPT1, LOW);

    if (!mem_reg_horloge) {
      switch (reg_horloge) {  // debut de la structure
        case 1:
          Serial.print(F("Entrer Heure: "));
          break;
        case 2:
          Serial.print(F("Entrer Minute: "));
          break;
        case 3:
          Serial.print(F("Entrer Seconde: "));
          break;
        case 4:
          Serial.print(F("Entrer Jour: "));
          break;
        case 5:
          Serial.print(F("Entrer Mois: "));
          break;
        case 6:
          Serial.print(F("Entrer Annee 20xx: "));
          break;
      }
      mem_reg_horloge = true;
    }
    if (Serial.available() > 0) {  // si caractère dans la file d'attente

      Serial.print(F("un nombre a ete recu")); //---- lecture du nombre reçu
      while (Serial.available() > 0) {
        // tant que buffer pas vide pour lire d'une traite tous les caractères reçus
        inByte = Serial.read();         // renvoie le 1er octet présent dans la file attente série (-1 si aucun)
        Serial.println(inByte);
        if (((inByte > 47) && (inByte < 58)) || (inByte == 13)) {
          ReceptionOctet = inByte - 48;  // transforme valeur ASCII en valeur décimale
          if ((ReceptionOctet >= 0) && (ReceptionOctet <= 9)) ReceptionNombre = (ReceptionNombre * 10) + ReceptionOctet;
          // si valeur reçue correspond à un chiffre on calcule nombre
          Serial.print(ReceptionNombre);
          Serial.print(reg_horloge);
        } else
          presence_teleinfo = -1;
      }  // fin while
      if (inByte == 13) {
        if ((ReceptionNombre > val_max[reg_horloge - 1]) || (ReceptionNombre == -1)) {
          Serial.println(F("Erreur horaire"));
          ReceptionNombre = 0;
          mem_reg_horloge = true;
        } else {
          Serial.print("cela bugge");
          switch (reg_horloge) {  // debut de la structure
            case 1:
              heure = ReceptionNombre;
              Serial.print("heure:");
              Serial.println(heure);
            case 2:
              minute = ReceptionNombre;
              break;
            case 3:
              seconde = ReceptionNombre;
              break;
            case 4:
              jour = ReceptionNombre;
              break;
            case 5:
              mois = ReceptionNombre;
              break;
            case 6:
              annee = 2000 + ReceptionNombre;
              break;
          }

          mem_reg_horloge = false;
          ReceptionNombre = 0;
          ++reg_horloge;

          if (reg_horloge > 6) {
            RTCsetTime();
            Serial.println(F("Reglage heure OK - installer le cavalier pour la teleinfo"));
            digitalWrite(LEC_CPT1, HIGH);
          }
        }
      }
    }
  }

  else {

    DateTime now = RTC.now();  // lecture de l'horloge
    minute = now.minute();
    heure = now.hour();
    seconde = now.second();

    if ((heure == 0) && (minute == 0) && (seconde == 0)) {
      annee = now.year();
      mois = now.month();
      jour = now.day();
      jour_semaine = now.dayOfTheWeek();
    }

    // passage à l'heure d'été +1 heure
    // la lib RTC a une fonction: dayOfWeek qui donne le jour de la semaine (la DS1307 se charge de tout !)
    // réponse: 0 -> dimanche, 1 -> lundi etc...
    //
    if ((heure == 2) && (minute == 0) && (seconde == 0) && (jour_semaine == 0) && (mois == 3) && (jour > 24)) {
      heure = 3;
      RTCsetTime();
    }

    // passage à l'heure d'hiver -1 heure
    if ((heure == 3) && (minute == 0) && (seconde == 0) && (jour_semaine == 0) && (mois == 10) && (jour > 24) && (mem_chg_heure == 0)) {
      heure = 2;
      RTCsetTime();
      mem_chg_heure = 1;
    }

    if ((heure == 23) && (minute == 59) && (seconde == 10))  // pour être sur de pas tomber pendant l'enregistrement toutes les minutes
    {
      if ((mem_sauv_journee == 0) && (compteursluOK))  // un seul enregistrement par jour !
      {
        fichier_annee();
        mem_sauv_journee = 1;
        mem_chg_heure = 0;
      }
    } else
      mem_sauv_journee = 0;

    if (seconde == 1) {
      if ((mem_sauv_minute == 0) && (compteursluOK))  // un seul enregistrement par minute !
      {
        enregistre();
        mem_sauv_minute = 1;
      }
    } else
      mem_sauv_minute = 0;

#ifdef message_systeme_USB
    if ((donnee_ok_cpt[1] == B00000111) && (mem_affichage_cpt2_present)) {
      if (mem_affichage_cpt2_present) Serial.println(F("- Compteur 2 detecte"));
      mem_affichage_cpt2_present = false;
    } else if ((!cpt2_present) && (mem_affichage_cpt2_present)) {
      if (mem_affichage_cpt2_present) Serial.println(F("- Compteur 2 non present !"));
      mem_affichage_cpt2_present = false;
    }
#endif

    if ((donnee_ok_cpt[0] == verif_cpt_lu) and (cpt2_present)) {
      if ((type_mono_tri[0] == 1) && (donnee_ok_cpt_ph[0] == B10000001)) bascule_compteur();
      else if ((type_mono_tri[0] == 3) && (donnee_ok_cpt_ph[0] == B10000111))
        bascule_compteur();
    } else if ((donnee_ok_cpt[1] == B00000001) or ((compteur_actif == 2) and (!cpt2_present))) {
      if ((type_mono_tri[1] == 1) && (donnee_ok_cpt_ph[1] == B10000001)) bascule_compteur();
      else if ((type_mono_tri[1] == 3) && (donnee_ok_cpt_ph[1] == B10000111))
        bascule_compteur();
      compteursluOK = true;
    }

    if (compteur_actif == 2) {
      if (presence_teleinfo > 200) {
        cpt2_present = false;
        compteursluOK = true;
        bascule_compteur();
      } else
        cpt2_present = true;
    }

    read_teleinfo();
  }
}

///////////////////////////////////////////////////////////////////
// Calcul Checksum teleinfo
///////////////////////////////////////////////////////////////////
char chksum(char *buff, uint8_t len) {
  int i;
  char sum = 0;
  for (i = 1; i < (len - 2); i++) sum = sum + buff[i];
  sum = (sum & 0x3F) + 0x20;
  return (sum);
}

///////////////////////////////////////////////////////////////////
// mise en forme Date & heure pour affichage ou enregistrement
///////////////////////////////////////////////////////////////////
void format_mois_jour() {
  sprintf(mois_jour, "%02d,%02d,", mois, jour);
}

// Convert normal decimal numbers to binary coded decimal
static uint8_t bin2bcd(uint8_t val) {
  return val + 6 * (val / 10);
}

///////////////////////////////////////////////////////////////////
// mise à l'heure de la RTC (DS1307)
///////////////////////////////////////////////////////////////////
void RTCsetTime(void) {
  Wire.beginTransmission(104);  // 104 is DS1307 device address (0x68)
  Wire.write(bin2bcd(0));       // start at register 0

  Wire.write(bin2bcd(seconde));       //Send seconds as BCD
  Wire.write(bin2bcd(minute));        //Send minutes as BCD
  Wire.write(bin2bcd(heure));         //Send hours as BCD
  Wire.write(bin2bcd(jour_semaine));  // dow
  Wire.write(bin2bcd(jour));          //Send day as BCD
  Wire.write(bin2bcd(mois));          //Send month as BCD
  Wire.write(bin2bcd(annee % 1000));  //Send year as BCD

  Wire.endTransmission();
}

enter image description here

I'm revisiting my Arduino stuff (I want to revive Teleinfo shield to monitor closely my power consumption). I just cannot get the thing to work (Teleinfo Shield + Uno Wifi).

The code is the following Teleinfo_Arduino_V0_3E.ino (just added some lines writing to serial to follow progress; and modified Serial.begin accordingly and "shortened" to stay within size limits but it's sending wrong characters ate beginning))

/*
              Datalogger Téléinfo 2 compteurs sur Arduino

              Compteur 1: consommation
              Compteur 2: production solaire en tarif BASE

              Juin 2011:
              v0.2  * passage automatique à l'heure d'été
                      correctif erreur abo BBR
                      modification ecriture sur SD (utilisation de teleinfoFile.print à la place s'une variable STRING
                      qui plante l'Arduino avec les abonnements BBR
              v0.2a * ajout mode sans puissance apparente pour ancien compteur et calcul de celle-ci pour les logiciels d'analyse
              v0.2b * pour Arduino 1.0 (mise à jour de la RTC et utilisation de la librairie SD livrée avec la 1.0)
              v0.2c * modif type de variable pour éviter d'avoir 2 enregistrements à la même minute (surtout sur des proc + rapide)
              v0.3  * détection automatique du type d'abonnement sur le compteur 1
              v0.3a * Fonction de mise à l'heure par l'usb (interface série) en 1200 bauds 7 bits parité pair
                      Procédure:
                      1- carte débranchée, enlevez la pile de son support (pour réinitialiser l'horloge)
                      2- enlevez le cavalier du shield téléinfo
                      3- configurer votre logiciel émulateur de terminal (termite,Hyperterminale...) en 1200 bauds 7 bits parité pair
                      4- mettre sous tension la carte.
                      -- Le programme détectera le reset de l'horloge et vous demandera de rentrer l'heure et la date. --

              v0.3b * Correction bug calcul PAP compteur 2, enregistrement journalier compteur 2
              v0.3c * Triphasé sur compteur 2
              v0.3d * correction bug retour ligne sur compteur 2 (entête fichier)
              v0.3e * Correction bug si pas de compteur 2
*/

#include <SD.h>
#include <SPI.h>
#include <Wire.h>
#include <RTClib.h>

const char version_logiciel[6] = "V0.3e";

// #define echo_USB            //envoie toutes les trames téléinfo sur l'USB
#define message_systeme_USB  //envoie des messages sur l'USB (init SD, heure au demarrage, et echo des erreures)

//*****************************************************************************************
byte inByte = 0;  // caractère entrant téléinfo
char buffteleinfo[21] = "";
byte bufflen = 0;
byte mem_sauv_minute = 1;
byte mem_sauv_journee = 1;
byte num_abo = 0;
byte type_mono_tri[2] = { 0, 0 };
uint8_t presence_teleinfo = 0;  // si signal teleinfo présent
byte presence_PAP = 0;          // si PAP présent
boolean cpt2_present = true;    // mémorisation de la présence du compteur 2
boolean compteursluOK = false;  // pour autoriser l'écriture de valeur sur la SD
boolean mem_affichage_cpt2_present = true;

int ReceptionOctet = 0;            // variable de stockage des octets reçus par port série
unsigned int ReceptionNombre = 0;  // variable de calcul du nombre reçu par port série
byte reg_horloge = 1;
boolean mem_reg_horloge = false;
const uint8_t val_max[6] = { 24, 59, 59, 31, 12, 99 };

// declarations Teleinfo
unsigned int papp = 0;  // Puissance apparente, VA

uint8_t IINST[2][3] = { { 0, 0, 0 }, { 0, 0, 0 } };  // Intensité Instantanée Phase 1, A  (intensité efficace instantanée) ou 1 phase en monophasé

unsigned long INDEX1 = 0;  // Index option Tempo - Heures Creuses Jours Bleus, Wh
unsigned long INDEX2 = 0;  // Index option Tempo - Heures Pleines Jours Bleus, Wh
unsigned long INDEX3 = 0;  // Index option Tempo - Heures Creuses Jours Blancs, Wh
unsigned long INDEX4 = 0;  // Index option Tempo - Heures Pleines Jours Blancs, Wh
unsigned long INDEX5 = 0;  // Index option Tempo - Heures Creuses Jours Rouges, Wh
unsigned long INDEX6 = 0;  // Index option Tempo - Heures Pleines Jours Rouges, Wh

// compteur 2 (solaire configuré en tarif BASE par ERDF)
unsigned long cpt2index = 0;     // Index option Base compteur production solaire, Wh
unsigned int cpt2puissance = 0;  // Puissance apparente compteur production solaire, VA

#define debtrame 0x02
#define debligne 0x0A
#define finligne 0x0D

// *************** déclaration carte micro SD ******************
const byte chipSelect = 4;

// *************** déclaration activation compteur 1 ou 2 ******
#define LEC_CPT1 5  // lecture compteur 1
#define LEC_CPT2 6  // lecture compteur 2
//
byte verif_cpt_lu = 0;
//

byte compteur_actif = 1;           // numero du compteur en cours de lecture
byte donnee_ok_cpt[2] = { 0, 0 };  // pour vérifier que les donnees sont bien en memoire avant ecriture dans fichier
byte donnee_ok_cpt_ph[2] = { 0, 0 };

// *************** variables RTC ************************************
byte minute, heure, seconde, jour, mois, jour_semaine;
unsigned int annee;
char date_heure[18];
char mois_jour[7];
byte mem_chg_heure = 0;  //pour pas passer perpetuellement de 3h à 2h du matin le dernier dimanche d'octobre
RTC_DS1307 RTC;

// ************** initialisation *******************************
void setup() {
  // initialisation du port 0-1 lecture Téléinfo
  Serial.begin(1200);
  // parité paire E
  // 7 bits data
  UCSR0C = B00100100;
#ifdef message_systeme_USB
  Serial.print(F("-- Teleinfo USB Arduino "));
  Serial.print(version_logiciel);
  Serial.println(F(" --"));
#endif
  // initialisation des sorties selection compteur
  pinMode(LEC_CPT1, OUTPUT);
  pinMode(LEC_CPT2, OUTPUT);
  digitalWrite(LEC_CPT1, HIGH);
  digitalWrite(LEC_CPT2, LOW);

  // verification de la présence de la microSD et si elle est initialisée:
#ifdef message_systeme_USB
  if (!SD.begin(chipSelect)) {
    Serial.println(F("> Erreur carte, ou carte absente !"));
    return;
  }
  Serial.println(F("> microSD initialisee !"));
#endif

  // initialisation RTC16

  Wire.begin();
  RTC.begin();

  if (!RTC.isrunning()) {
#ifdef message_systeme_USB
    Serial.println(F("RTC non configure !"));
#endif
  }

  DateTime now = RTC.now();  // lecture de l'horloge
  annee = now.year();
  mois = now.month();
  jour = now.day();
  heure = now.hour();
  minute = now.minute();
  jour_semaine = now.dayOfTheWeek();

  format_date_heure();
#ifdef message_systeme_USB
  Serial.println(date_heure);
#endif
}

// ************** boucle principale *******************************

void loop()  // Programme en boucle
{

  if (!(RTC.isrunning()) && (reg_horloge < 7)) {  // si l'horloge n'est pas configurée
    digitalWrite(LEC_CPT1, LOW);

    if (!mem_reg_horloge) {
      switch (reg_horloge) {  // debut de la structure
        case 1:
          Serial.print(F("Entrer Heure: "));
          break;
        case 2:
          Serial.print(F("Entrer Minute: "));
          break;
        case 3:
          Serial.print(F("Entrer Seconde: "));
          break;
        case 4:
          Serial.print(F("Entrer Jour: "));
          break;
        case 5:
          Serial.print(F("Entrer Mois: "));
          break;
        case 6:
          Serial.print(F("Entrer Annee 20xx: "));
          break;
      }
      mem_reg_horloge = true;
    }
    if (Serial.available() > 0) {  // si caractère dans la file d'attente

      Serial.print(F("un nombre a ete recu")); //---- lecture du nombre reçu
      while (Serial.available() > 0) {
        // tant que buffer pas vide pour lire d'une traite tous les caractères reçus
        inByte = Serial.read();         // renvoie le 1er octet présent dans la file attente série (-1 si aucun)
        Serial.println(inByte);
        if (((inByte > 47) && (inByte < 58)) || (inByte == 13)) {
          ReceptionOctet = inByte - 48;  // transforme valeur ASCII en valeur décimale
          if ((ReceptionOctet >= 0) && (ReceptionOctet <= 9)) ReceptionNombre = (ReceptionNombre * 10) + ReceptionOctet;
          // si valeur reçue correspond à un chiffre on calcule nombre
          Serial.print(ReceptionNombre);
          Serial.print(reg_horloge);
        } else
          presence_teleinfo = -1;
      }  // fin while
      if (inByte == 13) {
        if ((ReceptionNombre > val_max[reg_horloge - 1]) || (ReceptionNombre == -1)) {
          Serial.println(F("Erreur horaire"));
          ReceptionNombre = 0;
          mem_reg_horloge = true;
        } else {
          Serial.print("cela bugge");
          switch (reg_horloge) {  // debut de la structure
            case 1:
              heure = ReceptionNombre;
              Serial.print("heure:");
              Serial.println(heure);
            case 2:
              minute = ReceptionNombre;
              break;
            case 3:
              seconde = ReceptionNombre;
              break;
            case 4:
              jour = ReceptionNombre;
              break;
            case 5:
              mois = ReceptionNombre;
              break;
            case 6:
              annee = 2000 + ReceptionNombre;
              break;
          }

          mem_reg_horloge = false;
          ReceptionNombre = 0;
          ++reg_horloge;

          if (reg_horloge > 6) {
            RTCsetTime();
            Serial.println(F("Reglage heure OK - installer le cavalier pour la teleinfo"));
            digitalWrite(LEC_CPT1, HIGH);
          }
        }
      }
    }
  }

  else {

    DateTime now = RTC.now();  // lecture de l'horloge
    minute = now.minute();
    heure = now.hour();
    seconde = now.second();

    if ((heure == 0) && (minute == 0) && (seconde == 0)) {
      annee = now.year();
      mois = now.month();
      jour = now.day();
      jour_semaine = now.dayOfTheWeek();
    }

    // passage à l'heure d'été +1 heure
    // la lib RTC a une fonction: dayOfWeek qui donne le jour de la semaine (la DS1307 se charge de tout !)
    // réponse: 0 -> dimanche, 1 -> lundi etc...
    //
    if ((heure == 2) && (minute == 0) && (seconde == 0) && (jour_semaine == 0) && (mois == 3) && (jour > 24)) {
      heure = 3;
      RTCsetTime();
    }

    // passage à l'heure d'hiver -1 heure
    if ((heure == 3) && (minute == 0) && (seconde == 0) && (jour_semaine == 0) && (mois == 10) && (jour > 24) && (mem_chg_heure == 0)) {
      heure = 2;
      RTCsetTime();
      mem_chg_heure = 1;
    }

    if ((heure == 23) && (minute == 59) && (seconde == 10))  // pour être sur de pas tomber pendant l'enregistrement toutes les minutes
    {
      if ((mem_sauv_journee == 0) && (compteursluOK))  // un seul enregistrement par jour !
      {
        fichier_annee();
        mem_sauv_journee = 1;
        mem_chg_heure = 0;
      }
    } else
      mem_sauv_journee = 0;

    if (seconde == 1) {
      if ((mem_sauv_minute == 0) && (compteursluOK))  // un seul enregistrement par minute !
      {
        enregistre();
        mem_sauv_minute = 1;
      }
    } else
      mem_sauv_minute = 0;

#ifdef message_systeme_USB
    if ((donnee_ok_cpt[1] == B00000111) && (mem_affichage_cpt2_present)) {
      if (mem_affichage_cpt2_present) Serial.println(F("- Compteur 2 detecte"));
      mem_affichage_cpt2_present = false;
    } else if ((!cpt2_present) && (mem_affichage_cpt2_present)) {
      if (mem_affichage_cpt2_present) Serial.println(F("- Compteur 2 non present !"));
      mem_affichage_cpt2_present = false;
    }
#endif

    if ((donnee_ok_cpt[0] == verif_cpt_lu) and (cpt2_present)) {
      if ((type_mono_tri[0] == 1) && (donnee_ok_cpt_ph[0] == B10000001)) bascule_compteur();
      else if ((type_mono_tri[0] == 3) && (donnee_ok_cpt_ph[0] == B10000111))
        bascule_compteur();
    } else if ((donnee_ok_cpt[1] == B00000001) or ((compteur_actif == 2) and (!cpt2_present))) {
      if ((type_mono_tri[1] == 1) && (donnee_ok_cpt_ph[1] == B10000001)) bascule_compteur();
      else if ((type_mono_tri[1] == 3) && (donnee_ok_cpt_ph[1] == B10000111))
        bascule_compteur();
      compteursluOK = true;
    }

    if (compteur_actif == 2) {
      if (presence_teleinfo > 200) {
        cpt2_present = false;
        compteursluOK = true;
        bascule_compteur();
      } else
        cpt2_present = true;
    }

    read_teleinfo();
  }
}

///////////////////////////////////////////////////////////////////
// Calcul Checksum teleinfo
///////////////////////////////////////////////////////////////////
char chksum(char *buff, uint8_t len) {
  int i;
  char sum = 0;
  for (i = 1; i < (len - 2); i++) sum = sum + buff[i];
  sum = (sum & 0x3F) + 0x20;
  return (sum);
}

///////////////////////////////////////////////////////////////////
// mise en forme Date & heure pour affichage ou enregistrement
///////////////////////////////////////////////////////////////////
void format_mois_jour() {
  sprintf(mois_jour, "%02d,%02d,", mois, jour);
}

// Convert normal decimal numbers to binary coded decimal
static uint8_t bin2bcd(uint8_t val) {
  return val + 6 * (val / 10);
}

///////////////////////////////////////////////////////////////////
// mise à l'heure de la RTC (DS1307)
///////////////////////////////////////////////////////////////////
void RTCsetTime(void) {
  Wire.beginTransmission(104);  // 104 is DS1307 device address (0x68)
  Wire.write(bin2bcd(0));       // start at register 0

  Wire.write(bin2bcd(seconde));       //Send seconds as BCD
  Wire.write(bin2bcd(minute));        //Send minutes as BCD
  Wire.write(bin2bcd(heure));         //Send hours as BCD
  Wire.write(bin2bcd(jour_semaine));  // dow
  Wire.write(bin2bcd(jour));          //Send day as BCD
  Wire.write(bin2bcd(mois));          //Send month as BCD
  Wire.write(bin2bcd(annee % 1000));  //Send year as BCD

  Wire.endTransmission();
}

Example output on Serial Monitor

added 15313 characters in body
Source Link

The code is the following Teleinfo_Arduino_V0_3E.ino (just added some lines writing to serial to follow progress; and modified Serial.begin accordingly)

The code is the following Teleinfo_Arduino_V0_3E.ino (just added some lines writing to serial to follow progress; and modified Serial.begin accordingly and "shortened" to stay within size limits but it's sending wrong characters ate beginning))

/*
              Datalogger Téléinfo 2 compteurs sur Arduino

              Compteur 1: consommation
              Compteur 2: production solaire en tarif BASE

              Juin 2011:
              v0.2  * passage automatique à l'heure d'été
                      correctif erreur abo BBR
                      modification ecriture sur SD (utilisation de teleinfoFile.print à la place s'une variable STRING
                      qui plante l'Arduino avec les abonnements BBR
              v0.2a * ajout mode sans puissance apparente pour ancien compteur et calcul de celle-ci pour les logiciels d'analyse
              v0.2b * pour Arduino 1.0 (mise à jour de la RTC et utilisation de la librairie SD livrée avec la 1.0)
              v0.2c * modif type de variable pour éviter d'avoir 2 enregistrements à la même minute (surtout sur des proc + rapide)
              v0.3  * détection automatique du type d'abonnement sur le compteur 1
              v0.3a * Fonction de mise à l'heure par l'usb (interface série) en 1200 bauds 7 bits parité pair
                      Procédure:
                      1- carte débranchée, enlevez la pile de son support (pour réinitialiser l'horloge)
                      2- enlevez le cavalier du shield téléinfo
                      3- configurer votre logiciel émulateur de terminal (termite,Hyperterminale...) en 1200 bauds 7 bits parité pair
                      4- mettre sous tension la carte.
                      -- Le programme détectera le reset de l'horloge et vous demandera de rentrer l'heure et la date. --

              v0.3b * Correction bug calcul PAP compteur 2, enregistrement journalier compteur 2
              v0.3c * Triphasé sur compteur 2
              v0.3d * correction bug retour ligne sur compteur 2 (entête fichier)
              v0.3e * Correction bug si pas de compteur 2
*/

#include <SD.h>
#include <SPI.h>
#include <Wire.h>
#include <RTClib.h>

const char version_logiciel[6] = "V0.3e";

// #define echo_USB            //envoie toutes les trames téléinfo sur l'USB
#define message_systeme_USB  //envoie des messages sur l'USB (init SD, heure au demarrage, et echo des erreures)

//*****************************************************************************************
byte inByte = 0;  // caractère entrant téléinfo
char buffteleinfo[21] = "";
byte bufflen = 0;
byte mem_sauv_minute = 1;
byte mem_sauv_journee = 1;
byte num_abo = 0;
byte type_mono_tri[2] = { 0, 0 };
uint8_t presence_teleinfo = 0;  // si signal teleinfo présent
byte presence_PAP = 0;          // si PAP présent
boolean cpt2_present = true;    // mémorisation de la présence du compteur 2
boolean compteursluOK = false;  // pour autoriser l'écriture de valeur sur la SD
boolean mem_affichage_cpt2_present = true;

int ReceptionOctet = 0;            // variable de stockage des octets reçus par port série
unsigned int ReceptionNombre = 0;  // variable de calcul du nombre reçu par port série
byte reg_horloge = 1;
boolean mem_reg_horloge = false;
const uint8_t val_max[6] = { 24, 59, 59, 31, 12, 99 };

// declarations Teleinfo
unsigned int papp = 0;  // Puissance apparente, VA

uint8_t IINST[2][3] = { { 0, 0, 0 }, { 0, 0, 0 } };  // Intensité Instantanée Phase 1, A  (intensité efficace instantanée) ou 1 phase en monophasé

unsigned long INDEX1 = 0;  // Index option Tempo - Heures Creuses Jours Bleus, Wh
unsigned long INDEX2 = 0;  // Index option Tempo - Heures Pleines Jours Bleus, Wh
unsigned long INDEX3 = 0;  // Index option Tempo - Heures Creuses Jours Blancs, Wh
unsigned long INDEX4 = 0;  // Index option Tempo - Heures Pleines Jours Blancs, Wh
unsigned long INDEX5 = 0;  // Index option Tempo - Heures Creuses Jours Rouges, Wh
unsigned long INDEX6 = 0;  // Index option Tempo - Heures Pleines Jours Rouges, Wh

// compteur 2 (solaire configuré en tarif BASE par ERDF)
unsigned long cpt2index = 0;     // Index option Base compteur production solaire, Wh
unsigned int cpt2puissance = 0;  // Puissance apparente compteur production solaire, VA

#define debtrame 0x02
#define debligne 0x0A
#define finligne 0x0D

// *************** déclaration carte micro SD ******************
const byte chipSelect = 4;

// *************** déclaration activation compteur 1 ou 2 ******
#define LEC_CPT1 5  // lecture compteur 1
#define LEC_CPT2 6  // lecture compteur 2
//
byte verif_cpt_lu = 0;
//

byte compteur_actif = 1;           // numero du compteur en cours de lecture
byte donnee_ok_cpt[2] = { 0, 0 };  // pour vérifier que les donnees sont bien en memoire avant ecriture dans fichier
byte donnee_ok_cpt_ph[2] = { 0, 0 };

// *************** variables RTC ************************************
byte minute, heure, seconde, jour, mois, jour_semaine;
unsigned int annee;
char date_heure[18];
char mois_jour[7];
byte mem_chg_heure = 0;  //pour pas passer perpetuellement de 3h à 2h du matin le dernier dimanche d'octobre
RTC_DS1307 RTC;

// ************** initialisation *******************************
void setup() {
  // initialisation du port 0-1 lecture Téléinfo
  Serial.begin(1200);
  // parité paire E
  // 7 bits data
  UCSR0C = B00100100;
#ifdef message_systeme_USB
  Serial.print(F("-- Teleinfo USB Arduino "));
  Serial.print(version_logiciel);
  Serial.println(F(" --"));
#endif
  // initialisation des sorties selection compteur
  pinMode(LEC_CPT1, OUTPUT);
  pinMode(LEC_CPT2, OUTPUT);
  digitalWrite(LEC_CPT1, HIGH);
  digitalWrite(LEC_CPT2, LOW);

  // verification de la présence de la microSD et si elle est initialisée:
#ifdef message_systeme_USB
  if (!SD.begin(chipSelect)) {
    Serial.println(F("> Erreur carte, ou carte absente !"));
    return;
  }
  Serial.println(F("> microSD initialisee !"));
#endif

  // initialisation RTC16

  Wire.begin();
  RTC.begin();

  if (!RTC.isrunning()) {
#ifdef message_systeme_USB
    Serial.println(F("RTC non configure !"));
#endif
  }

  DateTime now = RTC.now();  // lecture de l'horloge
  annee = now.year();
  mois = now.month();
  jour = now.day();
  heure = now.hour();
  minute = now.minute();
  jour_semaine = now.dayOfTheWeek();

  format_date_heure();
#ifdef message_systeme_USB
  Serial.println(date_heure);
#endif
}

// ************** boucle principale *******************************

void loop()  // Programme en boucle
{

  if (!(RTC.isrunning()) && (reg_horloge < 7)) {  // si l'horloge n'est pas configurée
    digitalWrite(LEC_CPT1, LOW);

    if (!mem_reg_horloge) {
      switch (reg_horloge) {  // debut de la structure
        case 1:
          Serial.print(F("Entrer Heure: "));
          break;
        case 2:
          Serial.print(F("Entrer Minute: "));
          break;
        case 3:
          Serial.print(F("Entrer Seconde: "));
          break;
        case 4:
          Serial.print(F("Entrer Jour: "));
          break;
        case 5:
          Serial.print(F("Entrer Mois: "));
          break;
        case 6:
          Serial.print(F("Entrer Annee 20xx: "));
          break;
      }
      mem_reg_horloge = true;
    }
    if (Serial.available() > 0) {  // si caractère dans la file d'attente

      Serial.print(F("un nombre a ete recu")); //---- lecture du nombre reçu
      while (Serial.available() > 0) {
        // tant que buffer pas vide pour lire d'une traite tous les caractères reçus
        inByte = Serial.read();         // renvoie le 1er octet présent dans la file attente série (-1 si aucun)
        Serial.println(inByte);
        if (((inByte > 47) && (inByte < 58)) || (inByte == 13)) {
          ReceptionOctet = inByte - 48;  // transforme valeur ASCII en valeur décimale
          if ((ReceptionOctet >= 0) && (ReceptionOctet <= 9)) ReceptionNombre = (ReceptionNombre * 10) + ReceptionOctet;
          // si valeur reçue correspond à un chiffre on calcule nombre
          Serial.print(ReceptionNombre);
          Serial.print(reg_horloge);
        } else
          presence_teleinfo = -1;
      }  // fin while
      if (inByte == 13) {
        if ((ReceptionNombre > val_max[reg_horloge - 1]) || (ReceptionNombre == -1)) {
          Serial.println(F("Erreur horaire"));
          ReceptionNombre = 0;
          mem_reg_horloge = true;
        } else {
          Serial.print("cela bugge");
          switch (reg_horloge) {  // debut de la structure
            case 1:
              heure = ReceptionNombre;
              Serial.print("heure:");
              Serial.println(heure);
            case 2:
              minute = ReceptionNombre;
              break;
            case 3:
              seconde = ReceptionNombre;
              break;
            case 4:
              jour = ReceptionNombre;
              break;
            case 5:
              mois = ReceptionNombre;
              break;
            case 6:
              annee = 2000 + ReceptionNombre;
              break;
          }

          mem_reg_horloge = false;
          ReceptionNombre = 0;
          ++reg_horloge;

          if (reg_horloge > 6) {
            RTCsetTime();
            Serial.println(F("Reglage heure OK - installer le cavalier pour la teleinfo"));
            digitalWrite(LEC_CPT1, HIGH);
          }
        }
      }
    }
  }

  else {

    DateTime now = RTC.now();  // lecture de l'horloge
    minute = now.minute();
    heure = now.hour();
    seconde = now.second();

    if ((heure == 0) && (minute == 0) && (seconde == 0)) {
      annee = now.year();
      mois = now.month();
      jour = now.day();
      jour_semaine = now.dayOfTheWeek();
    }

    // passage à l'heure d'été +1 heure
    // la lib RTC a une fonction: dayOfWeek qui donne le jour de la semaine (la DS1307 se charge de tout !)
    // réponse: 0 -> dimanche, 1 -> lundi etc...
    //
    if ((heure == 2) && (minute == 0) && (seconde == 0) && (jour_semaine == 0) && (mois == 3) && (jour > 24)) {
      heure = 3;
      RTCsetTime();
    }

    // passage à l'heure d'hiver -1 heure
    if ((heure == 3) && (minute == 0) && (seconde == 0) && (jour_semaine == 0) && (mois == 10) && (jour > 24) && (mem_chg_heure == 0)) {
      heure = 2;
      RTCsetTime();
      mem_chg_heure = 1;
    }

    if ((heure == 23) && (minute == 59) && (seconde == 10))  // pour être sur de pas tomber pendant l'enregistrement toutes les minutes
    {
      if ((mem_sauv_journee == 0) && (compteursluOK))  // un seul enregistrement par jour !
      {
        fichier_annee();
        mem_sauv_journee = 1;
        mem_chg_heure = 0;
      }
    } else
      mem_sauv_journee = 0;

    if (seconde == 1) {
      if ((mem_sauv_minute == 0) && (compteursluOK))  // un seul enregistrement par minute !
      {
        enregistre();
        mem_sauv_minute = 1;
      }
    } else
      mem_sauv_minute = 0;

#ifdef message_systeme_USB
    if ((donnee_ok_cpt[1] == B00000111) && (mem_affichage_cpt2_present)) {
      if (mem_affichage_cpt2_present) Serial.println(F("- Compteur 2 detecte"));
      mem_affichage_cpt2_present = false;
    } else if ((!cpt2_present) && (mem_affichage_cpt2_present)) {
      if (mem_affichage_cpt2_present) Serial.println(F("- Compteur 2 non present !"));
      mem_affichage_cpt2_present = false;
    }
#endif

    if ((donnee_ok_cpt[0] == verif_cpt_lu) and (cpt2_present)) {
      if ((type_mono_tri[0] == 1) && (donnee_ok_cpt_ph[0] == B10000001)) bascule_compteur();
      else if ((type_mono_tri[0] == 3) && (donnee_ok_cpt_ph[0] == B10000111))
        bascule_compteur();
    } else if ((donnee_ok_cpt[1] == B00000001) or ((compteur_actif == 2) and (!cpt2_present))) {
      if ((type_mono_tri[1] == 1) && (donnee_ok_cpt_ph[1] == B10000001)) bascule_compteur();
      else if ((type_mono_tri[1] == 3) && (donnee_ok_cpt_ph[1] == B10000111))
        bascule_compteur();
      compteursluOK = true;
    }

    if (compteur_actif == 2) {
      if (presence_teleinfo > 200) {
        cpt2_present = false;
        compteursluOK = true;
        bascule_compteur();
      } else
        cpt2_present = true;
    }

    read_teleinfo();
  }
}

///////////////////////////////////////////////////////////////////
// Calcul Checksum teleinfo
///////////////////////////////////////////////////////////////////
char chksum(char *buff, uint8_t len) {
  int i;
  char sum = 0;
  for (i = 1; i < (len - 2); i++) sum = sum + buff[i];
  sum = (sum & 0x3F) + 0x20;
  return (sum);
}

///////////////////////////////////////////////////////////////////
// mise en forme Date & heure pour affichage ou enregistrement
///////////////////////////////////////////////////////////////////
void format_mois_jour() {
  sprintf(mois_jour, "%02d,%02d,", mois, jour);
}

// Convert normal decimal numbers to binary coded decimal
static uint8_t bin2bcd(uint8_t val) {
  return val + 6 * (val / 10);
}

///////////////////////////////////////////////////////////////////
// mise à l'heure de la RTC (DS1307)
///////////////////////////////////////////////////////////////////
void RTCsetTime(void) {
  Wire.beginTransmission(104);  // 104 is DS1307 device address (0x68)
  Wire.write(bin2bcd(0));       // start at register 0

  Wire.write(bin2bcd(seconde));       //Send seconds as BCD
  Wire.write(bin2bcd(minute));        //Send minutes as BCD
  Wire.write(bin2bcd(heure));         //Send hours as BCD
  Wire.write(bin2bcd(jour_semaine));  // dow
  Wire.write(bin2bcd(jour));          //Send day as BCD
  Wire.write(bin2bcd(mois));          //Send month as BCD
  Wire.write(bin2bcd(annee % 1000));  //Send year as BCD

  Wire.endTransmission();
}

The code is the following Teleinfo_Arduino_V0_3E.ino (just added some lines writing to serial to follow progress; and modified Serial.begin accordingly)

The code is the following Teleinfo_Arduino_V0_3E.ino (just added some lines writing to serial to follow progress; and modified Serial.begin accordingly and "shortened" to stay within size limits but it's sending wrong characters ate beginning))

/*
              Datalogger Téléinfo 2 compteurs sur Arduino

              Compteur 1: consommation
              Compteur 2: production solaire en tarif BASE

              Juin 2011:
              v0.2  * passage automatique à l'heure d'été
                      correctif erreur abo BBR
                      modification ecriture sur SD (utilisation de teleinfoFile.print à la place s'une variable STRING
                      qui plante l'Arduino avec les abonnements BBR
              v0.2a * ajout mode sans puissance apparente pour ancien compteur et calcul de celle-ci pour les logiciels d'analyse
              v0.2b * pour Arduino 1.0 (mise à jour de la RTC et utilisation de la librairie SD livrée avec la 1.0)
              v0.2c * modif type de variable pour éviter d'avoir 2 enregistrements à la même minute (surtout sur des proc + rapide)
              v0.3  * détection automatique du type d'abonnement sur le compteur 1
              v0.3a * Fonction de mise à l'heure par l'usb (interface série) en 1200 bauds 7 bits parité pair
                      Procédure:
                      1- carte débranchée, enlevez la pile de son support (pour réinitialiser l'horloge)
                      2- enlevez le cavalier du shield téléinfo
                      3- configurer votre logiciel émulateur de terminal (termite,Hyperterminale...) en 1200 bauds 7 bits parité pair
                      4- mettre sous tension la carte.
                      -- Le programme détectera le reset de l'horloge et vous demandera de rentrer l'heure et la date. --

              v0.3b * Correction bug calcul PAP compteur 2, enregistrement journalier compteur 2
              v0.3c * Triphasé sur compteur 2
              v0.3d * correction bug retour ligne sur compteur 2 (entête fichier)
              v0.3e * Correction bug si pas de compteur 2
*/

#include <SD.h>
#include <SPI.h>
#include <Wire.h>
#include <RTClib.h>

const char version_logiciel[6] = "V0.3e";

// #define echo_USB            //envoie toutes les trames téléinfo sur l'USB
#define message_systeme_USB  //envoie des messages sur l'USB (init SD, heure au demarrage, et echo des erreures)

//*****************************************************************************************
byte inByte = 0;  // caractère entrant téléinfo
char buffteleinfo[21] = "";
byte bufflen = 0;
byte mem_sauv_minute = 1;
byte mem_sauv_journee = 1;
byte num_abo = 0;
byte type_mono_tri[2] = { 0, 0 };
uint8_t presence_teleinfo = 0;  // si signal teleinfo présent
byte presence_PAP = 0;          // si PAP présent
boolean cpt2_present = true;    // mémorisation de la présence du compteur 2
boolean compteursluOK = false;  // pour autoriser l'écriture de valeur sur la SD
boolean mem_affichage_cpt2_present = true;

int ReceptionOctet = 0;            // variable de stockage des octets reçus par port série
unsigned int ReceptionNombre = 0;  // variable de calcul du nombre reçu par port série
byte reg_horloge = 1;
boolean mem_reg_horloge = false;
const uint8_t val_max[6] = { 24, 59, 59, 31, 12, 99 };

// declarations Teleinfo
unsigned int papp = 0;  // Puissance apparente, VA

uint8_t IINST[2][3] = { { 0, 0, 0 }, { 0, 0, 0 } };  // Intensité Instantanée Phase 1, A  (intensité efficace instantanée) ou 1 phase en monophasé

unsigned long INDEX1 = 0;  // Index option Tempo - Heures Creuses Jours Bleus, Wh
unsigned long INDEX2 = 0;  // Index option Tempo - Heures Pleines Jours Bleus, Wh
unsigned long INDEX3 = 0;  // Index option Tempo - Heures Creuses Jours Blancs, Wh
unsigned long INDEX4 = 0;  // Index option Tempo - Heures Pleines Jours Blancs, Wh
unsigned long INDEX5 = 0;  // Index option Tempo - Heures Creuses Jours Rouges, Wh
unsigned long INDEX6 = 0;  // Index option Tempo - Heures Pleines Jours Rouges, Wh

// compteur 2 (solaire configuré en tarif BASE par ERDF)
unsigned long cpt2index = 0;     // Index option Base compteur production solaire, Wh
unsigned int cpt2puissance = 0;  // Puissance apparente compteur production solaire, VA

#define debtrame 0x02
#define debligne 0x0A
#define finligne 0x0D

// *************** déclaration carte micro SD ******************
const byte chipSelect = 4;

// *************** déclaration activation compteur 1 ou 2 ******
#define LEC_CPT1 5  // lecture compteur 1
#define LEC_CPT2 6  // lecture compteur 2
//
byte verif_cpt_lu = 0;
//

byte compteur_actif = 1;           // numero du compteur en cours de lecture
byte donnee_ok_cpt[2] = { 0, 0 };  // pour vérifier que les donnees sont bien en memoire avant ecriture dans fichier
byte donnee_ok_cpt_ph[2] = { 0, 0 };

// *************** variables RTC ************************************
byte minute, heure, seconde, jour, mois, jour_semaine;
unsigned int annee;
char date_heure[18];
char mois_jour[7];
byte mem_chg_heure = 0;  //pour pas passer perpetuellement de 3h à 2h du matin le dernier dimanche d'octobre
RTC_DS1307 RTC;

// ************** initialisation *******************************
void setup() {
  // initialisation du port 0-1 lecture Téléinfo
  Serial.begin(1200);
  // parité paire E
  // 7 bits data
  UCSR0C = B00100100;
#ifdef message_systeme_USB
  Serial.print(F("-- Teleinfo USB Arduino "));
  Serial.print(version_logiciel);
  Serial.println(F(" --"));
#endif
  // initialisation des sorties selection compteur
  pinMode(LEC_CPT1, OUTPUT);
  pinMode(LEC_CPT2, OUTPUT);
  digitalWrite(LEC_CPT1, HIGH);
  digitalWrite(LEC_CPT2, LOW);

  // verification de la présence de la microSD et si elle est initialisée:
#ifdef message_systeme_USB
  if (!SD.begin(chipSelect)) {
    Serial.println(F("> Erreur carte, ou carte absente !"));
    return;
  }
  Serial.println(F("> microSD initialisee !"));
#endif

  // initialisation RTC16

  Wire.begin();
  RTC.begin();

  if (!RTC.isrunning()) {
#ifdef message_systeme_USB
    Serial.println(F("RTC non configure !"));
#endif
  }

  DateTime now = RTC.now();  // lecture de l'horloge
  annee = now.year();
  mois = now.month();
  jour = now.day();
  heure = now.hour();
  minute = now.minute();
  jour_semaine = now.dayOfTheWeek();

  format_date_heure();
#ifdef message_systeme_USB
  Serial.println(date_heure);
#endif
}

// ************** boucle principale *******************************

void loop()  // Programme en boucle
{

  if (!(RTC.isrunning()) && (reg_horloge < 7)) {  // si l'horloge n'est pas configurée
    digitalWrite(LEC_CPT1, LOW);

    if (!mem_reg_horloge) {
      switch (reg_horloge) {  // debut de la structure
        case 1:
          Serial.print(F("Entrer Heure: "));
          break;
        case 2:
          Serial.print(F("Entrer Minute: "));
          break;
        case 3:
          Serial.print(F("Entrer Seconde: "));
          break;
        case 4:
          Serial.print(F("Entrer Jour: "));
          break;
        case 5:
          Serial.print(F("Entrer Mois: "));
          break;
        case 6:
          Serial.print(F("Entrer Annee 20xx: "));
          break;
      }
      mem_reg_horloge = true;
    }
    if (Serial.available() > 0) {  // si caractère dans la file d'attente

      Serial.print(F("un nombre a ete recu")); //---- lecture du nombre reçu
      while (Serial.available() > 0) {
        // tant que buffer pas vide pour lire d'une traite tous les caractères reçus
        inByte = Serial.read();         // renvoie le 1er octet présent dans la file attente série (-1 si aucun)
        Serial.println(inByte);
        if (((inByte > 47) && (inByte < 58)) || (inByte == 13)) {
          ReceptionOctet = inByte - 48;  // transforme valeur ASCII en valeur décimale
          if ((ReceptionOctet >= 0) && (ReceptionOctet <= 9)) ReceptionNombre = (ReceptionNombre * 10) + ReceptionOctet;
          // si valeur reçue correspond à un chiffre on calcule nombre
          Serial.print(ReceptionNombre);
          Serial.print(reg_horloge);
        } else
          presence_teleinfo = -1;
      }  // fin while
      if (inByte == 13) {
        if ((ReceptionNombre > val_max[reg_horloge - 1]) || (ReceptionNombre == -1)) {
          Serial.println(F("Erreur horaire"));
          ReceptionNombre = 0;
          mem_reg_horloge = true;
        } else {
          Serial.print("cela bugge");
          switch (reg_horloge) {  // debut de la structure
            case 1:
              heure = ReceptionNombre;
              Serial.print("heure:");
              Serial.println(heure);
            case 2:
              minute = ReceptionNombre;
              break;
            case 3:
              seconde = ReceptionNombre;
              break;
            case 4:
              jour = ReceptionNombre;
              break;
            case 5:
              mois = ReceptionNombre;
              break;
            case 6:
              annee = 2000 + ReceptionNombre;
              break;
          }

          mem_reg_horloge = false;
          ReceptionNombre = 0;
          ++reg_horloge;

          if (reg_horloge > 6) {
            RTCsetTime();
            Serial.println(F("Reglage heure OK - installer le cavalier pour la teleinfo"));
            digitalWrite(LEC_CPT1, HIGH);
          }
        }
      }
    }
  }

  else {

    DateTime now = RTC.now();  // lecture de l'horloge
    minute = now.minute();
    heure = now.hour();
    seconde = now.second();

    if ((heure == 0) && (minute == 0) && (seconde == 0)) {
      annee = now.year();
      mois = now.month();
      jour = now.day();
      jour_semaine = now.dayOfTheWeek();
    }

    // passage à l'heure d'été +1 heure
    // la lib RTC a une fonction: dayOfWeek qui donne le jour de la semaine (la DS1307 se charge de tout !)
    // réponse: 0 -> dimanche, 1 -> lundi etc...
    //
    if ((heure == 2) && (minute == 0) && (seconde == 0) && (jour_semaine == 0) && (mois == 3) && (jour > 24)) {
      heure = 3;
      RTCsetTime();
    }

    // passage à l'heure d'hiver -1 heure
    if ((heure == 3) && (minute == 0) && (seconde == 0) && (jour_semaine == 0) && (mois == 10) && (jour > 24) && (mem_chg_heure == 0)) {
      heure = 2;
      RTCsetTime();
      mem_chg_heure = 1;
    }

    if ((heure == 23) && (minute == 59) && (seconde == 10))  // pour être sur de pas tomber pendant l'enregistrement toutes les minutes
    {
      if ((mem_sauv_journee == 0) && (compteursluOK))  // un seul enregistrement par jour !
      {
        fichier_annee();
        mem_sauv_journee = 1;
        mem_chg_heure = 0;
      }
    } else
      mem_sauv_journee = 0;

    if (seconde == 1) {
      if ((mem_sauv_minute == 0) && (compteursluOK))  // un seul enregistrement par minute !
      {
        enregistre();
        mem_sauv_minute = 1;
      }
    } else
      mem_sauv_minute = 0;

#ifdef message_systeme_USB
    if ((donnee_ok_cpt[1] == B00000111) && (mem_affichage_cpt2_present)) {
      if (mem_affichage_cpt2_present) Serial.println(F("- Compteur 2 detecte"));
      mem_affichage_cpt2_present = false;
    } else if ((!cpt2_present) && (mem_affichage_cpt2_present)) {
      if (mem_affichage_cpt2_present) Serial.println(F("- Compteur 2 non present !"));
      mem_affichage_cpt2_present = false;
    }
#endif

    if ((donnee_ok_cpt[0] == verif_cpt_lu) and (cpt2_present)) {
      if ((type_mono_tri[0] == 1) && (donnee_ok_cpt_ph[0] == B10000001)) bascule_compteur();
      else if ((type_mono_tri[0] == 3) && (donnee_ok_cpt_ph[0] == B10000111))
        bascule_compteur();
    } else if ((donnee_ok_cpt[1] == B00000001) or ((compteur_actif == 2) and (!cpt2_present))) {
      if ((type_mono_tri[1] == 1) && (donnee_ok_cpt_ph[1] == B10000001)) bascule_compteur();
      else if ((type_mono_tri[1] == 3) && (donnee_ok_cpt_ph[1] == B10000111))
        bascule_compteur();
      compteursluOK = true;
    }

    if (compteur_actif == 2) {
      if (presence_teleinfo > 200) {
        cpt2_present = false;
        compteursluOK = true;
        bascule_compteur();
      } else
        cpt2_present = true;
    }

    read_teleinfo();
  }
}

///////////////////////////////////////////////////////////////////
// Calcul Checksum teleinfo
///////////////////////////////////////////////////////////////////
char chksum(char *buff, uint8_t len) {
  int i;
  char sum = 0;
  for (i = 1; i < (len - 2); i++) sum = sum + buff[i];
  sum = (sum & 0x3F) + 0x20;
  return (sum);
}

///////////////////////////////////////////////////////////////////
// mise en forme Date & heure pour affichage ou enregistrement
///////////////////////////////////////////////////////////////////
void format_mois_jour() {
  sprintf(mois_jour, "%02d,%02d,", mois, jour);
}

// Convert normal decimal numbers to binary coded decimal
static uint8_t bin2bcd(uint8_t val) {
  return val + 6 * (val / 10);
}

///////////////////////////////////////////////////////////////////
// mise à l'heure de la RTC (DS1307)
///////////////////////////////////////////////////////////////////
void RTCsetTime(void) {
  Wire.beginTransmission(104);  // 104 is DS1307 device address (0x68)
  Wire.write(bin2bcd(0));       // start at register 0

  Wire.write(bin2bcd(seconde));       //Send seconds as BCD
  Wire.write(bin2bcd(minute));        //Send minutes as BCD
  Wire.write(bin2bcd(heure));         //Send hours as BCD
  Wire.write(bin2bcd(jour_semaine));  // dow
  Wire.write(bin2bcd(jour));          //Send day as BCD
  Wire.write(bin2bcd(mois));          //Send month as BCD
  Wire.write(bin2bcd(annee % 1000));  //Send year as BCD

  Wire.endTransmission();
}
added 100 characters in body
Source Link

I'm revisiting my Arduino stuff (I want to revive Teleinfo shield to monitor closely my power consumption). I just cannot get the thing to work (Teleinfo Shield + Uno Wifi).

When trying to check what's happening this is the kind of Serial Monitor screens that I get.

Any hints on how to solve? It happens with other Uno as well and different versions of IDE.

Thank for any help, the answers I found in different places didn't lead me to a solution.

I tried several baud settings, (same for port and monitor, each time) and sometimes nothing was written, sometimes complete garbage, sometimes as illustrated

I will attach theThe code is the following Teleinfo_Arduino_V0_3E.ino (which is a "standard" that I modifiedjust added some lines writing to "trace" what was happening)serial to follow progress; and modified Serial.begin accordingly)

MacBookPro 2018 runnning Monterey

enter image description here

I'm revisiting my Arduino stuff (I want to revive Teleinfo shield to monitor closely my power consumption). I just cannot get the thing to work (Teleinfo Shield + Uno Wifi).

When trying to check what's happening this is the kind of Serial Monitor screens that I get.

Any hints on how to solve? It happens with other Uno as well and different versions of IDE.

Thank for any help, the answers I found in different places didn't lead me to a solution.

I tried several baud settings, (same for port and monitor, each time) and sometimes nothing was written, sometimes complete garbage, sometimes as illustrated

I will attach the code (which is a "standard" that I modified to "trace" what was happening).

enter image description here

I'm revisiting my Arduino stuff (I want to revive Teleinfo shield to monitor closely my power consumption). I just cannot get the thing to work (Teleinfo Shield + Uno Wifi).

When trying to check what's happening this is the kind of Serial Monitor screens that I get.

Any hints on how to solve? It happens with other Uno as well and different versions of IDE.

Thank for any help, the answers I found in different places didn't lead me to a solution.

I tried several baud settings, (same for port and monitor, each time) and sometimes nothing was written, sometimes complete garbage, sometimes as illustrated

The code is the following Teleinfo_Arduino_V0_3E.ino (just added some lines writing to serial to follow progress; and modified Serial.begin accordingly)

MacBookPro 2018 runnning Monterey

enter image description here

added 264 characters in body
Source Link
Loading
added 9 characters in body; edited title
Source Link
ocrdu
  • 1.8k
  • 3
  • 12
  • 24
Loading
Source Link
Loading