吃樱桃不吐胡 发表于 2017-1-30 22:22:40

我的辉光管时钟制作过程

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

Paderboy 发表于 2017-1-31 10:33:46

:loveliness:不错不错。。。

galaxy 发表于 2017-1-31 14:11:56

讚 讚 讚

С罗 发表于 2017-2-17 23:58:26

有电路部分的设计图么

597464963 发表于 2017-6-28 11:00:45

感谢LZ,LZ的程序对我有很大启发,收藏了

太行摄狼 发表于 2017-7-3 17:13:22

楼主还是写详细点吧,对于没接触过辉光管的朋友会需要图纸,还有就是你的管子是国外的吧,电压这么高,要说明清楚,国产的接100多伏肯定烧了

1529835644 发表于 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自动生成的,空行太多。
页: [1]
查看完整版本: 我的辉光管时钟制作过程