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

Mini horloge matricielle LED

Composants et fournitures

Arduino Nano R3
× 1
Maxim Integrated DS3231M - ±5 ppm, horloge temps réel I2C
× 1
Bouton-poussoir, momentané
× 2
Module matriciel LED 32x8
× 1

Outils et machines nécessaires

Fer à souder (générique)

Applications et services en ligne

Arduino IDE

À propos de ce projet

Sur la page " Nick's LED Projects ", j'ai trouvé un projet d'horloge affichant l'heure sur 4 matrices avec 8x8 leds. Il a construit l'horloge avec des matrices du magasin "ICStation" qui vend des kits de bricolage pour panneaux de modules matriciels.

Avec un changement minime dans le code, j'ai fait mon horloge avec l'écran quatre en un du module matriciel MAX7219 qui est complètement plié et est beaucoup moins cher. Je l'ai acheté sur AliExpress.

L'horloge a de nombreuses fonctionnalités :

- Mode basique avec gros chiffres

- Mode diapositive où les chiffres défilent sur et hors de l'écran

- Petits chiffres avec mode secondes

- Temps écrit en mots, par ex. « midi dix »

- Affichage de la date

- Option 12/24 heures

- Option luminosité

- Option de mode d'horloge aléatoire qui change le mode d'affichage toutes les quelques heures.

- Menus pilotés par bouton-poussoir pour la configuration et la sélection de l'affichage.

Comme vous pouvez le voir sur le circuit, à l'exception des matrices, nous avons besoin d'une carte arduino, d'un module d'horloge temps réel et de deux boutons poussoirs pour les réglages. Vous pouvez télécharger des bibliothèques et du code modifié sur les liens ci-dessous.

Code

  • code
  • Bibliothèques
codeArduino
/************************************************ *************************Mini Clock v1.0, juillet 2014 par Nick HallDistribué sous les termes de la GPL.Pour obtenir de l'aide sur la façon de construire le horloge voir mon blog:http://123led.wordpress.com/Tested on IDE v1.6.5 ******************************* ****************************************** ///bibliothèques d'inclusion :#include "LedControl.h"#include // Bibliothèque de polices#include // Horloge DS1307#include "RTClib.h" // Horloge DS1307#include // Bibliothèque de boutons par Alexander Brevig// Setup LED Matrix// la broche 12 est connectée au DataIn sur l'affichage// la broche 11 est connectée au CLK sur l'affichage// la broche 10 est connectée à LOAD sur l'affichageLedControl lc =LedControl (12, 11, 10, 4); // définit les 3 broches comme 12, 11 et 10, puis définit 4 affichages (le maximum est de 8 affichages) // intensité de l'octet de variables globales =7 ; // Intensité/luminosité par défaut (0-15) byte clock_mode =0; // Mode d'horloge par défaut. Par défaut =0 (basic_mode) bool random_mode =0 ; // Définir le mode aléatoire - change le type d'affichage toutes les quelques heures. Par défaut =0 (désactivé) octet old_mode =clock_mode ; // Stocke le mode d'horloge précédent, donc si nous allons à date ou autre, nous savons à quel mode revenir après.bool ampm =0; // Définit l'heure de 12 ou 24 heures. 0 =24 heures. 1 =12 heures octet change_mode_time =0 ; // Maintient l'heure lorsque le mode d'horloge changera ensuite si en mode aléatoire.unsigned long delaytime =500; // On attend toujours un peu entre les mises à jour du displayint rtc[7]; // Contient la sortie de l'horloge en temps réelchar days[7][4] ={ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"} ; //tableau de jour - utilisé dans les modes slide, basic_mode et jumble (le DS1307 génère 1 à 7 valeurs pour le jour de la semaine)char daysfull[7][9] ={ "Dimanche", "Lundi", "Mardi", "Mer ", "Jeudi", "Vendredi", "Samedi"};suffixe de caractère[4][3] ={ "st", "nd", "rd", "th"}; // tableau de suffixes de date, utilisé dans les modes slide, basic_mode et jumble. e,g, 1st 2nd ...//define constants#define NUM_DISPLAY_MODES 3 // Modes d'affichage des nombres (contenant zéro comme premier mode)#define NUM_SETTINGS_MODES 4 // Modes de réglage des nombres =6 (contenant zéro comme premier mode)# define SLIDE_DELAY 20 // Le temps en millisecondes pour l'effet de diapositive par caractère en mode diapositive. Augmentez-le pour un effet plus lent#define cls clear_display // Effacer displayRTC_DS1307 ds1307; // Créer un objet RTC Button ButtonA =Button(2, BUTTON_PULLUP); // Configurer le bouton A (à l'aide de la bibliothèque de boutons) Button buttonB =Button(3, BUTTON_PULLUP); // Configurer le bouton B (à l'aide de la bibliothèque de boutons) void setup() { digitalWrite(2, HIGH); // activer la résistance pullup pour le bouton sur la broche 2 digitalWrite (3, HIGH); // activer la résistance pullup pour le bouton sur la broche 3 digitalWrite(4, HIGH); // activer la résistance pullup pour le bouton sur la broche 4 Serial.begin (9600); //démarrer la série //initialiser les 4 panneaux matriciels //nous avons déjà défini le nombre de périphériques lorsque nous avons créé le LedControl int devices =lc.getDeviceCount(); //nous devons initialiser tous les périphériques dans une boucle pour (int address =0; address =0 &&x <=7) { adresse =3; } si (x>=8 &&x <=15) { adresse =2; x =x - 8 ; } si (x>=16 &&x <=23) { adresse =1; x =x - 16 ; } si (x>=24 &&x <=31) { adresse =0; x =x - 24 ; } if (val ==1) { lc.setLed(adresse, y, x, vrai); } else { lc.setLed(adresse, y, x, faux); }}//clear screenvoid clear_display() { for (byte address =0; address <4; address++) { lc.clearDisplay(address); }}//fondu écran downvoid fade_down() { //fondu de l'intensité globale à 1 pour (octet i =intensité; i> 0; i--) { pour (adresse d'octet =0; adresse <4; adresse++) { lc .setIntensity(adresse, i); } délai(30); //changer ceci pour changer la vitesse de fondu enchaîné } clear_display(); //effacer complètement l'affichage (désactivé) //réinitialiser l'intention à la valeur globale pour (adresse d'octet =0 ; adresse <4 ; adresse++) { lc.setIntensity(adresse, intensité); }}//mise sous tension de la led de test et d'affichage du numéro de version du logicielvoid printver() { octet i =0 ; char ver_a[9] ="Vers 1.0" ; char ver_b[9] =" Bonjour ! " ; //tester toutes les leds. for (byte x =0; x <=31; x++) { for (byte y =0; y <=7; y++) { plot(x, y, 1); } } délai (500); fade_down(); while (ver_a[i]) { puttinychar((i * 4), 1, ver_a[i]); retard (35); je++ ; } délai (700); fade_down(); je =0 ; while (ver_b[i]) { puttinychar((i * 4), 1, ver_b[i]); retard (35); je++ ; } délai (700); fade_down();}// puttinychar// Copie un glyphe de 3x5 caractères de la structure de données myfont pour afficher la mémoire, avec son coin supérieur gauche à la coordonnée donnée// Ceci n'est pas optimisé et utilise simplement plot() pour dessiner chaque dot.void puttinychar (octet x, octet y, caractère c) { octet points ; if (c>='A' &&c <='Z' || (c>='a' &&c <='z') ) { c &=0x1F; // A-Z correspond à 1-26 } else if (c>='0' &&c <='9') { c =(c - '0') + 32; } else if (c ==' ') { c =0; // espace } else if (c =='.') { c =27; // point } else if (c ==':') { c =28; // deux-points } else if (c =='\'') { c =29; // guillemet simple } else if (c =='!') { c =30; // guillemet simple } else if (c =='?') { c =31; // guillemet simple } pour (byte col =0; col <3; col++) { dots =pgm_read_byte_near(&mytinyfont[c][col]); for (char row =0; row <5; row++) { if (dots &(16>> row)) plot(x + col, y + row, 1); else plot(x + col, y + ligne, 0); } }}void putnormalchar(octet x, octet y, char c){ octet points ; // si (c>='A' &&c <='Z' || (c>='a' &&c <='z') ) { // c &=0x1F; // A-Z correspond à 1-26 // } if (c>='A' &&c <='Z' ) { c &=0x1F; // A-Z correspond à 1-26 } else if (c>='a' &&c <='z') { c =(c - 'a') + 41; // A-Z correspond à 41-67 } else if (c>='0' &&c <='9') { c =(c - '0') + 31; } else if (c ==' ') { c =0; // espace } else if (c =='.') { c =27; // point final } else if (c =='\'') { c =28; // guillemet simple } else if (c ==':') { c =29; // flèche de sélection de mode horloge } else if (c =='>') { c =30; // flèche du sélecteur de mode d'horloge } else if (c>=-80 &&c <=-67) { c *=-1; } pour (char col =0; col <5; col++) { points =pgm_read_byte_near(&myfont[c][col]); for (char row =0; row <7; row++) { //vérifier que les coordonnées sont à l'écran avant d'essayer de tracer //if ((x>=0) &&(x <=31) &&(y>=0) &&(y <=7)){ if (dots &(64>> row)) { // seulement 7 lignes. plot(x + col, y + ligne, 1); } else { plot(x + col, y + ligne, 0); } //} } }}//small_mode//afficher l'heure en petits caractères 3x5 avec secondes displayvoid small_mode() { char textchar[8]; // les 16 caractères sur l'octet d'affichage mins =100; //mins octet secs =rtc[0]; //secondes octet old_secs =secs; //contient l'ancienne valeur des secondes - depuis la dernière mise à jour des secondes ou affichage - utilisé pour vérifier si les secondes ont changé cls(); // exécute la boucle principale de l'horloge tant que run_mode renvoie true while (run_mode()) { get_time(); //vérification de l'appui sur le bouton if (buttonA.uniquePress()) { switch_mode(); retourner; } if (boutonB.uniquePress()) { display_date(); retourner; } //si les secs ont changé, mettez-les à jour sur l'affichage secs =rtc[0]; if (secs !=old_secs) { //secs char buffer[3]; itoa(secs, buffer, 10); //fix - comme sinon si num a un zéro non significatif, par ex. "03" secondes, itoa le convertit en caractères avec un espace "3". if (secs <10) { buffer[1] =buffer[0]; tampon[0] ='0'; } puttinychar( 20, 1, ':'); //secondes deux-points puttinychar( 24, 1, buffer[0]); //secondes puttinychar( 28, 1, buffer[1]); //secondes old_secs =secs; } //si les minutes changent, changez l'heure if (mins !=rtc[1]) { //réinitialisez-les pour comparaison la prochaine fois mins =rtc[1]; octet heures =rtc[2] ; if (heures> 12) { heures =heures - ampm * 12; } if (heures <1) { heures =heures + ampm * 12; } //octet dow =rtc[3]; // le DS1307 sort 0 - 6 où 0 =dimanche0 - 6 où 0 =dimanche. //date d'octet =rtc[4]; //définir les caractères char buffer[3] ; itoa(heures, tampon, 10); //fix - comme sinon si num a un zéro non significatif, par ex. "03" heures, itoa le convertit en caractères avec un espace "3". if (heures <10) { buffer[1] =buffer[0]; //si nous sommes en mode 12 heures, videz le zéro non significatif. if (ampm) { buffer[0] =' '; } else { buffer[0] ='0'; } } //définir les heures chars textchar[0] =buffer[0]; textchar[1] =tampon[1] ; textchar[2] =':'; itoa (minutes, tampon, 10); if (mins <10) { buffer[1] =buffer[0] ; tampon[0] ='0'; } //définir les caractères min. textchar[3] =buffer[0]; textchar[4] =tampon[1]; //faire des secondes textchar[5] =':'; tampon [3] ; secondes =rtc[0] ; itoa(secs, buffer, 10); //fix - comme sinon si num a un zéro non significatif, par ex. "03" secondes, itoa le convertit en caractères avec un espace "3". if (secs <10) { buffer[1] =buffer[0]; tampon[0] ='0'; } //définir les secondes textchar[6] =buffer[0]; textchar[7] =tampon[1]; octet x =0 ; octet y =0 ; // affiche chaque caractère pour (octet x =0; x <6; x++) { puttinychar( x * 4, 1, textchar[x]); } } retard (50); } fade_down();}// basic_mode()// afficher l'heure en 5x7 caractèresvoid basic_mode(){ cls(); tampon de caractères[3] ; //pour la conversion int en char pour transformer les valeurs rtc en caractères, nous pouvons imprimer à l'écran byte offset =0; //utilisé pour décaler la position x des chiffres et centrer l'affichage lorsque nous sommes en mode 12 heures et que l'horloge n'affiche que 3 chiffres. par exemple. 3:21 octets x, y ; //utilisé pour dessiner une case transparente sur le "1" à gauche de l'affichage lorsque nous roulons de 12h59 à 1h00 en mode 12 heures. // effectuer une conversion 12/24 heures si ampm est défini sur 1 octet heures =rtc[2] ; if (heures> 12) { heures =heures - ampm * 12; } if (heures <1) { heures =heures + ampm * 12; } // effectuer une conversion de décalage if (ampm &&hours <10) { offset =2; } //définir la prochaine minute où nous affichons la date à //set_next_date(); // initialement défini mins sur la valeur 100 - il n'équivaudra donc jamais à rtc[1] sur la première boucle de l'horloge, ce qui signifie que nous dessinons l'affichage de l'horloge lorsque nous entrons dans la fonction byte secs =100; octet min =100 ; nombre entier =0 ; // exécute la boucle principale de l'horloge tant que run_mode renvoie true while (run_mode()) { // obtient l'heure de la puce d'horloge get_time(); //vérification de l'appui sur le bouton if (buttonA.uniquePress()) { switch_mode(); retourner; } if (boutonB.uniquePress()) { display_date(); retourner; } //vérifie s'il est temps d'afficher automatiquement la date //check_show_date(); //dessine le clignotant :comme si les secondes ont changé. if (secs !=rtc[0]) { //mettre à jour les secondes avec la nouvelle valeur secs =rtc[0]; //dessiner :tracé (15 - décalage, 2, 1); // top point plot (15 - offset, 5, 1); //nombre de points inférieurs =400 ; } //si le nombre est épuisé, désactivez le :if (count ==0) { plot (15 - offset, 2, 0); // top point plot (15 - offset, 5, 0); //point inférieur } else { count--; } // redessiner l'affichage si le bouton est enfoncé ou si mins !=rtc[1] c'est-à-dire si l'heure a changé par rapport à ce que nous avions stocké en minutes, (également déclenché lors de la première entrée de fonction lorsque mins est de 100) if (mins !=rtc[1]) { //mettre à jour les minutes et les heures avec les nouvelles valeurs mins =rtc[1]; heures =rtc[2]; // ajuste les heures d'ampm ​​en mode 12 heures if (hours> 12) { hours =hours - ampm * 12; } if (heures <1) { heures =heures + ampm * 12; } itoa(heures, tampon, 10); //si heures <10 le num ex. "3" heures, itoa convertit cela en caractères avec un espace "3" dont nous ne voulons pas si (heures <10) { buffer[1] =buffer[0]; tampon[0] ='0'; } //imprimer les heures //si nous sommes en mode 12 heures et heures <10, alors n'imprimons pas le zéro non significatif et définissons le décalage de manière à centrer l'affichage sur 3 chiffres. if (ampm &&heures <10) { décalage =2; // s'il est 1h00 du matin, effacez tout l'affichage car le décalage change à ce moment-là et nous devons effacer l'ancien 12h59 if ((hours ==1 &&mins ==0) ) { cls(); } } else { // else pas de décalage et impression des dizaines de chiffres des heures décalage =0; // s'il est 10h00, effacez tout l'affichage car le décalage change à ce moment-là et nous devons effacer l'ancien 9h59 if (hours ==10 &&mins ==0) { cls(); } putnormalchar(1, 0, buffer[0]); } // affiche les chiffres des heures putnormalchar(7 - offset, 0, buffer[1]); //print mins //ajout d'un zéro non significatif si mins <10 itoa (mins, buffer, 10); if (mins <10) { buffer[1] =buffer[0] ; tampon[0] ='0'; } // imprime les chiffres des dizaines et des unités putnormalchar(19 - offset, 0, buffer[0]); putnormalchar (25 - décalage, 0, tampon[1]); } } fade_down();}//comme basic_mode mais avec slide effectvoid slide() { byte digits_old[4] ={99, 99, 99, 99}; //anciennes valeurs dans lesquelles nous stockons l'heure. Défini sur quelque chose qui ne correspondra jamais à l'heure initialement afin que tous les chiffres soient dessinés lorsque le mode commence par l'octet digits_new[4] ; // l'heure des nouveaux chiffres glissera pour révéler l'octet digits_x_pos[4] ={25, 19, 7, 1} ; //x pos pour lequel dessiner chaque chiffre à char old_char[2]; //utilisé lorsque nous utilisons itoa pour transposer le chiffre courant (type byte) en un char à passer à la fonction d'animation char new_char[2]; //utilisé lorsque nous utilisons itoa pour transposer le nouveau chiffre (type byte) en un caractère à transmettre à la fonction d'animation //old_chars - stocke les 5 caractères de suffixe du jour et de la date à l'écran. par exemple. "mon" et "st". Nous les insérons dans l'animation de la diapositive en tant que caractère actuel lorsque ces caractères sont mis à jour. //Nous les avons initialement envoyés en tant que A, qui sont utilisés lorsque le clocl entre en mode et qu'aucun dernier caractère n'est stocké. //car vieux_cars[6] ="AAAAA"; // tracer les deux points de l'horloge sur l'affichage cls(); putnormalchar( 13, 0, ':'); octet old_secs =rtc[0] ; //stocker les secondes dans old_secs. Nous comparons les secondes et les anciennes secondes. Lorsqu'ils sont différents, nous redessinons l'affichage //run clock main loop tant que run_mode renvoie true while (run_mode()) { get_time(); //vérification de l'appui sur le bouton if (buttonA.uniquePress()) { switch_mode(); retourner; } if (boutonB.uniquePress()) { display_date(); retourner; } //si les secondes ont changé, mettez à jour l'affichage if (rtc[0] !=old_secs) { old_secs =rtc[0]; // effectuer une conversion 12/24 heures si ampm est défini sur 1 octet heures =rtc[2] ; if (heures> 12) { heures =heures - ampm * 12; } if (heures <1) { heures =heures + ampm * 12; } // diviser toute la date et l'heure en chiffres individuels - coller dans le tableau digits_new //rtc[0] =secs //array pos et digit stocké //digits_new[0] =(rtc[0]%10) ; //0 - secondes //digits_new[1] =((rtc[0]/10)%10) ; //1 - secondes dizaines //rtc[1] =min digits_new[0] =(rtc[1] % 10); //2 - minutes chiffres_nouveau[1] =((rtc[1] / 10) % 10); //3 - minutes dizaines //rtc[2] =heures digits_new[2] =(heures % 10); //4 - heures chiffres_nouveau[3] =((heures / 10) % 10); ///5 - dizaines d'heures //rtc[4] =date //digits_new[6] =(rtc[4]%10) ; ///6 - date //chiffres_nouveau[7] =((rtc[4]/10)%10) ; //7 - date des dizaines //dessine l'écran initial de tous les caractères. Après cela, nous dessinons simplement les modifications. //comparer les chiffres 0 à 3 (minutes et heures) pour (octet i =0; i <=3; i++) { // voir si le chiffre a changé... if (chiffres_ancien[i] !=chiffres_nouveau[i]) { // exécuter une séquence d'animation en 9 étapes pour chacun à son tour pour (byte seq =0; seq <=8; seq++) { // convertir le chiffre en chaîne itoa (chiffres_old[i], old_char, 10); itoa(chiffres_nouveau[i], nouveau_car, 10); // si défini sur le mode 12 heures et que nous sommes sur le chiffre 2 (mode dizaines d'heures), vérifiez s'il s'agit d'un zéro. Si c'est le cas, videz-le à la place afin que nous obtenions 14h00 et non 14h00 if (ampm &&i ==3) { if (digits_new[3] ==0) { new_char[0] =' '; } if (chiffres_old[3] ==0) { old_char[0] =' '; } } //dessine le cadre d'animation pour chaque chiffre slideanim(digits_x_pos[i], 0, seq, old_char[0], new_char[0]); retard(SLIDE_DELAY); } } } /* //comparer le chiffre de date 6 (unités) et (7) dizaines - si l'un de ces changements change, nous devons mettre à jour la ligne de date. Nous comparons les dizaines de dates du 31 janvier au 01 février, puis le chiffre des uns ne change pas si ((digits_old[6] !=digits_new[6]) || (digits_old[7] !=digits_new[7])) { //changer le jour affiché. La boucle ci-dessous parcourt chacun des 3 caractères à tour de rôle, par ex. "MON" for (byte day_char =0; day_char <=2; day_char++){ //exécuter la séquence d'animation pour chaque caractère pour (byte seq =0; seq <=8; seq++){ //le jour (0 - 6 ) Lisez ce nombre dans le tableau de caractères days. le nombre de secondes dans le tableau 0-2 obtient les 3 caractères du nom du jour, par ex. m o n slideanim(6*day_char,8,seq,old_chars[day_char],days[rtc[3]][day_char]); //6 x day_char nous donne le x pos pour le char delay(SLIDE_DELAY); } // enregistre les anciens caractères du jour dans le tableau old_chars à la position 0-2 du tableau. Nous l'utilisons la prochaine fois que nous changeons le jour et le transmettons à l'animation en tant que caractère actuel. Le caractère mis à jour est introduit en tant que nouveau caractère. old_chars[day_char] =jours[rtc[3]][day_char] ; } //changer le chiffre des dizaines de la date (si nécessaire) et le chiffre des unités. (le chiffre de la date changera toujours, mais le mettre dans la boucle 'if' le rend un peu plus propre au code.) for (byte i =7; i>=6; i--){ if (digits_old[i] !=digits_new[i]) { for (byte seq =0; seq <=8; seq++){ itoa(digits_old[i],old_char,10) ; itoa(chiffres_nouveau[i],nouveau_car,10) ; slideanim(digits_x_pos[i],8,seq,old_char[0],new_char[0]); retard(SLIDE_DELAY); } } } // affiche le suffixe du jour "nd" "rd" "th" etc. Premier calcul de la date suffixe de 2 lettres - par exemple st, nd, rd, th byte s =3; //la pos à partir de laquelle lire notre tableau de suffixes. octet date =rtc[4] ; if(date ==1 || date ==21 || date ==31) { s =0; } else if (date ==2 || date ==22) { s =1; } else if (date ==3 || date ==23) { s =2; } for (byte suffix_char =0; suffix_char <=1; suffix_char++){ for (byte seq =0; seq <=8; seq++){ slideanim((suffix_char*6)+36,8,seq,old_chars[suffix_char+3 ],suffixe[s][suffix_char]); // nous passons le tableau old_char char comme caractère courant et le tableau suffixe comme nouveau char delay(SLIDE_DELAY); } // enregistre le suffixe dans l'ancien tableau de caractères aux positions 3 et 5 du tableau. Nous utiliserons ces caractères la prochaine fois que nous modifierons le suffixe et l'alimenterons en animation en tant que caractère actuel. Le caractère mis à jour est introduit en tant que nouveau caractère. old_chars[suffix_char+3] =suffix[s][suffix_char] ; } }//fin de la ligne de date */ //sauvegarde du tableau de chiffres tol old pour comparaison prochaine boucle pour (byte i =0; i <=3; i++) { digits_old[i] =digits_new[i]; } }//secs/oldsecs }//while loop fade_down();}//appelé par slide//cela dessine l'animation d'un char glissant et l'autre glissant. Il y a 8 étapes dans l'animation, nous appelons la fonction pour dessiner l'une des étapes de 0-7 // les entrées sont char x et y, la séquence d'images d'animation (0-7) et les caractères actuels et nouveaux en cours de dessin.void slideanim(byte x, byte y, byte sequence, char current_c, char new_c) { // Pour faire glisser un caractère et un autre, nous avons besoin de 9 étapes ou cadres en séquence... // seq# 0123456 <-lignes de l'affichage // | ||||||| // seq0 0123456 START - toutes les lignes de l'affichage 0-6 affichent les caractères actuels lignes 0-6 // seq1 012345 le caractère actuel descend d'une ligne sur l'affichage. Nous ne voyons que les lignes 0-5. Il y a aux positions d'affichage 1-6 Il y a une ligne vide insérée en haut // seq2 6 01234 le caractère actuel descend de 2 lignes. nous ne voyons maintenant que les lignes 0-4 sur les lignes d'affichage 2-6 à l'écran. La ligne 1 de l'écran est vide. La ligne 0 affiche la ligne 6 du nouveau caractère // seq3 56 0123 // seq4 456 012 moitié ancien / moitié nouveau caractère // seq5 3456 01 // seq6 23456 0 // seq7 123456 // seq8 0123456 FIN - toutes les lignes affichent le nouveau char // d'en haut, nous pouvons voir... // currentchar exécute 0-6 puis 0-5 puis 0-4 jusqu'à 0. La position Y de départ augmente d'une ligne à chaque fois. //le nouveau caractère exécute 6 puis 5-6 puis 4-6 puis 3-6. la position Y de départ augmente d'un rang à chaque fois. //si le numéro de séquence est inférieur à 7, nous devons dessiner le caractère actuel if (sequence <7) { byte dots; // if (current_c>='A' &&|| (current_c>='a' &¤t_c <='z') ) { // current_c &=0x1F; // A-Z correspond à 1-26 // } if (current_c>='A' &¤t_c <='Z' ) { current_c &=0x1F; // A-Z correspond à 1-26 } else if (current_c>='a' &¤t_c <='z') { current_c =(current_c - 'a') + 41; // A-Z correspond à 41-67 } else if (current_c>='0' &¤t_c <='9') { current_c =(current_c - '0') + 31; } else if (current_c ==' ') { current_c =0; // espace } else if (current_c =='.') { current_c =27; // point final } else if (current_c =='\'') { current_c =28; // guillemet simple } else if (current_c ==':') { current_c =29; //deux-points } else if (current_c =='>') { current_c =30; // flèche du sélecteur de mode d'horloge } octet curr_char_row_max =7 - séquence; //le nombre maximum de lignes à dessiner est 6 - numéro de séquence octet start_y =séquence; // position y pour commencer - est identique au numéro de séquence. Nous incisons cette boucle // tracer chaque ligne jusqu'à la ligne maximale (calculée à partir du numéro de séquence) pour (byte curr_char_row =0; curr_char_row <=curr_char_row_max; curr_char_row++) { for (byte col =0; col <5; col++) { points =pgm_read_byte_near(&myfont[current_c][col]); if (dots &(64>> curr_char_row)) plot(x + col, y + start_y, 1); //plot conduit sur else plot(x + col, y + start_y, 0); //else plot led off } start_y++;//ajouter un à y pour que nous dessinions la ligne suivante un vers le bas } } //trace une ligne vide entre les caractères si la séquence est comprise entre 1 et 7. Si nous ne le faisons pas, nous obtenons les restes des caractères actuels dernière position laissée sur l'affichage if (sequence>=1 &&sequence <=8) { for (byte col =0; col <5; col++) { plot(x + col, y + (sequence - dix); //la position y pour tracer la ligne est équivalente au numéro de séquence - 1 } } //si la séquence est supérieure à 2, nous devons également commencer à dessiner le nouveau caractère if (séquence>=2) { //travailler sur l'octet de caractère points; //if (new_c>='A' &&new_c <='Z' || (new_c>='a' &&new_c <='z') ) { // new_c &=0x1F; // A-Z correspond à 1-26 //} if (new_c>='A' &&new_c <='Z' ) { new_c &=0x1F; // A-Z correspond à 1-26 } else if (new_c>='a' &&new_c <='z') { new_c =(new_c - 'a') + 41; // A-Z correspond à 41-67 } else if (new_c>='0' &&new_c <='9') { new_c =(new_c - '0') + 31; } else if (new_c ==' ') { new_c =0; // espace } else if (new_c =='.') { new_c =27; // point final } else if (new_c =='\'') { new_c =28; // guillemet simple } else if (new_c ==':') { new_c =29; // flèche du sélecteur de mode d'horloge } else if (new_c =='>') { new_c =30; // arrow_mode selector arrow } octet newcharrowmin =6 - (séquence - 2); // num de ligne minimum à dessiner pour le nouveau caractère - cela génère une sortie de 6 à 0 lorsque les numéros de séquence 2-8 sont alimentés. Il s'agit de la ligne minimale à dessiner pour le nouvel octet de char start_y =0 ; // position y pour commencer - est identique au numéro de séquence. nous l'incisons à chaque ligne // tracer chaque ligne vers le haut à partir de la ligne minimale (calculée par le numéro de séquence) jusqu'à 6 pour (byte newcharrow =newcharrowmin; newcharrow <=6; newcharrow++) { for (byte col =0; col <5; col++ ) { points =pgm_read_byte_near(&myfont[new_c][col]); if (dots &(64>> newcharrow)) plot(x + col, y + start_y, 1); //plot conduit sur else plot(x + col, y + start_y, 0); //else plot led off } start_y++;//ajoute un à y pour que nous dessinions la ligne suivante un vers le bas } }}//imprime une horloge en utilisant des mots plutôt que des nombres void word_clock() { cls(); nombres de caractères[19][10] ={ "un", "deux", "trois", "quatre", "cinq", "six", "sept", "huit", "neuf", "dix", "onze", "douze", "treize", "quatorze", "quinze", "seize", "dix-sept", "dix-huit", "dix-neuf" } ; char nombrestens[5][7] ={ "dix", "vingt", "trente", "quarante", "cinquante" } ; //potentiellement 3 lignes pour afficher char str_a[8]; char str_b[8]; char str_c[8]; //octet heures_y, mins_y ; //heures et minutes et positions pour les lignes heures et minutes octet heures =rtc[2]; if (heures> 12) { heures =heures - ampm * 12; } if (heures <1) { heures =heures + ampm * 12; } obtenir du temps(); // obtient l'heure à partir de l'octet de puce d'horloge old_mins =100; //stocker les minutes dans old_mins. Nous comparons les minutes et les anciennes minutes et lorsqu'elles sont différentes, nous redessinons l'affichage. Réglez-le sur 100 initialement pour que l'affichage soit dessiné lorsque le mode démarre. minutes d'octet ; // exécute la boucle principale de l'horloge tant que run_mode renvoie true while (run_mode()) { //vérifie si le bouton est pressé if (buttonA.uniquePress()) { switch_mode(); retourner; } if (boutonB.uniquePress()) { display_date(); } obtenir du temps(); // obtenir l'heure de la puce d'horloge mins =rtc[1]; //get mins //si mins est différent de old_mins - redessine l'affichage if (mins !=old_mins) { //mettre à jour old_mins avec la valeur actuelle des minutes old_mins =mins; //réinitialiser ces derniers pour comparaison la prochaine fois mins =rtc[1]; heures =rtc[2]; //transformer les heures au format 12 heures if (hours> 12) { hours =hours - 12; } if (heures ==0) { heures =12; } // diviser la valeur min en deux chiffres séparés int minsdigit =rtc[1] % 10; octet minsdigitten =(rtc[1] / 10) % 10 ; //si mins <=10 , alors la ligne du haut doit lire "minsdigti past" et la ligne du bas lit les heures if (mins <10) { strcpy (str_a, numbers[minsdigit - 1]); strcpy (str_b, "PASSÉ"); strcpy (str_c, nombres[heures - 1]); } //si mins =10, impossible d'utiliser minsdigit comme ci-dessus, donc cas particulier pour imprimer 10 dernières /n heure. if (mins ==10) { strcpy (str_a, nombres[9]); strcpy (str_b, " PASSÉ"); strcpy (str_c, nombres[heures - 1]); } //si l'heure n'est pas sur l'heure - c'est-à-dire que les deux chiffres des minutes ne sont pas nuls, //alors la première ligne lit "heures" et les 2 et 3ème lignes lisent "minstens" "mins", par ex. "trois /n vingt /n un" else if (minsdigitten !=0 &&minsdigit !=0 ) { strcpy (str_a, numbers[hours - 1]); // si mins est dans les ados, utilisez les ados du tableau de nombres pour la 2ème ligne, par ex. "quinze" //if (mins>=11 &&mins <=19) { if (mins <=19) { strcpy (str_b, nombres[mins - 1]); } else { strcpy (str_b, numbertens[minsdigitten - 1]); strcpy (str_c, nombres[minsdigit - 1]); } } // si le chiffre des minutes est zéro, ne l'imprime pas. lire lire "heures" "minstens" ex. "trois /n vingt" else if (minsdigitten !=0 &&minsdigit ==0 ) { strcpy (str_a, numbers[hours - 1]); strcpy (str_b, numbertens[minsdigitten - 1]); strcpy (str_c, ""); } //si les deux minutes sont à zéro, c'est-à-dire que c'est à l'heure, la ligne du haut indique "heures" et la ligne du bas indique "heures" else if (minsdigitten ==0 &&minsdigit ==0 ) { strcpy (str_a, nombres[heures - 1]); strcpy (str_b, "HORLOGE"); strcpy (str_c, ""); } }//fin de l'heure de travail //exécution en boucle //impression de la ligne un "douze" octet len ​​=0; while (str_a[len]) { len++; } ; // obtenir la longueur de l'octet du message offset_top =(31 - ((len - 1) * 4)) / 2; // //tracer les heures de la ligne octet i =0; while (str_a[i]) { puttinychar((i * 4) + offset_top, 1, str_a[i]); je++ ; } //maintenir l'affichage mais vérifier les pressions sur les boutons int counter =1000; while (counter> 0){ //vérification de l'appui sur le bouton if (buttonA.uniquePress()) { switch_mode(); retourner; } if (boutonB.uniquePress()) { display_date(); } retard(1); compteur--; } fade_down(); //impression de la ligne b len =0; while (str_b[len]) { len++; } ; // obtenir la longueur du message offset_top =(31 - ((len - 1) * 4)) / 2; je =0 ; while (str_b[i]) { puttinychar((i * 4) + offset_top, 1, str_b[i]); je++ ; } //maintenir l'affichage mais vérifier les pressions sur les boutons counter =1000; while (counter> 0){ if (buttonA.uniquePress()) { switch_mode(); retourner; } if (boutonB.uniquePress()) { display_date(); } retard(1); compteur--; } fade_down(); // affiche la ligne c si elle existe. longueur =0 ; while (str_c[len]) { len++; } ; // obtenir la longueur du message offset_top =(31 - ((len - 1) * 4)) / 2; je =0 ; while (str_c[i]) { puttinychar((i * 4) + offset_top, 1, str_c[i]); je++ ; } compteur =1000 ; while (counter> 0){ //vérification de l'appui sur le bouton if (buttonA.uniquePress()) { switch_mode(); retourner; } if (boutonB.uniquePress()) { display_date(); } retard(1); compteur--; } fade_down(); //maintenir l'affichage vide mais vérifier les pressions sur les boutons avant de recommencer. compteur =1000 ; while (counter> 0){ //vérification de l'appui sur le bouton if (buttonA.uniquePress()) { switch_mode(); retourner; } if (boutonB.uniquePress()) { display_date(); } retard(1); compteur--; } } fade_down();}/// scroll message - non utilisé actuellement - trop lent.void scroll() { char message[] ={"Bonjour "}; cls(); octet p =6 ; //pos actuelle dans l'octet de chaîne chara[] ={0, 1, 2, 3, 4, 5} ; //caractères de la chaîne int x[] ={0, 6, 12, 18, 24, 30} ; //xpos pour chaque octet de caractère y =0; //y pos // clear_buffer(); while (message[p] !='\0') { //dessiner les 6 caractères pour (byte c =0; c <6; c++) { putnormalchar(x[c],y,message[ chara[c] ] ); // dessine une ligne de pixels désactivée après chaque caractère, sinon les espaces entre les caractères contiennent des pixels du caractère précédent pour (octet yy =0; yy <8; yy ++) { plot(x[c] + 5, aa, 0); } // enlève un de chaque caractère position x[c] =x[c] - 1; } // réinitialiser un caractère s'il a disparu de l'écran pendant (byte i =0; i <=5; i++) { if (x[i] <-5 ) { x[i] =31; chara[i] =p; p++ ; } } }}//display_date - affiche le jour de la semaine, la date et le mois avec un curseur clignotant effectvoid display_date(){ cls(); //lire la date à partir de l'octet DS1307 dow =rtc[3]; // jour de la semaine 0 =dimanche octet date =rtc[4]; octet mois =rtc[5] - 1 ; //tableau de noms de mois à imprimer sur l'affichage. Certains sont raccourcis car nous n'avons que 8 caractères à jouer avec les noms de mois char[12][9] ={ "Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet" , "Août", "Sept", "Octobre", "Novembre", "Décembre" } ; // affiche le nom du jour // obtient la longueur du texte en pixels, de cette façon, nous pouvons le centrer sur l'affichage en devinant les pixels restants b2 et en l'utilisant comme octet de décalage len =0; while(daysfull[dow][len]) { len++; } ; décalage d'octet =(31 - ((len-1)*4)) / 2 ; //our offset to centre up the text //print the name int i =0; while(daysfull[dow][i]) { puttinychar((i*4) + offset , 1, daysfull[dow][i]); i++; } délai(1000); fade_down(); cls(); // print date numerals char buffer[3]; itoa(date,buffer,10); offset =10; //offset to centre text if 3 chars - e.g. 3rd // first work out date 2 letter suffix - eg st, nd, rd, th etc // char suffix[4][3]={"st", "nd", "rd", "th" }; is defined at top of code byte s =3; if(date ==1 || date ==21 || date ==31) { s =0; } else if (date ==2 || date ==22) { s =1; } else if (date ==3 || date ==23) { s =2; } //print the 1st date number puttinychar(0+offset, 1, buffer[0]); //if date is under 10 - then we only have 1 digit so set positions of sufix etc one character nearer byte suffixposx =4; //if date over 9 then print second number and set xpos of suffix to be 1 char further away if (date> 9){ suffixposx =8; puttinychar(4+offset, 1, buffer[1]); offset =8; //offset to centre text if 4 chars } //print the 2 suffix characters puttinychar(suffixposx+offset, 1, suffix[s][0]); puttinychar(suffixposx+4+offset, 1, suffix[s][1]); retard(1000); fade_down(); //print the month name //get length of text in pixels, that way we can centre it on the display by divindin the remaining pixels b2 and using that as an offset len =0; while(monthnames[month][len]) { len++; } ; offset =(31 - ((len-1)*4)) / 2; //our offset to centre up the text i =0; while(monthnames[month][i]) { puttinychar((i*4) +offset, 1, monthnames[month][i]); i++; } délai(1000); fade_down();}//dislpay menu to change the clock modevoid switch_mode() { //remember mode we are in. We use this value if we go into settings mode, so we can change back from settings mode (6) to whatever mode we were in. old_mode =clock_mode; char* modes[] ={ "Basic", "Small", "Slide", "Words", "Setup" }; byte next_clock_mode; byte firstrun =1; //loop waiting for button (timeout after 35 loops to return to mode X) for (int count =0; count <35; count++) { //if user hits button, change the clock_mode if (buttonA.uniquePress() || firstrun ==1) { count =0; cls(); if (firstrun ==0) { clock_mode++; } if (clock_mode> NUM_DISPLAY_MODES + 1 ) { clock_mode =0; } //print arrown and current clock_mode name on line one and print next clock_mode name on line two char str_top[9]; //strcpy (str_top, "-"); strcpy (str_top, modes[clock_mode]); next_clock_mode =clock_mode + 1; if (next_clock_mode> NUM_DISPLAY_MODES + 1 ) { next_clock_mode =0; } byte i =0; while (str_top[i]) { putnormalchar(i * 6, 0, str_top[i]); i++; } firstrun =0; } retard (50); }}//run clock main loop as long as run_mode returns truebyte run_mode() { //if random mode is on... check the hour when we change mode. if (random_mode) { //if hour value in change mode time =hours. then reurn false =i.e. exit mode. if (change_mode_time ==rtc[2]) { //set the next random clock mode and time to change it set_next_random(); //exit the current mode. renvoie 0 ; } } //else return 1 - keep running in this mode return 1;}//set the next hour the clock will change mode when random mode is onvoid set_next_random() { //set the next hour the clock mode will change - current time plus 1 - 4 hours get_time(); change_mode_time =rtc[2] + random (1, 5); //if change_mode_time now happens to be over 23, then set it to between 1 and 3am if (change_mode_time> 23) { change_mode_time =random (1, 4); } //set the new clock mode clock_mode =random(0, NUM_DISPLAY_MODES + 1); //pick new random clock mode}//dislpay menu to change the clock settingsvoid setup_menu() { char* set_modes[] ={ "Rndom", "24 Hr","Set", "Brght", "Exit"}; if (ampm ==0) { set_modes[1] =("12 Hr"); } byte setting_mode =0; byte next_setting_mode; byte firstrun =1; //loop waiting for button (timeout after 35 loops to return to mode X) for(int count=0; count <35; count++) { //if user hits button, change the clock_mode if(buttonA.uniquePress() || firstrun ==1){ count =0; cls(); if (firstrun ==0) { setting_mode++; } if (setting_mode> NUM_SETTINGS_MODES) { setting_mode =0; } //print arrown and current clock_mode name on line one and print next clock_mode name on line two char str_top[9]; strcpy (str_top, set_modes[setting_mode]); next_setting_mode =setting_mode + 1; if (next_setting_mode> NUM_SETTINGS_MODES) { next_setting_mode =0; } byte i =0; while(str_top[i]) { putnormalchar(i*6, 0, str_top[i]); i++; } firstrun =0; } retard (50); } //pick the mode switch(setting_mode){ case 0:set_random(); Pause; case 1:set_ampm(); Pause; case 2:set_time(); Pause; case 3:set_intensity(); Pause; case 4://exit menu break; } //change the clock from mode 6 (settings) back to the one it was in before clock_mode=old_mode;}//toggle random mode - pick a different clock mode every few hoursvoid set_random(){ cls(); char text_a[9] ="Off"; char text_b[9] ="On"; byte i =0; //if random mode is on, turn it off if (random_mode){ //turn random mode off random_mode =0; //print a message on the display while(text_a[i]) { putnormalchar((i*6), 0, text_a[i]); i++; } } else { //turn randome mode on. random_mode =1; //set hour mode will change set_next_random(); //print a message on the display while(text_b[i]) { putnormalchar((i*6), 0, text_b[i]); i++; } } delay(1500); //leave the message up for a second or so}//set 12 or 24 hour clockvoid set_ampm() { // AM/PM or 24 hour clock mode - flip the bit (makes 0 into 1, or 1 into 0 for ampm mode) ampm =(ampm ^ 1); cls();}//change screen intensityintensityvoid set_intensity() { cls(); byte i =0; char text[7] ="Bright"; while(text[i]) { puttinychar((i*4)+4, 0, text[i]); i++; } //wait for button input while (!buttonA.uniquePress()) { levelbar (0,6,(intensity*2)+2,2); //display the intensity level as a bar while (buttonB.isPressed()) { if(intensity ==15) { intensity =0; cls (); } else { intensity++; } //print the new value i =0; while(text[i]) { puttinychar((i*4)+4, 0, text[i]); i++; } //display the intensity level as a bar levelbar (0,6,(intensity*2)+2,2); //change the brightness setting on the displays for (byte address =0; address <4; address++) { lc.setIntensity(address, intensity); } delay(150); } }}// display a horizontal bar on the screen at offset xposr by ypos with height and width of xbar, ybarvoid levelbar (byte xpos, byte ypos, byte xbar, byte ybar) { for (byte x =0; x
LibrariesArduino
Aucun aperçu (téléchargement uniquement).

Schémas


Processus de fabrication

  1. Séquenceur LED
  2. horloge à coucou
  3. MATLAB - Matrice
  4. Combat de mini-boss
  5. horloge maîtresse
  6. Horloge de Berlin
  7. Horloge POV LED de style analogique
  8. Affichage de porte à matrice LED + détecteur de mouvement [Arduino Holiday]
  9. 8x éclairage LED par le son