舉啞鈴 10 次太容易,番茄要來挑戰跟著音樂動次動! 基礎系列最終章,快跟著番茄一起用 While 迴圈稱霸 Arduino!
在上一堂課程,番茄為我們示範了他的完美健身計畫 。還記得嗎?當時他的目標是:舉啞鈴 10 次!所以,番茄利用了 For 迴圈的概念,透過「比對」、「舉啞鈴」,還有「更新計數器」這三個步驟,來精準地完成他的目標。
經過了幾個月的努力,每天舉啞鈴 10 次對番茄來說,已經太容易了!所以,現在的番茄決定改用「一首歌的時間」來進行啞鈴訓練,也就是說在音樂播放的期間,不斷地舉啞鈴,一直到音樂結束才停止。
在這個新的健身計畫裡,番茄並不需要去紀錄自己舉啞鈴的次數;只要音樂播放的狀態還沒結束,就代表今天的健身計畫還沒完成。類似這一種不在乎重複次數,卻特別著重某個「事件」或「狀態」有沒有發生的重複性任務,while 迴圈就會是我們的首選!
WHILE 迴圈語法結構
While 迴圈的結構非常單純,只包含了一個 while 關鍵字、一組小括號與一組大括號。在每一次執行大括號裡的工作之前,程式都會先檢查小括號裡這個「重複條件」的狀態。如果狀態是「成立」、「高電位」、或是「true」的話,while 迴圈就執行一次大括號裡的任務,然後再回到小括號這邊,重新檢查「重複條件」的狀態。
就這樣不斷重複檢查、執行、檢查、執行這兩個動作,一直到「重複條件」的狀態變成「不成立」、「低電位」或是「false」的時候,程式才會跳出整個 while 迴圈,繼續執行後面的程式。
所以,若要把番茄新推出的健身計畫寫成程式碼,就會如下圖。只要「音樂正在播放」的條件成立,while 迴圈就會持續執行,一直到條件不成立,也就是「音樂停止」的時候,程式才會跳出 while 迴圈,結束任務。
小專案:按下按鈕停止 LED 閃爍
相同的概念,我們也可以套用在 Arduino 控制 LED 閃爍的程式上面。比如說:我想讓接腳 13 的 LED 在 Arduino 啟動之後就不斷地閃爍,一直到我按下接腳 7 所連接的按鈕為止。在這個範例當中,按鈕狀態就跟音樂播放的狀態一樣,是用來判斷迴圈要不要執行的事件;而閃爍 LED 則跟舉啞鈴一樣,都是我們要重複執行的工作。
所以,我們只要把「判斷接腳 7 電位狀態」的指令,放在 while 迴圈的小括號當中;然後在大括號裡,放上讓 LED 閃爍一次的程式碼就可以了。在上拉電阻 的模式下,只要按鈕沒有被按下去,接腳 7 就會維持高電位,讓小括號裡的重複條件「成立」,並執行閃爍 LED 的工作;就這樣不斷重複執行,一直到我們按下按鈕,重複條件「不成立」,程式在檢查完小括號之後就會立刻跳出 while 迴圈,結束迴圈工作的執行。
最後,我們只需要把這段程式放在 setup() 區塊中,並在前面進行接腳的初始設定,這個小專案就完成了,你也可以動手試試看唷!
For 與 while 迴圈的比較
說到這邊,我們已經可以幫 For 迴圈與 While 迴圈做一個簡單的總結了!如果你已經知道某一個工作需要重複執行的次數,或是明確的「起始值」跟「目標值」,需要將過程依序的印出或執行,那就推薦把任務交給 For 迴圈來處理!
因為在 For 迴圈的標準結構中,已經包含了計數器的「初始化」與「更新」的區塊,可以幫助你精準地追蹤工作執行的次數,並在達成目標的時候結束迴圈。而如果你需要用某個「事件」或「狀態」來決定某段程式碼要不要重複執行的話,交給乾淨簡潔的 while 迴圈絕對是更好的選擇!
因為任務並不受「重複次數」或是「目標值」的影響,自然,也就不需要使用「計數器」來紀錄工作執行的次數了。
For 與 while 迴圈的轉換
雖然這兩種迴圈是針對不同用途而設計的,但有時,我們也會看到一些程式特意使用 While 迴圈,來執行 For 迴圈擅長的工作,反之亦然。我們就拿上一堂課介紹的「在監控視窗裡印出數字 0-9」的 For 迴圈程式當作例子,轉換成 While 迴圈的程式,會是什麼樣子呢?
首先,是 for 迴圈裡的「初始化」步驟,我們可以把它放在整個 while 迴圈的前面,讓計數器在迴圈開始之前,能夠預先把初始值給設定好。而「重複條件」的概念,其實跟 while 迴圈的小括號是一模一樣的,只要「counter 小於 10」這個敘述成立,重複的工作就會持續進行。
接下來,我們直接把「要重複執行的工作」拉進 while 迴圈的大括號裡。最後一項「變數增減」的步驟,我們可以安插在 while 迴圈大括號裡的底部,讓計數器的數值在每一次執行完工作以後,都能依情況增加或減少。
就這樣,根據這些元素的特性設計相對應的語法結構,我們就能讓 While 迴圈實現與 For 迴圈完全相同的功能了。
壞習慣與無窮迴圈
但是!我們強烈的建議你,不要把迴圈各自擅長的任務交給另一個迴圈來處理,因為這不但會降低程式的可讀性,只要一個不小心,還有可能會引起非常混亂的結果。我們一樣拿剛才從 For 迴圈轉換到 While 迴圈的程式當作例子。
如果我們撰寫了「初始化」、「重複條件」跟「重複執行的工作」,卻忘記要在最後添加「變數增減」的步驟,就會造成 counter 這個計數器在初始化之後,永遠停留在 0 這個數字而不會往上增加。
也因為 counter 失去了紀錄執行次數的功能,while 迴圈的重複條件:counter < 10 將永遠成立,程式也就永遠被卡在這個 while 迴圈當中。我們可以從序列埠監控室窗裡看到這個現象。
這是初學者在使用 While 迴圈時很容易掉進的陷阱。我們稱這個現象叫做 Infinite Loop,也就是「無窮迴圈」或是「無限循環」。所以除非你有非常明確的目的,不然刻意地轉換迴圈結構,並不是一個聰明的作法唷!
當然,迴圈控制還有非常多有趣的玩法,像是可以強制跳出迴圈的 break 指令,或是可以跳過本次迴圈執行的 continue 指令,這些精采的技巧,我們就留在進階課程裡再跟各位介紹啦!
ONE LAST THING
就這樣子,Arduino SpeedUp 系列總共 14 堂課程 在這邊告一個段落。我們從基礎知識、基本指令、到完成第一個專案,又從電學概念、流程控制,到更複雜的模組使用,這些紮實的基本功,將可以幫助你探索更有趣、更深入的主題!
接下來,請一定要持續鎖定我們的官方網站 www.lazytomatolab.com,我們會在這裡持續更新有趣的課程內容,還有工作室的最新消息,歡迎朋友們來這裡泡茶聊天! 我們期待在下個系列推出時,還能見到充滿熱情的你唷!
請問一下~Arduino有沒有可以無線傳輸RS232碼的機板呢??
您好,這個部分我們並不清楚唷~
想請教一下while迴圈中事不是不能再有迴圈?這個狀況也出現在if上嗎?
while()
迴圈中是可以有其他迴圈的唷,if()
同樣也可以。