Arduino 進階




Panda Wu

2025/12/09

Recall - 常見腳位

  • GPIO (General Purpose Input/Output)
    • 透過程式控制 Pin 要輸出 High 還是 Low
  • ADC (Analog-to-Digital Converter)
    • 將連續變化的信號轉為離散的訊號
  • DAC (Digital-to-Analog Converter)
    • 將數位訊號轉為對應的模擬類比訊號
  • PWM (Pulse Width Modulation)

ref: https://datasheet.lcsc.com/lcsc/Ai-Thinker-NodeMCU-32SLua_C111436.pdf

Recall - 常用語法 1

  • void setup(): 程式啟動時只會執行一次。
  • void loop(): 在 void setup() 執行後,會無限重複執行這裡面的內容
  • pinMode(pin, mode)
    • pin: 腳位號碼
    • mode: INPUT, OUTPUT, INPUT_PULLUP
  • digitalWrite(pin, value)
    • value: HIGH, LOW

Recall - 常用語法 2

  • digitalRead(pin): return HIGH / LOW
  • analogRead(pin): return 0~4095 (int)
  • analogWrite(pin, value):
    • value: 0~255
  • delay(ms)

今天說什麼

  • UART
  • Wi-Fi
  • Interrupt

UART

UART 實作

// for computer serial monitor
Serial.begin(115200);
Serial.read();
Serial.write(2025);
Serial.println("Hello World");

// for communicate with the other device
HardwareSerial mySerial(2); 
mySerial.begin(115200, SERIAL_8N1, RXD1, TXD1);

UART Exercise

  1. 輸出文字到 Serial Monitor
  2. 自己傳訊息給自己並輸出
  3. 跟隔壁的同學互相傳訊息並輸出

UART Exercise - 3

#define RXD2 16
#define TXD2 17

String inputString = ""; 
HardwareSerial mySerial(2); 

void setup() {
  Serial.begin(115200);
  mySerial.begin(115200, SERIAL_8N1, RXD2, TXD2);
}

void loop() {
  while (mySerial.available()) {
    char inChar = (char)mySerial.read();
    if (inChar == '\n') {
      Serial.print("Received: ");
      Serial.println(inputString);
      inputString = ""; 
    } 
    else {
      inputString += inChar;
    }
  }

  if (Serial.available()) {
    char outByte = Serial.read();
    mySerial.write(outByte);
  }
}

Wi-Fi

  • Docs
  • 東西有點多,建議可以搭配 Google 和 AI 一起食用
  • 接下來先以一個例子讓大家淺嚐

Wi-Fi Exercise - 使用 Wi-Fi 來控制 LED

#include <WiFi.h>
#include <WebServer.h>

WebServer server(80);

void setup() {
  Serial.begin(115200);
  Serial.println("Start!");
  pinMode(LED_BUILTIN, OUTPUT);

  WiFi.softAP("test", "12345678");
  Serial.println("Start!");
  Serial.println(WiFi.softAPIP());

  server.on("/", []() {
    server.send(200, "text/html", "<h1>Control</h1><a href='/on'>ON</a><br><br><a href='/off'>OFF</a>");
  });

  server.on("/on", []() {
    digitalWrite(LED_BUILTIN, HIGH);
    server.send(200, "text/html", "<h1>LED IS ON</h1><a href='/'>Back</a>");
  });

  server.on("/off", []() {
    digitalWrite(LED_BUILTIN, LOW);
    server.send(200, "text/html", "<h1>LED IS OFF</h1><a href='/'>Back</a>");
  });

  server.begin();
}

void loop() {
  server.handleClient();
}

Interrupt

  • 中斷是一種硬體機制,允許外部訊號強制暫停 CPU 目前正在執行的主程式,
    優先處理緊急事件。
  • Docs
  • attachInterrupt(digitalPinToInterrupt(pin), ISR_Func, Mode)
    • ISR_Func
      • IRAM_ATTR Function Attribute: void IRAM_ATTR myISR()
      • 裡面的變數要用 volatile,避免因為編譯器優化導致變數沒有被正確更新
    • Mode: RISING / FALLING / CHANGE / LOW
  • detachInterrupt(digitalPinToInterrupt(pin))

Interrupt Exercise

用個按鈕控制 LED,如果在放個 delay 還能不能正常運作

Interrupt Exercise

volatile bool ledState = false;

void IRAM_ATTR handleButtonPress() {
  ledState = !ledState;
  digitalWrite(LED_BUILTIN, ledState);
}

void setup() {
  Serial.begin(115200);
  
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(22, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(22), handleButtonPress, FALLING);
}

void loop() {
  Serial.println("Hello");
  delay(5000); 
  Serial.println("hi hi");
  delay(1000);
}

Thanks for listening




本投影片採用

BY-NC-SA 許可協議。轉載請註明出處!

Google tag (gtag.js)

dark / light toggle btn

<style> #theme-toggle-btn { position: fixed; top: 20px; right: 20px; z-index: 9999; width: 50px; height: 50px; border-radius: 50%; border: none; background: #444; box-shadow: 0 4px 6px rgba(0,0,0,0.1); cursor: pointer; font-size: 24px; transition: 0.3s; display: flex; align-items: center; justify-content: center; padding: 0; } #theme-toggle-btn:hover { transform: scale(1.1); } #theme-toggle-btn.is-dark { background: #f0f0f0; } #theme-toggle-btn::after { content: '🌙'; } #theme-toggle-btn.is-dark::after { content: '☀️'; margin-top: 0; } </style> <button id="theme-toggle-btn" onclick="document.querySelectorAll('section').forEach(s=>s.classList.toggle('invert'));this.classList.toggle('is-dark')"> </button>