设为首页收藏本站

极客工坊

 找回密码
 注册

只需一步,快速开始

查看: 958|回复: 8

我的辉光管时钟制作过程

[复制链接]
发表于 2017-1-30 22:22:40 | 显示全部楼层 |阅读模式
本帖最后由 吃樱桃不吐胡 于 2017-1-30 22:38 编辑

    前言
    前段时间无意中在网上看到了辉光管时钟,一下就被吸引住了,立即决定要自己做一个。前两天发了个帖子晒了一下做的PM2.5监测仪,因为觉得太简单了,所以只发了图片,没有发制作过程。这次辉光管时钟我觉得还是可以发一下了,这也是我严格意义上的第一次真正DIY~
    先发两张成品图:
nEO_IMG_IMG_20170129_222844.jpg nEO_IMG_IMG_20170130_095049.jpg nEO_IMG_IMG_20170130_153025.jpg
    下面详细介绍制作过程:     
     一、方案选择
    决定自己制作以后就开始在网上寻找相关资料,这里必须感谢电子发烧论坛博学而笃志写的详细教程,经过几天学习确定了自己的方案:
    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个管子一块板,然后自己级联起来,因为是自己做着玩,所以省钱第一嘛。
nEO_IMG_IMG_20170116_134212.jpg
  2.译码电路和编程
   我是第一次使用74hc595,研究了一下,发现很简单,不要使用arduino的shiftout命令,自己编程序,控制datapin clockpin latchpin三个管脚的触发时序,思路清楚了,想移几位移几位。说的这里,我必须讲一下我买595的悲催过程,一共在网上买了4次,本来是很简单的管子,但我也不知道怎么那么倒霉,前两次买的40个里面就只挑出几个好的,这40个批号都一样,也不知道是不是买到了假货。后来又同时在不同卖家买了两批,批号和上次的都不一样,就全是好的:
IMG_20170106_214653.jpg

   下面是我测试74hc595的程序,两片级联,然后控制led灯轮流显示(对了,编程我一直用的mixly,因为用这个基本上只需要考虑编程的思路,不用自己去敲命令,不过为了大家看着方便,我用了mixly自动生成的语句,有些地方不是很精简,特别是pinMode语句在每次使用的时候都会生成一条,不知道是为什么,不影响使用,我也懒得删掉了,后面我会附上mixly的程序,在mixly看就很容易理解了)也不解释了,595的原理大家随便在网上都可以找到。
  1. long latchPin;
  2. long clockPin;
  3. long dataPin;

  4. void setup()
  5. {

  6.   latchPin = 12;

  7.   clockPin = 11;

  8.   dataPin = 7;

  9.   pinMode(latchPin, OUTPUT);

  10.   pinMode(dataPin, OUTPUT);

  11.   pinMode(clockPin, OUTPUT);

  12. }



  13. void loop()

  14. {

  15.   pinMode(clockPin, OUTPUT);

  16.   digitalWrite(clockPin,LOW);

  17.   pinMode(latchPin, OUTPUT);

  18.   digitalWrite(latchPin,LOW);

  19.   for (int i = 1; i <= 16; i = i + (1)) {

  20.     pinMode(latchPin, OUTPUT);

  21.     digitalWrite(latchPin,LOW);

  22.     for (int j = 1; j <= 16; j = j + (1)) {

  23.       pinMode(clockPin, OUTPUT);

  24.       digitalWrite(clockPin,LOW);

  25.       if (i == j) {

  26.         pinMode(dataPin, OUTPUT);

  27.         digitalWrite(dataPin,HIGH);



  28.       } else {

  29.         pinMode(dataPin, OUTPUT);

  30.         digitalWrite(dataPin,LOW);



  31.       }

  32.       pinMode(clockPin, OUTPUT);

  33.       digitalWrite(clockPin,HIGH);

  34.     }

  35.     pinMode(latchPin, OUTPUT);

  36.     digitalWrite(latchPin,HIGH);

  37.     delay(500);

  38.   }


  39. }
复制代码
这段程序理解清楚了,就可以实现用辉光管显示任意数字了。
nEO_IMG_IMG_20170125_221513.jpg
DS3231与EC11旋转编码器:EC11的主要功能就是设定时间,按一下旋转设定小时,再按一下旋转设定分钟,再按一下旋转设定秒钟,EC11的防抖与编程我在一个帖子里写过,就不在写了。DS3231的时间设定与读取在网上也可以搜到相关的文章,不再多写。

完整程序如下:
  1. #include <DS3231.h>

  2. #include <Wire.h>

  3. #include <PinChangeInt.h>



  4. long settime;

  5. long hour;

  6. long minute;

  7. long second;

  8. long TEMP_hour;

  9. long TEMP_minute;

  10. long TEMP_second;

  11. boolean h12;

  12. boolean pm;

  13. long num;

  14. long count;

  15. long switchPin;

  16. boolean switchPushed;

  17. long encoderPinA;

  18. long encoderPinB;

  19. long time;

  20. long int_num0;

  21. long int_num;

  22. boolean CW_1;

  23. boolean CW_2;

  24. long Number;

  25. long Num_Decade;

  26. long Num_Unit;

  27. long latchPin;

  28. long clockPin;

  29. long dataPin;

  30. long flag;



  31. DS3231 clock;

  32. int mixly_digitalRead(uint8_t pin) {

  33.   pinMode(pin, INPUT);

  34.   return digitalRead(pin);

  35. }



  36. void attachInterrupt_fun_switchPin() {

  37.   if (int_num0 == 0 && mixly_digitalRead(switchPin) == LOW) {

  38.     int_num0 = 1;



  39.   }

  40.   if (int_num0 == 1 && mixly_digitalRead(switchPin) == HIGH) {

  41.     switchPushed = true;

  42.     time = millis();

  43.     settime = settime + 1;

  44.     count = 0;

  45.     int_num0 = 0;



  46.   }

  47. }



  48. void attachPinInterrupt_fun_encoderPinA() {

  49.   if (switchPushed) {

  50.     if (int_num == 0 && mixly_digitalRead(encoderPinA) == LOW) {

  51.       CW_1 = mixly_digitalRead(encoderPinB);

  52.       int_num = 1;



  53.     }

  54.     if (int_num == 1 && mixly_digitalRead(encoderPinA) == HIGH) {

  55.       CW_2 = !mixly_digitalRead(encoderPinB);

  56.       if (CW_1 == true && CW_2 == true) {

  57.         count = count + 1;



  58.       }

  59.       if (CW_1 == false && CW_2 == false) {

  60.         count = count - 1;



  61.       }

  62.       int_num = 0;



  63.     }

  64.     time = millis();



  65.   }

  66. }



  67. void display(long x) {

  68.   Number = x;

  69.   if (Number >= 100) {

  70.     Num_Decade = 100;

  71.     Num_Unit = 100;



  72.   } else {

  73.     Num_Decade = Number / 10;

  74.     Num_Unit = (long) (Number) % (long) (10);



  75.   }

  76.   for (int i = 0; i <= 9; i = i + (1)) {

  77.     pinMode(clockPin, OUTPUT);

  78.     digitalWrite(clockPin,LOW);

  79.     if (i == Num_Decade) {

  80.       pinMode(dataPin, OUTPUT);

  81.       digitalWrite(dataPin,HIGH);



  82.     } else {

  83.       pinMode(dataPin, OUTPUT);

  84.       digitalWrite(dataPin,LOW);



  85.     }

  86.     pinMode(clockPin, OUTPUT);

  87.     digitalWrite(clockPin,HIGH);

  88.   }

  89.   for (int j = 0; j <= 9; j = j + (1)) {

  90.     pinMode(clockPin, OUTPUT);

  91.     digitalWrite(clockPin,LOW);

  92.     if (j == Num_Unit) {

  93.       pinMode(dataPin, OUTPUT);

  94.       digitalWrite(dataPin,HIGH);



  95.     } else {

  96.       pinMode(dataPin, OUTPUT);

  97.       digitalWrite(dataPin,LOW);



  98.     }

  99.     pinMode(clockPin, OUTPUT);

  100.     digitalWrite(clockPin,HIGH);

  101.   }

  102.   for (int k = 1; k <= 4; k = k + (1)) {

  103.     pinMode(clockPin, OUTPUT);

  104.     digitalWrite(clockPin,LOW);

  105.     pinMode(dataPin, OUTPUT);

  106.     digitalWrite(dataPin,HIGH);

  107.     pinMode(clockPin, OUTPUT);

  108.     digitalWrite(clockPin,HIGH);

  109.   }

  110. }



  111. void setup()

  112. {

  113.   settime = 0;

  114.   hour = clock.getHour(h12, pm);

  115.   minute = clock.getMinute();

  116.   second = clock.getSecond();

  117.   TEMP_hour = 0;

  118.   TEMP_minute = 0;

  119.   TEMP_second = 0;

  120.   h12 = false;

  121.   pm = true;

  122.   num = 0;

  123.   count = 0;

  124.   switchPin = 2;

  125.   switchPushed = false;

  126.   encoderPinA = 3;

  127.   encoderPinB = 4;

  128.   time = millis();

  129.   int_num0 = 0;

  130.   int_num = 0;

  131.   CW_1 = 0;

  132.   CW_2 = 0;

  133.   Number = 0;

  134.   Num_Decade = 0;

  135.   Num_Unit = 0;

  136.   latchPin = 12;

  137.   clockPin = 11;

  138.   dataPin = 6;

  139.   pinMode(switchPin, INPUT);

  140.   pinMode(encoderPinA, INPUT);

  141.   Wire.begin();

  142.   // STCP

  143.   pinMode(latchPin, OUTPUT);

  144.   pinMode(dataPin, OUTPUT);

  145.   // SHCP

  146.   pinMode(clockPin, OUTPUT);

  147.   attachInterrupt(digitalPinToInterrupt(switchPin),attachInterrupt_fun_switchPin,CHANGE);

  148.   PCintPort::attachInterrupt(encoderPinA,attachPinInterrupt_fun_encoderPinA,CHANGE);

  149.   flag = 0;

  150.   Serial.begin(9600);

  151. }



  152. void loop()

  153. {

  154.   // 转向判据1

  155.   // 转向判据2



  156.   // 正常显示时间

  157.   if (TEMP_second != clock.getSecond() && !switchPushed) {

  158.     TEMP_hour = clock.getHour(h12, pm);

  159.     TEMP_minute = clock.getMinute();

  160.     TEMP_second = clock.getSecond();

  161.     pinMode(latchPin, OUTPUT);

  162.     digitalWrite(latchPin,LOW);

  163.     display(TEMP_hour);

  164.     display(TEMP_minute);

  165.     display(TEMP_second);

  166.     pinMode(latchPin, OUTPUT);

  167.     digitalWrite(latchPin,HIGH);

  168.     Serial.println(String(TEMP_hour) + String(String(":") + String(String(TEMP_minute) + String(String(":") + String(TEMP_second)))));



  169.   }

  170.   if (switchPushed) {

  171.     if (millis() - time > 10000) {

  172.       switchPushed = false;

  173.       settime = 0;

  174.       flag = 0;

  175.       Serial.println("Time OUT!");



  176.     }



  177.   }

  178.   if (switchPushed) {

  179.     switch (settime) {

  180.      case 1:

  181.       hour = TEMP_hour + count;

  182.       if (hour >= 24) {

  183.         hour = (long) (hour) % (long) (24);



  184.       }

  185.       if (hour < 0) {

  186.         hour = (long) (hour) % (long) (24) + 24;



  187.       }

  188.       if (num != hour) {

  189.         num = hour;

  190.         pinMode(latchPin, OUTPUT);

  191.         digitalWrite(latchPin,LOW);

  192.         display(num);

  193.         display(100);

  194.         display(100);

  195.         pinMode(latchPin, OUTPUT);

  196.         digitalWrite(latchPin,HIGH);

  197.         Serial.println(String("SEThour:") + String(num));



  198.       }

  199.       break;

  200.      case 2:

  201.       if (flag == 0) {

  202.         clock.setHour(hour);

  203.         flag = 1;



  204.       }

  205.       minute = TEMP_minute + count;

  206.       if (minute >= 60) {

  207.         minute = (long) (minute) % (long) (60);



  208.       }

  209.       if (minute < 0) {

  210.         minute = (long) (minute) % (long) (60) + 60;



  211.       }

  212.       if (num != minute) {

  213.         num = minute;

  214.         pinMode(latchPin, OUTPUT);

  215.         digitalWrite(latchPin,LOW);

  216.         display(100);

  217.         display(num);

  218.         display(100);

  219.         pinMode(latchPin, OUTPUT);

  220.         digitalWrite(latchPin,HIGH);

  221.         Serial.println(String("SetMinute:  ") + String(num));



  222.       }

  223.       break;

  224.      case 3:

  225.       if (flag == 1) {

  226.         clock.setMinute(minute);

  227.         flag = 2;



  228.       }

  229.       second = TEMP_second + count;

  230.       if (second >= 60) {

  231.         second = (long) (second) % (long) (60);



  232.       }

  233.       if (second < 0) {

  234.         second = (long) (second) % (long) (60) + 60;



  235.       }

  236.       if (num != second) {

  237.         num = second;

  238.         pinMode(latchPin, OUTPUT);

  239.         digitalWrite(latchPin,LOW);

  240.         display(100);

  241.         display(100);

  242.         display(num);

  243.         pinMode(latchPin, OUTPUT);

  244.         digitalWrite(latchPin,HIGH);

  245.         Serial.println(String("SetSecond:  ") + String(num));



  246.       }

  247.       break;

  248.      case 4:

  249.       if (flag == 2) {

  250.         clock.setSecond(second);



  251.       }

  252.       switchPushed = false;

  253.       settime = 0;

  254.       Serial.println("Set time successed!");

  255.       flag = 0;

  256.       break;

  257.     }



  258.   }



  259. }
复制代码
程序里的串口打印语句都是用于调试的,可以删除。
最后,考虑到arduino promin ds3131还有升压模块全用杜邦线连接太过繁杂,又自己用洞洞板焊了一款控制板,把这三个模块整合在一起:
nEO_IMG_IMG_20170126_215849.jpg nEO_IMG_IMG_20170126_215907.jpg
底部线很乱,嘿嘿。
上面的全部搞定,就可以联调了:三块板子焊接到了一起,然后用塑料片和螺丝连接
nEO_IMG_IMG_20170127_075605.jpg
装进箱子,搞定~

箱子处理的不是很好,凑合了吧^_^
最后再放两张图:
由于视角问题,放在电视柜前的时候前面抬起30度左右看时间比较容易也好看,用了一下我女儿的小鸭子:
nEO_IMG_IMG_20170130_185647.jpg
不过我女儿不同意,只准我把小鸭子放上面。。T_T
nEO_IMG_IMG_20170130_190109.jpg
对了,最后说一下隔离时间用的冒号,按照网上的教程,基本上都是用的小氖灯,我也买了,但是我发现5mm磨砂头的橙色发光二极管也挺合适,就换成了二极管,另外二极管窜电阻要窜大点,先开始我窜了个300欧左右的,结果太亮,看着刺眼,而且亮度超过了辉光管,最后我直接窜了2.2k的,亮度才比较合适。前面第一张图就是用的300欧的,晚上看起很刺眼,第三张图和最后两张都是换成2.2k的效果。
nEO_IMG_IMG_20170130_153037.jpg

DisplayNumber_time_6_2.rar

11.35 KB, 阅读权限: 20, 下载次数: 2

回复

使用道具 举报

发表于 2017-2-17 23:58:26 | 显示全部楼层
有电路部分的设计图么
回复 支持 反对

使用道具 举报

发表于 2017-6-28 11:00:45 | 显示全部楼层
感谢LZ,LZ的程序对我有很大启发,收藏了
回复 支持 反对

使用道具 举报

发表于 2017-7-3 17:13:22 | 显示全部楼层
楼主还是写详细点吧,对于没接触过辉光管的朋友会需要图纸,还有就是你的管子是国外的吧,电压这么高,要说明清楚,国产的接100多伏肯定烧了
回复 支持 反对

使用道具 举报

发表于 2017-7-5 08:39:35 | 显示全部楼层
好长的代码,看了晕
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-7-18 10:30:33 | 显示全部楼层
太行摄狼 发表于 2017-7-3 17:13
楼主还是写详细点吧,对于没接触过辉光管的朋友会需要图纸,还有就是你的管子是国外的吧,电压这么高,要说 ...

管子是国产的哈,老毛子的管子是好,但是太贵了,我这就是做着玩而已。辉光管不是直接接170v的电压,是要接限流电阻的,否则遭烧了。因为我是直接用Sprint-Layout画的板子,所以没有原理图,原理图可以去网上搜严大师的教程哈。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-7-18 10:31:29 | 显示全部楼层
1529835644 发表于 2017-7-5 08:39
好长的代码,看了晕

哈哈,主要是由mixly自动生成的,空行太多。
回复 支持 反对

使用道具 举报

高级模式  
您需要登录后才可以回帖 登录 | 注册  

本版积分规则

Archiver|联系我们|极客工坊 ( 浙ICP备09023225号 )  

GMT+8, 2017-8-21 22:06 , Processed in 0.048175 second(s), 10 queries , File On.

Powered by Discuz! X3.3 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表