В прошлой статье мы разбирались с тем, как контролировать газоразрядные трубки при помощи Arduino. Сегодня мы построим полноценный проект при использовании данных трубок. И это будут интересные и очень необычные часы, которые обращают на себя внимание с первого взгляда.
Проект будет работать под управлением Arduino Mega. Также наши часы имеют светодиодную подсветку и блок кнопок, при помощи которых можно будет производить настройку без подключения к ПК.



Для начала прочитайте эту статью. Особенно обратите внимание на шаги 1-3. Из-за отсутствия 10К резисторов мне пришлось использовать по 2 5К резистора перед каждой трубкой.



Снова обращаемся к прошлой статье. Здесь мы не будем подробно рассматривать подключение, а только лишь обозначим шаги для создания готовых часов.
Для управления трубками мы использовали микросхемы K155ID1.
Для подключения потребуется отдельный чип для каждой трубки и отдельный выход на плате Arduino. Именно поэтому нам и понадобилась именно плата Arduino Mega, у которой больше портов ввода/вывода, чем у обычной платы Uno. Да, при таком подключении нам понадобиться 16 контактов, что для платы Mega не проблема.
Для подключения блока кнопок необходимо соединить “G” с питанием, а остальные контакты с аналоговыми выходами на плате. Были выбраны именно аналоговые выводы в связи с тем, что цифровые часто распознавали нажатую кнопку, когда на самом деле это было не так. И только установив значение действительно нажатой клавиши на 1023 (максимальное значение) на аналоговом выводе, удалось избавиться от этой проблемы.
После подключения микросхемы DS3231, трубок и светодиодов приступаем к программированию.


Прилагаю готовый код. «NixieJT1» - это полный код. «DS3231» поможет установить тактовый модуль.
#include <DS3231.h>
DS3231 rtc(SDA, SCL);
Time t;
#define A1 25
#define A2 24
#define A3 23
#define A4 22
#define B1 29
#define B2 28
#define B3 27
#define B4 26
#define C1 35
#define C2 34
#define C3 33
#define C4 32
#define D1 39
#define D2 38
#define D3 37
#define D4 36
int light4[] = {A1,A2,A3,A4};
int light3[] = {B1,B2,B3,B4};
int light2[] = {C1,C2,C3,C4};
int light1[] = {D1,D2,D3,D4};
#define bled 2
#define rled 3
#define gled 4 //The RGB LED lights
#define but1 0
#define but2 4
#define but3 1
#define but4 5
#define but5 2
#define but6 6
#define but7 3
#define but8 7
byte nowHour, nowMinute,nowSecond;
byte digA, digB, digC, digD, oldDigA;
byte modeNum = 0;
byte oldModeNum = 22;
int lightState = 0;
byte b1,b2,b3,b4,b5,b6,b7,b8;
void setup() {
rtc.begin();
pinMode(48,OUTPUT); digitalWrite(48,HIGH); //For the button matrix
for(int i=0; i<4; i++)
{
pinMode(light1[i],OUTPUT);
pinMode(light2[i],OUTPUT);
pinMode(light3[i],OUTPUT);
pinMode(light4[i],OUTPUT);
}
pinMode(rled,OUTPUT);pinMode(gled,OUTPUT);pinMode(bled,OUTPUT);
digitalWrite(rled,HIGH); digitalWrite(gled,HIGH); digitalWrite(bled,HIGH);
oldDigA = 11;
Serial.begin(9600);
}
void loop() {
//Serial.println("Starting Loop");
ReadPins();
CheckSubs();
GetTime();
DisplayTime();
RunLED(modeNum);
}
void ReadPins()
{
if(analogRead(but1)>1020) b1=1; else b1=0;
if(analogRead(but2)>1020) b2=1; else b2=0;
if(analogRead(but3)>1020) b3=1; else b3=0;
if(analogRead(but4)>1020) b4=1; else b4=0;
if(analogRead(but5)>1020) b5=1; else b5=0;
if(analogRead(but6)>1020) b6=1; else b6=0;
if(analogRead(but7)>1020) b7=1; else b7=0;
if(analogRead(but8)>1020) b8=1; else b8=0;
}
void CheckSubs()
{
byte delayTime = 150;
if(b1==1 || b2==1 || b3==1 || b4 == 1)
{
ChangeTime();
delay(delayTime);
}
else if(b5 == 1|| b6==1 || b7==1)
{
ChangeLED();
delay(delayTime+50);
}
else if(b8==1)
Eleven();
}
void ChangeTime()
{
byte prevHour = t.hour;
byte prevMin = t.min;
byte prevSec = t.sec;
int newHour, newMin;
newHour = prevHour;
newMin = prevMin;
if(b1==1)
{//Hour up by 1
newHour = prevHour+1;
if(newHour>=24) newHour=0;
}
else if(b2==1)
{//Hour down by one
newHour=prevHour-1;
if(newHour<=0) newHour=23;
}
if(b3==1)
{//Minute up by one
newMin = prevMin+1;
if(newMin>59) newMin=0;
}
else if(b4==1)
{//Minute down by one
newMin=prevMin-1;
if(newMin<0) newMin=59;
}
rtc.setTime(newHour,newMin,prevSec);
GetTime();
oldDigA = 11;
DisplayTime();
}
void ChangeLED()
{
if(b7==1)
modeNum = 0;
if(b6==1)
{
if(modeNum==0 || modeNum>=6)
modeNum = 1;
else
modeNum+=1;
}
if(b5==1)
{
if(modeNum==7)
modeNum = 8;
else
modeNum = 7;
}
}
void RunLED(byte modeNum)
{//Remember, LOW means ON!!
if(oldModeNum!=modeNum || modeNum>6)
switch(modeNum)
{
case 0: //Lights off
digitalWrite(rled,HIGH);
digitalWrite(gled,HIGH);
digitalWrite(bled,HIGH);
break;
case 1: //just red
digitalWrite(rled,LOW);
digitalWrite(gled,HIGH);
digitalWrite(bled,HIGH);
break;
case 2: //green
digitalWrite(rled,HIGH);
digitalWrite(gled,LOW);
digitalWrite(bled,HIGH);
break;
case 3: //blue
digitalWrite(rled,HIGH);
digitalWrite(gled,HIGH);
digitalWrite(bled,LOW);
break;
case 4: //purple
analogWrite(rled,180);
digitalWrite(gled,HIGH);
digitalWrite(bled,LOW);
break;
case 5: //orange
analogWrite(rled,0);
analogWrite(gled,180);
analogWrite(bled,255);
break;
case 6: //white
digitalWrite(rled,LOW);
digitalWrite(gled,LOW);
digitalWrite(bled,LOW);
break;
case 7: //smooth fade through all colors
{int rgbColor[3];
rgbColor[0] = 0; rgbColor[1] = 255; rgbColor[2] = 255;
for (int decColor = 0; decColor < 3; decColor += 1) {
ReadPins(); if(b1>0||b2>0||b3>0||b4>0||b5>0||b6>0||b7>0||b8>0) return;
int incColor = decColor == 2 ? 0 : decColor + 1;
// cross-fade the two colors.
for(int i = 255; i >0; i -= 1) {
rgbColor[decColor] += 1; //maybe flip these back
rgbColor[incColor] -= 1;
setColorRgb(rgbColor[0], rgbColor[1], rgbColor[2]);
ReadPins(); if(b1>0||b2>0||b3>0||b4>0||b5>0||b6>0||b7>0||b8>0) return; //if a button is pressed, quit this subroutine
delay(15);
}
}}
break;
case 8: //fade orange/purple/orange/etc
{analogWrite(rled,0);
analogWrite(gled,180);
analogWrite(bled,255);
byte rnum = 0;
byte gnum = 180;
byte bnum = 255;
byte delayNum = 7;
for(int h = 0; h<255; h++)
{
rnum = h*.7;
gnum = 179+h*.3;
bnum = 255-h;
analogWrite(rled,rnum);
analogWrite(gled,gnum);
analogWrite(bled,bnum);
ReadPins(); if(b1>0||b2>0||b3>0||b4>0||b5>0||b6>0||b7>0||b8>0) return;
delay(delayNum);
}
for(int h = 0; h<255; h++)
{
rnum = 180-h*.7;
gnum = 255-h*.3;
bnum = h;
analogWrite(rled,rnum);
analogWrite(gled,gnum);
analogWrite(bled,bnum);
ReadPins(); if(b1>0||b2>0||b3>0||b4>0||b5>0||b6>0||b7>0||b8>0) return;
delay(delayNum);
}
ReadPins(); if(b1>0||b2>0||b3>0||b4>0||b5>0||b6>0||b7>0||b8>0) return; }
break;
default:
break;
}
}
void setColorRgb(unsig
ned int red, unsigned int green, unsigned int blue) {
analogWrite(rled, red);
analogWrite(gled, green);
analogWrite(bled, blue);
}
void Eleven()
{
DisplayNumber(1,light1);
DisplayNumber(1,light2);
DisplayNumber(1,light3);
DisplayNumber(1,light4);
digitalWrite(gled,LOW);
digitalWrite(rled,HIGH);
digitalWrite(bled,HIGH);
delay(3000);
oldDigA = 11;
GetTime();
DisplayTime();
}
void GetTime()
{
// Serial.print("Running GetTime... ");
t=rtc.getTime();
nowHour = t.hour;
nowMinute = t.min;
nowSecond = t.sec;
if(nowHour>12) nowHour=nowHour-12;
if(nowHour == 0) nowHour = 12;
//Change these around if things aren't working.
digC = nowHour%10; //Second digit of the hour.
digD = nowHour/10; //First digit of the hour (1 or 0)
digA = nowMinute%10; //Second digit of the hour
digB = nowMinute/10; //First digit of the hour (40, 30, 20 etc)
if(digD==0) digD=3; //So that the first digit just won't be lit up at all.
}
void DisplayTime()
{
if(digA != oldDigA)
{
Serial.println("Changing Time!!\n\n\n\n");
DisplayNumber(digA,light1);
DisplayNumber(digB,light2);
DisplayNumber(digC,light3);
if(digD==0) digD=3; //So that the first digit just won't be lit up at all.
DisplayNumber(digD,light4);
}
oldDigA = digA;
delay(50);
}
void DisplayNumber(int thisNum, int thesePins[4])
{
switch(thisNum)
{
case 0:
digitalWrite(thesePins[0],LOW);
digitalWrite(thesePins[1],LOW);
digitalWrite(thesePins[2],LOW);
digitalWrite(thesePins[3],LOW);
break;
case 1:
digitalWrite(thesePins[0],LOW);
digitalWrite(thesePins[1],LOW);
digitalWrite(thesePins[2],LOW);
digitalWrite(thesePins[3],HIGH);
break;
case 2:
digitalWrite(thesePins[0],LOW);
digitalWrite(thesePins[1],LOW);
digitalWrite(thesePins[2],HIGH);
digitalWrite(thesePins[3],LOW);
break;
case 3:
digitalWrite(thesePins[0],LOW);
digitalWrite(thesePins[1],LOW);
digitalWrite(thesePins[2],HIGH);
digitalWrite(thesePins[3],HIGH);
break;
case 4:
digitalWrite(thesePins[0],LOW);
digitalWrite(thesePins[1],HIGH);
digitalWrite(thesePins[2],LOW);
digitalWrite(thesePins[3],LOW);
break;
case 5:
digitalWrite(thesePins[0],LOW);
digitalWrite(thesePins[1],HIGH);
digitalWrite(thesePins[2],LOW);
digitalWrite(thesePins[3],HIGH);
break;
case 6:
digitalWrite(thesePins[0],LOW);
digitalWrite(thesePins[1],HIGH);
digitalWrite(thesePins[2],HIGH);
digitalWrite(thesePins[3],LOW);
break;
case 7:
digitalWrite(thesePins[0],LOW);
digitalWrite(thesePins[1],HIGH);
digitalWrite(thesePins[2],HIGH);
digitalWrite(thesePins[3],HIGH);
break;
case 8:
digitalWrite(thesePins[0],HIGH);
digitalWrite(thesePins[1],LOW);
digitalWrite(thesePins[2],LOW);
digitalWrite(thesePins[3],LOW);
break;
case 9:
digitalWrite(thesePins[0],HIGH);
digitalWrite(thesePins[1],LOW);
digitalWrite(thesePins[2],LOW);
digitalWrite(thesePins[3],HIGH);
break;
default:
digitalWrite(thesePins[0],HIGH);
digitalWrite(thesePins[1],LOW);
digitalWrite(thesePins[2],HIGH);
digitalWrite(thesePins[3],LOW);
break;
}
}
Несколько советов:
Данная статья является авторским переводом с сайта instructables.com.
Данная статья является собственностью Amperkot.ru. При перепечатке данного материала активная ссылка на первоисточник, не закрытая для индексации поисковыми системами, обязательна.
Комментарии