Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
遇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小時內與您取得聯系。