這份課堂紀錄從 Arduino 與 Tinkercad 的練習開始,涵蓋串列輸出、感測器、LED、七段顯示器與中斷。內容依上課日期排列,搭配電路畫面和程式碼,方便回顧每次實作。
本篇重點- 依日期查找電路配置與程式範例
- 觀察感測器輸入與 LED、顯示器的輸出
- 比較傳值方式、函式與中斷控制的實作
原始實作記錄於 2019 年;以下操作畫面與程式範例保留當時版本。
以下依上課日期保留電路、程式與當時結果。先核對電路接線與腳位,再閱讀程式中的輸入、判斷與輸出,較容易理解各次練習的變化。
請至 Tinkercad 註冊帳號。
若已有 Autodesk 帳號,可依 Tinkercad 的登入方式使用既有帳號。
登入後,開啟原紀錄中的左上方 LOGO,找到Circuits(電路),再建立電路專案並加入元件。這是 2019 年介面紀錄,實際入口以使用版本為準。
2019年10月24日
先練習把資料送到電腦,再用週期性資料觀察波形與公式輸出。確認串列傳輸速率與監視器設定一致,才能正確閱讀數值。
傳資料到 PC
1 2 3 4 5 6 7 8 9 10 11
| const byte ledPin = 13;
void setup(){ Serial.begin(9600); Serial.println("Hello," ); Serial.print("\tLED pin is: "); Serial.print(ledPin); Serial.print("\nBYE!"); } void loop(){ }
|
- 執行後,結果為
1 2 3
| Hello, LED pin is: 13 BYE!
|
修改後的練習
1 2 3 4 5 6 7 8 9 10 11
| const long ledPin = 525566;
void setup(){ Serial.begin(9600); Serial.println("Hello," ); Serial.print("\tYongCheng: "); Serial.print(ledPin); Serial.print("\nBYE!"); } void loop(){ }
|
- 執行後,結果為
1 2 3
| Hello, YongCheng: 525566 BYE!
|
顯示正弦波
1 2 3 4 5 6 7 8 9 10 11 12 13
| void setup(){ Serial.begin(9600); }
void loop(){ float angle = 0;float sineData; for (angle = 0.0; angle <= 90; angle += 0.1) { sineData = sin(angle); Serial.println(sineData); delay(1); } }
|
- 執行後,顯示為

串列監視器畫出心形
先參考前面的「顯示正弦波」,了解資料輸出,再嘗試心形公式。我自己Google到的心形公式
(sqrt(cos(x))*cos(200*x)+sqrt(abs(x))-0.7)*(4-x^2)^0.01)
Arduino 的 C++ 語法中,^ 是位元 XOR,不是次方;次方可用 pow,平方也可寫成 x*x。下方保留原公式,但其中 4-x^2 仍需修正為相符的數學運算;也要注意平方根與分數次方的定義域。(pow的意思可以參考這裡連結)
(sqrt(cos(x))*cos(200*x)+sqrt(abs(x))-0.7)*pow((4-x^2),0.01)
1 2 3 4 5 6 7 8 9 10 11
| void setup(){ Serial.begin(9600); double angle = 0;float sineData; for (angle = -4.5; angle <= 4.5; angle += 0.008){ double x=angle; Serial.println(sqrt(cos(x))*cos(200*x)+sqrt(abs(x))-0.7)*pow((4-x*x),0.01); } }
void loop(){ }
|
- 執行後,顯示為

老師找到的心形公式
(sqrt(cos(x))*cos(300*x)+sqrt(abs(x))-0.2)*pow((4-x*x),0.01)
1 2 3 4 5 6 7 8 9 10 11
| void setup(){ Serial.begin(9600); double angle = 0;float sineData; for (angle = -4.5; angle <= 4.5; angle += 0.008){ double x=angle; Serial.println(sqrt(cos(x))*cos(300*x)+sqrt(abs(x))-0.2)*pow((4-x*x),0.01); } }
void loop(){ }
|
- 執行後,顯示為

試做一個電壓調節器
建立新的電路專案,加入一個Arduino Uno R3和電位器。先核對電源、接地及訊號腳位,再測試輸入數值如何變化。程式碼新增:
1 2 3 4 5 6 7 8 9 10 11 12
| const byte potPin = A0; int val;
void setup(){ Serial.begin(9600); } void loop(){ val = analogRead(potPin); Serial.println(val); delay(500); }
|
- 執行後,顯示為

修改後的練習
以類比讀值 512 為門檻控制 LED:先看程式使用 > 還是 >=,再判斷恰好等於 512 時屬於哪個分支。
讀值在另一個分支時關閉 LED。門檻與比較方向應依實際電路及程式確認。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| const byte potPin = A0; int val;
void setup(){ Serial.begin(9600); pinMode(13,OUTPUT); } void loop(){ val = analogRead(potPin); Serial.println(val); if(val>512){ digitalWrite(13,HIGH); } else { digitalWrite(13,LOW); } }
|
- 執行後,顯示為

2019年10月28日
這週把感測器輸入接到 LED 與七段顯示器。先只改變一個輸入,觀察數值,再確認程式判斷與輸出是否一致。
使用光敏電阻控制LED
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| const byte LED = 13; const byte CdS = A0;
void setup() { Serial.begin(9600); pinMode(13, OUTPUT); }
void loop(){ int val; val = analogRead(CdS); Serial.println(val); if(val>=700){ digitalWrite(13,HIGH); } else{ digitalWrite(13,LOW); } }
|
- 執行後,顯示為

74HC595控制「七段顯示器」
利用 74HC595 控制七段顯示器,依序顯示 0~9;先對照接線與各段編碼,再觀察輸出順序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| const byte datePin = 2; const byte latchPin = 3; const byte clockPin = 4;
byte index = 0;
const byte LEDs[10] = { B01111110, B00110000, B01101101, B01111001, B00110011, B01011011, B01011111, B01110000, B01111111, B01110011};
void setup() { pinMode(datePin, OUTPUT); pinMode(latchPin, OUTPUT); pinMode(clockPin, OUTPUT); }
void loop() { digitalWrite(latchPin, LOW); shiftOut(datePin,clockPin, LSBFIRST, LEDs[index]); digitalWrite(latchPin, HIGH); delay(1000); index ++; if (index == 10){ index = 0; } }
|
- 執行後,顯示為

修改後的練習
將七段顯示器顯示為「9、7、5、3、1」
電路配置與上一個範例相同,這次主要修改顯示順序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| const byte datePin = 2; const byte latchPin = 3; const byte clockPin = 4;
byte index = 0;
const byte LEDs[5] = { B01110011, B01110000, B01011011, B01111001, B00110000};
void setup() { pinMode(datePin, OUTPUT); pinMode(latchPin, OUTPUT); pinMode(clockPin, OUTPUT); }
void loop() { digitalWrite(latchPin, LOW); shiftOut(datePin,clockPin, LSBFIRST, LEDs[index]); digitalWrite(latchPin, HIGH); delay(1000); index ++; if (index == 5){ index = 0; } }
|
- 顯示結果為,依序「9、7、5、3、1」循環。

2019年11月11日
本段保留超音波與輸出控制練習。測距需對照模組接線與觸發方式;控制馬達時,也需確認驅動電路,而不是僅靠程式輸出腳位。
超音波
課本範例(9-29)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| const byte trigPin = 10; const int echoPin = 9; unsigned long d;
unsigned long ping(){ digitalWrite(trigPin, HIGH); microseconds(10); digitalWrite(trigPin, LOW); return pulseIn(echoPin, HIGH); } void setup() { pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); Serial.begin(9600); }
void loop() { d = ping() /58;
Serial.print(d); Serial.print("cm"); Serial.println();
delay(1000); }
|
修改後的練習
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| const int pingPin = 7; const int ledPin = 13;
void setup() { Serial.begin(9600); pinMode(ledPin, OUTPUT); }
void loop() { long duration, cm; pinMode(pingPin, OUTPUT); digitalWrite(pingPin, LOW); delayMicroseconds(2); digitalWrite(pingPin, HIGH); delayMicroseconds(5); digitalWrite(pingPin, LOW); pinMode(pingPin, INPUT); duration = pulseIn(pingPin, HIGH); cm = microsecondestToCentimeters(duration); Serial.print("Distance: "); Serial.print(cm); Serial.print("cm"); Serial.println(); if (cm < 100){ digitalWrite(ledPin, HIGH); } else { digitalWrite(ledPin, LOW); } delay(100); } long microsecondestToCentimeters(long microseconds){ return microseconds / 29 / 2; }
|
- 依此配置,執行後,結果為

電壓輸出
1 2 3 4
| void setup(){ analogWrite(10,102);} void loop(){ }
|
- 電路依此配置,執行後,結果為

變頻控制LED燈光和馬達
2019年11月18日
傳值、傳址、傳參考
- call by value(傳值):函式使用參數值的副本。
- call by address(傳址):以指標傳入位址,函式可透過指標操作原資料。
- call by reference(傳參考):以參考參數操作呼叫端的資料。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| void swap(int* x,int* y){ int temp = *x; *x = *y; *y = temp; } void setup(){ int a=10, b=20; Serial.begin(9600); Serial.println(String("Before swap: ")+ "\t" + a + "\t" +b); swap(&a,&b); Serial.println(String("After swap: ")+ "\t" + a + "\t" +b); } void loop(){ }
|
- 顯示如下:
1 2
| Before swap: 10 20 After swap: 20 10
|
8-1 函數
1 2 3 4 5 6 7 8 9 10 11 12
| coid cirArea(){ int r=5; float area = 3.14 *r *r; Serial.println(area); } void setup(){ Serial.begin(9600); } void loop(){ cirArea(); delay(2000); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
float ans;
float cirArea(int r) { float area = 3.14 * r * r; return area; }
void setup() { Serial.begin(9600); ans = cirArea(10); Serial.println(ans); ans = cirArea(20); Serial.println(ans); } void loop() { }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| double result = 0; double i; double SumCC() { double SumC=0; for (int n=1; n<101;n++){ SumC=(n*5/3)+SumC; } return SumC; } void setup() { Serial.begin(9600); for( i=0 ; i<300 ; i++){ result=SumCC()+result; } Serial.println(result); }
void loop(){ }
|
2019年12月02日

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| double fun(double t) { double A=2; double f=60; double result; double pi=3.1415926; result = A*sin(2*pi*f*t);
return result; }
void setup() { Serial.begin(9600); for(double t=0;t<=(1);t=t+0.001) { double result = fun(t); Serial.println(result); } }
void loop() { }
|
- 執行後,結果為

t = 0 度 ~ 360 度
x = A sin ( 2 π f t ) + B cos ( 2 π f t )
A = 0.2
B = 0.3
f = 60
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| double fun(double t) { double A=0.2; double B=0.3; double f=60; double result; double pi=3.1415926; result = A*sin(2*pi*f*t) + B*cos(2*pi*f*t);
return result; }
void setup() { Serial.begin(9600); for(double t=0;t<=(1);t=t+0.001) { double result = fun(t); Serial.println(result); } }
void loop() { }
|
- 執行後,結果為

老師上課補充
中斷可在觸發條件發生時執行對應的服務函式,暫時處理事件後再回到原流程。它不是所有情況都具有「最高權限」的意思,實際行為依晶片與設定而定。
中斷
- 線路配置圖

程式內容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| int pbInt = 0; int ledOut = A0; volatile int state = LOW; void setup() { pinMode(ledOut, OUTPUT); attachInterrupt(pbInt, stateChange, CHANGE); } void loop() { for (int i = 0; i < 100; i++) { delay(100); } } void stateChange() { state = !state; digitalWrite(ledOut, state); }
|
2019年12月09日
斜率
- x^2+5
-
2019年12月16日
外部中斷(FALLING)
FALLING 表示訊號由高轉低時觸發;CHANGE 表示訊號電位改變時觸發。可使用的中斷腳位與模式依板子而異,請先查閱對應規格。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
int SensorLED = 9; int SensorINPUT = 2; char state = LOW;
void setup() {
pinMode(SensorLED, OUTPUT); pinMode(SensorINPUT, INPUT_PULLUP);
attachInterrupt(0, blink, FALLING); }
void loop() {
if (state == HIGH) { state = LOW; digitalWrite(SensorLED, HIGH); delay(500); } else { digitalWrite(SensorLED, LOW); } } void blink() { state = !state; }
|
進階(CHANGE)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
int SensorLED = 9; int SensorINPUT = 2; char state = LOW;
void setup() {
pinMode(SensorLED, OUTPUT); pinMode(SensorINPUT, INPUT_PULLUP);
attachInterrupt(0, blink, CHANGE); }
void loop() {
if (state == HIGH) { state = LOW; digitalWrite(SensorLED, HIGH); delay(500); } else { digitalWrite(SensorLED, LOW); } } void blink() { state = !state; }
|
模擬與實體實作要分開確認
Tinkercad 畫面可協助觀察電路與程式,但實體板子仍需核對供電、腳位、元件規格及接線。修改時先測試單一感測器或輸出,再整合;中斷服務函式應保持簡短,避免在其中安排長時間等待。
參考:Arduino 官方語言參考。