原材料:树莓派zero×1、东德产RFT Z750M辉光管×4、ds1302时钟模块×1、K155ID1×1、5v升170v升压模块×1
辉光管工作原理:和普通的灯泡类似,辉光管内有10个铁片,分别是1-10十个数字,接通哪个就亮哪个,不过这种灯需要高压并限流,需要在电路上注意一下。
170v电压的获得与限流:5v升170v的模块可以从淘宝上轻易获得,这里用5v升压的原因是可以直接从树莓派上取得需要的电压,并且不建议自己DIY升压电路,可能会烧毁树莓派。至于限流,直接加电阻就可以了,我这里用的是20kΩ的电阻。之后阳极连170v加电阻,随便接一根阴极,辉光管就能亮起来了。
辉光管的驱动:因为每一只辉光管都有10+1=11只引脚,树莓派的GPIO肯定是不够用来控制四只辉光管,并且辉光管所需要的高压对树莓派来说也是一个问题,所以需要K155ID1译码器来控制每一只辉光管。下面是该译码器的引脚定义和真值表,需要输出哪个数字就可以在相应的引脚加上需要的高低电平,这样就解决了辉光管的驱动问题。
时间的获取与保存:众所周知,树莓派可以连接wifi进行时间的同步,但是断电后时间不能继续流逝,这就需要ds1302模块进行时间的存储,这里我们可以直接使用WiringPi自带的驱动程序对模块进行操作。文件位置在 WiringPi 安装包的 examples/ds1302.c,代码如下
/* * ds1302.c: * Real Time clock * * Copyright (c) 2013 Gordon Henderson. *********************************************************************** * This file is part of wiringPi: * https://projects.drogon.net/raspberry-pi/wiringpi/ * * wiringPi is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * wiringPi is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with wiringPi. If not, see <http://www.gnu.org/licenses/>. *********************************************************************** */ #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <string.h> #include <time.h> #include <wiringPi.h> #include <ds1302.h> // Register defines #define RTC_SECS 0 #define RTC_MINS 1 #define RTC_HOURS 2 #define RTC_DATE 3 #define RTC_MONTH 4 #define RTC_DAY 5 #define RTC_YEAR 6 #define RTC_WP 7 #define RTC_TC 8 #define RTC_BM 31 static unsigned int masks [] = { 0x7F, 0x7F, 0x3F, 0x3F, 0x1F, 0x07, 0xFF } ; /* * bcdToD: dToBCD: * BCD decode/encode ********************************************************************************* */ static int bcdToD (unsigned int byte, unsigned int mask) { unsigned int b1, b2 ; byte &= mask ; b1 = byte & 0x0F ; b2 = ((byte >> 4) & 0x0F) * 10 ; return b1 + b2 ; } static unsigned int dToBcd (unsigned int byte) { return ((byte / 10) << 4) + (byte % 10) ; } /* * ramTest: * Simple test of the 31 bytes of RAM inside the DS1302 chip ********************************************************************************* */ static int ramTestValues [] = { 0x00, 0xFF, 0xAA, 0x55, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0xF0, 0x0F, -1 } ; static int ramTest (void) { int addr ; int got ; int i = 0 ; int errors = 0 ; int testVal ; printf ("DS1302 RAM TEST\n") ; testVal = ramTestValues [i] ; while (testVal != -1) { for (addr = 0 ; addr < 31 ; ++addr) ds1302ramWrite (addr, testVal) ; for (addr = 0 ; addr < 31 ; ++addr) if ((got = ds1302ramRead (addr)) != testVal) { printf ("DS1302 RAM Failure: Address: %2d, Expected: 0x%02X, Got: 0x%02X\n", addr, testVal, got) ; ++errors ; } testVal = ramTestValues [++i] ; } for (addr = 0 ; addr < 31 ; ++addr) ds1302ramWrite (addr, addr) ; for (addr = 0 ; addr < 31 ; ++addr) if ((got = ds1302ramRead (addr)) != addr) { printf ("DS1302 RAM Failure: Address: %2d, Expected: 0x%02X, Got: 0x%02X\n", addr, addr, got) ; ++errors ; } if (errors == 0) printf ("-- DS1302 RAM TEST: OK\n") ; else printf ("-- DS1302 RAM TEST FAILURE. %d errors.\n", errors) ; return 0 ; } /* * setLinuxClock: * Set the Linux clock from the hardware ********************************************************************************* */ static int setLinuxClock (void) { char dateTime [20] ; char command [64] ; int clock [8] ; printf ("Setting the Linux Clock from the DS1302... ") ; fflush (stdout) ; ds1302clockRead (clock) ; // [MMDDhhmm[[CC]YY][.ss]] sprintf (dateTime, "%02d%02d%02d%02d%02d%02d.%02d", bcdToD (clock [RTC_MONTH], masks [RTC_MONTH]), bcdToD (clock [RTC_DATE], masks [RTC_DATE]), bcdToD (clock [RTC_HOURS], masks [RTC_HOURS]), bcdToD (clock [RTC_MINS], masks [RTC_MINS]), 20, bcdToD (clock [RTC_YEAR], masks [RTC_YEAR]), bcdToD (clock [RTC_SECS], masks [RTC_SECS])) ; sprintf (command, "/bin/date %s", dateTime) ; system (command) ; return 0 ; } /* * setDSclock: * Set the DS1302 block from Linux time ********************************************************************************* */ static int setDSclock (void) { struct tm* t = NULL ; time_t now ; int clock [8] ; printf ("Setting the clock in the DS1302 from Linux time... ") ; now = time (NULL) ; //gmtime_r (&now, &t) ; t = localtime(&now); clock [ 0] = dToBcd (t->tm_sec) ; // seconds clock [ 1] = dToBcd (t->tm_min) ; // mins clock [ 2] = dToBcd (t->tm_hour) ; // hours clock [ 3] = dToBcd (t->tm_mday) ; // date clock [ 4] = dToBcd (t->tm_mon + 1) ; // months 0-11 --> 1-12 clock [ 5] = dToBcd (t->tm_wday + 1) ; // weekdays (sun 0) clock [ 6] = dToBcd (t->tm_year - 100) ; // years clock [ 7] = 0 ; // W-Protect off ds1302clockWrite (clock) ; printf ("OK\n") ; return 0 ; } int main (int argc, char *argv []) { int i ; int clock [8] ; wiringPiSetup () ; ds1302setup (14, 30, 10) ; //此处填写ds1302模块对应的管脚 if (argc == 2) { /**/ if (strcmp (argv [1], "-slc") == 0) return setLinuxClock () ; else if (strcmp (argv [1], "-sdsc") == 0) return setDSclock () ; else if (strcmp (argv [1], "-rtest") == 0) return ramTest () ; else { printf ("Usage: ds1302 [-slc | -sdsc | -rtest]\n") ; return EXIT_FAILURE ; } } for (i = 0 ;; ++i) { printf ("%5d: ", i) ; ds1302clockRead (clock) ; printf (" %2d:%02d:%02d", bcdToD (clock [2], masks [2]), bcdToD (clock [1], masks [1]), bcdToD (clock [0], masks [0])) ; printf (" %2d/%02d/%04d", bcdToD (clock [3], masks [3]), bcdToD (clock [4], masks [4]), bcdToD (clock [6], masks [6]) + 2000) ; printf ("\n") ; delay (200) ; } return 0 ; }
以下是辉光管驱动程序
# coding=utf-8 import time import datetime import RPi.GPIO # 定义单个辉光管各段led对应的GPIO口 L = [[12, 20, 21, 16], [26, 13, 6, 19], [22, 17, 4, 27], [18, 24, 25, 23]] RPi.GPIO.setmode(RPi.GPIO.BCM) for i in range(0, 4): for j in range(0, 4): RPi.GPIO.setup(L[i][j], RPi.GPIO.OUT) # 指定no(1-4)号辉光管显示数字num(0-9) def showDigit(no, num): if (no): if (num == 0): RPi.GPIO.output(L[no - 1][0], False) RPi.GPIO.output(L[no - 1][1], False) RPi.GPIO.output(L[no - 1][2], False) RPi.GPIO.output(L[no - 1][3], False) elif (num == 1): RPi.GPIO.output(L[no - 1][0], True) RPi.GPIO.output(L[no - 1][1], False) RPi.GPIO.output(L[no - 1][2], False) RPi.GPIO.output(L[no - 1][3], False) elif (num == 2): RPi.GPIO.output(L[no - 1][0], False) RPi.GPIO.output(L[no - 1][1], True) RPi.GPIO.output(L[no - 1][2], False) RPi.GPIO.output(L[no - 1][3], False) elif (num == 3): RPi.GPIO.output(L[no - 1][0], True) RPi.GPIO.output(L[no - 1][1], True) RPi.GPIO.output(L[no - 1][2], False) RPi.GPIO.output(L[no - 1][3], False) elif (num == 4): RPi.GPIO.output(L[no - 1][0], False) RPi.GPIO.output(L[no - 1][1], False) RPi.GPIO.output(L[no - 1][2], True) RPi.GPIO.output(L[no - 1][3], False) elif (num == 5): RPi.GPIO.output(L[no - 1][0], True) RPi.GPIO.output(L[no - 1][1], False) RPi.GPIO.output(L[no - 1][2], True) RPi.GPIO.output(L[no - 1][3], False) elif (num == 6): RPi.GPIO.output(L[no - 1][0], False) RPi.GPIO.output(L[no - 1][1], True) RPi.GPIO.output(L[no - 1][2], True) RPi.GPIO.output(L[no - 1][3], False) elif (num == 7): RPi.GPIO.output(L[no - 1][0], True) RPi.GPIO.output(L[no - 1][1], True) RPi.GPIO.output(L[no - 1][2], True) RPi.GPIO.output(L[no - 1][3], False) elif (num == 8): RPi.GPIO.output(L[no - 1][0], False) RPi.GPIO.output(L[no - 1][1], False) RPi.GPIO.output(L[no - 1][2], False) RPi.GPIO.output(L[no - 1][3], True) elif (num == 9): RPi.GPIO.output(L[no - 1][0], True) RPi.GPIO.output(L[no - 1][1], False) RPi.GPIO.output(L[no - 1][2], False) RPi.GPIO.output(L[no - 1][3], True) # 防止阴极中毒,每隔一段时间循环点亮所有数字 def protect(): t = 2 for i in range(0, 10): showDigit(1, i) showDigit(2, i) showDigit(3, i) showDigit(4, i) time.sleep(t) t = 0.01 start_time = datetime.datetime.now() while True: now_time = datetime.datetime.now() time.sleep(t) showDigit(1, int(time.strftime("%H", time.localtime(time.time()))) / 10) showDigit(2, int(time.strftime("%H", time.localtime(time.time()))) % 10) showDigit(3, int(time.strftime("%M", time.localtime(time.time()))) / 10) showDigit(4, int(time.strftime("%M", time.localtime(time.time()))) % 10) if (now_time - start_time).seconds >= 600: start_time = datetime.datetime.now() protect()
发表评论