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

Arduino Shield NCS314 NIXIE Tubes Clock IN-14

Composants et fournitures

Bouclier Nixie Tubes IN-14 NCS314 Arduino pour Nixie Tubes Clock etc. .
Bouclier sur Nixie Tubes IN-14
× 1
Bouclier Nixie Tubes Clock IN-12 NCS312 pour xUSSR Nixie Tubes
× 1
Arduino UNO
Shield prend en charge Arduino UNO/Genuino ou Arduino MEGA
× 1
Arduino Mega 2560
Shield prend en charge Arduino UNO/Genuino ou Arduino MEGA
× 1
Alimentation 12V 1A
× 1
Boîtier en acrylique pour SHIELD NCS314
Beau acrylique modèle de Сase ACNS314 est entièrement compatible avec les versions Nixie Arduino Shield NCS314 HW de v1.X – 2 .X
× 1

Applications et services en ligne

Arduino IDE

À propos de ce projet

Présentation

Initialement, après avoir eu accès à une offre presque inépuisable de tubes Nixie soviétiques d'excellente qualité IN-12, IN-14 et IN-18, il allait faire un simple affichage des tubes Nixie en tant que Shield pour Arduino. Arduino à cette époque nous en avions déjà, donc le boitier restait pour les petits (c'est ce qu'on pensait à l'époque). À cette époque, nous ne savions rien sur la façon de traiter de telles lampes.

Très vite on a trouvé sur internet le schéma d'alimentation de telles lampes :

OUI! ça brille ! Le fait que nous ayons vu juste nous abasourdi est comme un petit miracle, et nous avons réalisé que nous sommes sur la bonne voie. Immédiatement commencé la séance photo :

Le lendemain, a commencé à discuter du concept du futur projet :pour simplifier et réduire le coût, il a été décidé d'utiliser le schéma avec un principe d'affichage dynamique, mais plus tard, il a été décidé de l'abandonner au profit du schéma avec un pleinement mode d'affichage statique. Bien que pour les tubes IN-14 Nixie, la différence visuelle ne soit pas perceptible, mais pour les lampes IN-18, la différence est perceptible - en mode dynamique, ils ne fonctionnent pas si brillant que beaucoup d'entre eux apparaissent, ce qu'on appelle l'effet de points bleus :

Le mode d'affichage dynamique est un mode dans lequel à chaque fois tous les tubes ne sont pas allumés, et un seul (à la fois), peut également être d'autres espèces lorsqu'il est allumé simultanément, par exemple, seulement deux lampes.

En discutant de l'avenir de l'appareil une fois qu'il aura été décidé de mettre en œuvre la possibilité d'afficher des informations sur les tubes provenant de l'ordinateur, cela permettra aux passionnés de créer leur propre appareil qui serait affiché sur les lampes, par exemple, le nombre de messages non lus ou le nombre de tours dans le jeu, comme Fallout.

Puis a commencé la sélection du matériel qui pourrait être des cathodes de commutation (numéros) dans les tubes. Le choix était évident - les registres à décalage avec SPI pour économiser les broches du MCU. Mais comme les tubes de tension d'alimentation sont très élevés - jusqu'à 200 volts, les options ne sont pas tellement:HV513, HV5812, HV5122. Et pendant que nous construisons l'appareil sur chacune de ces puces, nous nous sommes arrêtés au HV5812 (dans la nouvelle version de Shields NCS314 V2.X et NCS312 V1.X utilisaient IC HV5122). Cette puce est très pratique car elle permet de contrôler simultanément deux lampes, comme un registre 20 bits.

Pour contrôler 6 tubes, nous aurons besoin que trois de ces circuits soient connectés les uns aux autres en série. Cela permet une fois d'envoyer des paquets via SPI et ne se soucie pas de mettre à jour les informations sur les tubes, comme ce serait le cas avec un algorithme d'affichage dynamique. C'est-à-dire, en d'autres termes - tant que nous n'avons pas besoin de modifier les informations sur les tubes, le MCU peut être occupé à d'autres tâches, même à dormir !

Nous aimerions dire à propos du transfert de données sur SPI. Arudino peut transmettre à la fois, seulement 8 bits. Et nous avons besoin de 60, le nombre entier supérieur le plus proche est divisible par 8 est 64, et doit donc appliquer un peu de magie - pour former une grande variable de type non signé long long var64 bits pour chaque registre et passer 8 fois 8 bits à chaque fois par décaler tous les bits à l'intérieur de la variable vers la droite :

SPI.transfer(var64); SPI.transfer(var64>>48); SPI.transfer(var64>>40); SPI.transfer(var64>>32); SPI.transfer(var64>>24); SPI.transfer(var64>>16); SPI.transfer(var64>>8) ; SPI.transfer(iTmp);

Les objectifs qui ont été fixés et atteints ont été mis en œuvre :

  • Affichage statique basé sur des registres à décalage.
  • Machine à sous (empoisonnement à l'Ani)
  • Fournir les fonctions standard pour l'horloge, l'horloge, la date, l'heure, le réveil.
  • RTC (Real Time Clock) avec pile CR1220. (La nouvelle version de la carte V1.2-2.X utilise une puce de temps de haute précision RTC DS3231).
  • Mesure de la température DS18B20 [Celsius ou Fahrenheit].
  • Contrôle via le port IR TSOP4836 (fonctionne uniquement Mega). Vérifié avec Télécommande Sony RM-X151, Mais c'est possible et autre télécommande avec une fréquence de 36kHz.
  • Synchronisation de l'heure avec un GPS externe (fonctionne uniquement Mega)
  • Menu simple.
  • Gestion séparée du côlon (le point inférieur et supérieur)
  • Couleurs de rétroéclairage RVB avec une transfusion fluide
  • Sonnerie RTTTL pour l'alarme (Ring Tone Transfer Language)
  • Machine à sous (pour éviter les indicateurs d'empoisonnement)
  • En auto-test. (Vérifiez tous les numéros dans chaque affichage de 0 à 9, pour vérifier toutes les LED, un commutateur série couleurs bleu, rouge, vert, vérification du son (sonneries jouées)

Ces tâches qui n'ont pas pu être réalisées pleinement.

  • Capteur de lumière

Code

  • Fichier sans titre
Fichier sans titreC/C++
const String FirmwareVersion="010000";//Format _X.XX__ //NIXIE CLOCK SHIELD NCS314 par GRA &AFCH ([email protected])//25.05.2016 #include #include #include #include #include #include octet const LEpin=7 ; //pin Latch Enabled données acceptées alors que HI levelconst byte DHVpin=5; // off/on MAX1771 Driver Hight Voltage (DHV) 110-220V octet const RedLedPin=9; //Sortie MCU WDM pour LED rouges octet 9-gconst GreenLedPin=6 ; //Sortie MCU WDM pour LED vertes octet 6-bconst BlueLedPin=3 ; //Sortie MCU WDM pour LED bleues 3-rconst byte pinSet=A0;const byte pinUp=A2;const byte pinDown=A1;const byte pinBuzzer=2;const byte pinUpperDots=12; //La valeur HAUTE allume un octet dotsconst pinLowerDots=8; //La valeur HAUTE allume un mot dotsconst fpsLimit=16666; // 1/60*1.000.000 //limiter le taux de rafraîchissement maximum sur 60 fpsString stringToDisplay="000000";// Le contenu de cette chaîne sera affiché sur les tubes (doit avoir une longueur de 6 caractères)int menuPosition=0; // 0 - heure // 1 - date // 2 - alarme // 3 - octet de mode 12/24 heures blinkMask=B00000000; // masque de bits pour les chiffres clignotants (1 - clignotement, 0 - lumière constante) //-------------------------0----- -1----------2----------3--------4--------5------ ---6---------7---------8---------9-----//octet lowBytesArray[]={B11111110,B11111101 ,B11111011,B11110111,B11101111,B11011111,B10111111,B01111111,B11111111,B11111111} ;//octet highBytesArray[]={B1111111,B1111111,B1111111,B1111111,B1111111,B11111111,B11111111,B11111}attern=11111,B dooctet B00000000 ; //masque de bits pour séparer les points //B00000000 - désactiver les points haut et bas //B1100000 - désactiver tous les points#define DS1307_ADDRESS 0x68byte zero =0x00; //solution de contournement pour le problème #527int RTC_hours, RTC_minutes, RTC_seconds, RTC_day, RTC_month, RTC_year, RTC_day_of_week;//-- ------------0--------1--- -----2-------3--------4--------5--------6--------7 --------8--------9--------10-------11-------12------- 13-------14// noms :Heure, Date, Alarme, 12/24 heures, minutes, secondes, jour, mois, année, heure, minute, seconde alarme01 hour_format // 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1int parent[15]={ 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4};int firstChild[15] ={4, 7, 10, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};int lastChild[15]={ 6, 9, 13, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};int value[15]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24};int maxValue[15]={ 0, 0, 0, 0, 23, 59, 59, 31, 12, 99, 23, 59, 59, 1, 24};int minValue[ 15]={ 0, 0, 0, 12, 00, 00, 00, 1, 1, 00, 00, 00, 00, 0, 12};byte blinkPattern[15]={ B00000000, B00000000, B00000000, B00000000, B00000011, B00001100, B00110000, B00000011, B00001100, B00110000, B00000011, B00001100, B00110000, B110000 00, B00001100};#define TimeIndex 0 #define DateIndex 1 #define AlarmIndex 2 #define hModeIndex 3 #define TimeHoursIndex 4 #define TimeMintuesIndex 5#define TimeSecondsIndex 6#define DateDayIndex 7#define DateMonthIndex 8#define DateYearHex 9 #define AlarmYearHour 9 #define define AlarmMinuteIndex 11#define AlarmSecondIndex 12#define Alarm01 13#define hModeValueIndex 14bool editMode=false;long downTime=0;long upTime=0;const long settingDelay=150;bool BlinkUp=false;bool BlinkDown=false;non signé long enterEditModeTime=0;bool RGBLedsOn=true;byte RGBLEDsEEPROMAddress=0; octet HourFormatEEPROMAddress=1;byte AlarmTimeEEPROMAddress=2;//3,4,5byte AlarmArmedEEPROMAddress=6; //boutons épingles déclarationsClickButton setButton(pinSet, LOW, CLICKBTN_PULLUP);ClickButton upButton(pinUp, LOW, CLICKBTN_PULLUP);ClickButton downButton(pinDown, LOW, CLICKBTN_PULLUP);//////////////// ///Tone tone1;#define isdigit(n) (n>='0' &&n <='9')//char *song ="MissionImp:d=16,o=6,b=95:32d, 32d#,32d,32d#,32d,32d#,32d,32d#,32d,32d,32d#,32e,32f,32f#,32g,g,8p,g,8p,a#,p,c7,p, g,8p,g,8p,f,p,f#,p,g,8p,g,8p,a#,p,c7,p,g,8p,g,8p,f,p,f#,p,a#, g,2d,32p,a#,g,2c#,32p,a#,g,2c,a#5,8c,2p,32p,a#5,g5,2f#,32p,a#5,g5,2f, 32p,a#5,g5,2e,d#,8d";char *song ="PinkPanther:d=4,o=5,b=160:8d#,8e,2p,8f#,8g,2p,8d# ,8e,16p,8f#,8g,16p,8c6,8b,16p,8d#,8e,16p,8b,2a#,2p,16a,16g,16e,16d,2e";//char *song=" VanessaMae:d=4,o=6,b=70:32c7,32b,16c7,32g,32p,32g,32p,32d#,32p,32d#,32p,32c,32p,32c,32p,32c7,32b, 16c7,32g#,32p,32g#,32p,32f,32p,16f,32c,32p,32c,32p,32c7,32b,16c7,32g,32p,32g,32p,32d#,32p,32d#,32p, 32c,32p,32c,32p,32g,32f,32d#,32d,32c,32d,32d#,32c,32d#,32f,16g,8p,16d7,32c7,32d7,32a#,32d7,32a,32d7, 32g,32d7,32d7,32p,32d7,3 2p,32d7,32p,16d7,32c7,32d7,32a#,32d7,32a,32d7,32g,32d7,32d7,32p,32d7,32p,32d7,32p,32g,32f,32d#,32d,32c,32d, 32d#,32c,32d#,32f,16c";//char *song="DasBoot:d=4,o=5,b=100:d#.4,8d4,8c4,8d4,8d#4,8g4, a#.4,8a4,8g4,8a4,8a#4,8d,2f.,p,f.4,8e4,8d4,8e4,8f4,8a4,c.,8b4,8a4,8b4,8c,8e,2g. ,2p";//char *song="Scatman:d=4,o=5,b=200:8b,16b,32p,8b,16b,32p,8b,2d6,16p,16c#.6,16p. ,8d6,16p,16c#6,8b,16p,8f#,2p.,16c#6,8p,16d.6,16p.,16c#6,16b,8p,8f#,2p,32p,2d6,16p ,16c#6,8p,16d.6,16p.,16c#6,16a.,16p.,8e,2p.,16c#6,8p,16d.6,16p.,16c#6,16b,8p, 8b,16b,32p,8b,16b,32p,8b,2d6,16p,16c#.6,16p.,8d6,16p,16c#6,8b,16p,8f#,2p.,16c#6,8p, 16d.6,16p.,16c#6,16b,8p,8f#,2p,32p,2d6,16p,16c#6,8p,16d.6,16p.,16c#6,16a.,16p.,8e ,2p.,16c#6,8p,16d.6,16p.,16c#6,16a,8p,8e,2p,32p,16f#.6,16p.,16b.,16p.";//char * chanson="Maïs éclaté:d=4,o=5,b=160:8c6,8a#,8c6,8g,8d#,8g,c,8c6,8a#,8c6,8g,8d#,8g,c,8c6 ,8d6,8d#6,16c6,8d#6,16c6,8d#6,8d6,16a#,8d6,16a#,8d6,8c6,8a#,8g,8a#,c6";//char *chanson="WeWishYou:d=4,o=5,b=200:d,g,8g,8a,8g,8f#,e,e,e,a,8a,8b,8a,8g,f#,d,d, b,8b,8c6,8b ,8a,g,e,d,e,a,f#,2g,d,g,8g,8a,8g,8f#,e,e,e,a,8a,8b,8a,8g,f#,d, d,b,8b,8c6,8b,8a,g,e,d,e,a,f#,1g,d,g,g,g,2f#,f#,g,f#,e,2d,a,b ,8a,8a,8g,8g,d6,d,d,e,a,f#,2g";#define OCTAVE_OFFSET 0char *p;int notes[] ={ 0,NOTE_C4, NOTE_CS4, NOTE_D4, NOTE_DS4, NOTE_E4, NOTE_F4 , NOTE_FS4, NOTE_G4, NOTE_GS4, NOTE_A4, NOTE_AS4, NOTE_B4,NOTE_C5, NOTE_CS5, NOTE_D5, NOTE_DS5, NOTE_E5, NOTE_F5, NOTE_FS5, NOTE_G5, NOTE_GS5, NOTE_A5, NOTE_AS5, NOTE_B6, NOTE_DS_6, NOTE_FS_6_ , NOTE_G6, NOTE_GS6, NOTE_A6, NOTE_AS6, NOTE_B6,NOTE_C7, NOTE_CS7, NOTE_D7, NOTE_DS7, NOTE_E7, NOTE_F7, NOTE_FS7, NOTE_G7, NOTE_GS7, NOTE_A7, NOTE_AS7, NOTE_B7} ;{0,0,1,[/]/ 1 -1,0,0,//2 0,1,0,//3 0,0,-1,//4 1,0,0,//5 0,-1,0} ; // tableau avec règles RVB (0 - ne rien faire, -1 - decrese, +1 - incresevoid setRTCDateTime(byte h, byte m, byte s, byte d, byte mon, byte y, byte w=1);int functionDownButton=0;int functionUpButton=0;/****************************************** ******************************************************** *************Init Program**************************************** ******************************************************** ****************/configuration vide () { digitalWrite (DHVpin, LOW); // off MAX1771 Driver Hight Voltage (DHV) 110-220V Wire.begin (); // setRTCDateTime(23,40,00,25,7,15,1) ; Serial.begin(115200); Serial.println(""); if (EEPROM.read(HourFormatEEPROMAddress)!=12) value[hModeValueIndex]=24; else value[hModeValueIndex]=12; if (EEPROM.read(RGBLEDsEEPROMAddress)!=0) RGBLedsOn=true; else RGBLedsOn=false; if (EEPROM.read(AlarmTimeEEPROMAddress)==255) value[AlarmHourIndex]=0; else value[AlarmHourIndex]=EEPROM.read(AlarmTimeEEPROMAddress); si (EEPROM.read(AlarmTimeEEPROMAddress+1)==255) value[AlarmMinuteIndex]=0; e lse value[AlarmMinuteIndex]=EEPROM.read(AlarmTimeEEPROMAddress+1); si (EEPROM.read(AlarmTimeEEPROMAddress+2)==255) value[AlarmSecondIndex]=0 ; else value[AlarmSecondIndex]=EEPROM.read(AlarmTimeEEPROMAddress+2); if (EEPROM.read(AlarmArmedEEPROMAddress)==255) value[Alarm01]=0 ; else value[Alarm01]=EEPROM.read(AlarmArmedEEPROMAddress); tone1.begin(pinBuzzer); chanson=parseSong(chanson); pinMode(LEpin, SORTIE); pinMode(DHVpin, SORTIE); pinMode(RedLedPin, SORTIE); pinMode(GreenLedPin, SORTIE); pinMode (BlueLedPin, SORTIE); // Configuration SPI SPI.begin(); // SPI.setDataMode (SPI_MODE3) ; // Mode 3 SPI SPI.setClockDivider(SPI_CLOCK_DIV128) ; // SCK =16MHz/128 =125kHz //les broches des boutons inits pinMode (pinSet, INPUT_PULLUP); pinMode(pinUp, INPUT_PULLUP); pinMode(pinDown, INPUT_PULLUP); ////////////////////////// pinMode(pinBuzzer, SORTIE); // objets boutons inits setButton.debounceTime =20; // Temporisateur anti-rebond en ms setButton.multiclickTime =30; // Limite de temps pour les clics multiples setButton.longClickTime =2000; // temps jusqu'à ce que les "clics maintenus enfoncés" enregistrent upButton.debounceTime =20; // Temporisateur anti-rebond en ms upButton.multiclickTime =30; // Limite de temps pour les clics multiples upButton.longClickTime =2000; // temps jusqu'à ce que les "clics maintenus enfoncés" enregistrent downButton.debounceTime =20; // Temporisateur anti-rebond en ms downButton.multiclickTime =30; // Limite de temps pour les clics multiples downButton.longClickTime =2000; // temps jusqu'au registre des "clics maintenus enfoncés" // digitalWrite(DHVpin, HIGH); // sur MAX1771 Driver Hight Voltage (DHV) 110-220V //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!! //doTest(); //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! getRTCTime(); setTime(RTC_hours, RTC_minutes, RTC_seconds, RTC_day, RTC_month, RTC_year); digitalWrite(DHVpin, LOW); // off MAX1771 Driver Hight Voltage (DHV) 110-220V setRTCDateTime(RTC_hours,RTC_minutes,RTC_seconds,RTC_day,RTC_month,RTC_year,1) ; //���������� ������ ��� ��������� ����� � RTC ����� �������� � ����� ���������� digitalWrite(DHVpin, HIGH); // sur MAX1771 Driver Hight Voltage (DHV) 110-220V //p=song;}void rotateLeft(uint8_t &bits){ uint8_t high_bit =bits &(1 <<7) ? dix; bits =(bits <<1) | high_bit;}int rotateur=0; //index dans le tableau avec des "règles" RVB (augmenter de un tous les 255 cycles) int cycle=0; //cycle counterint RedLight=255;int GreenLight=0;int BlueLight=0;unsigned long prevTime=0; // l'heure du tube laser était allumée non signée long prevTime4FireWorks=0; //heure du dernier RVB changé//int minuteL=0; //������� ����� �����/****************************** ******************************************************** *******************************Programme PRINCIPAL****************** ******************************************************** ********************************************/boucle vide() { p=jouer de la musique(p); if ((millis()-prevTime4FireWorks)>5) { rotateFireWorks(); //changer la couleur (par 1 étape) prevTime4FireWorks=millis(); } doIndication(); setButton.Update(); upButton.Update(); downButton.Update(); if (editMode==false) { blinkMask=B00000000; } else if ((millis()-enteringEditModeTime)>600000) { editMode=false; menuPosition=firstChild[menuPosition] ; blinkMask=blinkPattern[menuPosition] ; } if (setButton.clicks>0) //clic court { p=0; //couper la musique ))) tone1.play(1000,100); enterEditModeTime=millis(); MenuPosition=menuPosition+1; if (menuPosition==hModeIndex+1) menuPosition=TimeIndex; Serial.print(F("menuPosition=")); Serial.println(menuPosition); Serial.print(F("value=")); Serial.println(value[menuPosition]); blinkMask=blinkPattern[menuPosition] ; if ((parent[menuPosition-1]!=0) et (lastChild[parent[menuPosition-1]-1]==(menuPosition-1))) { if ((parent[menuPosition-1]-1==1 ) &&(!isValidDate())) { menuPosition=DateDayIndex; retourner; } editMode=false ; menuPosition=parent[menuPosition-1]-1; if (menuPosition==TimeIndex) setTime(value[TimeHoursIndex], value[TimeMintuesIndex], value[TimeSecondsIndex], day(), month(), year()); if (menuPosition==DateIndex) setTime(hour(), minute(), second(),value[DateDayIndex], value[DateMonthIndex], 2000+value[DateYearIndex]); if (menuPosition==AlarmIndex) {EEPROM.write(AlarmTimeEEPROMAddress,value[AlarmHourIndex]); EEPROM.write(AlarmTimeEEPROMAddress+1,value[AlarmMinuteIndex]); EEPROM.write(AlarmTimeEEPROMAddress+2,value[AlarmSecondIndex]); EEPROM.write(AlarmArmedEEPROMAddress, value[Alarm01]);}; if (menuPosition==hModeIndex) EEPROM.write(HourFormatEEPROMAddress, value[hModeValueIndex]); digitalWrite(DHVpin, LOW); // off MAX1771 Driver Hight Voltage (DHV) 110-220V setRTCDateTime(hour(),minute(),second(),day(),month(),year()%1000,1) ; digitalWrite (DHVpin, HAUT); // sur MAX1771 Driver Hight Voltage (DHV) 110-220V } value[menuPosition]=extractDigits(blinkMask); } if (setButton.clicks<0) //clic long { tone1.play(1000,100); if (!editMode) { enterEditModeTime=millis(); if (menuPosition==TimeIndex) stringToDisplay=PreZero(hour())+PreZero(minute())+PreZero(second()); //format de 24 heures temporairement activé pendant que les paramètres } menuPosition=firstChild[menuPosition]; if (menuPosition==AlarmHourIndex) {value[Alarm01]=1; /*digitalWrite(pinUpperDots, HIGH);*/dotPattern=B10000000;} editMode=!editMode; blinkMask=blinkPattern[menuPosition] ; value[menuPosition]=extractDigits(blinkMask); } if (upButton.clicks !=0) functionUpButton =upButton.clicks; if (upButton.clicks>0) { p=0; //couper la musique ))) tone1.play(1000,100); incrémentValeur(); } if (functionUpButton ==-1 &&upButton.depressed ==true) { BlinkUp=false; if (editMode==true) { if ( (millis() - upTime)> settingDelay) { upTime =millis();// + settingDelay; incrémentValeur(); } } } else BlinkUp=true ; if (downButton.clicks !=0) functionDownButton =downButton.clicks; if (downButton.clicks>0) { p=0; //couper la musique ))) tone1.play(1000,100); dirementValue(); } if (functionDownButton ==-1 &&downButton.depressed ==true) { BlinkDown=false; if (editMode==true) { if ( (millis() - downTime)> settingDelay) { downTime =millis();// + settingDelay; dirementValue(); } } } else BlinkDown=true ; if (!editMode) { if (upButton.clicks<0) { tone1.play(1000,100); RGBLedsOn=true ; EEPROM.write(RGBLEDsEEPROMAdresse,1) ; Serial.println("RGB=on"); } if (downButton.clicks<0) { tone1.play(1000,100); RGBLedsOn=false ; EEPROM.write(RGBLEDsEEPROMAdresse,0) ; Serial.println("RGB=off"); } } static bool updateDateTime=false; switch (menuPosition) { case TimeIndex://mode horaire stringToDisplay=updateDisplayString(); doDotBlink(); checkAlarmTime(); Pause; case DateIndex ://mode date stringToDisplay=PreZero(day())+PreZero(month())+PreZero(year()%1000); dotPattern=B01000000;//activer les points inférieurs /*digitalWrite(pinUpperDots, LOW); digitalWrite(pinLowerDots, HIGH);*/ checkAlarmTime(); Pause; case AlarmIndex ://mode d'alarme stringToDisplay=PreZero(value[AlarmHourIndex])+PreZero(value[AlarmMinuteIndex])+PreZero(value[AlarmSecondIndex]); if (value[Alarm01]==1) /*digitalWrite(pinUpperDots, HIGH);*/ dotPattern=B10000000; //activer les points supérieurs else { /*digitalWrite(pinUpperDots, LOW); digitalWrite(pinLowerDots, LOW);*/ dotPattern=B00000000; //désactiver les points supérieurs } checkAlarmTime(); Pause; case hModeIndex ://12/24 heures mode stringToDisplay="00"+String(value[hModeValueIndex])+"00" ; dotPattern=B00000000;//désactiver tous les points /*digitalWrite(pinUpperDots, LOW); digitalWrite(pinLowerDots, LOW);*/ checkAlarmTime(); Pause; }}String PreZero(int digit){ if (digit<10) return String("0")+String(digit); else return String(digit);}void rotateFireWorks(){ if (!RGBLedsOn) { analogWrite(RedLedPin,0 ); analogWrite(GreenLedPin,0) ; analogWrite (BlueLedPin, 0); retourner; } RedLight=RedLight+fireforks[rotator*3] ; GreenLight=GreenLight+fireforks[rotator*3+1] ; BlueLight=BlueLight+fireforks[rotator*3+2] ; analogWrite(RedLedPin,RedLight ); analogWrite(GreenLedPin,GreenLight); analogWrite (BlueLedPin, BlueLight); cycle=cycle+1; if (cycle==255) { rotateur=rotateur+1; cycle=0; } if (rotator>5) rotateur=0;}void doIndication(){ //octet statique b=B00000001; statique non signé long lastTimeInterval1Started ; if ((micros()-lastTimeInterval1Started)>2 ; Var64|=tmpVar64; Var64=(Var64>>4) ; entier non signé iTmp=0 ; iTmp=Var64>>56 ; SPI.transfer(iTmp); iTmp=Var64>>48 ; SPI.transfer(iTmp); iTmp=Var64>>40 ; SPI.transfer(iTmp); iTmp=Var64>>32 ; SPI.transfer(iTmp); iTmp=Var64>>24 ; SPI.transfer(iTmp); iTmp=Var64>>16 ; SPI.transfer(iTmp); iTmp=Var64>>8 ; SPI.transfer(iTmp); iTmp=Var64; SPI.transfer(iTmp); digitalWrite(LEpin, LOW); // verrouillage des données }octet CheckButtonsState(){ static boolean buttonWasChecked; long startBuzzTime statique non signé ; long lastTimeButtonsPressed statique non signé ; if ((digitalRead(pinSet)==0)||(digitalRead(pinUp)==0)||(digitalRead(pinDown)==0)) { if (buttonsWasChecked==false) startBuzzTime=millis(); buttonWasChecked=true ; } else boutonsWasChecked=false ; if (millis()-startBuzzTime<30) { digitalWrite(pinBuzzer, HIGH); } else { digitalWrite(pinBuzzer, LOW); }}String updateDisplayString(){ static non signé long lastTimeStringWasUpdated; if ((millis()-lastTimeStringWasUpdated)>1000) { //Serial.println("doDotBlink"); //doDotBlink(); lastTimeStringWasUpdated=millis(); if (value[hModeValueIndex]==24) return PreZero(hour())+PreZero(minute())+PreZero(second()); else return PreZero(hourFormat12())+PreZero(minute())+PreZero(second()); } return stringToDisplay;}void doTest(){ Serial.print(F("Firmware version:")); Serial.println(FirmwareVersion.substring(1,2)+"."+FirmwareVersion.substring(2,4)); Serial.println(F("Démarrer le test")); int adc=analogRead(A3) ; float Uinput=4,6*(5,0*adc)/1024,0+0,7 ; Serial.print(F("U input=")); Serial.print(Uinput); p=chanson ; parseSong(p); analogWrite(RedLedPin,255); retard(1000); analogWrite (RedLedPin, 0); analogWrite(GreenLedPin,255); retard(1000); analogWrite(GreenLedPin,0) ; analogWrite(BlueLedPin,255); retard(1000); //pendant(1); String testStringArray[12]={"000000","111111","222222","333333","444444","555555","666666","777777","888888","999999","", ""} ; if (Uinput<10) testStringArray[10]="000"+String(int(Uinput*100)); else testStringArray[10]="00"+String(int(Uinput*100)); testStringArray[11]=Version du micrologiciel ; int délai=500 ; test bool=1; octet strIndex=0; non signé long startOfTest=millis(); for (int i=0; i<12; i++) { if ((millis()-startOfTest)>dlay) { startOfTest=millis(); strIndex=strIndex+1; if (strIndex==10) dlay=3000; si (strIndex==12) test=0 ; switch (strIndex) { /* cas 10 :SPI.transfer((b|B0100000)&B11111100); Pause; cas 11 : SPI.transfer((b|B0100000)&B11001110); Pause; */ //par défaut :SPI.transfer(b|B1100000); par défaut :stringToDisplay=testStringArray[strIndex] ; } } délaiMicrosecondes (2000); } ; Serial.println(F("Arrêter le test")); }void doDotBlink(){ static non signé long lastTimeBlink=millis(); static bool dotState=0; if ((millis()-lastTimeBlink)>1000) { lastTimeBlink=millis(); dotState=!dotState; if (dotState) { dotPattern=B11000000; /*digitalWrite(pinUpperDots, HIGH); digitalWrite(pinLowerDots, HIGH);*/ } else { dotPattern=B00000000; /*digitalWrite(pinUpperDots, LOW); digitalWrite(pinLowerDots, LOW);*/ } }}void setRTCDateTime(byte h, byte m, byte s, byte d, byte mon, byte y, byte w){ Wire.beginTransmission(DS1307_ADDRESS); Wire.write(zéro); //arrêt de l'oscillateur Wire.write(decToBcd(s)); Wire.write(decToBcd(m)); Wire.write(decToBcd(h)); Wire.write(decToBcd(w)); Wire.write(decToBcd(d)); Wire.write(decToBcd(mon)); Wire.write(decToBcd(y)); Wire.write(zéro); //start Wire.endTransmission();}byte decToBcd(byte val){// Convertir les nombres décimaux normaux en retour décimal codé binaire ( (val/10*16) + (val%10) );}byte bcdToDec(byte val ) {// Convertir les nombres décimaux codés binaires en nombres décimaux normaux return ( (val/16*10) + (val%16) );}void getRTCTime(){ Wire.beginTransmission(DS1307_ADDRESS); Wire.write(zéro); Wire.endTransmission(); Wire.requestFrom(DS1307_ADDRESS, 7); RTC_seconds =bcdToDec(Wire.read()); RTC_minutes =bcdToDec(Wire.read()); RTC_hours =bcdToDec(Wire.read() &0b111111); //24 heures RTC_day_of_week =bcdToDec(Wire.read()); //0-6 -> dimanche - samedi RTC_day =bcdToDec(Wire.read()); RTC_month =bcdToDec(Wire.read()); RTC_year =bcdToDec(Wire.read());}mot doEditBlink(int pos){ if (!BlinkUp) renvoie 0 ; si (!BlinkDown) renvoie 0 ; int lowBit=blinkMask>>pos; lowBit=lowBit&B00000001; statique long non signé lastTimeEditBlink=millis(); static bool blinkState=false ; masque de mot=0 ; static int tmp=0;//blinkMask; if ((millis()-lastTimeEditBlink)>300) { lastTimeEditBlink=millis(); FlashState=!blinkState; /*Serial.print("blinkpattern="); Serial.println(blinkPattern[menuPosition]); if (((blinkPattern[menuPosition]>>8)&1==1) &&blinkState==true) digitalWrite(pinLowerDots, HIGH); else digitalWrite(pinLowerDots, LOW); if (((blinkPattern[menuPosition]>>7)&1==1) &&blinkState==true) digitalWrite(pinUpperDots, HIGH); else digitalWrite(pinUpperDots, LOW); */ if (blinkState) tmp=0; sinon tmp=blinkMask; } if (((dotPattern&~tmp)>>6)&1==1) digitalWrite(pinLowerDots, HIGH); else digitalWrite(pinLowerDots, LOW); if (((dotPattern&~tmp)>>7)&1==1) digitalWrite(pinUpperDots, HIGH); else digitalWrite(pinUpperDots, LOW); if ((blinkState==true) &&(lowBit==1)) mask=0xFFFF;//mask=B11111111; return mask;}int extractDigits(byte b){ String tmp="1"; /*Serial.print("motif de clignotement="); Serial.println(b); Serial.print("stringToDisplay="); Serial.println(stringToDisplay);*/ if (b==B00000011) { tmp=stringToDisplay.substring(0,2); /*Serial.print("stringToDisplay1="); Serial.println(stringToDisplay);*/ } if (b==B00001100) { tmp=stringToDisplay.substring(2,4); /*Serial.print("stringToDisplay2="); Serial.println(stringToDisplay);*/ } if (b==B00110000) { tmp=stringToDisplay.substring(4); /*Serial.print("stringToDisplay3="); Serial.println(stringToDisplay);*/ } /*Serial.print("stringToDisplay4="); Serial.println(stringToDisplay);*/ return tmp.toInt();}void injectDigits(byte b, int value){ if (b==B00000011) stringToDisplay=PreZero(value)+stringToDisplay.substring(2); if (b==B00001100) stringToDisplay=stringToDisplay.substring(0,2)+PreZero(value)+stringToDisplay.substring(4); if (b==B00110000) stringToDisplay=stringToDisplay.substring(0,4)+PreZero(value);}bool isValidDate(){ int days[12]={31,28,31,30,31,30,31,31,30,31,30,31}; if (value[DateYearIndex]%4==0) days[1]=29; if (value[DateDayIndex]>days[value[DateMonthIndex]-1]) return false; else return true; }byte default_dur =4;byte default_oct =6;int bpm =63;int num;long wholenote;long duration;byte note;byte scale;char* parseSong(char *p){ // Absolutely no error checking in here // format:d=N,o=N,b=NNN:// find the start (skip name, etc) while(*p !=':') p++; // ignore name p++; // skip ':' // get default duration if(*p =='d') { p++; p++; // skip "d=" num =0; while(isdigit(*p)) { num =(num * 10) + (*p++ - '0'); } if(num> 0) default_dur =num; p++; // skip comma } // get default octave if(*p =='o') { p++; p++; // skip "o=" num =*p++ - '0'; if(num>=3 &&num <=7) default_oct =num; p++; // skip comma } // get BPM if(*p =='b') { p++; p++; // skip "b=" num =0; while(isdigit(*p)) { num =(num * 10) + (*p++ - '0'); } bpm =num; p++; // skip colon } // BPM usually expresses the number of quarter notes per minute wholenote =(60 * 1000L / bpm) * 4; // this is the time for whole note (in milliseconds) return p;} // now begin note loop static unsigned long lastTimeNotePlaying=0; char* playmusic(char *p) { if(*p==0) { return p; } if (millis()-lastTimeNotePlaying>duration) lastTimeNotePlaying=millis(); else return p; // first, get note duration, if available num =0; while(isdigit(*p)) { num =(num * 10) + (*p++ - '0'); } if(num) duration =wholenote / num; else duration =wholenote / default_dur; // we will need to check if we are a dotted note after // now get the note note =0; switch(*p) { case 'c':note =1; Pause; case 'd':note =3; Pause; case 'e':note =5; Pause; case 'f':note =6; Pause; case 'g':note =8; Pause; case 'a':note =10; Pause; case 'b':note =12; Pause; case 'p':default:note =0; } p++; // now, get optional '#' sharp if(*p =='#') { note++; p++; } // now, get optional '.' dotted note if(*p =='.') { duration +=duration/2; p++; } // now, get scale if(isdigit(*p)) { scale =*p - '0'; p++; } else { scale =default_oct; } scale +=OCTAVE_OFFSET; if(*p ==',') p++; // skip comma for next note (or we may be at the end) // now play the note if(note) { tone1.play(notes[(scale - 4) * 12 + note], duration); if (millis()-lastTimeNotePlaying>duration) lastTimeNotePlaying=millis(); else return p; tone1.stop(); } else { return p; } Serial.println(F("Incorrect Song Format!")); return 0; //error } void incrementValue() { enteringEditModeTime=millis(); if (editMode==true) { if(menuPosition!=hModeValueIndex) // 12/24 hour mode menu position value[menuPosition]=value[menuPosition]+1; else value[menuPosition]=value[menuPosition]+12; if (value[menuPosition]>maxValue[menuPosition]) value[menuPosition]=minValue[menuPosition]; if (menuPosition==Alarm01) { if (value[menuPosition]==1) /*digitalWrite(pinUpperDots, HIGH);*/dotPattern=B10000000;//turn on all dots /*else digitalWrite(pinUpperDots, LOW); */ dotPattern=B00000000; //turn off all dots } injectDigits(blinkMask, value[menuPosition]); } } void dicrementValue(){ enteringEditModeTime=millis(); if (editMode==true) { if (menuPosition!=hModeValueIndex) value[menuPosition]=value[menuPosition]-1; else value[menuPosition]=value[menuPosition]-12; if (value[menuPosition]1000)) Alarm1SecondBlock=false; if (Alarm1SecondBlock==true) return; if ((hour()==value[AlarmHourIndex]) &&(minute()==value[AlarmMinuteIndex]) &&(second()==value[AlarmSecondIndex])) { lastTimeAlarmTriggired=millis(); Alarm1SecondBlock=true; Serial.println(F("Wake up, Neo!")); p=song; }}
Prog NIXIE Clock Tubes Shield NCS314
https://github.com/afch/NixeTubesShieldNCS314/

Schémas


Processus de fabrication

  1. horloge de vision Arduino pov
  2. Contrôleur DMX Web
  3. Horloge de mots simple (Arduino)
  4. Horloge Arduino avec heures de prière islamique
  5. Arduino Spybot
  6. horloge maîtresse
  7. Fabriquer une horloge Nixie avec Arduino dans un boîtier en bois MDF
  8. Horloge matricielle à 7 segments
  9. Réveil simple avec DS1302 RTC