\documentclass[12pt,a4paper]{article} \usepackage[top=0.75in, bottom=0.75in, left=0.75in, right=0.75in]{geometry} \usepackage[utf8]{inputenc} \usepackage{amsmath} \usepackage{amsfonts} \usepackage{amssymb} \usepackage{xurl} \usepackage{listings} \usepackage{xcolor} \usepackage{booktabs} \lstset{ % General setup for the package language=C, basicstyle=\footnotesize\ttfamily, numbers=left, numberstyle=\small, frame=tb, tabsize=4, columns=fixed, showstringspaces=false, showtabs=false, keepspaces, commentstyle=\color{gray}, keywordstyle=\color{blue} } \usepackage{xeCJK} \setCJKmainfont{TW-Kai} \setCJKmonofont{Noto Sans Mono CJK TC} \author{1082B0006 林宏信} \title{} \begin{document} \begin{titlepage} \begin{center} \vspace*{1cm} \Huge \textbf{國立臺北科技大學} \vspace{0.5cm} \textbf{學生實習心得報告} \vspace{1.5cm} \textbf{} \vspace*{\fill} \begin{flushleft} \large 學期:110 學年度第 2 學期\\ 科別:智慧自動化控制科 \\ 班級:三年級 \\ 學號:1082B0004、1082B0006 \\ 姓名:劉予安、林宏信\\ 課程名稱:機電整合與實習\\ 授課老師:李政宏 博士\\ \end{flushleft} \end{center} \end{titlepage} \section{單元名稱:LED 特效燈} \section{實習設備與材料} \begin{table}[h!] \begin{center} \begin{tabular}{c|c|c|c} \toprule 項次 & 品名 & 數量 \\ \midrule 1 & Arduino & 1 \\ 2 & LED & 8 \\ 3 & 按鈕 & 4 \\ \bottomrule \end{tabular} \end{center} \end{table} \section{實習步驟} 這次的實作是要製作一個可透過按鈕切換不同模式的特效燈,每個特效運用 8 個數位 LED 做出各式的效果。這個實作在一開始的設計就有一個需要注意之處:由於按鈕可能在任何時間被按下,然而一個模式跑的過程需要時間,若沒有特別設計,就會需要使用者按著按鈕直到一個模式的週期結束,而這是不佳的使用者體驗。因此我在此運用與第一次實作相同的技巧,用計時器來取代 delay,達到非阻塞的設計。 首先是切換模式的函式,本函式運用靜態區域變數 last 儲存前一個狀態,在按下按鈕時,將其設為對應的模式並回傳。 \lstinputlisting[linerange={41-51}]{week4-4.ino} 接著即是程式的主迴圈,每次依據現在的模式,呼叫對應的函式。 \lstinputlisting[linerange={103-118}]{week4-4.ino} 接著是這個程式最特別之處:call\_interval。這個函式會每隔 DELAY 的時間,執行傳入的函式指標 f。雖然目前是使用固定的 DELAY 常數,但這個函式可以透過多接受一個參數,來改變要等待的時間,就可以實現不同的模式跑不同的 delay。藉由 call\_interval 函式,各模式燈光控制的函式就可以簡化為一個單次執行的程式。 \lstinputlisting[linerange={26-33}]{week4-4.ino} 最後就是三種模式各別的控制函式,每個函式會接受一個 clk 或 value 的參數,用來代表目前執行到第幾次。首先是二進位模式,我使用右移運算元來將數字除二,接著再取餘,即可用一行程式碼做出二進位的燈光。 \lstinputlisting[linerange={57-61}]{week4-4.ino} 格雷碼則是先將輸入用格雷碼的公式運算後,代入前面的二進位程式。 \lstinputlisting[linerange={63-65}]{week4-4.ino} 最複雜的則是隨機點亮燈光的程式,由於一個燈光點亮後會持續 3 個週期,因此需要用變數儲存每個燈的狀態。我運用一個陣列來存每個燈光剩餘的「血量」,0 代表不亮,大於 0 則代表亮,每個週期會將亮著的燈血量減一。接著是隨機點亮的程式,使用 do while 迴圈,在選到沒亮的燈前,會不停抽選燈,將其點亮。 \lstinputlisting[linerange={71-95}]{week4-4.ino} \section{問題與討論} 在 get\_mode 的地方仍然有個小 bug:當按著比較前面的按鈕時,同時按後面的按鈕,會讓後面的按鈕觸發。如按著 B4 還沒放開時,同時按下 B1,這時模式會被切為 1 號模式;但反之按著 B1 時按下 B4,仍然會是 1 號模式。這是由於程式是由前往後檢查,找到一個按下的按鈕就會回傳。但由於只要按鈕按著就會不停的重設計數器,要等到放開所有按鈕,燈光才會開始動作,經過評估沒有必要設計更複雜邏輯來解決。 \section{心得與建議} 這次的實驗過程體驗到了一個不斷讓程式碼精進的過程,從一開始的原型開發,專注在功能的實作,接著不斷的簡化、重構程式碼,使其愈加精鍊,最後得到了相當簡潔的程式碼,這樣的過程給了我很大的成就感。 \pagebreak{} \section{完整程式碼} \lstinputlisting{week4-4.ino} \end{document}