矿石收音机论坛

 找回密码
 加入会员

QQ登录

只需一步,快速开始

搜索
查看: 12142|回复: 46

转载----用指针式电压表制作超 · 极客时钟!《无线电》杂志 公众号

[复制链接]
     
发表于 2017-2-8 16:39:05 | 显示全部楼层 |阅读模式
本帖最后由 八兆天空 于 2017-2-8 16:41 编辑

转载于 《无线电》公众号
无线电杂志  微信号 radiomagazine

   01.jpg


看到标题,可能很多朋友已经按捺不住自己了!没错!就是这种非常硬核的极客风格,今天来学习一下如何使用指针式的电压表来作为指针,显示当前的时间和温度吧!

02.jpg
实际上,这个设计原理非常好懂:单片机使用PWM并通过电阻分压来得到0~2V的电压值,而这个电压则是表头的满偏电压,而将其分成60份后,就可以用来指示60分钟或60秒的示数了。时间采用实时时钟DC1307来保存,而温度则通过读写单线温度传感器DS18B20得到。整个设计的主控单片机使用Picaxe 14M2单片机。不过说实话,这个单片机使用什么都无所谓,只要能够有三路PWM输出(或软或硬)即可。
  

原理非常简单,可能最难的地方在于如何分出适当的电压值。将2V分成60份,每份电压值为0.033V,因此表盘的设计和电压的输出就全都要参照这个电压值来设计。每增加一个分度,PWM都要相应地增加0.033V的电压值,而这又要考虑到PWM的精度和外部的低通滤波电路。因此这个设计还需要一定的思考才行!

03.jpg
其他的诸如操作DC1307和DS18B20的程序我想大家已经非常熟悉了,此处不再赘述。如果想要借鉴源程序的话欢迎在公众号的对话中回复“电压表时钟”以取得源程序哦!
04.jpg
本文为 无线电杂志 微信公众平台原创文章。详细内容及高清大图请查阅《无线电》杂志。版权所有,欢迎个人转发至朋友圈。公众号、报刊等转载请给本公众号后台留言获得授权。
…………………………………………………




无线电杂志
微信号:radiomagazine长按识别二维码关注我们


评分

3

查看全部评分

     
 楼主| 发表于 2017-2-8 16:39:42 | 显示全部楼层
电压表时钟 · 源程序
2017-01-16 WTH 无线电杂志

电压表时钟的正文,请看一楼


;源程序由WTH编写,运行于PicAxe

14M2上,阅读程序可以让你了解思

路。
;    Project Name: 3 Panel Meter Clock
; REV: FIN (everything works fine with

clock and temp)
;
;    Start Date:  Feb 12, 2012
;   
;    Program Rev History/Ideas:
; - to set clock push M or H button
; - push main button to display temp

F, C, and K
; - Routine to drive 3 meters to full

scale when main button AND (M OR

H)
; is pressed.  This is to allow

adjustment of trimmers to full scale.
; Adjustment to zero scale should be

done first with power off.
;
; *******************************
;    PICAXE PE Rev: MacAXEPad 1.3.2
;
#picaxe14m2
'define memory locations as symbols
symbol hour_meter = c.0 'LEG 7
symbol minute_meter = c.2 'LEG 5
symbol second_meter = b.2 ' LEG 11
symbol temp_switch = pinc.4 ' LEG3
symbol temp_sensor = b.5 'LEG8
symbol hour_set = pinc.3 'LEG3
symbol minute_set = pinc.1 'LEG6
symbol CthermoValue = b10
symbol FthermoValue = b11
symbol KthermoValue = w6 'b12 and

b13
symbol seconds = b0
symbol minutes = b1
symbol hours = b2
symbol day = b3
symbol date = b4
symbol month = b5
symbol year = b6
symbol blinky = b7
symbol Tens_Digi = b8   ;Used to get

the Tens Digit from the $HEX RTC

value
symbol Ones_Digi = b9 ;Used to get

the Ones Digit from the $HEX RTC

value
' w7 (b14 and b15) is used to control

the PCM to the meters
' Set the time on the DS1307 RTC
i2cslave %11010000, i2cslow, i2cbyte ;

set PICAXE as master and DS1307

slave address
pause 50
'Set all meters to full scale with 100%

duty cycle
pwmout hour_meter,99,400        
pwmout minute_meter,99,400   
pwmout second_meter,99,400   
'\/ \/ \/ \/ Un_REM THESE LINES

(BELOW) IF SETTING UP A NEW RTC  \/

\/ \/ \/
#rem
' Set the RTC chip time
;  write time and date e.g. to 11:59:00

on Thurs 25/12/03
'; would be "writei2c 0,($00, $59, $11,

$03, $25, $12, $03, 010000)"
' readi2c 0, (b0,b1,b2,b3,b4,b5,b6,b7)

reads back the data
let seconds = $00 ; 00-59 Note all

BCD format
let minutes = $00     ; 00-59 Note all

BCD format   
let hours = $01 ; 01-12 Note all BCD

format
let day = $03     ; program does not

use date, date, month, year
let date = $22      
let month = $03  
let year = $12      
let blinky = 000000 ; 010000 would

Enable output at 1Hz blink rate.  

000000 is no blink
writei2c 0,(seconds, minutes, hours,

day, date, month, year, blinky)
pause 50
#endrem
'/\ /\ /\ /\ Un_REM THESE LINES

(ABOVE) IF SETTING UP A NEW RTC  /\

/\ /\ /\
; POWER ON SELF TEST.  Send all three

meters to FULL Scale and back to 0
'NOTE:  pwmduty hour_meter, w7  

---->> w7 ranges from 0 to 400 to

move meter from 0VDC to 2VDC
for w7 = 400 to 0 step -1' pwmduty

needs a (W)ord var, not a (B)yte var
pwmduty hour_meter, w7 'adjust

PWM Duty from 100% to 0%
pwmduty minute_meter, w7
pwmduty second_meter, w7
next w7
main:
if temp_switch = 1 then
do ' while hour_set = 1 or minute_set

= 1 then 'if main buttom and H or M

set button pushed then
pwmduty hour_meter, 400 ' move all

meters to full scale to allow trimmer

adjust.  Do 0 meter adjust  1st with

power off.
pwmduty minute_meter, 400
pwmduty second_meter, 400
loop while hour_set = 1 or minute_set

= 1
end if ' temp_switch = 1
if temp_switch = 1 and hour_set = 0

and minute_set = 0 then
do 'while temp_switch is pressed
gosub DisplayTemp
loop while temp_switch = 1 and

hour_set = 0 and minute_set = 0
end if
'read the RTC and display the time
readi2c 0, (seconds, minutes, hours,

day, date, month, year, blinky)
pause 10
'\/ \/ \/ \/ \/ SECONDS SECONDS

SECONDS \/ \/ \/ \/ \/
;Convert the Seconds from the RTC to

Base10 and update the meter
if temp_switch = 0 and minute_set =

1 and hour_set = 1 then 'all pressed.  

Seconds to $00
gosub Seconds_set
end if
Ones_digi = seconds & 0x0F   ' zero

out the top four bits
Tens_Digi = seconds & 0xF0   ' zero

out the lower four bits
Tens_Digi = Tens_Digi / 2 ' each

divide by 2 shifts the
Tens_Digi = Tens_Digi / 2 ' bits LEFT.  

Four shift get
Tens_Digi = Tens_Digi / 2 ' them all to

the lower four bits
Tens_Digi = Tens_Digi / 2
Tens_Digi = Tens_Digi * 10 'Now shift

the Base10 value to Tens place
seconds = Tens_Digi + Ones_Digi

'complete. Now $ss is ss (in Base10)
' Update the seconds meter with a

w9 value of 0 to 400
w7 =  seconds * 677 / 100  ;

(400/59=6.77) scale 0-59 seconds to

0-400 for PWM
pwmduty second_meter, w7
'/\ /\ /\ /\ SECONDS END /\ /\ /\ /\

/\ /\ /\
'\/ \/ \/ \/ MINUTES MINUTES

MINUTES \/ \/ \/ \/ \/
if temp_switch = 0 and minute_set =

1 and hour_set = 0 then 'if

temp_switch and M is pressed then

add on minute
gosub Minutes_set
end if
;Convert the Minutes from the RTC to

Base10 and update the meter
Ones_digi = minutes & 0x0F   ' zero

out the top four bits
Tens_digi = minutes & 0xF0   ' zero

out the lower four bits
Tens_Digi = Tens_Digi / 2 ' each

divide by 2 shifts the
Tens_Digi = Tens_Digi / 2 ' bits LEFT.  

Four shift get
Tens_Digi = Tens_Digi / 2 ' them all to

the lower four bits
Tens_Digi = Tens_Digi / 2
Tens_Digi = Tens_Digi * 10 'Now shift

the Base10 value to Tens place
minutes = Tens_Digi + Ones_Digi

'complete. Now $mm is mm (in

Base10)
'Update the minutes meter with a w9

value of 0 to 400
If minute_set = 0 then 'dont update if

we are setting the minutes.  Should

correct this in Minutes_set routine
w7 = minutes * 677 / 100 ;

(400/59=6.77) scale 0-59 minutes to

0-400 for PWM
pwmduty minute_meter, w7
end if
'/\ /\ /\ /\ /\ MINUTES END /\ /\ /\ /\

/\
'\/ \/ \/ \/ \/ HOURS HOURS HOURS

\/ \/ \/ \/
if temp_switch = 0 and minute_set =

0 and hour_set = 1 then 'if

temp_switch and M is pressed then

add on minute
gosub Hours_set
end if
;Convert the Hours from the RTC to

Base10 and update the meter
Ones_digi = hours & 0x0F   ' zero out

the top four bits
Tens_digi = hours & 0xF0   ' zero out

the lower four bits
Tens_Digi = Tens_Digi / 2 ' each

divide by 2 shifts the
Tens_Digi = Tens_Digi / 2 ' bits LEFT.  

Four shift get
Tens_Digi = Tens_Digi / 2 ' them all to

the lower four bits
Tens_Digi = Tens_Digi / 2
Tens_Digi = Tens_Digi * 10 'Now shift

the Base10 value to Tens place
hours = Tens_Digi + Ones_Digi

'complete. Now $hh is hh (in Base10)
if hours > 12 then
hours = hours - 12
end if
if hours = 0 then
hours = 12
end if
' Update the hours meter with a w9

value of 0 to 400
w7 = hours * 3636  ; (400/11 = 36.36)  

scale 1 to 12 hours to 0-400 for PWM
w7 = w7 - 3636 'subtract  y interceot

to start PCM at 0 to 1 o'clock.
w7 = w7 / 100 'scale 1 to 12 hours to

0-400 for PWM
pwmduty hour_meter, w7
'/\ /\ /\ /\ /\ HOURS END /\ /\ /\ /\

/\
goto main
DisplayTemp:
readtemp temp_sensor,

CthermoValue
w7 = CthermoValue * 677 / 100

'(400/59=6.77) scale C to 0-400 for

PWM
pwmduty minute_meter, w7 'C (raw)

in the minutes meter)
'Convert C to F
FthermoValue = 9 * CthermoValue / 5

+ 32
w7 = FthermoValue * 364  ; (400/11 =

36.36)  scale 10 to 120F  to 0-400 for

PWM
w7 = w7 - 3636 'subtract  y interceot

to start PCM at 0 to 10F
w7 = w7 / 100 'scale 0-400 for PWM
pwmduty hour_meter, w7 '(F (x10) on

the hours meter
'Convert C to K
KthermoValue = CthermoValue + 273
w7 = KthermoValue / 10
w7 = w7 * 677 / 100
pwmduty second_meter, w7 'Kelvin

*100 on the seconds meter
return 'DisplayTemp
Seconds_Set:
seconds = $00
writei2c 0,(seconds, minutes, hours,

day, date, month, year, blinky)
pause 50
w7 =  seconds * 677 / 100  ;

(400/59=6.77) scale 0-59 seconds to

0-400 for PWM
pwmduty second_meter, w7
return 'Seconds_set
Minutes_Set:
readi2c 0, (seconds, minutes, hours,

day, date, month, year, blinky)
;Convert the Minutes from the RTC to

Base10 and update the meter
Ones_digi = minutes & 0x0F   ' zero

out the top four bits
Tens_digi = minutes & 0xF0   ' zero

out the lower four bits
Tens_Digi = Tens_Digi / 2 ' each

divide by 2 shifts the
Tens_Digi = Tens_Digi / 2 ' bits LEFT.  

Four shift get
Tens_Digi = Tens_Digi / 2 ' them all to

the lower four bits
Tens_Digi = Tens_Digi / 2
Tens_Digi = Tens_Digi * 10 'Now shift

the Base10 value to Tens place
minutes = Tens_Digi + Ones_Digi

'complete. Now $mm is mm (in

Base10)
minutes = minutes + 1
if minutes > 59 then
minutes = 0
end if
'convert base10 minutes to BCD here

then write new minute value to RTC
Ones_Digi = minutes // 10
Tens_Digi = minutes - Ones_Digi
Tens_Digi = Tens_Digi / 10
Tens_Digi = Tens_Digi * 2  ' shift the

lower right bits
Tens_Digi = Tens_Digi * 2  ' to the

upper left.
Tens_Digi = Tens_Digi * 2
Tens_Digi = Tens_Digi * 2
Tens_Digi = Tens_Digi OR Ones_Digi

'OR function on the two values to get

8 bit BDC
'Now Ten_digi = minutes in packed

BCD.  Just using Tens_Digi as a temp

var
writei2c 0,(seconds, Tens_Digi, hours,

day, date, month, year, blinky)
pause 50
'Update the minutes meter with a w9

value of 0 to 400
w7 = minutes * 677 / 100 ;

(400/59=6.77) scale 0-59 minutes to

0-400 for PWM
pwmduty minute_meter, w7
pause 500
return ' Minutes_Set
Hours_Set: 'HOURS SET WORKS

PERFECT
readi2c 0, (seconds, minutes, hours,

day, date, month, year, blinky)
;Convert the Hours from the RTC to

Base10 and update the meter
Ones_digi = hours & 0x0F   ' zero out

the top four bits
Tens_digi = hours & 0xF0   ' zero out

the lower four bits
Tens_Digi = Tens_Digi / 2 ' each

divide by 2 shifts the
Tens_Digi = Tens_Digi / 2 ' bits LEFT.  

Four shift get
Tens_Digi = Tens_Digi / 2 ' them all to

the lower four bits
Tens_Digi = Tens_Digi / 2
Tens_Digi = Tens_Digi * 10 'Now shift

the Base10 value to Tens place
hours = Tens_Digi + Ones_Digi

'complete. Now $hh is hh (in Base10)
hours = hours + 1
if hours > 12 then
hours = hours - 12
end if
if hours = 0 then
hours = 12
end if
if hours > 9 then
if hours = 10 then
hours = $10
end if
if hours = 11 then
hours = $11
end if
if hours = 12 then
hours = $12
end if
end if
writei2c 0,(seconds, minutes, hours,

day, date, month, year, blinky)
pause 50
;Convert the Hours from the RTC to

Base10 and update the meter
Ones_digi = hours & 0x0F   ' zero out

the top four bits
Tens_digi = hours & 0xF0   ' zero out

the lower four bits
Tens_Digi = Tens_Digi / 2 ' each

divide by 2 shifts the
Tens_Digi = Tens_Digi / 2 ' bits LEFT.  

Four shift get
Tens_Digi = Tens_Digi / 2 ' them all to

the lower four bits
Tens_Digi = Tens_Digi / 2
Tens_Digi = Tens_Digi * 10 'Now shift

the Base10 value to Tens place
hours = Tens_Digi + Ones_Digi

'complete. Now $hh is hh (in Base10)
' Update the hours meter with a w9

value of 0 to 400
w7 = hours * 3636  ; (400/11 = 36.36)  

scale 1 to 12 hours to 0-400 for PWM
w7 = w7 - 3636 'subtract  y interceot

to start PCM at 0 to 1 o'clock.
w7 = w7 / 100 'scale 1 to 12 hours to

0-400 for PWM
pwmduty hour_meter, w7
pause 1000

return ' Hours_Set

评分

2

查看全部评分

回复 支持 反对

使用道具 举报

     
发表于 2017-2-8 17:17:53 | 显示全部楼层
好思路.
用4个或者5个表头, 每个表头只要能显示0-9这几个数值, 就可以让指针万用表具备与4位或者5位数码管显示的万用表相同的分辨率了.
回复 支持 反对

使用道具 举报

     
发表于 2017-2-15 21:51:20 | 显示全部楼层
作者 大才小用 能有这样的技术 我就去 做表头 和家用定时器  不过作者可能是都会 了才做些与众不同的东西
回复 支持 反对

使用道具 举报

     
发表于 2017-2-19 22:49:37 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

     
发表于 2017-3-16 17:41:43 | 显示全部楼层
这是就是炫一下,没有什么实际效用,首先就是读数不明显
回复 支持 反对

使用道具 举报

     
发表于 2017-3-22 13:33:51 | 显示全部楼层
眉间尺 发表于 2017-2-8 17:17
好思路.
用4个或者5个表头, 每个表头只要能显示0-9这几个数值, 就可以让指针万用表具备与4位或者5位数码 ...

每个表盘100刻度,视觉可直读两位数。两个表盘四位数,最大是9999,比三位半还强。
不过看完第一表盘,记住读数,再看第二表盘的读数,合拢起来才是结果,会很不方便,怪怪的,拿来玩可以。
回复 支持 反对

使用道具 举报

     
发表于 2017-3-22 14:33:51 | 显示全部楼层
没有数码管的时代,就是用这个办法显示数字电路的输出的,按数字电路的权值取电阻就可以显示一位数字信息。
回复 支持 反对

使用道具 举报

     
发表于 2017-3-22 17:01:56 | 显示全部楼层
老柳 发表于 2017-3-22 13:33
每个表盘100刻度,视觉可直读两位数。两个表盘四位数,最大是9999,比三位半还强。
不过看完第一表盘, ...

看数码管如果看了个位忘了十位或者百位也不行啊.
回复 支持 反对

使用道具 举报

     
发表于 2017-3-22 20:48:55 | 显示全部楼层
学习看看听很高级
回复 支持 反对

使用道具 举报

     
发表于 2017-3-22 20:49:16 | 显示全部楼层
不错的作品!
单片机,不懂。想学,老了,太迟了。
回复 支持 反对

使用道具 举报

     
发表于 2017-3-26 13:38:03 | 显示全部楼层
不知道源程序是用什么语言写的。
回复 支持 反对

使用道具 举报

     
发表于 2017-3-30 19:49:04 | 显示全部楼层
独特风格 学习一下
回复 支持 反对

使用道具 举报

     
发表于 2017-4-5 07:45:36 | 显示全部楼层
换三个猫头表加黄色背光更赞
回复 支持 反对

使用道具 举报

     
发表于 2017-4-5 09:44:22 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 加入会员

本版积分规则

小黑屋|手机版|矿石收音机 ( 蒙ICP备05000029号-1 )

蒙公网安备 15040402000005号

GMT+8, 2025-4-27 03:01

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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