IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Arduino Discussion :

RTC DS3231 sans librairie


Sujet :

Arduino

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre chevronné Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    1 002
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 1 002
    Par défaut RTC DS3231 sans librairie
    Bonjour

    Il est possible d'utiliser le DS3231 (horloge RTC) beaucoup plus efficacement sans librairie, juste avec <wire.h>

    Datasheet ici : https://www.digikey.fr/fr/datasheets...ds3231-ds3231s

    Le code :

    Quelques fonctions et variables globales :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    #define CLOCK_ADDRESS 0x68 // Adresse du DS3231 ; elle peut être changée si besoin à coup de fer à souder sur les pads A0, A1 et A2
    uint8_t Clock_ss;
    uint8_t Clock_mm;
    uint8_t Clock_hh;
    uint8_t Clock_d;
    uint8_t Clock_m;
    uint8_t Clock_y;
    void I2C_Write_BCD(uint8_t val) {
    	Wire.write(val + 6 * (val / 10));
    }
    uint8_t I2C_Read_BCD() {
    	uint8_t val = Wire.read();
    	return val - 6 * (val >> 4);
    }
    Pour lire l'heure :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    void get_RTC_time() {
    	Wire.beginTransmission(CLOCK_ADDRESS);
    	Wire.write(0x00); // 1st register
    	Wire.endTransmission();
    	Wire.requestFrom(CLOCK_ADDRESS, 7); // 7 bytes to read
    	Clock_ss = I2C_Read_BCD();
    	Clock_mm = I2C_Read_BCD();
    	Clock_hh = I2C_Read_BCD();
    	I2C_Read_BCD(); // Day of week not used
    	Clock_d = I2C_Read_BCD();
    	Clock_m = I2C_Read_BCD() & 0b00001111; // Do not need century
    	Clock_y = I2C_Read_BCD();
    }
    Pour régler l'heure :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Wire.beginTransmission(CLOCK_ADDRESS);
    Wire.write(0x00); // 1st register
    I2C_Write_BCD(Clock_ss); // Seconds
    I2C_Write_BCD(Clock_mm); // Minutes
    I2C_Write_BCD(Clock_hh & 0b10111111); // Hour - bit 6 is set to 0 for 24h format
    I2C_Write_BCD(0); // Day of week - not used
    I2C_Write_BCD(Clock_d); // Date
    I2C_Write_BCD(Clock_m); // Month - bit 7 is century not used
    I2C_Write_BCD(Clock_y ); // Year
    Wire.endTransmission();
    Pour info, le bit "Century" du DS3231 doit être laissé à 0 pour le millénaire actuel (la datasheet n'est pas très explicite à ce sujet)

    J'ai testé ça marche, l'an 2000 est bien une année bissextile (passage du 28/02/2000 au 29/02/2000 à 23h59:59)

    (l'an 2000 est bissextile mais pas 1900 : https://fr.wikipedia.org/wiki/Ann%C3...gr%C3%A9gorien.)

    Le DS3231 utilise du BCD ce qui facilite l'utilisation directe pour affichage (afficheurs 7 segments, LCD) mais quand on utilise la date pour des calculs ou avec sprintf_P() c'est inutile.

    Je n'utilise pas le mode 12h AM/PM car c'est pénible pour les calculs et ça demande d'être plus vigilant pour lire et écrire le DS3231.
    Si vous voulez un affichage en mode 12h autant le faire vous même dans votre code d'affichage ça ne prendra pas plus de ressources et ça sera certainement plus fiable.

    Je vais m'attaquer au AHT20 d'Adafruit (capteur humidité et température) de la même façon, directement en I2C, car la bibliothèque d'Adafruit est inutilement très consommatrice d'octets de code et de RAM

    Moralité : il vaut mieux piloter les périphériques I2C directement en I2C...
    A la base, I2C a été conçu sur mesure pour la programmation sur microcontrôleurs, <wire.h> est suffisante.
    Dommage la documentation des vendeurs propose toujours d'utiliser de lourdes bibliothèques, qu'il faut éplucher pour retrouver les commandes I2C...

    A bientôt

  2. #2
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 922
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 922
    Par défaut
    La bibliothèque RTCLib n’est pas si lourde et ajoute quelques fonctions et 2 classes bien pratiques (le code des fonctions non utilisé est viré à l’édition de lien.)

    si vous avez à rajouter la gestion des alarmes, la gestion de la petite mémoire, la gestion de la sortie d’horloge et du code pour gérer le temps, je ne suis pas sûr que vous seriez bcp plus concis (même si on peut faire sans doute un peu mieux).

  3. #3
    Membre chevronné Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    1 002
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 1 002
    Par défaut
    Bonjour,

    J'ai pourtant gagné plus de 598 octets de flash en procédant ainsi

    Par rapport à la bibliothèque :
    - mon code permet de mettre à jour l'horloge en écrivant tout les registres d'un coup (la bibliothèque impose de faire des appels séparés pour chaque valeur)
    - de même pour la lecture en une fois sans passer par une structure DateTime

    C'est à la fois plus compact et plus rapide !

    Pour l'AHT20 c'est encore pire.

    Le code de la librairie Adafruit est incroyablement lourd... et stupide

    Etant donné la précision du capteur d'humidité (+/- 2%) ça ne sert à rien de coder cette valeur sur 20 bits et de la stocker dans un float.
    C'est trop lourd pour un Arduino.
    Un octet suffit.
    Et c'est un principe de base de la métrologie, n'afficher que des chiffres significatifs !

    Pour la température pareil, avec une précision de +/-0.3°C on peut se contenter d'un entier qui stockera des dixièmes de degrés, il faut juste en tenir compte pour l'affichage et les calculs.

    A bientôt

  4. #4
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 922
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 922
    Par défaut
    J'ai pourtant gagné plus de 598 octets de flash en procédant ainsi
    c'est difficile de comparer si vous n'offrez pas la même API.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
      static void adjust(const DateTime &dt);
      bool lostPower(void);
      static DateTime now();
      static Ds3231SqwPinMode readSqwPinMode();
      static void writeSqwPinMode(Ds3231SqwPinMode mode);
      bool setAlarm1(const DateTime &dt, Ds3231Alarm1Mode alarm_mode);
      bool setAlarm2(const DateTime &dt, Ds3231Alarm2Mode alarm_mode);
      void disableAlarm(uint8_t alarm_num);
      void clearAlarm(uint8_t alarm_num);
      bool alarmFired(uint8_t alarm_num);
      void enable32K(void);
      void disable32K(void);
      bool isEnabled32K(void);
      static float getTemperature(); // in Celsius degree
    Je n'utilise pas le mode 12h AM/PM car c'est pénible pour les calculs et ça demande d'être plus vigilant pour lire et écrire le DS3231.
    aux USA c'est ce qu'on utilise elle plus souvent. Quand on fait une bibliothèque on essaye de s'adapter à un public plus large - c'est sur que ça peut avoir un coût et que faire quelque chose qui correspond juste au besoin c'est plus compact.

  5. #5
    Membre chevronné Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    1 002
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 1 002
    Par défaut
    Citation Envoyé par Jay M Voir le message
    c'est difficile de comparer si vous n'offrez pas la même API.
    Justement, le compilateur devrait éliminer les fonctions que je n'utilise pas, ce qu'il a du mal à faire

    A bientôt

  6. #6
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 922
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 922
    Par défaut
    Il a besoin de la classe DateTime par exemple et des bibliothèques sous jacentes de gestion du temps

    - mon code permet de mettre à jour l'horloge en écrivant tout les registres d'un coup (la bibliothèque impose de faire des appels séparés pour chaque valeur)
    hum... La fonction adjust règle tout d'un coup
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    void RTC_DS3231::adjust(const DateTime &dt) {
      Wire.beginTransmission(DS3231_ADDRESS);
      Wire._I2C_WRITE((byte)DS3231_TIME); // start at location 0
      Wire._I2C_WRITE(bin2bcd(dt.second()));
      Wire._I2C_WRITE(bin2bcd(dt.minute()));
      Wire._I2C_WRITE(bin2bcd(dt.hour()));
      // The RTC must know the day of the week for the weekly alarms to work.
      Wire._I2C_WRITE(bin2bcd(dowToDS3231(dt.dayOfTheWeek())));
      Wire._I2C_WRITE(bin2bcd(dt.day()));
      Wire._I2C_WRITE(bin2bcd(dt.month()));
      Wire._I2C_WRITE(bin2bcd(dt.year() - 2000U));
      Wire.endTransmission();
     
      uint8_t statreg = read_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG);
      statreg &= ~0x80; // flip OSF bit
      write_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG, statreg);
    }
    Notez le commentaire
    The RTC must know the day of the week for the weekly alarms to work.
    qui nécessite donc d'avoir la fonction dayOfTheWeek() alors que vous faites
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	I2C_Read_BCD(); // Day of week not used
    ==> vous ne pourrez pas utiliser les alarmes

  7. #7
    Membre chevronné Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    1 002
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 1 002
    Par défaut
    Citation Envoyé par electroremy Voir le message
    C'est vraiment très étrange que le DS3231 ait besoin de DayOfWeek pour les alarmes.
    C'est juste un compteur de jour de 0 à 6, alors que ce qui compte pour une alarme c'est la date et l'heure ?

    Bref encore un truc à tester

    Les alarmes sont vraiment intéressantes dans le cas de figure où on souhaite réveiller un Arduino en état de veille.
    Si l'Arduino est allumé en permanence, l'alarme présente moins d'intérêt, car on peut faire cela dans le code dans loop()
    L'utilisation de l'alarme avec un Arduino allumé nécessite d'utiliser une interruption ce qui est bordelique quand on utilise le bus SPI et/ou un émetteur infrarouge.

    Remarque importante : je constate que je ne suis pas partit de la même bibliothèque DS3231 que vous car elle n'a pas la fonction adjust()

    A bientôt

  8. #8
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 922
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 922
    Par défaut
    Je pense que c’est pour mettre les alarmes tous les mardis par exemple

    Remarque importante : je constate que je ne suis pas partit de la même bibliothèque DS3231 que vous car elle n'a pas la fonction adjust()
    il s'agit de RTClib

  9. #9
    Membre chevronné Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    1 002
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 1 002
    Par défaut
    Citation Envoyé par Jay M Voir le message
    Je pense que c’est pour mettre les alarmes tous les mardis par exemple
    Je comprend ce sont des alarmes hebdomadaires, qui se répètent chaque semaine.

    C'est parfaitement adapté aux applications domotiques, tel que les thermostats programmables pour chauffage central.

    Mais ça ne permet pas de faire des alarmes plus évoluées en fonction des dates.

    Bon à savoir.

  10. #10
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 922
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 922
    Par défaut
    il y a 2 alarmes sur une DS3231

    L'alarme #1 peut être configurée:
    - Alarme une fois par seconde
    - Alarme lorsque les secondes correspondent
    - Alarme lorsque les minutes et les secondes correspondent
    - Alarme lorsque les heures, les minutes et les secondes correspondent
    - Alarme lorsque la date (jour du mois), les heures, les minutes et les secondes correspondent
    - Alarme lorsque le jour de la semaine, les heures, les minutes et les secondes correspondent

    L'alarme #2 a moins de modes:
    - Alarme une fois par minute (chaque fois que les secondes sont 0)
    - Alarme lorsque les minutes correspondent
    - Alarme lorsque les heures et les minutes correspondent
    - Alarme lorsque la date (jour du mois), les heures et les minutes correspondent
    - Alarme lorsque le jour de la semaine, les heures et les minutes correspondent

    donc c'est assez flexible, mais ça ne traite pas tous les cas (les premier mardi du mois par exemple)

  11. #11
    Membre chevronné Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    1 002
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 1 002
    Par défaut
    D'accord oui c'est super intéressant

    Une solution est, lorsqu'une alarme est déclenchée, de programmer la suivante avec l'Arduino.
    De cette façon on peut faire ce qu'on veut.
    A condition d'avoir une alimentation secourue bien sûr (si pas de chance coupure de courant pendant l'alarme)

  12. #12
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 922
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 922
    Par défaut
    Oui et la deuxième alarme peut-être un moyen de limiter le risque même s’il ne peut pas être nul

Discussions similaires

  1. [Graphique] Camembert en php sans librairie
    Par frogs dans le forum Bibliothèques et frameworks
    Réponses: 4
    Dernier message: 10/11/2008, 14h03
  2. Réponses: 9
    Dernier message: 04/05/2008, 12h18
  3. Lecture midi, portable et sans librairie
    Par otspot dans le forum C++
    Réponses: 4
    Dernier message: 20/01/2008, 20h40
  4. jsf ajaxisé sans librairie supplémentaire
    Par bashou dans le forum JSF
    Réponses: 2
    Dernier message: 01/10/2007, 23h20
  5. Lecture fichier wav sans librairie
    Par websurfeur dans le forum C
    Réponses: 3
    Dernier message: 12/09/2006, 10h51

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo