Indicateur d'horloge LED à faire soi-même. Grande horloge LED. Processeurs de bits STM

Il n’y a pas si longtemps, il est devenu nécessaire d’avoir une horloge dans la maison, mais uniquement électronique, car je n’aime pas les horloges parce qu’elles font tic-tac. J'ai pas mal d'expérience dans les circuits de soudure et de gravure. Après avoir parcouru Internet et lu quelques ouvrages, j’ai décidé de choisir le schéma le plus simple, car je n’ai pas besoin d’une montre avec réveil.

J'ai choisi ce schéma parce que c'est facile fabriquez votre propre montre

Commençons, alors de quoi avons-nous besoin pour fabriquer une montre de nos propres mains ? Eh bien, bien sûr, des mains, des compétences (même pas grandes) dans la lecture de schémas de circuits, de fer à souder et de pièces détachées. Voici une liste complète de ce que j'ai utilisé :

Quartz 10 MHz – 1 pièce, microcontrôleur ATtiny 2313, résistances 100 Ohm – 8 pièces, 3 pièces. 10 kOhm, 2 condensateurs de 22 pF, 4 transistors, 2 boutons, indicateur LED KEM-5641-ASR 4 bits (RL-F5610SBAW/D15). J'ai effectué l'installation sur un PCB unilatéral.

Mais il y a un défaut dans ce schéma: les broches du microcontrôleur (ci-après dénommées MK), qui sont chargées de contrôler les décharges, reçoivent une charge tout à fait décente. Le courant total est bien supérieur au courant maximum du port, mais avec une indication dynamique, le MK n'a pas le temps de surchauffer. Pour éviter tout dysfonctionnement du MK, nous ajoutons des résistances de 100 Ohm aux circuits de décharge.

Dans ce schéma, l'indicateur est contrôlé selon le principe d'indication dynamique, selon lequel les segments indicateurs sont contrôlés par des signaux provenant des sorties correspondantes du MK. Le taux de répétition de ces signaux est supérieur à 25 Hz et de ce fait, la lueur des chiffres indicateurs semble continue.

Montres électroniques fabriquées selon le schéma ci-dessus ne peut afficher que l'heure (heures et minutes), et les secondes sont indiquées par un point entre les segments, qui clignote. Pour contrôler le mode de fonctionnement de la montre, des interrupteurs à bouton-poussoir sont prévus dans sa structure, qui contrôlent le réglage des heures et des minutes. Ce circuit est alimenté par une alimentation 5V. Lors de la fabrication du circuit imprimé, une diode Zener 5V a été incluse dans le circuit.

Comme j'ai une alimentation 5V, j'ai exclu la diode Zener du circuit.

Pour réaliser la planche, le circuit a été appliqué à l'aide d'un fer à repasser. C'est-à-dire que le circuit imprimé a été imprimé sur une imprimante à jet d'encre en utilisant du papier glacé ; il peut être extrait de magazines sur papier glacé modernes. Ensuite, le textolite de la taille requise a été découpé. Ma taille s'est avérée être de 36*26 mm. Une si petite taille est due au fait que toutes les pièces sont sélectionnées dans un boîtier CMS.

La planche a été gravée en utilisant du chlorure ferrique (FeCl 3 ). En termes de temps, la gravure a duré environ une heure, puisque le bain avec la planche était sur la cheminée ; la température élevée affecte le temps de gravure ; aucun cuivre n'a été utilisé dans la planche ; Mais n'en faites pas trop avec la température.

Pendant que le processus de gravure se déroulait, afin de ne pas me creuser la tête et d'écrire un firmware pour que l'horloge fonctionne, je suis allé sur Internet et j'ai trouvé un firmware pour ce schéma. Comment flasher MK peut également être trouvé sur Internet. J'ai utilisé un programmeur qui ne flashe que les ATMEGA MK.

Et enfin, notre carte est prête et nous pouvons commencer à souder nos montres. Pour souder, vous avez besoin d'un fer à souder de 25 W avec une pointe fine afin de ne pas brûler le MK et les autres pièces. Nous effectuons la soudure avec soin et soudons de préférence toutes les pattes du MK pour la première fois, mais uniquement séparément. Pour ceux qui ne sont pas au courant, sachez que les pièces fabriquées dans un boîtier CMS ont de l'étain sur leurs bornes pour un soudage rapide.

Et voici à quoi ressemble la carte avec les pièces soudées.

Vous pouvez trouver de nombreux modèles et options différents de montres numériques électroniques en vente, mais la plupart d'entre elles sont conçues pour une utilisation en intérieur, car les nombres sont petits. Cependant, il est parfois nécessaire de placer une horloge dans la rue - par exemple sur le mur d'une maison, ou dans un stade, une place, c'est-à-dire là où elle sera visible de loin par de nombreuses personnes. À cette fin, ce circuit d'une grande horloge LED a été développé et assemblé avec succès, auquel vous pouvez connecter (via des commutateurs à transistor internes) des indicateurs LED de n'importe quelle taille. Vous pouvez agrandir le schéma de principe en cliquant dessus :

Description de l'horloge

  1. Montre. Dans ce mode, il existe un type standard d'affichage de l'heure. Il existe une correction numérique de la précision de l'horloge.
  2. Thermomètre. Dans ce cas, l'appareil mesure la température de la pièce ou de l'air extérieur à partir d'un capteur. Plage de -55 à +125 degrés.
  3. Le contrôle de l'alimentation est fourni.
  4. Affiche alternativement des informations sur l'indicateur - une horloge et un thermomètre.
  5. Pour enregistrer les paramètres et les paramètres en cas de perte de 220 V, une mémoire non volatile est utilisée.


La base de l'appareil est l'ATMega8 MK, qui est flashé en réglant les fusibles selon le tableau :

Gestion du fonctionnement et de l'horloge

Lorsque vous allumez la montre pour la première fois, un écran de démarrage publicitaire apparaîtra à l'écran, après quoi elle passera à l'affichage de l'heure. En appuyant sur un bouton SET_TIME l'indicateur ira en cercle à partir du mode principal :

  • mode d'affichage des minutes et des secondes. Dans ce mode, si vous appuyez simultanément sur le bouton PLUS Et MOINS, alors les secondes seront réinitialisées ;
  • régler les minutes de l'heure actuelle ;
  • régler l'horloge actuelle ;
  • symbole t. Réglage de la durée d'affichage de l'horloge ;
  • symbole o. Temps d'affichage des symboles d'indication de température externe (out);
  • le montant de la correction quotidienne de la précision de l'horloge. Symbole c et la valeur de correction. Réglage des limites de -25 à 25 sec. La valeur sélectionnée sera ajoutée ou soustraite de l'heure actuelle chaque jour à 0 heure 0 minute et 30 secondes. Pour plus de détails, lisez les instructions qui se trouvent dans l'archive avec les fichiers du micrologiciel et du circuit imprimé.

Régler l'horloge

Tout en maintenant les boutons enfoncés PLUS/MOINS Nous effectuons une fixation accélérée des valeurs. Après avoir modifié les paramètres, après 10 secondes, les nouvelles valeurs seront écrites dans la mémoire non volatile et seront lues à partir de là lors de la remise sous tension. Les nouveaux paramètres prennent effet lors de l'installation. Le microcontrôleur surveille la présence de l'alimentation principale. Lorsqu'il est éteint, l'appareil est alimenté par une source interne. Le schéma du module d'alimentation redondant est présenté ci-dessous :


Pour réduire la consommation de courant, l'indicateur, les capteurs et les boutons sont éteints, mais l'horloge elle-même continue de compter le temps. Dès l'apparition de la tension secteur 220 V, toutes les fonctions d'indication sont rétablies.


Puisque l'appareil a été conçu comme une grande horloge LED, il dispose de deux écrans : une grande LED - pour la rue, et un petit LCD - pour une configuration facile de l'écran principal. Le grand écran est situé à plusieurs mètres de la centrale et est relié par deux câbles de 8 fils. Pour contrôler les anodes de l'indicateur externe, des commutateurs à transistors sont utilisés selon le schéma donné dans les archives. Auteurs du projet : Alexandrovitch & SOIR.

Il existe de nombreuses façons d'assembler une montre électronique de vos propres mains : les schémas sont largement présentés dans la littérature et sur Internet. La plupart des implémentations modernes sont basées sur des microcontrôleurs. La mise en œuvre de tels projets nécessite souvent des compétences pratiques approfondies et des connaissances théoriques dans le domaine de l'électronique : la capacité d'utiliser des logiciels spécialisés, de créer des circuits imprimés à la maison à l'aide d'une gravure au chlorure ferrique et d'une bonne soudure. Vous devez également disposer d’une variété d’outils et de fournitures.

Cependant, il existe un moyen simple et abordable d'assembler une montre électronique de vos propres mains à la maison : utiliser la plateforme Arduino. Il s'agit d'un complexe logiciel et matériel spécialement conçu pour enseigner les bases de la programmation et de l'électronique. Avec l'aide d'Arduino, n'importe qui, même sans formation préalable particulière, peut construire une horloge électronique de ses propres mains : des schémas de circuit, des programmes d'ingénierie et même un fer à souder ne sont pas nécessaires !

La connexion de tous les composants électroniques est effectuée sur une planche à pain à contact spécial (« sans soudure »), ce qui élimine le risque de brûlures, coupures et autres blessures. Vous pouvez donc travailler avec le concepteur Arduino avec des enfants. Une manière visuelle de présenter un schéma de circuit vous aidera à éviter de commettre des erreurs lors de l'assemblage de l'appareil.

Étape 1. Liste des composants

Pour assembler une horloge simple sur des matrices LED, vous n'aurez besoin que de quelques composants bon marché :

  • Plateforme Arduino. Les modèles les plus simples feront l'affaire - ou Micro ;
  • planche à pain de contact ;
  • fils de connexion pour planche à pain;
  • Module d'horloge en temps réel Adafruit DS3231 ;
  • Module matriciel LED 32x8 MAX7219 ;
  • deux boutons.

Vous aurez également besoin d'un ordinateur personnel et d'un câble USB-mini-USB pour charger le programme de contrôle en mémoire. C'est tout : un fer à souder, des décapants, des couteaux de montage et autres outils professionnels ne sont pas nécessaires : toutes les opérations sont effectuées à la main. Peut-être que dans certains cas, il est plus pratique d'utiliser une pince à épiler, mais vous pouvez vous en passer.


Étape 2. Assemblage du circuit électronique

Le circuit d'une horloge électronique avec indication LED utilisant Arduino semblera assez simple même pour les radioamateurs inexpérimentés. Seuls quelques fils sont nécessaires pour l'assemblage. Tableau de connexion :

Module Arduino → Matrice LED 32x8 MAX7219

Module Arduino → Horloge temps réel Adafruit DS3231

Module Arduino → boutons

D2 - bouton 1

D3 - bouton 2

La deuxième broche des boutons est connectée à GND.

Il vous suffit de faire attention et de vous rappeler comment les trous de contact sur la planche à pain sont connectés les uns aux autres. Le schéma suivant illustre la méthode de connexion interne des trous de contact :


Deux rangées (1 et 4) des deux côtés sont court-circuitées horizontalement - elles sont généralement utilisées comme ligne électrique +5 V et masse GND. Tous les contacts internes (2 et 3) sont fermés verticalement. Dans ce cas, le circuit imprimé est divisé verticalement et horizontalement en deux parties symétriques indépendantes l'une de l'autre. Cela permet, par exemple, d'assembler deux appareils différents sur une même carte.

Le schéma d'une horloge électronique avec indication LED, ainsi que la disposition des éléments sur le circuit imprimé, sont présentés dans l'illustration :

Vérifiez soigneusement que toutes les connexions sont conformes au schéma présenté. Assurez-vous également que les conducteurs sont bien fixés dans les trous de contact du circuit imprimé.


Étape 3. Micrologiciel Arduino

Une fois l'assemblage et le test du circuit terminés, vous pouvez commencer à charger le programme de contrôle (ou « firmware ») dans la mémoire Arduino.


Pour ce faire, vous devez installer l'environnement de développement officiel gratuit - . Vous aurez également besoin du code source du projet, que vous pouvez télécharger ci-dessous dans l'archive avec toutes les bibliothèques et un croquis, et si vous avez juste besoin d'un croquis, vous pouvez le copier séparément :

//include les bibliothèques : #include "LedControl.h" #include // Bibliothèque de polices #include // Horloge DS1307 #include "RTClib.h" // Horloge DS1307 #include // Bibliothèque de boutons par Alexander Brevig // Configuration de la matrice LED // la broche 12 est connectée au DataIn sur l'écran // la broche 11 est connectée au CLK sur l'écran // la broche 10 est connectée à LOAD sur l'écran LedControl lc = LedContrôle(6, 5, 4, 4); // définit les 3 broches sur 12, 11 et 10, puis définit 4 affichages (le maximum est de 8 affichages) // intensité d'octet des variables globales = 7 ; // Intensité/luminosité par défaut (0-15) byte clock_mode = 0 ; // Mode 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 (off) octet old_mode = clock_mode ; // Stocke le mode d'horloge précédent, donc si nous allons à ce jour ou autre, nous savons à quel mode revenir après. booléen ampères = 0 ; // Définit une heure sur 12 ou 24 heures. 0 = 24 heures. 1 = octet de 12 heures change_mode_time = 0 ; // Conserve l'heure à laquelle le mode d'horloge changera ensuite s'il est en mode aléatoire. délai long non signé = 500 ; // On attend toujours un peu entre les mises à jour du display int rtc; // Contient la sortie de l'horloge en temps réel char jours = ( "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ); //tableau de jours - utilisé dans les modes slide, basic_mode et jumble (le DS1307 génère 1 à 7 valeurs pour le jour de la semaine) char dayfull = ( "Dimanche", "Lundi", "Mardi", "Mer", "Jeudi" ", "Vendredi", "Samedi" ); char suffixe = ("st", "nd", "rd", "th" ); // tableau de suffixes de date, utilisé dans les modes slide, basic_mode et jumble. e,g, 1st 2nd ... // définir des constantes #define NUM_DISPLAY_MODES 3 // Modes d'affichage des nombres (avec zéro comme premier mode) #define NUM_SETTINGS_MODES 4 // Modes de paramètres des nombres = 6 (avec zéro comme premier mode) # définir SLIDE_DELAY 20 // Le temps en millisecondes pour l'effet de diapositive par caractère en mode diapositive. Augmentez cette valeur pour un effet plus lent #define cls clear_display // Effacer l'affichage RTC_DS1307 ds1307; // Créer un objet RTC Button boutonA = Button(2, BUTTON_PULLUP); // Configuration du bouton A (en utilisant 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); // allume la résistance pullup pour le bouton sur la broche 4 Serial.begin(9600); //démarre la série //initialise les 4 panneaux matriciels //nous avons déjà défini le nombre de périphériques lors de la création le LedControl int devices = lc.getDeviceCount(); //nous devons initialiser tous les appareils dans une boucle pour (int adresse = 0; adresse< devices; address++) { /*The MAX72XX is in power-saving mode on startup*/ lc.shutdown(3-address, false); /* Set the brightness to a medium values */ lc.setIntensity(3-address, intensity); /* and clear the display */ lc.clearDisplay(3-address); } //Setup DS1307 RTC #ifdef AVR Wire.begin(); #else Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino #endif ds1307.begin(); //start RTC Clock if (! ds1307.isrunning()) { Serial.println("RTC is NOT running!"); ds1307.adjust(DateTime(__DATE__, __TIME__)); // sets the RTC to the date & time this sketch was compiled } //Show software version & hello message printver(); //enable red led digitalWrite(13, HIGH); } void loop() { //run the clock with whatever mode is set by clock_mode - the default is set at top of code. switch (clock_mode){ case 0: basic_mode(); break; case 1: small_mode(); break; case 2: slide(); break; case 3: word_clock(); break; case 4: setup_menu(); break; } } //plot a point on the display void plot (byte x, byte y, byte val) { //select which matrix depending on the x coord byte address; if (x >= 0 &&x<= 7) { address = 3; } if (x >= 8 &&x<= 15) { address = 2; x = x - 8; } if (x >= 16 &&x<= 23) { address = 1; x = x - 16; } if (x >= 24 &&x<= 31) { address = 0; x = x - 24; } if (val == 1) { lc.setLed(address, y, x, true); } else { lc.setLed(address, y, x, false); } } //clear screen void clear_display() { for (byte address = 0; address < 4; address++) { lc.clearDisplay(address); } } //fade screen down void fade_down() { //fade from global intensity to 1 for (byte i = intensity; i >0 ; i--) ( pour (adresse d'octet = 0 ; adresse< 4; address++) { lc.setIntensity(address, i); } delay(30); //change this to change fade down speed } clear_display(); //clear display completely (off) //reset intentsity to global val for (byte address = 0; address < 4; address++) { lc.setIntensity(address, intensity); } } //power up led test & display software version number void printver() { byte i = 0; char ver_a = "MADE"; char ver_b = "IN"; char ver_c = "RUSSIA"; //test all leds. for (byte x = 0; x <= 32; x++) { for (byte y = 0; y <= 7; y++) { plot(x, y, 1); } } delay(300); fade_down(); while (ver_a[i]) { puttinychar((i * 4), 1, ver_a[i]); delay(35); i++; } delay(500); fade_down(); i = 0; while (ver_b[i]) { puttinychar((i * 4), 1, ver_b[i]); delay(35); i++; } delay(500); fade_down(); i = 0; while (ver_c[i]) { puttinychar((i * 4), 1, ver_c[i]); delay(35); i++; } delay(500); fade_down(); } // puttinychar // Copy a 3x5 character glyph from the myfont data structure to display memory, with its upper left at the given coordinate // This is unoptimized and simply uses plot() to draw each dot. void puttinychar(byte x, byte y, char c) { byte dots; if (c >= "A" &&c<= "Z" || (c >= "un" && c<= "z")) { c &= 0x1F; // A-Z maps to 1-26 } else if (c >= "0" &&c<= "9") { c = (c - "0") + 32; } else if (c == " ") { c = 0; // space } else if (c == ".") { c = 27; // full stop } else if (c == ":") { c = 28; // colon } else if (c == "\"") { c = 29; // single quote mark } else if (c == "!") { c = 30; // single quote mark } else if (c == "?") { c = 31; // single quote mark } for (byte col = 0; col < 3; col++) { dots = pgm_read_byte_near(&mytinyfont[c]); for (char row = 0; row < 5; row++) { if (dots & (16 >> ligne)) plot(x + col, y + ligne, 1);<= "Z" || (c >= "un" && c<= "z")) { // c &= 0x1F; // A-Z maps to 1-26 // } if (c >= "A" &&c<= "Z") { c &= 0x1F; // A-Z maps to 1-26 } else if (c >= "un" && c<= "z") { c = (c - "a") + 41; // A-Z maps to 41-67 } else if (c >= "0" &&c<= "9") { c = (c - "0") + 31; } else if (c == " ") { c = 0; // space } else if (c == ".") { c = 27; // full stop } else if (c == "\"") { c = 28; // single quote mark } else if (c == ":") { c = 29; // clock_mode selector arrow } else if (c == ">sinon plot(x + col, y + ligne, 0);<= -67) { c *= -1; } for (char col = 0; col < 5; col++) { dots = pgm_read_byte_near(&myfont[c]); for (char row = 0; row < 7; row++) { //check coords are on screen before trying to plot //if ((x >) ) ) void putnormalchar(octet x, octet y, char c) ( points d'octet; // if (c >= "A" && c<= 31) && (y >") ( c = 30; // flèche de sélection clock_mode ) sinon si (c >= -80 && c<= 7)){ if (dots & (64 >= 0) && (x< 10) { buffer = buffer; buffer = "0"; } puttinychar(20, 1, ":"); //seconds colon puttinychar(24, 1, buffer); //seconds puttinychar(28, 1, buffer); //seconds old_secs = secs; } //if minute changes change time if (mins != rtc) { //reset these for comparison next time mins = rtc; byte hours = rtc; if (hours > < 1) { hours = hours + ampm * 12; } //byte dow = rtc; // the DS1307 outputs 0 - 6 where 0 = Sunday0 - 6 where 0 = Sunday. //byte date = rtc; //set characters char buffer; itoa(hours, buffer, 10); //fix - as otherwise if num has leading zero, e.g. "03" hours, itoa coverts this to chars with space "3 ". if (hours < 10) { buffer = buffer; //if we are in 12 hour mode blank the leading zero. if (ampm) { buffer = " "; } else { buffer = "0"; } } //set hours chars textchar = buffer; textchar = buffer; textchar = ":"; itoa (mins, buffer, 10); if (mins < 10) { buffer = buffer; buffer = "0"; } //set mins characters textchar = buffer; textchar = buffer; //do seconds textchar = ":"; buffer; secs = rtc; itoa(secs, buffer, 10); //fix - as otherwise if num has leading zero, e.g. "03" secs, itoa coverts this to chars with space "3 ". if (secs < 10) { buffer = buffer; buffer = "0"; } //set seconds textchar = buffer; textchar = buffer; byte x = 0; byte y = 0; //print each char for (byte x = 0; x < 6 ; x++) { puttinychar(x * 4, 1, textchar[x]); } } delay(50); } fade_down(); } // basic_mode() // show the time in 5x7 characters void basic_mode() { cls(); char buffer; //for int to char conversion to turn rtc values into chars we can print on screen byte offset = 0; //used to offset the x postition of the digits and centre the display when we are in 12 hour mode and the clock shows only 3 digits. e.g. 3:21 byte x, y; //used to draw a clear box over the left hand "1" of the display when we roll from 12:59 ->= 0) && (y< 1) { hours = hours + ampm * 12; } //do offset conversion if (ampm && hours < 10) { offset = 2; } //set the next minute we show the date at //set_next_date(); // initially set mins to value 100 - so it wll never equal rtc on the first loop of the clock, meaning we draw the clock display when we enter the function byte secs = 100; byte mins = 100; int count = 0; //run clock main loop as long as run_mode returns true while (run_mode()) { //get the time from the clock chip get_time(); //check for button press if (buttonA.uniquePress()) { switch_mode(); return; } if (buttonB.uniquePress()) { display_date(); return; } //check whether it"s time to automatically display the date //check_show_date(); //draw the flashing: as on if the secs have changed. if (secs != rtc) { //update secs with new value secs = rtc; //draw: plot (15 - offset, 2, 1); //top point plot (15 - offset, 5, 1); //bottom point count = 400; } //if count has run out, turn off the: if (count == 0) { plot (15 - offset, 2, 0); //top point plot (15 - offset, 5, 0); //bottom point } else { count--; } //re draw the display if button pressed or if mins != rtc i.e. if the time has changed from what we had stored in mins, (also trigggered on first entering function when mins is 100) if (mins != rtc) { //update mins and hours with the new values mins = rtc; hours = rtc; //adjust hours of ampm set to 12 hour mode if (hours >> row)) ( // seulement 7 lignes. plot(x + col, y + row, 1); ) else ( plot(x + col, y + row, 0); ) //) ) ) ) //small_mode //affiche l'heure en petits caractères 3x5 avec les secondes display void small_mode() ( char textchar; // les 16 caractères sur l'affichage byte mins = 100; //mins byte secs = rtc; //secondes byte old_secs = secs; / /contient l'ancienne valeur des secondes - depuis la dernière mise à jour des secondes o display - 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érifier la pression sur le bouton if (buttonA.uniquePress()) ( switch_mode(); return; ) if (buttonB.uniquePress()) ( display_date(); return; ) //si les secondes ont changé, mettez-les à jour sur l'affichage secs = rtc; if (secs != old_secs) ( //secs char buffer; itoa(secs, buffer, 10); //fix - sinon si num a un zéro non significatif, par exemple "03" secondes, itoa couvre cela en caractères avec un espace "3".if(secs< 1) { hours = hours + ampm * 12; } itoa(hours, buffer, 10); //if hours < 10 the num e.g. "3" hours, itoa coverts this to chars with space "3 " which we dont want if (hours < 10) { buffer = buffer; buffer = "0"; } //print hours //if we in 12 hour mode and hours < 10, then don"t print the leading zero, and set the offset so we centre the display with 3 digits. if (ampm && hours < 10) { offset = 2; //if the time is 1:00am clear the entire display as the offset changes at this time and we need to blank out the old 12:59 if ((hours == 1 && mins == 0)) { cls(); } } else { //else no offset and print hours tens digit offset = 0; //if the time is 10:00am clear the entire display as the offset changes at this time and we need to blank out the old 9:59 if (hours == 10 && mins == 0) { cls(); } putnormalchar(1, 0, buffer); } //print hours ones digit putnormalchar(7 - offset, 0, buffer); //print mins //add leading zero if mins < 10 itoa (mins, buffer, 10); if (mins < 10) { buffer = buffer; buffer = "0"; } //print mins tens and ones digits putnormalchar(19 - offset, 0, buffer); putnormalchar(25 - offset, 0, buffer); } } fade_down(); } //like basic_mode but with slide effect void slide() { byte digits_old = {99, 99, 99, 99}; //old values we store time in. Set to somthing that will never match the time initially so all digits get drawn wnen the mode starts byte digits_new; //new digits time will slide to reveal byte digits_x_pos = {25, 19, 7, 1}; //x pos for which to draw each digit at char old_char; //used when we use itoa to transpose the current digit (type byte) into a char to pass to the animation function char new_char; //used when we use itoa to transpose the new digit (type byte) into a char to pass to the animation function //old_chars - stores the 5 day and date suffix chars on the display. e.g. "mon" and "st". We feed these into the slide animation as the current char when these chars are updated. //We sent them as A initially, which are used when the clocl enters the mode and no last chars are stored. //char old_chars = "AAAAA"; //plot the clock colon on the display cls(); putnormalchar(13, 0, ":"); byte old_secs = rtc; //store seconds in old_secs. We compare secs and old secs. WHen they are different we redraw the display //run clock main loop as long as run_mode returns true while (run_mode()) { get_time(); //check for button press if (buttonA.uniquePress()) { switch_mode(); return; } if (buttonB.uniquePress()) { display_date(); return; } //if secs have changed then update the display if (rtc != old_secs) { old_secs = rtc; //do 12/24 hour conversion if ampm set to 1 byte hours = rtc; if (hours >> row)) ( // seulement 7 lignes. plot(x + col, y + row, 1); ) else ( plot(x + col, y + row, 0); ) //) ) ) ) //small_mode //affiche l'heure en petits caractères 3x5 avec les secondes display void small_mode() ( char textchar; // les 16 caractères sur l'affichage byte mins = 100; //mins byte secs = rtc; //secondes byte old_secs = secs; / /contient l'ancienne valeur des secondes - depuis la dernière mise à jour des secondes o display - 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érifier la pression sur le bouton if (buttonA.uniquePress()) ( switch_mode(); return; ) if (buttonB.uniquePress()) ( display_date(); return; ) //si les secondes ont changé, mettez-les à jour sur l'affichage secs = rtc; if (secs != old_secs) ( //secs char buffer; itoa(secs, buffer, 10); //fix - sinon si num a un zéro non significatif, par exemple "03" secondes, itoa couvre cela en caractères avec un espace "3".if(secs< 1) { hours = hours + ampm * 12; } //split all date and time into individual digits - stick in digits_new array //rtc = secs //array pos and digit stored //digits_new = (rtc%10); //0 - secs ones //digits_new = ((rtc/10)%10); //1 - secs tens //rtc = mins digits_new = (rtc % 10); //2 - mins ones digits_new = ((rtc / 10) % 10); //3 - mins tens //rtc = hours digits_new = (hours % 10); //4 - hour ones digits_new = ((hours / 10) % 10); //5 - hour tens //rtc = date //digits_new = (rtc%10); //6 - date ones //digits_new = ((rtc/10)%10); //7 - date tens //draw initial screen of all chars. After this we just draw the changes. //compare digits 0 to 3 (mins and hours) for (byte i = 0; i <= 3; i++) { //see if digit has changed... if (digits_old[i] != digits_new[i]) { //run 9 step animation sequence for each in turn for (byte seq = 0; seq <= 8 ; seq++) { //convert digit to string itoa(digits_old[i], old_char, 10); itoa(digits_new[i], new_char, 10); //if set to 12 hour mode and we"re on digit 2 (hours tens mode) then check to see if this is a zero. If it is, blank it instead so we get 2.00pm not 02.00pm if (ampm && i == 3) { if (digits_new == 0) { new_char = " "; } if (digits_old == 0) { old_char = " "; } } //draw the animation frame for each digit slideanim(digits_x_pos[i], 0, seq, old_char, new_char); delay(SLIDE_DELAY); } } } /* //compare date digit 6 (ones) and (7) tens - if either of these change we need to update the date line. We compare date tens as say from Jan 31 ->1h00 du matin en mode 12 heures.<=2 ; day_char++){ //run the anim sequence for each char for (byte seq = 0; seq <=8 ; seq++){ //the day (0 - 6) Read this number into the days char array. the seconds number in the array 0-2 gets the 3 chars of the day name, e.g. m o n slideanim(6*day_char,8,seq,old_chars,days); //6 x day_char gives us the x pos for the char delay(SLIDE_DELAY); } //save the old day chars into the old_chars array at array pos 0-2. We use this next time we change the day and feed it to the animation as the current char. The updated char is fed in as the new char. old_chars = days; } //change the date tens digit (if needed) and ones digit. (the date ones digit wil alwaus change, but putting this in the "if" loop makes it a bit neater code wise.) for (byte i = 7; i >//effectuer une conversion 12/24 heures si ampm est défini sur 1 octet heures = rtc ;<=8 ; seq++){ itoa(digits_old[i],old_char,10); itoa(digits_new[i],new_char,10); slideanim(digits_x_pos[i],8,seq,old_char,new_char); delay(SLIDE_DELAY); } } } //print the day suffix "nd" "rd" "th" etc. First work out date 2 letter suffix - eg st, nd, rd, th byte s = 3; //the pos to read our suffix array from. byte date = rtc; 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[s]); // we pass in the old_char array char as the current char and the suffix array as the new char delay(SLIDE_DELAY); } //save the suffic char in the old chars array at array pos 3 and 5. We use these chars next time we change the suffix and feed it to the animation as the current char. The updated char is fed in as the new char. old_chars = suffix[s]; } }//end do date line */ //save digita array tol old for comparison next loop for (byte i = 0; i <= 3; i++) { digits_old[i] = digits_new[i]; } }//secs/oldsecs }//while loop fade_down(); } //called by slide //this draws the animation of one char sliding on and the other sliding off. There are 8 steps in the animation, we call the function to draw one of the steps from 0-7 //inputs are are char x and y, animation frame sequence (0-7) and the current and new chars being drawn. void slideanim(byte x, byte y, byte sequence, char current_c, char new_c) { // To slide one char off and another on we need 9 steps or frames in sequence... // seq# 0123456 <-rows of the display // | ||||||| // seq0 0123456 START - all rows of the display 0-6 show the current characters rows 0-6 // seq1 012345 current char moves down one row on the display. We only see it"s rows 0-5. There are at display positions 1-6 There is a blank row inserted at the top // seq2 6 01234 current char moves down 2 rows. we now only see rows 0-4 at display rows 2-6 on the display. Row 1 of the display is blank. Row 0 shows row 6 of the new char // seq3 56 0123 // seq4 456 012 half old / half new char // seq5 3456 01 // seq6 23456 0 // seq7 123456 // seq8 0123456 END - all rows show the new char //from above we can see... //currentchar runs 0-6 then 0-5 then 0-4 all the way to 0. starting Y position increases by 1 row each time. //new char runs 6 then 5-6 then 4-6 then 3-6. starting Y position increases by 1 row each time. //if sequence number is below 7, we need to draw the current char if (sequence < 7) { byte dots; // if (current_c >si (heures > 12) ( heures = heures - ampm * 12; ) si (heures<= "z")) { // current_c &= 0x1F; // A-Z maps to 1-26 // } if (current_c >12) ( heures = heures - ampm * 12; ) si (heures<= "Z") { current_c &= 0x1F; // A-Z maps to 1-26 } else if (current_c >01 février, alors le chiffre des uns ne change pas si ((digits_old != digits_new) || (digits_old != digits_new)) ( //change le jour affiché. La boucle ci-dessous parcourt tour à tour chacun des 3 caractères, par exemple "MON" pour (octet day_char = 0 ; day_char<= "z") { current_c = (current_c - "a") + 41; // A-Z maps to 41-67 } else if (current_c >= 6 ; i--)( if (digits_old[i] != digits_new[i]) ( for (byte seq = 0; seq<= "9") { current_c = (current_c - "0") + 31; } else if (current_c == " ") { current_c = 0; // space } else if (current_c == ".") { current_c = 27; // full stop } else if (current_c == "\"") { current_c = 28; // single quote mark } else if (current_c == ":") { current_c = 29; //colon } else if (current_c == ">= "A" && || (current_c >= "a" && current_c<= curr_char_row_max; curr_char_row++) { for (byte col = 0; col < 5; col++) { dots = pgm_read_byte_near(&myfont); if (dots & (64 >> curr_char_row)) plot(x + col, y + start_y, 1); //plot mené sur else plot(x + col, y + start_y, 0); //sinon, le tracé s'éteint ) start_y++;//ajoute un à y pour dessiner la ligne suivante un vers le bas ) ) //dessine une ligne vide entre les caractères si la séquence est comprise entre 1 et 7. Si nous ne faisons pas cela, nous obtenons les restes des caractères actuels, dernière position restante sur l'écran si (séquence >= 1 && séquence<= 8) { for (byte col = 0; col < 5; col++) { plot(x + col, y + (sequence - 1), 0); //the y position to draw the line is equivalent to the sequence number - 1 } } //if sequence is above 2, we also need to start drawing the new char if (sequence >= 2) ( //travailler les points d'octets de caractères ; //if (new_c >= "A" && new_c<= "Z" || (new_c >= "a" && nouveau_c<= "z")) { // new_c &= 0x1F; // A-Z maps to 1-26 //} if (new_c >= "A" && nouveau_c<= "Z") { new_c &= 0x1F; // A-Z maps to 1-26 } else if (new_c >= "a" && nouveau_c<= "z") { new_c = (new_c - "a") + 41; // A-Z maps to 41-67 } else if (new_c >= "0" && nouveau_c<= "9") { new_c = (new_c - "0") + 31; } else if (new_c == " ") { new_c = 0; // space } else if (new_c == ".") { new_c = 27; // full stop } else if (new_c == "\"") { new_c = 28; // single quote mark } else if (new_c == ":") { new_c = 29; // clock_mode selector arrow } else if (new_c == ">") ( new_c = 30; // flèche de sélection clock_mode ) byte newcharrowmin = 6 - (séquence - 2); // numéro de ligne minimum à dessiner pour un nouveau caractère - cela génère une sortie de 6 à 0 lorsqu'il est alimenté avec les numéros de séquence 2-8 . Il s'agit de la ligne minimale à dessiner pour le nouvel octet de caractère start_y = 0; // la position y à laquelle commencer - est la même que le numéro de séquence. // trace chaque ligne à partir du minimum de ligne (calculé par numéro de séquence). ) ) jusqu'à 6 pour (octet newcharrow = newcharrowmin; newcharrow<= 6; newcharrow++) { for (byte col = 0; col < 5; col++) { dots = pgm_read_byte_near(&myfont); if (dots & (64 >> newcharrow)) plot(x + col, y + start_y, 1); //plot mené sur else plot(x + col, y + start_y, 0); //sinon, le tracé est désactivé) start_y++;//ajoutez-en un à y pour que nous dessinions la ligne suivante vers le bas) ) ) //imprime une horloge en utilisant des mots plutôt que des nombres void word_clock() ( cls(); char number = ( "one ", "deux", "trois", "quatre", "cinq", "six", "sept", "huit", "neuf", "dix", "onze", "douze", "treize", "quatorze", "quinze", "seize", "dix-sept", "dix-huit", "dix-neuf" ); nombres chartens = ( "dix", "vingt", "trente", "quarante", "cinquante" ); //potentiellement 3 lignes pour afficher char str_a; char str_c; //byte hours_y, mins_y; //heures et minutes et positions pour les lignes d'heures et de minutes hours = rtc * 12;< 1) { hours = hours + ampm * 12; } get_time(); //get the time from the clock chip byte old_mins = 100; //store mins in old_mins. We compare mins and old mins & when they are different we redraw the display. Set this to 100 initially so display is drawn when mode starts. byte mins; //run clock main loop as long as run_mode returns true while (run_mode()) { //check for button press if (buttonA.uniquePress()) { switch_mode(); return; } if (buttonB.uniquePress()) { display_date(); } get_time(); //get the time from the clock chip mins = rtc; //get mins //if mins is different from old_mins - redraw display if (mins != old_mins) { //update old_mins with current mins value old_mins = mins; //reset these for comparison next time mins = rtc; hours = rtc; //make hours into 12 hour format if (hours >12) ( heures = heures - 12; ) if (heures == 0) ( heures = 12; ) //diviser la valeur des minutes en deux chiffres distincts int minsdigit = rtc % 10;<= 10 , then top line has to read "minsdigti past" and bottom line reads hours if (mins < 10) { strcpy (str_a, numbers); strcpy (str_b, "PAST"); strcpy (str_c, numbers); } //if mins = 10, cant use minsdigit as above, so soecial case to print 10 past /n hour. if (mins == 10) { strcpy (str_a, numbers); strcpy (str_b, " PAST"); strcpy (str_c, numbers); } //if time is not on the hour - i.e. both mins digits are not zero, //then make first line read "hours" and 2 & 3rd lines read "minstens" "mins" e.g. "three /n twenty /n one" else if (minsdigitten != 0 && minsdigit != 0) { strcpy (str_a, numbers); //if mins is in the teens, use teens from the numbers array for the 2nd line, e.g. "fifteen" //if (mins >octet minsdigitten = (rtc / 10) % 10 ;<= 19) { if (mins <= 19) { strcpy (str_b, numbers); } else { strcpy (str_b, numberstens); strcpy (str_c, numbers); } } // if mins digit is zero, don"t print it. read read "hours" "minstens" e.g. "three /n twenty" else if (minsdigitten != 0 && minsdigit == 0) { strcpy (str_a, numbers); strcpy (str_b, numberstens); strcpy (str_c, ""); } //if both mins are zero, i.e. it is on the hour, the top line reads "hours" and bottom line reads "o"clock" else if (minsdigitten == 0 && minsdigit == 0) { strcpy (str_a, numbers); strcpy (str_b, "O"CLOCK"); strcpy (str_c, ""); } }//end worknig out time //run in a loop //print line a "twelve" byte len = 0; while (str_a) { len++; }; //get length of message byte offset_top = (31 - ((len - 1) * 4)) / 2; // //plot hours line byte i = 0; while (str_a[i]) { puttinychar((i * 4) + offset_top, 1, str_a[i]); i++; } //hold display but check for button presses int counter = 1000; while (counter >0)( //vérifie la pression sur le bouton if (buttonA.uniquePress()) ( switch_mode(); return; ) if (buttonB.uniquePress()) ( display_date(); ) delay(1); counter--; ) fade_down ();< 6; c++) { putnormalchar(x[c],y,message[ chara[c] ]); //draw a line of pixels turned off after each char,otherwise the gaps between the chars have pixels left in them from the previous char for (byte yy = 0 ; yy < 8; yy ++) { plot(x[c] + 5, yy, 0); } //take one off each chars position x[c] = x[c] - 1; } //reset a char if it"s gone off screen for (byte i = 0; i <= 5; i++) { if (x[i] < -5) { x[i] = 31; chara[i] = p; p++; } } } } //display_date - print the day of week, date and month with a flashing cursor effect void display_date() { cls(); //read the date from the DS1307 byte dow = rtc; // day of week 0 = Sunday byte date = rtc; byte month = rtc - 1; //array of month names to print on the display. Some are shortened as we only have 8 characters across to play with char monthnames = { "January", "February", "March", "April", "May", "June", "July", "August", "Sept", "October", "November", "December" }; //print the day 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 byte len = 0; while(daysfull) { len++; }; byte offset = (31 - ((len-1)*4)) / 2; //our offset to centre up the text //print the name int i = 0; while(daysfull[i]) { puttinychar((i*4) + offset , 1, daysfull[i]); i++; } delay(1000); fade_down(); cls(); // print date numerals char buffer; 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={"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); //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); offset = 8; //décalage pour centrer le texte si 4 caractères ) //imprimer les 2 caractères du suffixe puttinychar(suffixposx+offset, 1, suffix[s ]);< 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; ) // imprimer la flèche et le nom du mode d'horloge actuel sur la première ligne et imprimer le nom du mode d'horloge suivant sur la ligne deux char str_top ;< 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;) //imprimer la flèche et le nom du mode d'horloge actuel sur la première ligne et imprimer le nom du mode d'horloge suivant sur la ligne deux char str_top ;< 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, ybar void levelbar (byte xpos, byte ypos, byte xbar, byte ybar) { for (byte x = 0; x < xbar; x++) { for (byte y = 0; y <= ybar; y++) { plot(x+xpos, y+ypos, 1); } } } //set time and date routine void set_time() { cls(); //fill settings with current clock values read from clock get_time(); byte set_min = rtc; byte set_hr = rtc; byte set_date = rtc; byte set_mnth = rtc; int set_yr = rtc; //Set function - we pass in: which "set" message to show at top, current value, reset value, and rollover limit. set_date = set_value(2, set_date, 1, 31); set_mnth = set_value(3, set_mnth, 1, 12); set_yr = set_value(4, set_yr, 2013, 2099); set_hr = set_value(1, set_hr, 0, 23); set_min = set_value(0, set_min, 0, 59); ds1307.adjust(DateTime(set_yr, set_mnth, set_date, set_hr, set_min)); cls(); } //used to set min, hr, date, month, year values. pass //message = which "set" message to print, //current value = current value of property we are setting //reset_value = what to reset value to if to rolls over. E.g. mins roll from 60 to 0, months from 12 to 1 //rollover limit = when value rolls over int set_value(byte message, int current_value, int reset_value, int rollover_limit){ cls(); char messages = { "Set Mins", "Set Hour", "Set Day", "Set Mnth", "Set Year"}; //Print "set xyz" top line byte i = 0; while(messages[i]) { puttinychar(i*4 , 1, messages[i]); i++; } delay(2000); cls(); //print digits bottom line char buffer = " "; itoa(current_value,buffer,10); puttinychar(0 , 1, buffer); puttinychar(4 , 1, buffer); puttinychar(8 , 1, buffer); puttinychar(12, 1, buffer); delay(300); //wait for button input while (!buttonA.uniquePress()) { while (buttonB.isPressed()){ if(current_value < rollover_limit) { current_value++; } else { current_value = reset_value; } //print the new value itoa(current_value, buffer ,10); puttinychar(0 , 1, buffer); puttinychar(4 , 1, buffer); puttinychar(8 , 1, buffer); puttinychar(12, 1, buffer); delay(150); } } return current_value; } void get_time() { //get time DateTime now = ds1307.now(); //save time to array rtc = now.year(); rtc = now.month(); rtc = now.day(); rtc = now.dayOfWeek(); //returns 0-6 where 0 = Sunday rtc = now.hour(); rtc = now.minute(); rtc = now.second(); //flash arduino led on pin 13 every second //if ((rtc % 2) == 0) { // digitalWrite(13, HIGH); //} //else { // digitalWrite(13, LOW); //} //print the time to the serial port - useful for debuging RTC issues /* Serial.print(rtc); Serial.print(":"); Serial.print(rtc); Serial.print(":"); Serial.println(rtc); */ }

strcpy(str_top, set_modes);


La compilation du code du programme et son chargement ultérieur dans la mémoire du microcontrôleur prendront un certain temps, généralement pas plus d'une minute. La réussite de l'opération sera signalée dans la console Arduino IDE. Après quoi il ne reste plus qu'à redémarrer l'Arduino à l'aide du bouton Reset de l'appareil - une simple horloge sur matrices LED est prête !

Horloge prête sur Arduino

L'horloge est réglée à l'aide de deux boutons. L'appareil prend en charge les formats horaires 12 et 24 heures, affiche la date et le jour de la semaine et affiche l'heure avec ou sans secondes. Il est également possible de modifier la luminosité des LED.


Vous souhaiterez probablement ajouter plus de fonctionnalités à l'avenir (par exemple, un thermomètre) ou installer l'appareil dans un corps de votre propre conception - de bons résultats peuvent être obtenus en fabriquant sur des machines de découpe laser. Mais maintenant, vous pouvez dire en toute sécurité que vous avez assemblé de vos propres mains une montre électronique à part entière !

Je me souviens... Il y a trente ans, six indicateurs constituaient un petit trésor. Quiconque pouvait alors fabriquer une horloge en utilisant la logique TTL avec de tels indicateurs était considéré comme un expert sophistiqué dans son domaine.

La lueur des indicateurs de décharge de gaz semblait plus chaude. Après quelques minutes, je me demandais si ces vieilles lampes fonctionneraient et je voulais en faire quelque chose. Il est désormais très simple de fabriquer une telle montre. Tout ce dont vous avez besoin c'est d'un microcontrôleur...

Comme en même temps je m'intéressais à la programmation de microcontrôleurs dans des langages de haut niveau, j'ai décidé de jouer un peu. J'ai essayé de construire une horloge simple utilisant des indicateurs numériques de décharge de gaz.

Objectif de la conception

J'ai décidé que l'horloge devait avoir six chiffres et que l'heure devait être réglée avec un nombre minimum de boutons. De plus, je voulais essayer d'utiliser plusieurs des familles de microcontrôleurs les plus courantes de différents fabricants. J'avais l'intention d'écrire le programme en C.

Les indicateurs à décharge gazeuse nécessitent une haute tension pour fonctionner. Mais je ne voulais pas être confronté à une tension secteur dangereuse. La montre était censée être alimentée par une tension inoffensive de 12 V.

Puisque mon objectif principal était le jeu, vous ne trouverez ici aucune description de la conception mécanique ou des dessins de carrosserie. Si vous le souhaitez, vous pouvez changer vous-même la montre selon vos goûts et votre expérience.

Voici ce que j'ai obtenu :

  • Affichage de l'heure : HH MM SS
  • Indication d'alarme : HH MM --
  • Mode d'affichage de l'heure : 24 heures
  • Précision ±1 seconde par jour (selon le cristal de quartz)
  • Tension d'alimentation : 12 V
  • Consommation de courant : 100 mA

Diagramme d'horloge

Pour un appareil doté d'un affichage numérique à six chiffres, le mode multiplex était une solution naturelle.

Le but de la plupart des éléments du schéma fonctionnel (Figure 1) est clair sans commentaire. Dans une certaine mesure, la tâche non standard consistait à créer un convertisseur de niveaux TTL en signaux de commande d'indicateurs haute tension. Les pilotes d'anode sont fabriqués à l'aide de transistors NPN et PNP haute tension. Le diagramme est emprunté à Stefan Kneller (http://www.stefankneller.de).

La puce TTL 74141 contient un décodeur BCD et un pilote haute tension pour chaque chiffre. Il peut être difficile de commander une seule puce. (Même si je ne sais plus si quelqu'un en fabrique encore). Mais si vous trouvez des indicateurs de décharge de gaz, le 74141 se trouve peut-être quelque part à proximité :-). A l'époque de la logique TTL, il n'existait pratiquement aucune alternative à la puce 74141. Essayez donc d'en trouver un quelque part.

Les indicateurs nécessitent une tension d'environ 170 V. Cela n'a aucun sens de développer un circuit spécial pour un convertisseur de tension, car il existe un grand nombre de puces de convertisseur élévateur. J'ai choisi l'IC34063, peu coûteux et largement disponible. Le circuit convertisseur est presque entièrement copié de la fiche technique du MC34063. Un interrupteur d'alimentation T13 vient d'y être ajouté. L'interrupteur interne n'est pas adapté à une tension aussi élevée. J'ai utilisé une self comme inductance pour le convertisseur. Il est représenté sur la figure 2 ; son diamètre est de 8 mm et sa longueur est de 10 mm.

L'efficacité du convertisseur est assez bonne et la tension de sortie est relativement sûre. Avec un courant de charge de 5 mA, la tension de sortie chute à 60 V. R32 agit comme une résistance de détection de courant.

Pour alimenter la logique, le régulateur linéaire U4 est utilisé. Il y a de la place sur le circuit et la carte pour une batterie de secours. (3,6 V - NiMH ou NiCd). D7 et D8 sont des diodes Schottky, et la résistance R37 est conçue pour limiter le courant de charge en fonction des caractéristiques de la batterie. Si vous construisez des montres juste pour le plaisir, vous n'aurez pas besoin de la batterie D7, D8 et R37.

Le circuit final est illustré à la figure 3.

Graphique 3.

Les boutons de réglage de l'heure sont connectés via des diodes. L'état des boutons est vérifié en mettant un « 1 » logique sur la sortie correspondante. En prime, un émetteur piézo est connecté à la sortie du microcontrôleur. Pour faire taire ce méchant grincement, utilisez un petit interrupteur. Un marteau conviendrait tout à fait pour cela, mais c'est un dernier recours :-).

Une liste des composants du circuit, un dessin du circuit imprimé et un schéma de configuration peuvent être trouvés dans la section « Téléchargements ».

Processeur

Presque n'importe quel microcontrôleur doté d'un nombre suffisant de broches, dont le nombre minimum requis est indiqué dans le tableau 1, peut contrôler ce dispositif simple.

Tableau 1.
Fonction Conclusions
Nutrition 2
Résonateur à quartz 2
Gestion des anodes 6
Chauffeur 74141 4
Saisie du bouton 1
Émetteur piézo 1
Total 16

Chaque constructeur développe ses propres familles et types de microcontrôleurs. L'emplacement des broches est individuel pour chaque type. J'ai essayé de concevoir une carte universelle pour plusieurs types de microcontrôleurs. La carte dispose d'une prise à 20 broches. Avec quelques câbles de liaison, vous pouvez l'adapter à différents microcontrôleurs.

Les microcontrôleurs testés dans ce circuit sont répertoriés ci-dessous. Vous pouvez expérimenter avec d'autres types. L'avantage du système est la possibilité d'utiliser différents processeurs. En règle générale, les radioamateurs utilisent une seule famille de microcontrôleurs et disposent du programmeur et des outils logiciels correspondants. Il peut y avoir des problèmes avec les microcontrôleurs d'autres fabricants, je vous ai donc donné la possibilité de choisir un processeur de votre famille préférée.

Toutes les spécificités de la mise sous tension des différents microcontrôleurs sont reflétées dans les tableaux 2...5 et les figures 4...7.

Tableau 2.
Échelle libre
Taper MC68HC908QY1
Résonateur à quartz 12 MHz
Condensateurs C1, C2 22 pF
Programme freescale.zip
(voir rubrique "Téléchargements")
Paramètres

Remarque : Une résistance de 10 MΩ est connectée en parallèle avec le résonateur à quartz.

Tableau 3.
Puce
Taper PIC16F628A
Résonateur à quartz 32,768 kHz
Condensateurs C1, C2 22 pF
Programme pic628.zip
(voir rubrique "Téléchargements")
Paramètres Int. Générateur 4 MHz - E/S RA6,
MCLR désactivé, WDT désactivé, LVP désactivé,
BROUT OFF, CP OFF, PWRUP OFF

Remarque : Le microcircuit doit être tourné de 180° dans le support.

Tableau 4.
Atmel
Taper ATtiny2313
Résonateur à quartz 12 MHz
Condensateurs C1, C2 15 pF
Programme attiny.zip
(voir rubrique "Téléchargements")
Paramètres Carré. Oscillateur 8 MHz, RESET ON

Remarque : ajoutez les composants SMD R et C à la broche RESET (10 kΩ et 100 nF).

Tableau 5.
Atmel
Taper AT89C2051
Résonateur à quartz 12 MHz
Condensateurs C1, C2 22 pF
Programme at2051.zip
(voir rubrique "Téléchargements")
Paramètres --

Remarque : ajoutez les composants SMD R et C à la broche RESET (10 kΩ et 100 nF) ; connectez les broches marquées d'astérisques au bus d'alimentation +Ub via des résistances SMD de 3,3 kOhm.

Lorsque vous comparez les codes de différents microcontrôleurs, vous verrez qu’ils sont très similaires. Il existe des différences dans l'accès aux ports et la définition des fonctions d'interruption, ainsi que dans ce qui dépend des composants matériels.

Le code source se compose de deux sections. Fonction principal() configure les ports et démarre une minuterie qui génère des signaux d'interruption. Après cela, le programme scanne les boutons enfoncés et définit l'heure et les valeurs d'alarme appropriées. Là, dans la boucle principale, l'heure actuelle est comparée au réveil et l'émetteur piézo est allumé.

La deuxième partie est un sous-programme permettant de gérer les interruptions de minuterie. Un sous-programme appelé toutes les millisecondes (en fonction des capacités de la minuterie) incrémente les variables de temps et contrôle les chiffres d'affichage. De plus, l'état des boutons est vérifié.

Faire tourner le circuit

Lors de l'installation des composants et de la configuration, commencez par la source d'alimentation. Soudez le régulateur U4 et les composants environnants. Vérifiez la tension de 5 V pour U2 et de 4,6 V pour U1. L'étape suivante consiste à assembler le convertisseur haute tension. Utilisez la résistance d'ajustement R36 pour régler la tension à 170 V. Si la plage de réglage n'est pas suffisante, modifiez légèrement la résistance de la résistance R33. Installez maintenant la puce U2, les transistors et les résistances de l'anode et du circuit pilote numérique. Connectez les entrées U2 au bus GND et connectez l'une des résistances R25 - R30 en série au bus d'alimentation +Ub. Les numéros des indicateurs doivent s'allumer dans les positions correspondantes. À la dernière étape de vérification du circuit, connectez la broche 19 du microcircuit U1 à la terre - l'émetteur piézo doit émettre un bip.

Vous trouverez les codes sources et les programmes compilés dans le fichier ZIP correspondant dans la rubrique « Téléchargements ». Après avoir flashé le programme dans le microcontrôleur, vérifiez soigneusement chaque broche en position U1 et installez le fil et les cavaliers à souder nécessaires. Reportez-vous aux images du microcontrôleur ci-dessus. Si le microcontrôleur est programmé et connecté correctement, son générateur devrait commencer à fonctionner. Vous pouvez régler l'heure et l'alarme. Attention! Il y a de la place sur le tableau pour un bouton supplémentaire - c'est un bouton de rechange pour les futures extensions :-).

Vérifiez la précision de la fréquence du générateur. Si ce n'est pas dans la plage attendue, modifiez légèrement les valeurs des condensateurs C1 et C2. (Soudez les petits condensateurs en parallèle ou remplacez-les par d'autres). La précision de la montre devrait s'améliorer.

Conclusion

Les petits processeurs 8 bits conviennent tout à fait aux langages de haut niveau. C n'était pas initialement destiné aux petits microcontrôleurs, mais pour des applications simples, vous pouvez très bien l'utiliser. Le langage assembleur est mieux adapté aux tâches complexes qui nécessitent des temps critiques ou une charge CPU maximale. Pour la plupart des radioamateurs, les versions gratuites et shareware limitées du compilateur C conviennent.

La programmation C est la même pour tous les microcontrôleurs. Vous devez connaître les fonctions matérielles (registres et périphériques) du type de microcontrôleur sélectionné. Soyez prudent avec les opérations sur les bits - le langage C n'est pas adapté à la manipulation de bits individuels, comme on peut le voir dans l'exemple de l'original pour ATtiny.

Avez-vous terminé ? Alors connectez-vous pour contempler les tubes à vide et regardez...

...le bon vieux temps est de retour... :-)

NDLR

Un analogue complet du SN74141 est le microcircuit K155ID1, produit par le logiciel Minsk Integral.
Le microcircuit peut être facilement trouvé sur Internet.

Cette horloge est assemblée sur un chipset bien connu - K176IE18 (compteur binaire pour horloge avec générateur de signal de cloche),

K176IE13 (compteur d'horloge avec alarme) et K176ID2 (convertisseur de code binaire à sept segments)

Lorsque l'appareil est allumé, des zéros sont automatiquement écrits dans le compteur des heures et des minutes et dans le registre mémoire du réveil de la puce U2. Pour installer

l'heure, appuyez sur le bouton S4 (Time Set) et maintenez-le enfoncé, appuyez sur le bouton S3 (Hour) - pour régler l'heure ou S2 (Min) - pour régler

minutes. Dans ce cas, les lectures des indicateurs correspondants commenceront à changer avec une fréquence de 2 Hz de 00 à 59 puis à nouveau 00. Au moment de la transition

de 59 à 00 le compteur horaire augmentera d'une unité. Le réglage de l'heure de l'alarme est le même, il vous suffit de la maintenir enfoncée

bouton S5 (réglage d'alarme). Après avoir réglé l'heure de l'alarme, vous devez appuyer sur le bouton S1 pour activer l'alarme (contacts

fermé). Le bouton S6 (Reset) est utilisé pour forcer la réinitialisation des indicateurs des minutes à 00 lors de la configuration. Les LED D3 et D4 jouent un rôle

points de division clignotant à une fréquence de 1 Hz. Les indicateurs numériques sur le schéma sont situés dans le bon ordre, c'est-à-dire viens en premier

indicateurs d'heures, deux points de séparation (LED D3 et D4) et indicateurs de minutes.

L'horloge utilisait des résistances R6-R12 et R14-R16 d'une puissance de 0,25 W, le reste de 0,125 W. Résonateur à quartz XTAL1 à une fréquence de 32 768Hz -

sentinelle ordinaire, les transistors KT315A peuvent être remplacés par n'importe quel silicium de faible puissance de structure appropriée, KT815A - avec des transistors

puissance moyenne avec un coefficient de transfert de courant de base statique d'au moins 40, diodes - tout silicium de faible puissance. Tweeter BZ1

dynamique, sans générateur intégré, résistance d'enroulement 45 Ohm. Le bouton S1 est naturellement verrouillé.

Les indicateurs utilisés sont le vert TOS-5163AG, vous pouvez utiliser n'importe quel autre indicateur avec une cathode commune sans réduire

résistance des résistances R6-R12. Sur la figure, vous pouvez voir le brochage de cet indicateur ; les conclusions sont présentées sous condition, car présenté

vue de dessus.

Après avoir assemblé la montre, vous devrez peut-être régler la fréquence de l'oscillateur à cristal. Cela peut être fait de manière plus précise en contrôlant numériquement

à l'aide d'un fréquencemètre, la période d'oscillation est de 1 s à la broche 4 du microcircuit U1. Le réglage du générateur au fur et à mesure que l'horloge progresse nécessitera des dépenses beaucoup plus importantes.

temps. Vous devrez peut-être également régler la luminosité des LED D3 et D4 en sélectionnant la résistance de la résistance R5, afin que tout

brillait uniformément et brillamment. Le courant consommé par l'horloge ne dépasse pas 180 mA.

La montre est alimentée par une alimentation classique, montée sur un microcircuit stabilisateur positif 7809 avec une tension de sortie de +9V et un courant de 1,5A.