2021 機器人加課
PWM
Simulating a PWM output
這個練習只是為了幫助你熟悉 C 語言的使用方式,實際上我們不常這樣應用!
現在你已經知道 PWM 就是控制 Duty cycle ,為了更了解運作原理,我們可以用程式模擬硬體電路的運作方式。
策略
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
- 設定 number of slots (num)
- 為每個燈設定亮度 (brightness)
- 假設有一個 counter 會不斷從 0 數到 num 也就是
- 當 counter 大於 brightness 的時候,輸出
1
,否則為 0
Blocking v.s. Non-blocking
- Blocking: 利用
delay()
製造 的延遲
- Non-blocking: 如果用
delay()
程式會卡住,因此會被 block 在 delay()
。如果要 Non-blocking 有兩種常見的方法:
- 可以用
millis()
判斷當下時間是否需要更新資料
- 利用硬體 timer 輔助
Timer interrupt
Why Interrupt Is Necessary?
試想像在煮開水,三不五時總要走過來看一下確定水開了沒,假設我們3分鐘走回來檢查一次,那麼會有二種情況:
- 走過來時水早已開了。 ← 大部份的情況。
- 走過來時水剛剛好開了。 ← 機率很低。
若很忙時間被打亂,沒辦法固定時間來檢查怎麼辦?
有沒有什麼更好的做法?
情境
如果在上面 Simulating a PWM output
的例子中, Arduino 不就沒辦法做其他的事情了嗎? 大部分的時間都被困在 delay()
裡面了
What is interrupt?
『處理器接收到來自硬體或軟體的訊號,提示發生了某個事件,應該被注意,這種情況就稱為中斷。』
中斷觸發與執行的流程:
- 中斷觸發,暫停目前的Process,並保存執行狀況。
- 根據Interrupt Table查詢對應的中斷服務常式(ISR, Interrupt Service Routine)Address。
- 跳至該Address(執行)。
- ISR執行完畢。
- 回到中斷前的Process並繼續執行。
Types of interrupts
硬體中斷 (Hardware Interrupt)
以某個Pin做為外部中斷的觸發,當發生特殊條件時進行中斷。Arduino 328中,具有Interrupt的pin為2、3。
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
Example:
Note: functionA
是一個自定義 function 的名字,你可以自己設計。
軟體中斷(Software Interrupt)
當發生特殊情況時,E.X.除以零。
Traps in writing ISR functions
在 ISR 函式內部會 改變 其值的變數,在宣告時必須在前面加上 volatile
這個關鍵字。當一個變數加入了 volatile 的宣告,那麼程式在 Compile 時就不會去最佳化與此變數相關的程式碼。
Example:
General OS Usually are Interrupt Driven
由於電腦主要在處理各種 I/O 操作,而 I/O 操作過程往往會因為速度不能相比( I/O 相較於 CPU 慢許多),故會以非同步的方式進行處理,I/O device 會在處理完後產生 Interrupt 告知 CPU 。
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
And Timer?
Arduino 利用內部的計數器電路計算 clock 震盪的次數,可以得到規律的時間計數。
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
Note: 所有的 timer 都會相依於 Arduino 的 system clock 。大部分 Arduino 的 clock 是 16MHz ,但是有些電源使用 3.3V 的 clock 是 8MHz ,所以設定 timer function 時要注意當時的 clock 。
Q: 很多 library 都會使用 timer ,那你也要用的時候怎麼辦?
A: 沒辦法,要不就你換一個 timer 用,要不就你不要用 library
Atmega 328p 有三組 timer 可以用:
- Timer 0(8bit):像是
delay()
、millis()
、micros()
都是使用到 timer 0
- Timer 1(16bit) :Servo library 使用 timer 1
- Timer 2(8bit) :
tone()
使用到 timer 2
可以在其他晶片上還有更多 timer。E.X. Arduino mega Board(Atmega 2560)
Atmega 328p 上的三個 timer 都不太一樣,大家一定要習慣查表,不要一直複製貼上不知道自己在寫什麼,核心概念都是一樣的,這邊有一個很完整的 資料 ,甚至有人做出 計算機。
接下來以 timer2 舉例:
下面是存放各種 timer 資料的 Registers:
- TCCRx - Timer/Counter Control Register. The prescaler can be configured here.
用來設定 timer 工作模式的 register ,例如說如果要 timer 工作在 CTC mode 表示要讓 register 中 WGM21
的地方為 1
其他為 0。
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
如果要設定 prescaler:
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
- TCNTx - Timer/Counter Register. The actual timer value is stored here.
- OCRx - Output Compare Register (Trigger Value)
- ICRx - Input Capture Register (only for 16bit timer)
- TIMSKx - Timer/Counter Interrupt Mask Register. To enable/disable timer interrupts.
- TIFRx - Timer/Counter Interrupt Flag Register. Indicates a pending timer interrupt.
Example:
Create your own library
Steps:
- Create an INTERFACE to your library: mylib.h
- Create an IMPLEMENTATION of your library: mylib.c
- Create a LIBRARY OBJECT FILE that can be linked with programs that want to use our library code (Compiler 會幫你做這件事)
- USE the library in other C code: #include “mylib.h”
將介面 (INTERFACE) 與實作 (IMPLEMENTATION) 分開,Why?
Create a .h
file
在 header file 內宣告函式介面 (Interface)
P.S. #開頭的敘述是給編譯器的指示
為了防止編譯器重複宣告及定義(每當include header file就會讀到這段程式碼)所以需要用 if 來判斷是否已經執行。

Create a .cpp
file
Cpp file,Arduino IDE 會自動編譯並 link ,不需要手動操作。

在程式碼中,用include將建立的header file include進來。

Declare a Global Variable in Your Library
若要定義全域變數,需在宣告的型態前面加上 extern 關鍵字,表示該變數的宣告會在某個 include 該 header file 的檔案中。

Overloading in Arduino

Learning to use third party library
不要再只會複製貼上了!
如果今天,你要用一個全新的 library 或是很少人在用,沒有什麼文獻資料,怎麼辦?
學會看懂別人在寫什麼,別人想要表達什麼!
舉例:
Servo Library
移位暫存器 (Shift Register)
Arduino 上面的 pin 不夠多怎麼辦 ?
A: 將序列 (serial) 資料轉成 並列 (parallel) 資料
功能

移位暫存器 74595 的內部構造,包含
- Shift register
- storage register
- 3 state output (control)


74HC595
74595 datasheet


74575 |
Name |
Description |
Arduino |
ST_CP |
Latch |
latch |
10 |
SH_CP |
Shift Clock |
clock |
13 |
DS |
Data In |
資料(data) |
11 |
Output Enable |
OE |
Enable (negative logic) |
GND |
RESET |
MR |
重置 (negtive logic) |
+5 |
SQH |
Q7' |
Serial Data Out |
X |