本帖最后由 吃樱桃不吐胡 于 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的效果。 |