Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Manufacturing Technology >> Processus de fabrication

Construisez une Horloge 7 Segments avec Arduino Nano, DS3231 RTC et Luminosité Auto LDR

Composants et fournitures

Composant Quantité Notes
Arduino Nano R3 1 Compatible Arduino Uno ou Elegoo Uno
Adafruit 7-Segment Backpack - Chiffres 1,2" (Hauts) 1 Optionnel si acheté en pack
Adafruit 1,2" 4-Digits 7-Segments I2C Backpack - Vert 1
Adafruit DS3231 1 Ou DS1307 si préféré
Résistance 100 kΩ 1
Photorésistance (LDR) 1
Plaque d'essai (breadboard) 1
Fils de connexion (jumper wires) 1 10-14 pièces
Pile bouton CR1220 1 Pour sauvegarde RTC

Applications et services en ligne

À propos de ce projet

Introduction

À l'ère où l'on a toujours une montre au poignet ou un smartphone, une horloge Arduino Uno/Nano peut sembler banale. D'autres dispositifs synchronisés NTP sont constamment en ligne via Internet.

Histoire

Un ami a refusé, pour des raisons personnelles, un appareil avec connexion WiFi dans sa chambre. J'ai donc équipé l'Arduino d'une horloge autonome.

Choisir le bon composant

J'ai été surpris par le nombre de produits différents chez Adafruit : selon la tension souhaitée et la précision. J'ai retenu deux options : le DS1307 (moins cher) et le DS3231 (probablement plus précis).

Les deux fonctionnent avec cette horloge. Pour utiliser le DS1307, attention au câblage correct et à la restriction sur l'affichage de la température : mettez en commentaire // la fonction displayTemp(); dans la loop().

Adapter le sketch

J'ai recherché un sketch existant, trouvé chez un autre membre, puis l'ai restructuré et adapté en conservant ses commentaires en tchèque et en ajoutant des remarques en anglais.

L'affichage devait être le plus grand possible, d'où le choix d'un afficheur 7 segments : je voulais seulement l'heure en vue.

Bonne surprise en examinant les sketches : le DS3231 offre la lecture de la température, ce que le DS1307 ne propose pas (en plus de son imprécision).

Initialisation des horloges

Si vous avez une pile bouton CR1220, suivez le court tutoriel d'Adafruit pour configurer les horloges. En résumé, l'heure n'est pas récupérée depuis Internet, mais depuis l'horloge locale du PC. L'horodatage de téléversement est transféré aux modules RTC.

Fonctionnalités

J'ai ajouté la matrice LED pour l'affichage de l'heure et de la température. La durée d'affichage de chacun est configurable via des variables.

Le contrôle des points clignotants et des chiffres sur la matrice LED est bien documenté dans le sketch. Je renvoie aux sources Adafruit pour plus de détails.

Le sketch inclut :

Dans la vidéo, vous avez remarqué l'alternance heure/température. Avez-vous remarqué le point à gauche sur l'image ? Il change de position (haut/bas) selon les secondes.

Donnez-moi votre avis si vous savez comment afficher « ERR » sur la matrice en cas de panne de l'horloge. Actuellement, « bEEF » s'affiche :

Construisez une Horloge 7 Segments avec Arduino Nano, DS3231 RTC et Luminosité Auto LDR
// oh no, no data!
Serial.println("DS3231 Sensor Error - cant read temperature");
matrix.print(0xBEEF, HEX); // inform the user with BEEF
matrix.writeDisplay();
delay(5000);

Évolutions possibles

Mise à jour 01.02.2019 :

Le transfert du breadboard vers une carte perforée permanente est terminé. Quelques photos :

Construisez une Horloge 7 Segments avec Arduino Nano, DS3231 RTC et Luminosité Auto LDR
Construisez une Horloge 7 Segments avec Arduino Nano, DS3231 RTC et Luminosité Auto LDR
Construisez une Horloge 7 Segments avec Arduino Nano, DS3231 RTC et Luminosité Auto LDR
Construisez une Horloge 7 Segments avec Arduino Nano, DS3231 RTC et Luminosité Auto LDR
Construisez une Horloge 7 Segments avec Arduino Nano, DS3231 RTC et Luminosité Auto LDR

Le code mis à jour v1.1 et une image Fritzing personnalisée sont disponibles en pièce jointe.

Code

MyClock v1.0 C/C++
// MyClock v1.0
// Ingo Lohs
// Hardware: testé avec Arduino Uno et Arduino Nano (ATmega328P [Old Bootloader]) via Arduino IDE v1.8.8

/* Théorie pour la matrice ht16k33
Le plus simple est d'appeler print - comme avec Serial
print(variable,HEX) - affiche un nombre hexadécimal, de 0000 à FFFF
print(variable,DEC) ou print(variable) - affiche un entier décimal, de 0000 à 9999
Pour plus de contrôle, utilisez writeDigitNum(location, number) - écrit le chiffre (0-9) à un emplacement.
Emplacement #0 = tout à gauche, #2 = points des deux points (colon), #4 = tout à droite.
Pour contrôler le colon et les points décimaux, utilisez writeDigitNum(location, bitmap).
(Note : les deux points du colon central sont câblés ensemble, impossible de les adresser séparément.)
Spécifiez 2 pour l'emplacement et les bits sont mappés ainsi :
0x02 - colon central (les deux points)
0x04 - colon gauche - point bas
0x08 - colon gauche - point haut
0x10 - point décimal
Pour un point décimal, appelez writeDigitNum(location, number, true).
Pour dessiner le colon, utilisez drawColon(true ou false).
Pour un contrôle total des segments, utilisez writeDigitRaw(location, bitmask).
N'oubliez pas writeDisplay() après dessin pour "sauvegarder" la mémoire vers la matrice via I2C.
Source: https://www.mouser.com/ds/2/737/adafruit-led-backpack-932846.pdf */

#include <Wire.h>
#include <Adafruit_GFX.h>
#include "Adafruit_LEDBackpack.h"

#define DS3231_I2C_ADDRESS 0x68

int ldr_sensor = A0;        // LDR avec 100kΩ vers GND, autre patte 5V
int ldr_value = 0;          // Valeur LDR
int brightness_matrix;      // Luminosité matrice
int threshold_brightness = 400; // Seuil
int blinkrate_value = 0;    // Taux clignotement matrice
int delay_matrix_time = 20; // Durée affichage heure (20 sec)
int delay_matrix_temp = 2000; // Durée affichage temp (2 sec)
int blinky_dot = 2;         // Clignotement rien - côté gauche 2 points simples

Adafruit_7segment matrix = Adafruit_7segment();

byte decToBcd(byte val) {
  return ((val / 10 * 16) + (val % 10));
}

byte bcdToDec(byte val) {
  return ((val / 16 * 10) + (val % 16));
}

void setup() {
  Serial.begin(9600);
  Wire.begin();
  matrix.begin(0x70);
}

void loop() {
  lightBrightness();   // Ajustement luminosité matrice
  matrixBlinkrate();   // Ajustement taux clignotement
  displayTime();       // Afficher heure RTC
  displayTemp();       // Afficher température
}

void lightBrightness() {
  ldr_value = analogRead(ldr_sensor);
  Serial.print("LDR: ");
  Serial.println(ldr_value);
  if (ldr_value <= threshold_brightness) {
    brightness_matrix = 0;  // Lumineux le jour
  } else {
    brightness_matrix = 15; // Sombre la nuit
  }
}

void matrixBlinkrate() {
  matrix.blinkRate(blinkrate_value);
}

void displayTime() {
  matrix.setBrightness(brightness_matrix);
  matrix.clear();

  for (uint16_t i = 0; i < delay_matrix_time; i++) {
    byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
    getDateDs3231(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);

    byte se = second, mi = minute, ho = hour, we = dayOfWeek;
    byte dm = dayOfMonth, mo = month, ye = year;

    // Passage heure d'été - dernier dimanche de mars à 2h
    if ((dayOfWeek == 7) && (dayOfMonth >= 25) && (month == 3) && (hour == 2)) {
      setDS3231time(se, mi, 3, we, dm, mo, ye);
    }

    // Passage heure d'hiver
    if ((dayOfWeek == 7) && (dayOfMonth >= 25) && (month == 10) && (hour == 1) && (year != 1)) {
      setDS3231time(se, mi, ho, we, dm, mo, 1);
    }
    if ((dayOfWeek == 7) && (dayOfMonth >= 25) && (month == 10) && (hour == 3) && (year == 1)) {
      setDS3231time(se, mi, 2, we, dm, mo, 0);
    }

    /* Emplacement #2 contrôle aussi les 2 points simples gauche (blinky_dot) :
    2 = ne clignote rien
    3 = ne clignote rien
    4 = clignote point haut gauche
    5 = clignote point haut gauche
    6 = clignote point haut gauche + les deux points colon central
    7 = clignote point haut gauche + les deux points colon central
    8 = clignote point bas gauche
    9 = clignote point bas gauche
    10 = clignote point bas gauche + les deux points colon central
    11 = clignote point bas gauche + les deux points colon central
    12 = clignote les deux points gauche sans colon central */

    // Format heures: _0:mm
    if (hour > 9) {
      matrix.writeDigitNum(0, (hour / 10), false);
      matrix.writeDigitNum(1, (hour % 10), false);
    } else {
      matrix.writeDigitNum(1, hour, false);
    }

    // Points des secondes à gauche
    if (se <= 30) {
      blinky_dot = 10; // point bas gauche + colon central
    } else if (se > 30) {
      blinky_dot = 6;  // point haut gauche + colon central
    }
    matrix.writeDigitRaw(2, blinky_dot);
    matrix.writeDigitNum(3, (minute / 10), false);
    matrix.writeDigitNum(4, (minute % 10), false);
    matrix.writeDisplay();

    // Clignotement double points pour demi-secondes
    delay(500);
    matrix.drawColon(false);
    matrix.writeDisplay();
    delay(500);
  }
}

void displayTemp() {
  matrix.setBrightness(brightness_matrix);
  matrix.clear();
  byte temp = get3231Temp();
  int abs_temp = abs(temp);

  matrix.writeDigitNum(1, (abs_temp % 10), false);
  if (temp < 0) matrix.writeDigitRaw(0, 64);
  if (temp <= -10) matrix.writeDigitRaw(2, 12);
  if (temp >= 10) matrix.writeDigitNum(0, (abs_temp / 10), false);
  if (temp <= -10) matrix.writeDigitNum(0, (abs_temp / 10), false);
  matrix.writeDigitRaw(3, 99); // "°"
  matrix.writeDigitRaw(4, 57); // "C"
  matrix.writeDisplay();

  Serial.print("Température en C: ");
  Serial.println(get3231Temp());

  delay(delay_matrix_temp);
}

void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year) {
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0);
  Wire.write(decToBcd(second));
  Wire.write(decToBcd(minute));
  Wire.write(decToBcd(hour));
  Wire.write(decToBcd(dayOfWeek));
  Wire.write(decToBcd(dayOfMonth));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(year));
  Wire.endTransmission();
}

void getDateDs3231(byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month, byte *year) {
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}

float get3231Temp() {
  byte tMSB, tLSB;
  float temp3231;
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0x11);
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 2);
  if (Wire.available()) {
    tMSB = Wire.read();
    tLSB = Wire.read();
    temp3231 = (tMSB & B01111111);
    temp3231 += ((tLSB >> 6) * 0.25);
    return temp3231;
  } else {
    Serial.println("DS3231 Sensor Error - cant read temperature");
    matrix.print(0xBEEF, HEX);
    matrix.writeDisplay();
    delay(5000);
  }
}
MyClock v1.1 C/C++

Correction heure d'été/hiver

// MyClock v1.1
// Ingo Lohs
// Hardware: testé avec Arduino Uno et Arduino Nano (ATmega328P [Old Bootloader]) via Arduino IDE v1.8.8
// Changement v1.0 > v1.1 : dayOfWeek == 1 au lieu de 7 dans displayTime() pour détection correcte du dimanche

/* Théorie pour la matrice ht16k33 ... (identique v1.0) */

#include <Wire.h>
#include <Adafruit_GFX.h>
#include "Adafruit_LEDBackpack.h"

#define DS3231_I2C_ADDRESS 0x68

int ldr_sensor = A0;
int ldr_value = 0;
int brightness_matrix;
int threshold_brightness = 400;
int blinkrate_value = 0;
int delay_matrix_time = 20;
int delay_matrix_temp = 2000;
int blinky_dot = 2;

Adafruit_7segment matrix = Adafruit_7segment();

byte decToBcd(byte val) { return ((val / 10 * 16) + (val % 10)); }
byte bcdToDec(byte val) { return ((val / 16 * 10) + (val % 16)); }

void setup() {
  Serial.begin(9600);
  Wire.begin();
  matrix.begin(0x70);
}

void loop() {
  lightBrightness();
  matrixBlinkrate();
  displayTime();
  displayTemp();
}

void lightBrightness() {
  ldr_value = analogRead(ldr_sensor);
  Serial.print("LDR: "); Serial.println(ldr_value);
  if (ldr_value <= threshold_brightness) brightness_matrix = 0;
  else brightness_matrix = 15;
}

void matrixBlinkrate() { matrix.blinkRate(blinkrate_value); }

void displayTime() {
  matrix.setBrightness(brightness_matrix);
  matrix.clear();
  for (uint16_t i = 0; i < delay_matrix_time; i++) {
    byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
    getDateDs3231(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
    byte se = second, mi = minute, ho = hour, we = dayOfWeek;
    byte dm = dayOfMonth, mo = month, ye = year;

    // Passage heure d'été - dernier dimanche de mars à 2h (dayOfWeek == 1 = dimanche)
    if ((dayOfWeek == 1) && (dayOfMonth >= 25) && (month == 3) && (hour == 2)) {
      setDS3231time(se, mi, 3, we, dm, mo, ye);
    }
    // Passage heure d'hiver
    if ((dayOfWeek == 1) && (dayOfMonth >= 25) && (month == 10) && (hour == 1) && (year != 1)) {
      setDS3231time(se, mi, ho, we, dm, mo, 1);
    }
    if ((dayOfWeek == 1) && (dayOfMonth >= 25) && (month == 10) && (hour == 3) && (year == 1)) {
      setDS3231time(se, mi, 2, we, dm, mo, 0);
    }

    if (hour > 9) {
      matrix.writeDigitNum(0, (hour / 10), false);
      matrix.writeDigitNum(1, (hour % 10), false);
    } else {
      matrix.writeDigitNum(1, hour, false);
    }

    if (se <= 30) blinky_dot = 10;
    else if (se > 30) blinky_dot = 6;

    matrix.writeDigitRaw(2, blinky_dot);
    matrix.writeDigitNum(3, (minute / 10), false);
    matrix.writeDigitNum(4, (minute % 10), false);
    matrix.writeDisplay();
    delay(500);
    matrix.drawColon(false);
    matrix.writeDisplay();
    delay(500);
  }
}

void displayTemp() {
  matrix.setBrightness(brightness_matrix);
  matrix.clear();
  byte temp = get3231Temp();
  int abs_temp = abs(temp);
  matrix.writeDigitNum(1, (abs_temp % 10), false);
  if (temp < 0) matrix.writeDigitRaw(0, 64);
  if (temp <= -10) matrix.writeDigitRaw(2, 12);
  if (temp >= 10) matrix.writeDigitNum(0, (abs_temp / 10), false);
  if (temp <= -10) matrix.writeDigitNum(0, (abs_temp / 10), false);
  matrix.writeDigitRaw(3, 99);
  matrix.writeDigitRaw(4, 57);
  matrix.writeDisplay();
  Serial.print("Température en C: ");
  Serial.println(get3231Temp());
  delay(delay_matrix_temp);
}

void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year) {
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0);
  Wire.write(decToBcd(second));
  Wire.write(decToBcd(minute));
  Wire.write(decToBcd(hour));
  Wire.write(decToBcd(dayOfWeek));
  Wire.write(decToBcd(dayOfMonth));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(year));
  Wire.endTransmission();
}

void getDateDs3231(byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month, byte *year) {
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}

float get3231Temp() {
  byte tMSB, tLSB;
  float temp3231;
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0x11);
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 2);
  if (Wire.available()) {
    tMSB = Wire.read();
    tLSB = Wire.read();
    temp3231 = (tMSB & B01111111);
    temp3231 += ((tLSB >> 6) * 0.25);
    return temp3231;
  } else {
    Serial.println("DS3231 Sensor Error - cant read temperature");
    matrix.print(0xBEEF, HEX);
    matrix.writeDisplay();
    delay(5000);
  }
}
GitHub

https://github.com/ILohs/MySketches

Schémas

Chemin LDR corrigé

Construisez une Horloge 7 Segments avec Arduino Nano, DS3231 RTC et Luminosité Auto LDR
Construisez une Horloge 7 Segments avec Arduino Nano, DS3231 RTC et Luminosité Auto LDR

Processus de fabrication

  1. Horloge POV Arduino : Construire un affichage LED à persistance rétinienne
  2. Construire une horloge Numitron rétro avec Arduino : simple, fiable et économe en énergie
  3. Construire une horloge murale design avec anneaux Neopixel 60 LED Adafruit et Arduino
  4. Horloge Arduino temps réel pour les heures de prière islamiques
  5. Construire une horloge maître LED personnalisée avec alarme – Visible à 12 mètres
  6. Moniteur de Température et Horloge Temps Réel Arduino avec Écran TFT 3.2"
  7. Contrôler 2 moteurs pas-à-pas avec Arduino Nano et joystick – Tutoriel Visuino
  8. Montre connectée Arduino DIY : Construisez votre propre montre style Apple Watch
  9. Construire un Réveil Fiable avec RTC DS1302 et Arduino UNO