遇JS,做一个简易数字时钟。
《JavaScript》学习过程中的心得与总结
1、做一个数字时钟,首先我们先放上图片,给他的背景加点颜色
<body style="color: #FF9900; background-color: #cccccc">
<img src="images/0.jpg" />
<img src="images/0.jpg" />
时
<img src="images/0.jpg" />
<img src="images/0.jpg" />
分
<img src="images/0.jpg" />
<img src="images/0.jpg" />
秒
</body>
现在是这个样子:
在给他设置一个按钮,用更新系统时间:
<input id="btn1" type="button" value="更新时间">
2、想做一个数字时钟,最重要的是先想办法获取系统时间。
所以 我们写一个JS,来获取系统时间
<script type="text/javascript">
window.onload=function (){
//上一篇文章已经讲过,windows.onload的作用
var Img=document.getElementsByTagName('img');
var Btn=document.getElementById('btn1');
var i=0;
Btn.onclick=function() {
var oDate=new Date();
//初始化创建一个新对象(获取系统时间
var str=oDate.getHours()+'点'+oDate.getMinutes()+'分'+oDate.getSeconds()+'秒';
</script>
现在当我们点击更新按钮时,我们的程序显示如下:
3、获取系统时间之后我们发现,我们的时间是有六张图片的,可是我们在更新系统时间时发现当一秒钟时我们的系统时间显示为21点10分4秒
我们如果想让它显示21时10分04秒应该怎么做呢?
我们应该创建一个函数,让他去判断
function toDouble(num) {
if (num<10)
{
return '0'+num;
}
else
{
return ''+num;
} }
var str=toDouble(oDate.getHours())+toDouble(oDate.getMinutes())+toDouble(oDate.getSeconds());
alert(str);
</script> </head>
此时,获取系统时间就完成了
anvas是HTMl5中的重要标签之一,它可以在浏览器中绘制图形。canvas标签需要指定一个宽度和高度。
本文将包括以下内容:
<canvas id="canvas" width="200" height="200"></canvas>
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
我们首先获取到canvas元素,然后使用 getContext方法 获取2D上下文,从而可以控制canvas。
// 绘制时钟外框
function drawBorder(){
ctx.beginPath(); //开始绘制路径
ctx.arc(100, 100, 90, 0, Math.PI * 2); //绘制圆形
ctx.strokeStyle='black'; //设置颜色
ctx.lineWidth=5; //设置线条宽度
ctx.stroke(); //绘制路径
}
这个代码块中,我们使用 beginPath()方法 开始绘制,然后使用arc()方法绘制圆形。圆心的坐标为(100, 100),半径为90像素。我们还使用strokeStyle属性设置颜色,使用lineWidth属性设置线条宽度,并最终使用stroke()方法绘制。
//绘制刻度
function drawTicks() {
for (var i=0; i < 60; i++) {
ctx.beginPath(); //开始绘制路径
ctx.lineWidth=(i%5==0) ? 5 : 2; //设置线条宽度
ctx.strokeStyle=(i%5==0) ? '#e2e2e2' : '#f2f2f2'; //设置颜色
var angle=(i/60) * (2*Math.PI); //计算角度
var x=100 + Math.cos(angle) * 80; //计算X坐标
var y=100 + Math.sin(angle) * 80; //计算Y坐标
ctx.moveTo(x, y); //移动到刻度点
ctx.lineTo(100, 100); //向圆心连线
ctx.stroke(); //绘制路径
}
}
这个代码块中,我们使用for循环来绘制60个刻度。在每个迭代中,我们设置线条宽度和颜色,然后计算出刻度点的坐标,并使用moveTo()方法移动到该点。接下来,我们使用lineTo()方法将该点与圆心连线,并使用stroke()方法绘制路径。
//绘制指针
function drawHands() {
var now=new Date(); //获取当前时间
var hour=now.getHours(); //获取小时
var minute=now.getMinutes(); //获取分钟
var second=now.getSeconds(); //获取秒钟
var hourAngle=(hour/12) * (Math.PI*2) - (Math.PI/2); //计算时针角度
var minuteAngle=(minute/60) * (Math.PI*2) - (Math.PI/2); //计算分针角度
var secondAngle=(second/60) * (Math.PI*2) - (Math.PI/2); //计算秒针角度
//绘制时针
ctx.beginPath(); //开始绘制路径
ctx.lineWidth=8; //设置线条宽度
ctx.strokeStyle='black'; //设置颜色
ctx.moveTo(100, 100); //移动到圆心
ctx.lineTo(100 + Math.cos(hourAngle) * 60, 100 + Math.sin(hourAngle) * 60); //绘制路径
ctx.stroke(); //绘制路径
//绘制分针
ctx.beginPath(); //开始绘制路径
ctx.lineWidth=5; //设置线条宽度
ctx.strokeStyle='black'; //设置颜色
ctx.moveTo(100, 100); //移动到圆心
ctx.lineTo(100 + Math.cos(minuteAngle) * 80, 100 + Math.sin(minuteAngle) * 80); //绘制路径
ctx.stroke(); //绘制路径
//绘制秒针
ctx.beginPath(); //开始绘制路径
ctx.lineWidth=2; //设置线条宽度
ctx.strokeStyle='red'; //设置颜色
ctx.moveTo(100, 100); //移动到圆心
ctx.lineTo(100 + Math.cos(secondAngle) * 90, 100 + Math.sin(secondAngle) * 90); //绘制路径
ctx.stroke(); //绘制路径
//绘制圆心
ctx.beginPath(); //开始绘制路径
ctx.arc(100, 100, 5, 0, Math.PI * 2); //绘制圆形
ctx.fillStyle='black'; //设置填充色
ctx.fill(); //填充路径
}
在这个代码块中,我们首先获取当前的时间,然后计算时针、分针和秒针的角度。我们使用beginPath()方法开始绘制路径,然后使用moveTo()方法移动到圆心。使用lineTo()方法绘制指针,并使用stroke()方法绘制路径。最后,我们使用arc()方法绘制圆心,并使用fill()方法填充路径。
setInterval(function() {
ctx.clearRect(0, 0, canvas.width, canvas.height); //清空画布
drawBorder(); //绘制时钟外框
drawTicks(); //绘制刻度
drawHands(); //绘制指针
}, 1000);
在这个代码块中,我们使用clearRect()方法清空画布,让我们可以重新绘制指针。然后,每秒钟调用drawBorder、drawTicks、drawHands函数,以重新绘制时钟。
希望本文能够对您有所帮助,感谢您的阅读!
人人为我,我为人人,谢谢您的浏览,我们一起加油吧。
周和大家介绍一个漂亮的墨水屏电子钟,兼具气象站功能(可以通过GPS自动设置),用4节AAA电池可以续航6个月左右,而且,为了保证安全和可靠性,它不需要任何网络连接。
特点包括:
这个项目有两个不同的版本,分别是 “简易”版本 和 “低功率”版本。
“简易”版本是基于Arduino Nano的。这个版本的目的是尽量减少成本、零件数量和制作的复杂性;缺点是你需要用一个USB 5V适配器来给时钟供电。
“低功率”版本使用一个32k的振荡器,以极小的功率保持精确的计时。这个振荡器让时钟可以用电池运行。
这些材料和上面的简易版本一样:
此外,你还需要:
前面说有两个版本,这个是一个额外的版本,之所以会有这么一个额外的版本,就是因为我们现在处于 "零件荒 ",像Atmega328P这样的芯片会长期缺货。
你可以用 "简单 "版本的固件运行这个版本,或者,如果你对自己的焊接技术有信心,你可以在微控制器上焊接一个32k的晶体(如上图所示),并使用32k版本的固件(更多细节见下节)。
上面的原理图是用一个 "便宜的GPS "解决方案来连接的,但是如果你用了别的(比如Adafruit)的设置来替换原理图中的GPS部分,你也可以使用别的(比如Adafruit的)GPS(如上一步的原理图所示)。
与竞争对手(12美元)相比,Adafruit的GPS装置很贵(30美元)。如果你认为增加的功能(在低功耗部件部分有描述)不 "值得",你可以把任何能以9600波特传输NMEA字符串的GPS模块丢进去(大多数的GPS模块都可以)。
但现在有一个新的问题需要解决:这些单元中的大多数缺乏一个启用/禁用引脚,而GPS单元通常消耗30-100毫安的电力。我们可以用一个N-MOSFET(或类似的)黑掉一个禁用开关。上面的原理图显示了基本的想法。我们也可以在falstad[1]中进行尝试。
这个电源开关电路是有取舍的。如果你有兴趣了解更多细节,请参见附录B。
如果你正在制作 "简易 "版本,你不需要阅读这一部分。对于“低功率”版本,这些改装将大大改善电池寿命。
为了说明问题,我们将假设电源来自一组AAA电池,可以提供1000毫安时。让我们假设你使用的是32K的Adafruit版本,并且没有做任何修改。下面是一个电源分解的例子。
因此,我们有(50 + 166 + 6 + 100 + 500)=822 uA的平均电流消耗,相当于约50天的功率。
如果去掉MS8607 LED和GPS上拉电阻,我们的用电量就会减少到222 uA,也就是大约187天的用电量,大大增加了使用时间。
1、首先,建议从MS8607上拆下LED(具体如上图所示)
2、Adafruit GPS上的上拉电阻是由Adafruit的设计人员添加的,使得EN引脚变成一个可选项。不过它也有一个缺点,就是当你把它拉到地(禁用GPS)时,大约有500uA的电流在上拉电阻中被消耗掉了。由于这个设计的使能引脚是主动驱动的,你可以去掉这个电阻(具体如上图所示)
3、专业的迷你修改。搜索引擎搜索 "Arduino mini低功耗 "了解详情,基本上,你会想去掉电压调节器和LED,来减少电源使用。我们改用MS8607的电压调节器(3.3V,空闲时损失35-55uA的功率)为pro mini供电。
4、在pro mini的照片中,我还去掉了晶体振荡器,为32K晶体的芯片做准备。只有在32K晶体版本的情况下才去掉这个晶体,而且只有在对pro mini的内熔丝进行重新编程后才去掉,后面会解释。
在这个步骤中,我附上了nano和32k晶体版本的.hex文件(这两个版本都适用于pro-mini,如果你不确定使用哪个版本,就使用nano版本)。
如果想自己构建/修改源代码,可以访问GitHub:https://github.com/mattwach/epaper_clock
注意,这段代码没有使用Arduino库,因为产生的代码太大,无法在Atmega328P上安装(而且这是我的个人偏好)。它是用C语言编写的,使用了Arduino[2]也使用的AVR基础库作为基础。如果你想编译代码,你需要安装(免费的)avr-gcc工具[3],克隆epaper项目[4]的源码。然后进入firmware/[5]目录并输入。
make
如果代码建立了,可以打开Makefile[6],看看这些选项。
# This is the Low-power stand alone chip configuration.
CLOCK_MODE ?=USE_32K_CRYSTAL
UART_MODE ?=HARDWARE_UART
F_CPU ?=8000000
# This is the easy-to-build firmware that is based on an Ardino Nano
#CLOCK_MODE ?=USE_CPU_CRYSTAL
#UART_MODE ?=SOFTWARE_UART
#F_CPU ?=16000000
如果你正在构建32k晶体固件,配置已经正确了。如果构建nano的版本,你需要注释32k那段,取消注释nano那段代码,然后再次make。
还有一个特殊的调试模式,通过硬件UART以9600波特的速度转储日志信息。你现在可以忽略,但要记住它,因为它以后可能会有用。
# Uncomment to activate debug via the UART TX (9600 baud)
#DEBUG_CFLAG :=-DDEBUG
最后,你可以通过改变几个变量来决定GPS应该多长时间被激活。默认每天运行一次,但如果GPS需要很长时间锁定,它会减少运行频率,从而减少电池的消耗。请在src/gps.c[7]中阅读所有相关内容。
这部分的文件可以在文末下载!
本节是为那些上传代码到独立的Atmega328P芯片的小伙伴准备的,如果你要上传到Arduino Nano,请跳到下一个步骤。
你需要一个ISP(或ICSP)编程器。可以用一个备用的Aruino Uno/Nano自己做一个。可以在搜索引擎搜索"Arduino ISP Programmer" 请注意,这些指南中的很多内容都假定你的真正目的是安装一个引导程序,但对于我们来说,不需要引导程序,因为我们将直接用ICSP上传.hex文件。
在我的Atmega328P上,断电检测设置为3.5V(貌似是旧版本),所以我用这个命令禁用断电检测。
/usr/bin/avrdude -patmega328p -cusbasp -Uefuse:w:0xFF:m
你的可能不一样,这取决于你的“ISP programmer”(-c选项)。也有可能你不需要设置,只是以防万一。
我们可以使用一个叫avrdude的免费工具,来把它创建的十六进制文件上传到你的Uno/Nano/。我们也可以直接用命令行下载并使用avrdude。
这里是我在nano版本中使用的avrdude命令(通过make上传)。
供参考:
/usr/bin/avrdude \
-v \
-patmega328p \
-carduino \
-P/dev/ttyUSB0 \
-b57600 \
-D \
-Uflash:w:epaper_firmware_using_arduino_nano.hex:i
这个是我在ISP版本中使用的:
/usr/bin/avrdude \
-v \
-patmega328p \
-cusbasp \
-Uflash:w:epaper_firmware_using_32k_crystal.hex:i
这边使用的是Linux。Mac和Windows也能正常工作,但像-P这样的选项会有所不同(即在Windows中可能是-PCOM1)。
同样,这部分的文件可以在文末下载!
如果你正在制作 "简易 "版本,请跳过这一步。如果你使用的是32k晶体固件,则需要安装晶体以使固件发挥作用。
首先(!) 你还需要配置ATMega328P的内部内熔丝,以使用内部的8Mhz晶体。
先做这一步很重要,因为32K晶体将取代任何现有晶体。如果你不改变这些内熔丝,芯片会变得没有反应,直到你重新连接一个8或16Mhz的振荡器。
据我所知,Arduino pro mini也需要ISP来改变内熔丝(但我可能是错的)。我查找了 "Arduino ISP",来获得正确的引脚映射,以便将ISP连接器与面包板对接(如上图所示)。
在连接了我的ISP programmer后,可以用这个命令检查当前的内熔丝配置。
$ avrdude -patmega328p -cusbasp
...
avrdude: safemode: Fuses OK (E:FF, H:DE, L:E2)
L:E2是我们想要的内部8mhz的设置。如果你的值不一样,可以用类似于这个的命令来更新它。
/usr/bin/avrdude -patmega328p -cusbasp -Ulfuse:w:0xE2:m
然后重新检查。
内熔丝设置完毕后,你就可以焊接晶体了。建议将晶体直接连接到微控制器引脚上,以减少杂散电容。太多的电容会使晶体需要更长的时间来开始振荡(或无法启动)。
请参考步骤1、步骤2或步骤3中你所选择的设计原理图。
如果测试正常,我们可以把所有东西转移到一个更“永久”的固定装置上。
你可以选择使用perf板,用CNC切割板子,或者把设计送到工厂去制造。
Kicad设计文件可以在schematic/目录[9]中找到。有三种硬件可供选择(都是从后面显示的,因为这是你手工布线的方式)。
我用我的CNC机器制作ATMega328P版本。如果你没有用CNC切割过PCB而又感兴趣,可以尝试在搜索引擎上搜索 "3018 PCB",你会发现很多关于这个主题的视频和文章。
间隙设置0.4毫米,但你可以更窄(可能不会更宽)。我使用Flatcam将Kicad的Gerber输出转换为G代码。
相关文件可以在文末下载到。
你可以设计你想要的任何类型的外观,非常鼓励大家发挥创意!
这里分享一下我是怎么制作的(所有的设计文件都可以在文末下载到)。
我的设计使用了一个3D打印的支撑结构和两个CNC部件:一个顶盖和前面板。数控部件是用木头做的,因为我认为它比塑料看起来更漂亮。我在OpenSCAD中预先设计了整个东西。
我用0.2毫米的层高打印了主要结构。在我的3D打印机上,打印花了5个小时多一点。
我使用OpenSCAD的 "projection"[10] 功能,为顶盖和前板创建了2D DXF文件。
我通常会使用一个名为 "Carbide Create"[11]的免费程序,为数控机床制作G代码。但面板有一个45度的倒角,而Carbide Create是一个太基本的程序,不能很好地处理这个问题(至少我通过谷歌搜索他们网站上的论坛,得出了这个结论)。所以我尝试了一个不同的程序,叫做"CamBam"[12],它的效果非常好。(CamBam不是免费的,但可以免费使用40次)
你的32k/CPU晶体不会是完美的。当GPS开启时,它将修正漂移。但是如果漂移不好或者你的GPS信号不好,你也可以在固件中应用一个校正。目前这需要构建代码。在main.c的顶部,有一些被注释掉的定义。
// Clock drift correction
// If your clock runs too fast or too slow, then you can enable these
//#define CORRECT_CLOCK_DRIFT
// number of seconds that a second should be added or removed
//#define CLOCK_DRIFT_SECONDS_PER_CORRECT 1800
// define this if the clock is too slow, otherwise leave it commented out
//#define CLOCK_DRIFT_TOO_SLOW
你可以取消对上面两个#define语句的加注,以启用校正。
只需取消对CLOCK_DRIFT_TOO_SLOW的注释(你的时钟已经慢了的话)。
如果你的时钟太快了,就不要注释。唯一要做的是设置CLOCK_DRIFT_SECONDS_PER_CORRECT...
等了大约一天,然后看看时钟漂移了多少。例如,你可能要等23个小时。如果这时你看到时钟慢了10秒,那么你的修正将是。
(3600 * 23) / 10=8280秒,每次修正。
#define CORRECT_CLOCK_DRIFT
#define CLOCK_DRIFT_SECONDS_PER_CORRECT 8280
#define CLOCK_DRIFT_TOO_SLOW
只需尝试一个像5000这样的数字,并在你注意到时钟仍然过快或过慢时对其进行完善。还是太慢?试试2,500。太快了?试试10,000。保持记录,并反复完善到可接受的数值,就像你在某些时候可能玩过的猜数字游戏一样。
重温一下第四步"便宜GPS " 里描述的电源控制电路,上面的电源切断电路被称为 "low side switch"。它的好处是比较容易理解,而且零件数量少。尽管如此,还是有一些设计上的问题。
但是,UART是一个数字信号,地线的差异并不大,所以也许它无论如何都会工作?我试过了,而且工作得很好......起初,但随着时间的推移,我逐渐发现它并不可靠。为了了解原因,我们参考一下我最初选择的BS170作为我的N-MOSFET的特性曲线[13]。
在X轴的3.3V时,我们将坐在图上的3.0和4.0V线之间。因此,也许我们会得到100mA?也许足够?
万用表告诉我,GPS消耗40-60mA,但我认为这是一个平均值。根据GPS试图做什么,它只是需要比晶体管能够允许的更多的电流,因此GPS的地(MOSFET漏极)电压会上升。这既造成了UART错误,又降低了GPS装置的整体电压,而GPS装置有时仍然可以工作,有时则进入复位循环。
一个解决方案是使用一个 "high side"电源电路,在上面增加一个P-MOSFET来实现这个目标。见上面的原理图。这消除了单独接地的问题,并提供一个完整的5V(电池)栅极电压波动,这将使相关的P-MOSFET完全打开。
这里[14]是falstad中的一个高边设计实例。
目前我已经订购了带有低端布线的PCB,所以我的次要解决方案是放弃BS170,而用FQP30N06L代替。这种较高电流的MOSFET(最大30A!)似乎严重过剩,而且确实如此,但其曲线看起来要好得多。在3.3V电压下,大约有10A的电流余量,比BS170改进了100倍,现在应该足够了;而且确实没有恢复不稳定。
[1]falstad: http://www.falstad.com/circuit/circuitjs.html?ctz=CQAgjCAMB0l3BWcMBMcUHYMGZIA4UA2ATmIxAUgoqoQFMBaMMAKADMLiUQUAWKwvx5Ds3MNCQwELAEoUMhEIIphuyqlSGSoUCSwBOSoczVCUfHZRYAPJQnJpeIDJAeuQTiwHEACgGUWACMlfHAUPGcwRRQwJ0gWAHd5RWVBATjEo3Ss8FUoFgBzHJQEFJFIOPzDBC5hTWJooSoweFkPZT5NUTqdTSpsaGxe3WkAZ3bPIV4GnuaQNgBDABtRugMPGc6NxVENZHg4Qu2QXePsbEUNFiA
[2]Arduino: https://www.arduino.cc/
[3]avr-gcc工具: https://www.pololu.com/docs/0J61/6.3
[4]epaper项目: https://github.com/mattwach/epaper_clock
[5]firmware目录: https://github.com/mattwach/epaper_clock/tree/main/firmware
[6]Makefile: https://github.com/mattwach/epaper_clock/blob/main/src/Makefile
[7]src/gps.c: https://github.com/mattwach/epaper_clock/blob/main/src/gps.c
[8]https://www.nongnu.org/avrdude/: https://www.nongnu.org/avrdude/
[9]schematic/: https://github.com/mattwach/epaper_clock/tree/main/schematic
[10]projection功能: https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Using_the_2D_Subsystem#3D_to_2D_Projection
[11]Carbide Create: https://carbide3d.com/carbidecreate/
[12]CamBam: http://www.cambam.info/
[13]N-MOSFET的特性曲线: https://www.onsemi.com/pdf/datasheet/mmbf170-d.pdf
[14]falstad中的一个高边设计实例: http://www.falstad.com/circuit/circuitjs.html?ctz=CQAgjCAMB0l3BWcMBMcUHYMGZIA4UA2ATmIxAUgoqoQFMBaMMAKADMLiUQUAWKwvx5Ds3MNCQxIKdiEFUwGQnKFgUeELwjjJsGQCcVCpRULHlC+JBYB3OX3DrTCp9bsIzjjR-NQWAJWcvTWJlNQ0qKiFJKCgJFkMMNHATJKp1CJoWAA8QHHIiDQw8AowIXmEQAHEABQBlFgAjOTwNMC480J5ivwBzPOSMgapRSL87Qg9gtOC3YenkxQtbIxTleR4Ha36NlCmN3ArIhM5uPiiu89iweADNQWEo0UfYqJHobFe4hBYAZ3uKldeJchAoQGwAIYAG1+dBYQA
原文链接:https://www.instructables.com/E-Paper-Clock/
原文作者:mattwach
译文首发:DF创客社区 https://mc.dfrobot.com.cn/thread-313226-1-1.html
转载请注明原作者及出处
*请认真填写需求信息,我们会在24小时内与您取得联系。