我的辉光管时钟制作过程
本帖最后由 吃樱桃不吐胡 于 2017-1-30 22:38 编辑前言
前段时间无意中在网上看到了辉光管时钟,一下就被吸引住了,立即决定要自己做一个。前两天发了个帖子晒了一下做的PM2.5监测仪,因为觉得太简单了,所以只发了图片,没有发制作过程。这次辉光管时钟我觉得还是可以发一下了,这也是我严格意义上的第一次真正DIY~
先发两张成品图:
下面详细介绍制作过程:
一、方案选择
决定自己制作以后就开始在网上寻找相关资料,这里必须感谢电子发烧论坛博学而笃志写的详细教程,经过几天学习确定了自己的方案:
1.主控:arduino pro mini
2.时间芯片DS3231
3.时间调整方法:旋转编码器EC11,一键设定
4.译码芯片:74hc595(我觉得这应该是最简单的方案)
5.升压电路:5v升170v(这部份本应该自建,但没找到5v升压方案,大部分都是12v升压方案,所以最后在某宝买的,加运费50大洋) 6.封装:单只葡萄酒箱子一个
二、主要制作过程
1.电路设计
这部分很关键,先开始还想用洞洞板自己焊,研究了一下,发现光飞线都得累死个人啊,最终决定要画pcb板来打样。但悲剧的是,本人以前是学强电的,从来没学过画pcb T_T。还好身边有个同事是大牛级的(有多牛呢,上初中就自己设计电路板了,现在自己设计高精度电压电源,精确到小数点后7位!),经过牛人指点,发现了Sprint-Layout,这个软件非常简单,基本上学习了1个多小时就可以自己画板子了。在牛人的指点下,用了几个晚上完成了电路板的设计,发给淘宝商家进行打样。电路板我没有把所有管子设计在一块板子上,而是2个管子一块板,然后自己级联起来,因为是自己做着玩,所以省钱第一嘛。
2.译码电路和编程
我是第一次使用74hc595,研究了一下,发现很简单,不要使用arduino的shiftout命令,自己编程序,控制datapin clockpin latchpin三个管脚的触发时序,思路清楚了,想移几位移几位。说的这里,我必须讲一下我买595的悲催过程,一共在网上买了4次,本来是很简单的管子,但我也不知道怎么那么倒霉,前两次买的40个里面就只挑出几个好的,这40个批号都一样,也不知道是不是买到了假货。后来又同时在不同卖家买了两批,批号和上次的都不一样,就全是好的:
下面是我测试74hc595的程序,两片级联,然后控制led灯轮流显示(对了,编程我一直用的mixly,因为用这个基本上只需要考虑编程的思路,不用自己去敲命令,不过为了大家看着方便,我用了mixly自动生成的语句,有些地方不是很精简,特别是pinMode语句在每次使用的时候都会生成一条,不知道是为什么,不影响使用,我也懒得删掉了,后面我会附上mixly的程序,在mixly看就很容易理解了)也不解释了,595的原理大家随便在网上都可以找到。
long latchPin;
long clockPin;
long dataPin;
void setup()
{
latchPin = 12;
clockPin = 11;
dataPin = 7;
pinMode(latchPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
}
void loop()
{
pinMode(clockPin, OUTPUT);
digitalWrite(clockPin,LOW);
pinMode(latchPin, OUTPUT);
digitalWrite(latchPin,LOW);
for (int i = 1; i <= 16; i = i + (1)) {
pinMode(latchPin, OUTPUT);
digitalWrite(latchPin,LOW);
for (int j = 1; j <= 16; j = j + (1)) {
pinMode(clockPin, OUTPUT);
digitalWrite(clockPin,LOW);
if (i == j) {
pinMode(dataPin, OUTPUT);
digitalWrite(dataPin,HIGH);
} else {
pinMode(dataPin, OUTPUT);
digitalWrite(dataPin,LOW);
}
pinMode(clockPin, OUTPUT);
digitalWrite(clockPin,HIGH);
}
pinMode(latchPin, OUTPUT);
digitalWrite(latchPin,HIGH);
delay(500);
}
}这段程序理解清楚了,就可以实现用辉光管显示任意数字了。
DS3231与EC11旋转编码器:EC11的主要功能就是设定时间,按一下旋转设定小时,再按一下旋转设定分钟,再按一下旋转设定秒钟,EC11的防抖与编程我在一个帖子里写过,就不在写了。DS3231的时间设定与读取在网上也可以搜到相关的文章,不再多写。
完整程序如下:
#include <DS3231.h>
#include <Wire.h>
#include <PinChangeInt.h>
long settime;
long hour;
long minute;
long second;
long TEMP_hour;
long TEMP_minute;
long TEMP_second;
boolean h12;
boolean pm;
long num;
long count;
long switchPin;
boolean switchPushed;
long encoderPinA;
long encoderPinB;
long time;
long int_num0;
long int_num;
boolean CW_1;
boolean CW_2;
long Number;
long Num_Decade;
long Num_Unit;
long latchPin;
long clockPin;
long dataPin;
long flag;
DS3231 clock;
int mixly_digitalRead(uint8_t pin) {
pinMode(pin, INPUT);
return digitalRead(pin);
}
void attachInterrupt_fun_switchPin() {
if (int_num0 == 0 && mixly_digitalRead(switchPin) == LOW) {
int_num0 = 1;
}
if (int_num0 == 1 && mixly_digitalRead(switchPin) == HIGH) {
switchPushed = true;
time = millis();
settime = settime + 1;
count = 0;
int_num0 = 0;
}
}
void attachPinInterrupt_fun_encoderPinA() {
if (switchPushed) {
if (int_num == 0 && mixly_digitalRead(encoderPinA) == LOW) {
CW_1 = mixly_digitalRead(encoderPinB);
int_num = 1;
}
if (int_num == 1 && mixly_digitalRead(encoderPinA) == HIGH) {
CW_2 = !mixly_digitalRead(encoderPinB);
if (CW_1 == true && CW_2 == true) {
count = count + 1;
}
if (CW_1 == false && CW_2 == false) {
count = count - 1;
}
int_num = 0;
}
time = millis();
}
}
void display(long x) {
Number = x;
if (Number >= 100) {
Num_Decade = 100;
Num_Unit = 100;
} else {
Num_Decade = Number / 10;
Num_Unit = (long) (Number) % (long) (10);
}
for (int i = 0; i <= 9; i = i + (1)) {
pinMode(clockPin, OUTPUT);
digitalWrite(clockPin,LOW);
if (i == Num_Decade) {
pinMode(dataPin, OUTPUT);
digitalWrite(dataPin,HIGH);
} else {
pinMode(dataPin, OUTPUT);
digitalWrite(dataPin,LOW);
}
pinMode(clockPin, OUTPUT);
digitalWrite(clockPin,HIGH);
}
for (int j = 0; j <= 9; j = j + (1)) {
pinMode(clockPin, OUTPUT);
digitalWrite(clockPin,LOW);
if (j == Num_Unit) {
pinMode(dataPin, OUTPUT);
digitalWrite(dataPin,HIGH);
} else {
pinMode(dataPin, OUTPUT);
digitalWrite(dataPin,LOW);
}
pinMode(clockPin, OUTPUT);
digitalWrite(clockPin,HIGH);
}
for (int k = 1; k <= 4; k = k + (1)) {
pinMode(clockPin, OUTPUT);
digitalWrite(clockPin,LOW);
pinMode(dataPin, OUTPUT);
digitalWrite(dataPin,HIGH);
pinMode(clockPin, OUTPUT);
digitalWrite(clockPin,HIGH);
}
}
void setup()
{
settime = 0;
hour = clock.getHour(h12, pm);
minute = clock.getMinute();
second = clock.getSecond();
TEMP_hour = 0;
TEMP_minute = 0;
TEMP_second = 0;
h12 = false;
pm = true;
num = 0;
count = 0;
switchPin = 2;
switchPushed = false;
encoderPinA = 3;
encoderPinB = 4;
time = millis();
int_num0 = 0;
int_num = 0;
CW_1 = 0;
CW_2 = 0;
Number = 0;
Num_Decade = 0;
Num_Unit = 0;
latchPin = 12;
clockPin = 11;
dataPin = 6;
pinMode(switchPin, INPUT);
pinMode(encoderPinA, INPUT);
Wire.begin();
// STCP
pinMode(latchPin, OUTPUT);
pinMode(dataPin, OUTPUT);
// SHCP
pinMode(clockPin, OUTPUT);
attachInterrupt(digitalPinToInterrupt(switchPin),attachInterrupt_fun_switchPin,CHANGE);
PCintPort::attachInterrupt(encoderPinA,attachPinInterrupt_fun_encoderPinA,CHANGE);
flag = 0;
Serial.begin(9600);
}
void loop()
{
// 转向判据1
// 转向判据2
// 正常显示时间
if (TEMP_second != clock.getSecond() && !switchPushed) {
TEMP_hour = clock.getHour(h12, pm);
TEMP_minute = clock.getMinute();
TEMP_second = clock.getSecond();
pinMode(latchPin, OUTPUT);
digitalWrite(latchPin,LOW);
display(TEMP_hour);
display(TEMP_minute);
display(TEMP_second);
pinMode(latchPin, OUTPUT);
digitalWrite(latchPin,HIGH);
Serial.println(String(TEMP_hour) + String(String(":") + String(String(TEMP_minute) + String(String(":") + String(TEMP_second)))));
}
if (switchPushed) {
if (millis() - time > 10000) {
switchPushed = false;
settime = 0;
flag = 0;
Serial.println("Time OUT!");
}
}
if (switchPushed) {
switch (settime) {
case 1:
hour = TEMP_hour + count;
if (hour >= 24) {
hour = (long) (hour) % (long) (24);
}
if (hour < 0) {
hour = (long) (hour) % (long) (24) + 24;
}
if (num != hour) {
num = hour;
pinMode(latchPin, OUTPUT);
digitalWrite(latchPin,LOW);
display(num);
display(100);
display(100);
pinMode(latchPin, OUTPUT);
digitalWrite(latchPin,HIGH);
Serial.println(String("SEThour:") + String(num));
}
break;
case 2:
if (flag == 0) {
clock.setHour(hour);
flag = 1;
}
minute = TEMP_minute + count;
if (minute >= 60) {
minute = (long) (minute) % (long) (60);
}
if (minute < 0) {
minute = (long) (minute) % (long) (60) + 60;
}
if (num != minute) {
num = minute;
pinMode(latchPin, OUTPUT);
digitalWrite(latchPin,LOW);
display(100);
display(num);
display(100);
pinMode(latchPin, OUTPUT);
digitalWrite(latchPin,HIGH);
Serial.println(String("SetMinute:") + String(num));
}
break;
case 3:
if (flag == 1) {
clock.setMinute(minute);
flag = 2;
}
second = TEMP_second + count;
if (second >= 60) {
second = (long) (second) % (long) (60);
}
if (second < 0) {
second = (long) (second) % (long) (60) + 60;
}
if (num != second) {
num = second;
pinMode(latchPin, OUTPUT);
digitalWrite(latchPin,LOW);
display(100);
display(100);
display(num);
pinMode(latchPin, OUTPUT);
digitalWrite(latchPin,HIGH);
Serial.println(String("SetSecond:") + String(num));
}
break;
case 4:
if (flag == 2) {
clock.setSecond(second);
}
switchPushed = false;
settime = 0;
Serial.println("Set time successed!");
flag = 0;
break;
}
}
}程序里的串口打印语句都是用于调试的,可以删除。
最后,考虑到arduino promin ds3131还有升压模块全用杜邦线连接太过繁杂,又自己用洞洞板焊了一款控制板,把这三个模块整合在一起:
底部线很乱,嘿嘿。
上面的全部搞定,就可以联调了:三块板子焊接到了一起,然后用塑料片和螺丝连接
装进箱子,搞定~
箱子处理的不是很好,凑合了吧^_^
最后再放两张图:
由于视角问题,放在电视柜前的时候前面抬起30度左右看时间比较容易也好看,用了一下我女儿的小鸭子:
不过我女儿不同意,只准我把小鸭子放上面。。T_T
对了,最后说一下隔离时间用的冒号,按照网上的教程,基本上都是用的小氖灯,我也买了,但是我发现5mm磨砂头的橙色发光二极管也挺合适,就换成了二极管,另外二极管窜电阻要窜大点,先开始我窜了个300欧左右的,结果太亮,看着刺眼,而且亮度超过了辉光管,最后我直接窜了2.2k的,亮度才比较合适。前面第一张图就是用的300欧的,晚上看起很刺眼,第三张图和最后两张都是换成2.2k的效果。 :loveliness:不错不错。。。 讚 讚 讚
有电路部分的设计图么 感谢LZ,LZ的程序对我有很大启发,收藏了 楼主还是写详细点吧,对于没接触过辉光管的朋友会需要图纸,还有就是你的管子是国外的吧,电压这么高,要说明清楚,国产的接100多伏肯定烧了 好长的代码,看了晕 太行摄狼 发表于 2017-7-3 17:13
楼主还是写详细点吧,对于没接触过辉光管的朋友会需要图纸,还有就是你的管子是国外的吧,电压这么高,要说 ...
管子是国产的哈,老毛子的管子是好,但是太贵了,我这就是做着玩而已。辉光管不是直接接170v的电压,是要接限流电阻的,否则遭烧了。因为我是直接用Sprint-Layout画的板子,所以没有原理图,原理图可以去网上搜严大师的教程哈。 1529835644 发表于 2017-7-5 08:39
好长的代码,看了晕
哈哈,主要是由mixly自动生成的,空行太多。
页:
[1]