Skip to content

Instantly share code, notes, and snippets.

@EvanHsieh0415
Last active December 27, 2024 07:45
Show Gist options
  • Save EvanHsieh0415/e430d1417044ee9d1be5e0e81c833068 to your computer and use it in GitHub Desktop.
Save EvanHsieh0415/e430d1417044ee9d1be5e0e81c833068 to your computer and use it in GitHub Desktop.

Test 1

#include <dht11.h> // 引入 DHT11 感測器的數據
#define DHTPIN 2 // DHT11 DATA 腳位接到 D2
dht11 dht; // 建立 DHT11 物件
void setup() {
  Serial.begin(9600); // 初始化序列埠,波特率為 9600
}
void loop() {
  delay(2000); // 每 2 秒讀取一次數據
  int chk = dht.read(DHTPIN); // 讀取 DHT11 數據
  if (chk == DHTLIB_OK) {
    Serial.print("濕度:");
    Serial.print(dht.humidity);
    Serial.print("%\t");
    Serial.print("溫度:");
    Serial.print(dht.temperature);
    Serial.println("°C");
  } else {
    Serial.println("無法讀取感測器數據!");
  }
}

Test 2

#include <dht11.h>
#define DHTPIN 2 
#define GREEN_LED 3
#define RED_LED 4
dht11 dht;

void setup() {
  Serial.begin(9600); // 初始化序列埠,波特率為 9600
  pinMode(GREEN_LED, OUTPUT); // 設定綠燈為輸出
  pinMode(RED_LED, OUTPUT);   // 設定紅燈為輸出
}

void loop() {
  delay(2000); // 每 2 秒讀取一次數據
  int chk = dht.read(DHTPIN); // 讀取 DHT11 數據
  if (chk == DHTLIB_OK) {
    Serial.print("濕度:");
    Serial.print(dht.humidity);
    Serial.print("%\t");
    Serial.print("溫度:");
    Serial.print(dht.temperature);
    Serial.println("°C");
    if (dht.humidity < 60) {
      digitalWrite(GREEN_LED, HIGH);
      digitalWrite(RED_LED, LOW); 
    } else {
      digitalWrite(GREEN_LED, LOW);   
      digitalWrite(RED_LED, HIGH);    
    }
  } else {
    Serial.println("無法讀取感測器數據!");
    digitalWrite(GREEN_LED, LOW);   
    digitalWrite(RED_LED, LOW);    
  }
}

Test 3

#include <dht11.h>
#define DHT_PIN 2
#define RED_PIN 3
#define GREEN_PIN 4
#define BUTTON_PIN 5
dht11 DHT11;
int buttonState = 0;
float humidity, temperature;

void setup() {
  Serial.begin(9600);
  pinMode(RED_PIN, OUTPUT);
  pinMode(GREEN_PIN, OUTPUT);
  pinMode(BUTTON_PIN, INPUT);
}

void loop() {
  delay(1000);
  int check = DHT11.read(DHT_PIN);
  if (!digitalRead(BUTTON_PIN)) buttonState += 1;
  switch (buttonState % 3) {
    case 0:
      humidity = (float)DHT11.humidity;
      Serial.print("濕度%:");
      Serial.print(humidity, 2);
      if (humidity < 30) {
        Serial.println(" 合適,停止除溼");
        digitalWrite(GREEN_PIN, 1);
        digitalWrite(RED_PIN, 0);
      } else {
        Serial.println(" 太潮濕,啟動除溼");
        digitalWrite(GREEN_PIN, 0);
        digitalWrite(RED_PIN, 1);
      }
      break;
    case 1:
      temperature = (float)DHT11.temperature;
      Serial.print("溫度℃:"); Serial.println(temperature, 2);
      digitalWrite(GREEN_PIN, 0);
      digitalWrite(RED_PIN, 0);
      break;
    default:
      Serial.println("故障中");
      break;
  }
}

Test 4

//七段顯示器 0~9
#define NUM 8
int pins[NUM] = {2, 3, 4, 5, 6, 7, 8, 9};
#define t true
#define f false

// 數字 0 到 9 對應七段顯示器段的開關狀態
boolean data[10][NUM] = {
  {t, t, t, t, t, t, f, f}, // 0
  {f, t, t, f, f, f, f, f}, // 1
  {t, t, f, t, t, f, t, f}, // 2
  {t, t, t, t, f, f, t, f}, // 3
  {f, t, t, f, f, t, t, f}, // 4
  {t, f, t, t, f, t, t, f}, // 5
  {t, f, t, t, t, t, t, f}, // 6
  {t, t, t, f, f, f, f, f}, // 7
  {t, t, t, t, t, t, t, f}, // 8
  {t, t, t, t, f, t, t, f}  // 9
};

void setup() {
  // 設置每個控制腳位為輸出模式
  for(int i = 0; i < NUM; i++) {
    pinMode(pins[i], OUTPUT);
  }
}

// 顯示某一數字 n
void writeNumber(int n) {
  for(int i = 0; i < NUM; i++) {
    digitalWrite(pins[i], data[n][i] == t ? HIGH : LOW);
  }
}

void loop() {
  // 自動循環顯示數字 0 到 9
  for(int n = 0; n <= 9; n++) {
    writeNumber(n);   // 顯示數字 n
    delay(1000);       // 顯示 1 秒鐘
  }
  // 這裡不需要做額外的處理,因為 loop() 本身會不斷重複
}

Test 5

//序列埠輸入
#define NUM 8
int pins[NUM] = {2, 3, 4, 5, 6, 7, 8, 9};
#define t true
#define f false

// 數字 0 到 9 對應七段顯示器段的開關狀態
boolean data[10][NUM] = {
  {t, t, t, t, t, t, f, f}, // 0
  {f, t, t, f, f, f, f, f}, // 1
  {t, t, f, t, t, f, t, f}, // 2
  {t, t, t, t, f, f, t, f}, // 3
  {f, t, t, f, f, t, t, f}, // 4
  {t, f, t, t, f, t, t, f}, // 5
  {t, f, t, t, t, t, t, f}, // 6
  {t, t, t, f, f, f, f, f}, // 7
  {t, t, t, t, t, t, t, f}, // 8
  {t, t, t, t, f, t, t, f}  // 9
};

void setup() {
  // 設置每個控制腳位為輸出模式
  for (int i = 0; i < NUM; i++) {
    pinMode(pins[i], OUTPUT);
  }
  // 開啟序列埠通信,設置波特率為 9600
  Serial.begin(9600);
  while (!Serial) {
    // 等待序列端口準備好
  }
  Serial.println("請輸入一個數字(0-9):");
}

// 顯示某一數字 n
void writeNumber(int n) {
  for (int i = 0; i < NUM; i++) {
    digitalWrite(pins[i], data[n][i] == t ? HIGH : LOW);
  }
}

void loop() {
  // 檢查是否有數據可讀
  if (Serial.available() > 0) {
    // 讀取輸入的字元
    char incomingByte = Serial.read();
    // 忽略回車和換行符
    if (incomingByte == '\n' || incomingByte == '\r') {
      return;
    }
    // 檢查是否是數字
    if (isDigit(incomingByte)) {
      // 將接收到的字符轉換為數字
      int number = incomingByte - '0'; // '0' 的 ASCII 值是 48,減去 48 使其成為數字 0 到 9
      Serial.print("顯示數字: ");
      Serial.println(number);
      writeNumber(number); // 顯示對應的數字
      // 顯示 1 秒後再繼續
      delay(1000); // 延遲 1 秒
    } else {
      // 如果不是數字,顯示錯誤訊息
      Serial.println("無效輸入,請輸入 0 到 9 的數字。");
    }
  }
}

Test 6

//序列埠輸入 0~9 E or F
#define NUM 8
int pins[NUM] = {2, 3, 4, 5, 6, 7, 8, 9};

#define t true
#define f false

// 數字 0 到 9 對應七段顯示器段的開關狀態
boolean data[10][NUM] = {
  {t, t, t, t, t, t, f, f}, // 0
  {f, t, t, f, f, f, f, f}, // 1
  {t, t, f, t, t, f, t, f}, // 2
  {t, t, t, t, f, f, t, f}, // 3
  {f, t, t, f, f, t, t, f}, // 4
  {t, f, t, t, f, t, t, f}, // 5
  {t, f, t, t, t, t, t, f}, // 6
  {t, t, t, f, f, f, f, f}, // 7
  {t, t, t, t, t, t, t, f}, // 8
  {t, t, t, t, f, t, t, f}  // 9
};

// 'e' 或 'E' 對應的開關狀態
boolean eData[NUM] = {t, f, f, t, t, t, t, t}; // {t, f, f, t, t, t, t, t}

// 'f' 或 'F' 對應的開關狀態
boolean fData[NUM] = {t, f, f, f, t, t, t, t}; // {t, f, f, f, t, t, t, t}

// 顯示某一數字 n
void writeNumber(int n) {
  for (int i = 0; i < NUM; i++) {
    digitalWrite(pins[i], data[n][i] == t ? HIGH : LOW);
  }
}

// 顯示字母 'e' 或 'E'
void writeLetterE() {
  for (int i = 0; i < NUM; i++) {
    digitalWrite(pins[i], eData[i] == t ? HIGH : LOW);
  }
}

// 顯示字母 'f' 或 'F'
void writeLetterF() {
  for (int i = 0; i < NUM; i++) {
    digitalWrite(pins[i], fData[i] == t ? HIGH : LOW);
  }
}

void setup() {
  // 設置每個控制腳位為輸出模式
  for (int i = 0; i < NUM; i++) {
    pinMode(pins[i], OUTPUT);
  }

  // 開啟序列埠通信,設置波特率為 9600
  Serial.begin(9600);
  while (!Serial) {
    // 等待序列端口準備好
  }
  Serial.println("請輸入一個數字(0-9)或字母 'e', 'f', 'E', 'F':");
}

void loop() {
  // 檢查是否有數據可讀
  if (Serial.available() > 0) {
    // 讀取輸入的字元
    char incomingByte = Serial.read();
    
    // 忽略回車和換行符
    if (incomingByte == '\n' || incomingByte == '\r') {
      return;
    }
    
    // 檢查是否是數字
    if (isDigit(incomingByte)) {
      // 將接收到的字符轉換為數字
      int number = incomingByte - '0'; // '0' 的 ASCII 值是 48,減去 48 使其成為數字 0 到 9

      Serial.print("顯示數字: ");
      Serial.println(number);
      writeNumber(number); // 顯示對應的數字

      // 顯示 1 秒後再繼續
      delay(1000); // 延遲 1 秒
    } 
    // 檢查是否是字母 'e' 或 'E'
    else if (incomingByte == 'e' || incomingByte == 'E') {
      Serial.print("顯示字母: ");
      Serial.println(incomingByte);  // 顯示輸入的字母
      writeLetterE(); // 顯示字母 'e' 或 'E'

      // 顯示 1 秒後再繼續
      delay(1000); // 延遲 1 秒
    }
    // 檢查是否是字母 'f' 或 'F'
    else if (incomingByte == 'f' || incomingByte == 'F') {
      Serial.print("顯示字母: ");
      Serial.println(incomingByte);  // 顯示輸入的字母
      writeLetterF(); // 顯示字母 'f' 或 'F'

      // 顯示 1 秒後再繼續
      delay(1000); // 延遲 1 秒
    } 
    else {
      // 如果不是數字或 'e'/'E' 或 'f'/'F',顯示錯誤訊息
      Serial.println("無效輸入,請輸入 0 到 9 的數字或字母 'e', 'f' 或 'E', 'F'。");
    }
  }
}

Test 7

//F 1~5 B 5~1
#define NUM 8
int pins[NUM] = {2, 3, 4, 5, 6, 7, 8, 9};

#define t true
#define f false

// 數字 0 到 9 對應七段顯示器段的開關狀態
boolean data[10][NUM] = {
  {t, t, t, t, t, t, f, f}, // 0
  {f, t, t, f, f, f, f, f}, // 1
  {t, t, f, t, t, f, t, f}, // 2
  {t, t, t, t, f, f, t, f}, // 3
  {f, t, t, f, f, t, t, f}, // 4
  {t, f, t, t, f, t, t, f}, // 5
  {t, f, t, t, t, t, t, f}, // 6
  {t, t, t, f, f, f, f, f}, // 7
  {t, t, t, t, t, t, t, f}, // 8
  {t, t, t, t, f, t, t, f}  // 9
};

void setup() {
  // 設置每個控制腳位為輸出模式
  for (int i = 0; i < NUM; i++) {
    pinMode(pins[i], OUTPUT);
  }

  // 開啟序列埠通信,設置波特率為 9600
  Serial.begin(9600);
  while (!Serial) {
    // 等待序列端口準備好
  }
  Serial.println("請輸入一個數字(0-9)或 'F' 顯示 1 到 5 或 'B' 顯示 5 到 1:");
}

// 顯示某一數字 n
void writeNumber(int n) {
  for (int i = 0; i < NUM; i++) {
    digitalWrite(pins[i], data[n][i] == t ? HIGH : LOW);
  }
}

void loop() {
  // 檢查是否有數據可讀
  if (Serial.available() > 0) {
    // 讀取輸入的字元
    char incomingByte = Serial.read();
    
    // 忽略回車和換行符
    if (incomingByte == '\n' || incomingByte == '\r') {
      return;
    }
    
    // 處理數字 0 到 9 的情況
    if (isDigit(incomingByte)) {
      int number = incomingByte - '0'; // '0' 的 ASCII 值是 48,減去 48 使其成為數字 0 到 9
      Serial.print("顯示數字: ");
      Serial.println(number);
      writeNumber(number); // 顯示對應的數字
      delay(1000); // 顯示 1 秒後再繼續
    } 
    // 處理 F 或 f 輸入
    else if (incomingByte == 'F' || incomingByte == 'f') {
      if (incomingByte == 'F') {
        Serial.println("輸入F 顯示1~5");
      } else {
        Serial.println("輸入f 顯示1~5");
      }
      
      // 顯示數字 1 到 5,顯示 1 秒後換下一個數字
      for (int i = 1; i <= 5; i++) {
        writeNumber(i);
        delay(1000); // 顯示 1 秒
      }
    }
    // 處理 B 或 b 輸入
    else if (incomingByte == 'B' || incomingByte == 'b') {
      if (incomingByte == 'B') {
        Serial.println("輸入B 顯示5~1");
      } else {
        Serial.println("輸入b 顯示5~1");
      }
      
      // 顯示數字 5 到 1,顯示 1 秒後換下一個數字
      for (int i = 5; i >= 1; i--) {
        writeNumber(i);
        delay(1000); // 顯示 1 秒
      }
    }
    else {
      // 如果不是有效的輸入,顯示錯誤訊息
      Serial.println("無效輸入,請輸入 0 到 9 的數字或 'F' 或 'B'。");
    }
  }
}

Test 8

//七段顯示器,光敏電阻 0 or 1
#define NUM 8
int pins[NUM] = {2, 3, 4, 5, 6, 7, 8, 9};  // 七段顯示器腳位
#define LDR_PIN A0  // 光敏電阻接在A0腳位

#define t true
#define f false

// 數字 0 到 9 對應七段顯示器段的開關狀態
boolean data[10][NUM] = {
  {t, t, t, t, t, t, f, f}, // 0
  {f, t, t, f, f, f, f, f}, // 1
  {t, t, f, t, t, f, t, f}, // 2
  {t, t, t, t, f, f, t, f}, // 3
  {f, t, t, f, f, t, t, f}, // 4
  {t, f, t, t, f, t, t, f}, // 5
  {t, f, t, t, t, t, t, f}, // 6
  {t, t, t, f, f, f, f, f}, // 7
  {t, t, t, t, t, t, t, f}, // 8
  {t, t, t, t, f, t, t, f}  // 9
};

void setup() {
  // 初始化顯示器腳位
  for (int i = 0; i < NUM; i++) {
    pinMode(pins[i], OUTPUT);
  }
  pinMode(LDR_PIN, INPUT);  // 設置光敏電阻腳位為輸入
}

void loop() {
  int ldrValue = analogRead(LDR_PIN);  // 讀取光敏電阻的值

  // 根據光敏電阻的值判斷顯示 0 或 1
  if (ldrValue < 20) {  // 當光線遮擋,LDR值較低
    displayNumber(0);  // 顯示數字 0
  } else {  // 當光線未遮擋,LDR值較高
    displayNumber(1);  // 顯示數字 1
  }

  delay(500);  // 延遲一段時間,防止顯示過快切換
}

// 顯示數字函數
void displayNumber(int number) {
  for (int i = 0; i < NUM; i++) {
    digitalWrite(pins[i], data[number][i] ? HIGH : LOW);  // 根據數字設置每個段的開關
  }
}

Test 9

//TMUST Major in IT
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

void setup() {
  Serial.begin(9600);
  lcd.begin(16, 2);
  for(int i = 0; i < 3; i++) { // 閃爍三次
    lcd.backlight(); // 開啟背光
    delay(250);
    lcd.noBacklight(); // 關閉背光
    delay(250);
  }
  
  lcd.backlight();  // 輸出初始化文字直接顯示
  lcd.setCursor(4, 0);
  lcd.print("TMUST");
  lcd.setCursor(0, 1);
  lcd.print("Major in IT");
  delay(1000);
}

void loop() {
  if(Serial.available()){
    char x = Serial.read();
    lcd.println(x);
    delay(1000);
  }
}

Test 10

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <dht11.h>

#define DHT_PIN 2

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
dht11 DHT11;

String repeat(String content, int times) {
  String value = "";
  for (int i = 0; i < times; i++) value += content;
  return value;
}

void println(String content, int line = 0) {
  lcd.setCursor(0, line);
  lcd.print(content + repeat(" ", 16 - content.length()));
}

char currentMode = ' '; // 初始為空狀態

void setup() {
  Serial.begin(9600);
  lcd.begin(16, 2);
}

void loop() {
  // 檢查是否有新輸入
  if (Serial.available()) {
    char n = Serial.read();
    n = toupper(n); // Convert to uppercase to handle both cases (T/t, H/h, C/c)

    if (n == 'T' || n == 'H' || n == 'C') {
      currentMode = n; // 更新模式
      lcd.clear();      // 清除 LCD 顯示
    }
  }

  // 根據當前模式顯示溫溼度資料
  DHT11.read(DHT_PIN);

  switch (currentMode) {
    case 'T': // 顯示溫度
      println("Temp: " + (String)(int)DHT11.temperature + (char)0xDF + "C");
      break;
    case 'H': // 顯示濕度
      println("Hum: " + (String)(int)DHT11.humidity + "%");
      break;
    case 'C': // 顯示溫度和濕度
      println("Temp: " + (String)(int)DHT11.temperature + (char)0xDF + "C");
      println("Hum: " + (String)(int)DHT11.humidity + "%", 1);
      break;
  }

  delay(1000); // 每秒更新一次
}

Test 11

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

#define TRIG_PIN 9  // 超音波傳感器的 Trigger 引腳
#define ECHO_PIN 10 // 超音波傳感器的 Echo 引腳

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

String repeat(String content, int times) {
  String value = "";
  for (int i = 0; i < times; i++) value += content;
  return value;
}

void println(String content, int line = 0) {
  lcd.setCursor(0, line);
  lcd.print(content + repeat(" ", 16 - content.length()));
}

void setup() {
  lcd.begin(16, 2);
  
  // 設定 Trigger 引腳為輸出,Echo 引腳為輸入
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
}

long readDistance() {
  // 發送脈衝到 Trigger 引腳開始測量
  digitalWrite(TRIG_PIN, LOW);  // 先確保 Trigger 是低電位
  delayMicroseconds(2);          // 小延遲
  digitalWrite(TRIG_PIN, HIGH); // 發送高電位脈衝
  delayMicroseconds(10);         // 脈衝寬度 10 微秒
  digitalWrite(TRIG_PIN, LOW);  // 停止脈衝

  // 從 Echo 引腳讀取脈衝持續時間
  long duration = pulseIn(ECHO_PIN, HIGH); // 計時脈衝持續時間

  // 計算距離 (聲速是 343 米每秒,轉換為厘米)
  long distance = (duration / 2) / 29.1; // 轉換時間為距離
  return distance;
}

void loop() {
  // 測量距離
  long distance = readDistance();

  // 顯示距離在第一行
  println("D: " + String(distance) + " cm");

  // 如果距離大於 50 公分,顯示 "Safe!"(安全)
  if (distance > 50) {
    println("Safe!", 1);
  } 
  // 如果距離在 20 公分到 50 公分之間,顯示 "Warning!"(警告)
  else if (distance >= 20 && distance <= 50) {
    println("Warning!", 1);
  } 
  // 如果距離小於 20 公分,顯示 "Dangerous!"(危險)
  else {
    println("Dangerous!", 1);
  }

  delay(1000); // 每秒更新一次顯示
}

Test 12

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

#define TRIG_PIN 9  // 超音波傳感器的 Trigger 引腳
#define ECHO_PIN 10 // 超音波傳感器的 Echo 引腳

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

String repeat(String content, int times) {
  String value = "";
  for (int i = 0; i < times; i++) value += content;
  return value;
}

void println(String content, int line = 0) {
  lcd.setCursor(0, line);
  lcd.print(content + repeat(" ", 16 - content.length()));
}

void setup() {
  lcd.begin(16, 2);
  
  // 設定 Trigger 引腳為輸出,Echo 引腳為輸入
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
}

long readDistance() {
  // 發送脈衝到 Trigger 引腳開始測量
  digitalWrite(TRIG_PIN, LOW);  // 先確保 Trigger 是低電位
  delayMicroseconds(2);          // 小延遲
  digitalWrite(TRIG_PIN, HIGH); // 發送高電位脈衝
  delayMicroseconds(10);         // 脈衝寬度 10 微秒
  digitalWrite(TRIG_PIN, LOW);  // 停止脈衝

  // 從 Echo 引腳讀取脈衝持續時間
  long duration = pulseIn(ECHO_PIN, HIGH); // 計時脈衝持續時間

  // 計算距離 (聲速是 343 米每秒,轉換為厘米)
  long distance = (duration / 2) / 29.1; // 轉換時間為距離
  return distance;
}

void loop() {
  // 測量距離
  long distance = readDistance();

  // 顯示距離在第一行
  println("Distance: " + String(distance) + " cm");

  // 如果距離大於 50 公分,顯示 "Safe!"(安全)
  if (distance > 50) {
    println("Safe!", 1);
  } 
  // 如果距離在 20 公分到 50 公分之間,顯示 "Warning!"(警告)
  else if (distance >= 20 && distance <= 50) {
    println("Warning!", 1);
  } 
  // 如果距離小於 20 公分,顯示 "Dangerous!"(危險)
  else {
    println("Dangerous!", 1);
  }

  delay(1000); // 每秒更新一次顯示
}

Test 13

// 定義 LED 和蜂鳴器的腳位
const int ledH = 2;  // LED 1
const int ledR = 3;  // LED 2
const int ledL = 4;  // LED 3
const int ledB = 5;  // LED 4
const int buzzerPin = 6;  // 蜂鳴器腳位

// 記錄 LED 狀態
bool isR = false;
bool isL = false;
bool isH = false;
bool isB = false;
bool isBuzzerOn = true; // 一開始蜂鳴器就開啟

void setup() {
  // 設定腳位為輸出
  pinMode(ledH, OUTPUT);
  pinMode(ledR, OUTPUT);
  pinMode(ledL, OUTPUT);
  pinMode(ledB, OUTPUT);
  pinMode(buzzerPin, OUTPUT);  // 設定蜂鳴器腳位為輸出
  
  // 一開始就讓蜂鳴器發聲(設為 1000Hz 頻率)
  tone(buzzerPin, 1000); // 蜂鳴器發聲

  // 初始化序列埠通信
  Serial.begin(9600);
}

void loop() {
  // 檢查序列埠輸入
  if (Serial.available() > 0) {
    char command = Serial.read();  // 讀取單個字元指令
    
    // 將字元轉換為小寫
    command = tolower(command);

    // 根據輸入的字元設定對應的 LED 狀態
    if (command == 'h') {
      isH = true;
      Serial.println("頭燈開啟");
    } else if (command == 'r') {
      isR = true;
      isL = false;  // r 輸入時,l 不能同時閃爍
      Serial.println("右轉燈");
    } else if (command == 'l') {
      isL = true;
      isR = false;  // l 輸入時,r 不能同時閃爍
      Serial.println("左轉燈");
    } else if (command == 'b') {
      isB = true;
      Serial.println("煞車燈");
    } else if (command == 's') {
      // 當收到 s 指令時,關閉所有 LED 和停止蜂鳴器
      isH = false;
      isR = false;
      isL = false;
      isB = false;
      noTone(buzzerPin); // 停止蜂鳴器
      Serial.println("全部停止");
    }
  }

  // 控制 LED 根據狀態
  // 控制 h LED
  if (isH) {
    digitalWrite(ledH, HIGH); // LED 1 恆亮
  } else {
    digitalWrite(ledH, LOW);
  }
  
  // 控制 b LED
  if (isB) {
    digitalWrite(ledB, HIGH); // LED 4 恆亮
  } else {
    digitalWrite(ledB, LOW);
  }

  // 控制 r LED
  if (isR) {
    digitalWrite(ledR, HIGH); // LED 2 閃爍
    delay(500);  // 閃爍速度
    digitalWrite(ledR, LOW);
    delay(500);
  }

  // 控制 l LED
  if (isL) {
    digitalWrite(ledL, HIGH); // LED 3 閃爍
    delay(500);  // 閃爍速度
    digitalWrite(ledL, LOW);
    delay(500);
  }

  // 控制蜂鳴器(持續發聲 or 停止)
  if (isBuzzerOn) {
    tone(buzzerPin, 1000);  // 蜂鳴器發聲,保持在 1000Hz
  } else {
    noTone(buzzerPin);   // 停止蜂鳴器
  }

  // 如果沒有輸入任何指令,關閉所有 LED
  if (!isH && !isR && !isL && !isB) {
    digitalWrite(ledH, LOW);
    digitalWrite(ledR, LOW);
    digitalWrite(ledL, LOW);
    digitalWrite(ledB, LOW);
  }
}

Test 14

// 定義七段顯示器的每個段
int segA = 2;
int segB = 3;
int segC = 4;
int segD = 5;
int segE = 6;
int segF = 7;
int segG = 8;

// LED引腳
int led1 = 9;
int led2 = 10;

// 光敏電阻引腳
int ldrPin = A0;

// 七段顯示器顯示的數字(基於共陰顯示)
int displayA[] = {HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, LOW}; // a b c d e f
int displayB[] = {LOW, HIGH, HIGH, LOW, LOW, LOW, LOW}; // b c

void setup() {
  // 初始化七段顯示器引腳
  pinMode(segA, OUTPUT);
  pinMode(segB, OUTPUT);
  pinMode(segC, OUTPUT);
  pinMode(segD, OUTPUT);
  pinMode(segE, OUTPUT);
  pinMode(segF, OUTPUT);
  pinMode(segG, OUTPUT);
  
  // 初始化LED引腳
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  
  // 初始關閉LED
  digitalWrite(led1, LOW);
  digitalWrite(led2, LOW);
  
  // 初始化光敏電阻引腳
  pinMode(ldrPin, INPUT);

  // 啟用 Serial 監控,以便調試
  Serial.begin(9600);
}

void loop() {
  // 讀取光敏電阻的值
  int ldrValue = analogRead(ldrPin);
  
  // 打印光敏電阻的值(用於調試)
  Serial.println(ldrValue);

  // 設定一個閾值來判斷是否被遮住(閾值可以根據需要調整)
  if (ldrValue < 23) {  // 假設遮住時 LDR 的值小於 23
    // 顯示 a b c d e f
    displaySegments(displayA);
    
    // 點亮 LED 2,熄滅 LED 1
    digitalWrite(led1, LOW);
    digitalWrite(led2, HIGH);  // 使 LED 2 點亮
  } else {
    // 顯示 b c
    displaySegments(displayB);

    digitalWrite(led1, HIGH);  // 使 LED 1 點亮
    digitalWrite(led2, LOW);   // 使 LED 2 熄火
  }
}

void displaySegments(int segments[]) {
  // 控制每個段顯示相應的狀態
  digitalWrite(segA, segments[0]);
  digitalWrite(segB, segments[1]);
  digitalWrite(segC, segments[2]);
  digitalWrite(segD, segments[3]);
  digitalWrite(segE, segments[4]);
  digitalWrite(segF, segments[5]);
  digitalWrite(segG, segments[6]);
}

Test 15

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // LCD 顯示器配置
const int greenLedPin = 13;   // 綠燈 LED 連接到 13 腳
const int redLedPin = 12;     // 紅燈 LED 連接到 12 腳
const int buzzerPin = 8;      // 蜂鳴器連接到 8 腳
const String correctPassword = "1234"; // 正確的密碼
int errorCount = 0;           // 錯誤次數
unsigned long lastErrorTime = 0; // 記錄錯誤時間
unsigned long lastRedLedBlinkTime = 0; // 記錄紅燈閃爍的時間
bool redLedState = false;     // 紅燈的狀態

void setup() {
  Serial.begin(9600);  // 開啟序列埠通信 
  lcd.begin(16, 2);    // 初始化 LCD 顯示器
  pinMode(greenLedPin, OUTPUT);  // 設定綠燈 LED 腳位為輸出
  pinMode(redLedPin, OUTPUT);    // 設定紅燈 LED 腳位為輸出
  pinMode(buzzerPin, OUTPUT);    // 設定蜂鳴器腳位為輸出

  // 在 LCD 顯示器上顯示訊息
  lcd.clear();
  lcd.print("Input key no.:");
  Serial.println("請輸入密碼");
}

void loop() {
  // 如果序列埠有資料可讀
  if (Serial.available()) {
    String inputPassword = Serial.readStringUntil('\n'); // 讀取序列埠的輸入密碼
    inputPassword.trim();  // 去除可能的空白字符

    // 顯示用戶輸入的密碼數字
    lcd.clear();
    lcd.print("Input key no.");
    lcd.setCursor(0, 1);  // 第二行顯示
    lcd.print(inputPassword);  // 顯示輸入的密碼數字

    delay(2000); // 顯示輸入的密碼數字 2 秒

    if (inputPassword == correctPassword) {
      // 密碼正確,顯示訊息並亮綠燈
      lcd.clear();
      lcd.print("Key no. correct!");
      lcd.setCursor(0, 1); // 移動到第二行
      lcd.print("Open!");
      digitalWrite(greenLedPin, HIGH);  // 開啟綠燈
      digitalWrite(redLedPin, LOW);     // 關閉紅燈
      noTone(buzzerPin); // 停止蜂鳴器聲音
      Serial.println("密碼正確");
      delay(2000);  // 顯示2秒
      lcd.clear();
      lcd.print("Enter password:");
      errorCount = 0;  // 重置錯誤計數器
    } else {
      // 密碼錯誤,顯示訊息並亮紅燈
      lcd.clear();
      lcd.print("Key no. wrong!");
      lcd.setCursor(0, 1); // 移動到第二行
      lcd.print("Close!");
      digitalWrite(redLedPin, HIGH);   // 開啟紅燈
      digitalWrite(greenLedPin, LOW);  // 關閉綠燈
      errorCount++;  // 錯誤次數增加
      lastErrorTime = millis(); // 記錄錯誤時間
      Serial.println("密碼錯誤");
      
      if (errorCount >= 3) {
        Serial.println("錯誤次數超過3次");
        lcd.clear();
        lcd.print("Key no. wrong!");
        lcd.setCursor(0, 1); // 移動到第二行
        lcd.print("Alarm!");
        activateBuzzer(true);  // 啟動蜂鳴器
      }
      delay(2000);  // 顯示2秒
      lcd.clear();
      lcd.print("Enter password:");
    }
  }

  if (errorCount >= 3) {
    blinkRedLed();  // 開始閃爍紅燈
  }
}

// 控制蜂鳴器的開關,使用 tone() 函數
void activateBuzzer(bool state) {
  if (state) {
    tone(buzzerPin, 1000); // 發出 1000 Hz 的音調
    lcd.clear();
    lcd.print("Key no. wrong!");
    lcd.setCursor(0, 1); // 移動到第二行
    lcd.print("Alarm!");
  } else {
    noTone(buzzerPin);  // 停止蜂鳴器聲音
  }
}

// 控制紅燈閃爍
void blinkRedLed() {
  unsigned long currentMillis = millis();

  // 每 0.5 秒閃爍一次紅燈
  if (currentMillis - lastRedLedBlinkTime >= 500) {
    lastRedLedBlinkTime = currentMillis;
    redLedState = !redLedState; // 改變紅燈狀態
    digitalWrite(redLedPin, redLedState ? HIGH : LOW); // 設定紅燈狀態
  }
}

Test 16

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // LCD 顯示器配置
const int greenLedPin = 13;   // 綠燈 LED 連接到 13 腳
const int redLedPin = 12;     // 紅燈 LED 連接到 12 腳
const int lightSensorPin = A0; // 光敏電阻連接到 A0 腳
const String correctPassword = "1234"; // 正確的密碼
int errorCount = 0;           // 錯誤次數
unsigned long lastLightCheckTime = 0; // 記錄上次光敏電阻檢查時間
unsigned long lastErrorTime = 0; // 記錄錯誤時間
unsigned long lastRedLedBlinkTime = 0; // 記錄紅燈閃爍的時間
bool redLedState = false;     // 紅燈的狀態

void setup() {
  Serial.begin(9600);  // 開啟序列埠通信 
  lcd.begin(16, 2);    // 初始化 LCD 顯示器
  pinMode(greenLedPin, OUTPUT);  // 設定綠燈 LED 腳位為輸出
  pinMode(redLedPin, OUTPUT);    // 設定紅燈 LED 腳位為輸出

  // 在 LCD 顯示器上顯示訊息
  lcd.clear();
  lcd.print("Input key no.:");
  Serial.println("請輸入密碼");
}

void loop() {
  unsigned long currentMillis = millis();

  // 每秒判斷一次光敏電阻
  if (currentMillis - lastLightCheckTime >= 1000) { // 每秒檢查一次
    lastLightCheckTime = currentMillis;  // 更新上次檢查時間
    int lightLevel = analogRead(lightSensorPin); // 讀取光敏電阻的值

    // 顯示光敏電阻的值到序列埠
    Serial.print("Light sensor value: ");
    Serial.println(lightLevel);

    // 根據光敏電阻的值來控制 LCD 顯示器
    if (lightLevel > 1015) { // 如果光線較暗(遮住時)
      lcd.display();  // 顯示 LCD
    } else {  // 如果光線充足(未遮住時)
      lcd.noDisplay();  // 關閉 LCD 顯示
    }
  }

  // 如果序列埠有資料可讀
  if (Serial.available()) {
    String inputPassword = Serial.readStringUntil('\n'); // 讀取序列埠的輸入密碼
    inputPassword.trim();  // 去除可能的空白字符

    // 顯示用戶輸入的密碼數字
    lcd.clear();
    lcd.print("Input key no.");
    lcd.setCursor(0, 1);  // 第二行顯示
    lcd.print(inputPassword);  // 顯示輸入的密碼數字

    delay(2000); // 顯示輸入的密碼數字 2 秒

    if (inputPassword == correctPassword) {
      // 密碼正確,顯示訊息並亮綠燈
      lcd.clear();
      lcd.print("Key no. correct!");
      lcd.setCursor(0, 1); // 移動到第二行
      lcd.print("Open!");
      digitalWrite(greenLedPin, HIGH);  // 開啟綠燈
      digitalWrite(redLedPin, LOW);     // 關閉紅燈
      Serial.println("密碼正確");
      delay(2000);  // 顯示2秒
      lcd.clear();
      lcd.print("Enter password:");
      errorCount = 0;  // 重置錯誤計數器
    } else {
      // 密碼錯誤,顯示訊息並亮紅燈
      lcd.clear();
      lcd.print("Key no. wrong!");
      lcd.setCursor(0, 1); // 移動到第二行
      lcd.print("Close!");
      digitalWrite(redLedPin, HIGH);   // 開啟紅燈
      digitalWrite(greenLedPin, LOW);  // 關閉綠燈
      errorCount++;  // 錯誤次數增加
      lastErrorTime = millis(); // 記錄錯誤時間
      Serial.println("密碼錯誤");
      
      if (errorCount >= 3) {
        Serial.println("錯誤次數超過3次");
        lcd.clear();
        lcd.print("Key no. wrong!");
        lcd.setCursor(0, 1); // 移動到第二行
        lcd.print("Alarm!");
      }
      delay(2000);  // 顯示2秒
      lcd.clear();
      lcd.print("Enter password:");
    }
  }

  if (errorCount >= 3) {
    blinkRedLed();  // 開始閃爍紅燈
  }
}

// 控制紅燈閃爍
void blinkRedLed() {
  unsigned long currentMillis = millis();

  // 每 0.5 秒閃爍一次紅燈
  if (currentMillis - lastRedLedBlinkTime >= 500) {
    lastRedLedBlinkTime = currentMillis;
    redLedState = !redLedState; // 改變紅燈狀態
    digitalWrite(redLedPin, redLedState ? HIGH : LOW); // 設定紅燈狀態
  }
}

Test 17

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SPI.h>  // Include the SPI library for MAX7219

// 設定 LCD 顯示器地址,這是 16x2 顯示器常見的 I2C 地址
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // LCD 顯示器配置

// 設定引腳
const int buttonPin = 2;        // 按鈕引腳
const int buzzerPin = 3;        // 蜂鳴器引腳
const int trigPin = 4;          // 超音波 Trig 引腳
const int echoPin = 5;          // 超音波 Echo 引腳

int counter = 0;                // 計數器
bool lastButtonState = LOW;     // 上一次按鈕狀態

// MAX7219 顯示設定
const byte DECODEMODE = 0x9;
const byte INTENSITY = 0xA;
const byte SCANLIMIT = 0xB;
const byte SHUTDOWN = 0xC;
const byte DISPLAYTEST = 0xF;

const uint8_t STOP[8] = {
    0b00111100,
    0b01000010,
    0b10000101,
    0b10001001,
    0b10010001,
    0b10100001,
    0b01000010,
    0b00111100
};

void max7219(byte reg, byte data) {
    digitalWrite(SS, LOW);     // 設置 SS 引腳為低電位,開始 SPI 通信
    SPI.transfer(reg);         // 傳送寄存器地址
    SPI.transfer(data);        // 傳送數據
    digitalWrite(SS, HIGH);    // 設置 SS 引腳為高電位,結束 SPI 通信
}

void displaySTOP() {
    for (int row = 0; row < sizeof(STOP); row++) {
        max7219(row + 1, STOP[row]); // 顯示停止圖案
    }
}

void initMAX7219() {
    pinMode(SS, OUTPUT);         // 設置 SS 引腳為輸出
    digitalWrite(SS, HIGH);      // 默認 SS 引腳為高電位
    
    // 初始化 MAX7219
    max7219(DISPLAYTEST, 0x00);  // 禁用顯示測試
    max7219(SHUTDOWN, 0x01);     // 啟用顯示
    max7219(DECODEMODE, 0x00);   // 禁用 BCD 解碼
    max7219(SCANLIMIT, 0x07);    // 設置顯示範圍為 8 位數
    max7219(INTENSITY, 0x08);    // 設置顯示亮度
}

long getDistance() {
    digitalWrite(trigPin, LOW); 
    delayMicroseconds(2);
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);

    long duration = pulseIn(echoPin, HIGH);  // 讀取回波信號的時間
    long distance = (duration / 2) * 0.0343; // 計算距離(單位:厘米)
    return distance;
}

void setup() {
    pinMode(buttonPin, INPUT_PULLUP);  // 設定按鈕為輸入,開啟內建上拉電阻
    pinMode(buzzerPin, OUTPUT);        // 設定蜂鳴器為輸出
    pinMode(trigPin, OUTPUT);          // 設定 Trig 引腳為輸出
    pinMode(echoPin, INPUT);           // 設定 Echo 引腳為輸入

    Serial.begin(9600);               // 啟用序列監控器(可選)

    lcd.begin(16, 2);  // 初始化 LCD 顯示器
    lcd.backlight();   // 開啟背光
    lcd.clear();       // 清空顯示器
    
    SPI.begin();       // 初始化 SPI
    initMAX7219();     // 初始化 MAX7219 顯示器
    
    // 初始化 MAX7219 不顯示任何圖案
    for (int i = 0; i < 8; i++) {
        max7219(i + 1, 0x00);  // 設置顯示為空
    }
}

void loop() {
    int buttonState = digitalRead(buttonPin);  // 讀取按鈕狀態
    long distance = getDistance();             // 讀取超音波感測器距離

    // 如果距離小於 20 公分,則減少計數器(但不能小於 0)
    if (distance < 20) {
        if (counter > 0) {
            counter--;  // 減少計數器
        }
        delay(200);  // 減少計數器後延遲,避免過快減少
    }

    // 檢查按鈕狀態,計數器 +1
    if (buttonState == LOW && lastButtonState == HIGH) {  // 按鈕按下
        counter++;  // 增加計數器
        delay(200);  // 防止按鈕重複觸發
    }

    lastButtonState = buttonState;  // 更新按鈕狀態

    // 顯示當前計數器的值在 LCD 上
    lcd.clear();  // 每次更新清除顯示
    Serial.print("目前人數");
    Serial.println(counter);
    if (counter < 9) {
        lcd.setCursor(0, 0);    // 設定顯示起始位置
        lcd.print("People: ");
        lcd.print(counter);     // 顯示計數器的值
        lcd.setCursor(0, 1);    // 顯示第二行
        lcd.print("Welcome");
    } else {
        lcd.setCursor(0, 0);
        lcd.print("People: ");
        lcd.print(counter);
        lcd.setCursor(0, 1);
        lcd.print("Not Allow");
        tone(buzzerPin, 1000);  // 播放蜂鳴器聲音
        displaySTOP();          // 顯示 STOP 字符
        Serial.println("管制進入");
        
    }

    delay(100);  // 延遲,避免過度佔用處理器資源
}

Test 18

const int BUTTON_PIN = 2;
const int LED_1_PIN = 4;
const int LED_2_PIN = 6;
const int LED_3_PIN = 8;
int count = 0;

void setup() {
  Serial.begin(9600);
  pinMode(BUTTON_PIN, INPUT);
  pinMode(LED_1_PIN, OUTPUT);
  pinMode(LED_2_PIN, OUTPUT);
  pinMode(LED_3_PIN, OUTPUT);
}

void only(int led) {
  digitalWrite(LED_1_PIN, led == LED_1_PIN);
  digitalWrite(LED_2_PIN, led == LED_2_PIN);
  digitalWrite(LED_3_PIN, led == LED_3_PIN);
}
void all(int value) {
  digitalWrite(LED_1_PIN, value);
  digitalWrite(LED_2_PIN, value);
  digitalWrite(LED_3_PIN, value);
}

void loop() {
  delay(250);
  if (digitalRead(BUTTON_PIN)) count += 1;
  Serial.println(String(digitalRead(BUTTON_PIN)) + "" + String(count));
  if (count > 0) {
    switch (count % 5) {
      case 1:
        only(LED_1_PIN);
        break;
      case 2:
        only(LED_2_PIN);
        break;
      case 3:
        only(LED_3_PIN);
        break;
      case 4:
        all(1);
        break;
      case 0:
        all(0);
        break;
      
    }
  }
}

Test 19

#include <dht11.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// 定義 DHT11 的數據腳位
#define DHTPIN 2

// 定義 LED 腳位
#define GREEN_LED 3 // 綠燈接到 D3
#define RED_LED 4    // 紅燈接到 D4

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

dht11 dht;

String repeat(String content, int times) {
  String value = "";
  for (int i = 0; i < times; i++) value += content;
  return value;
}

void lcdPrint(LiquidCrystal_I2C lcd, String content) {
  String subContent;

  subContent = content.substring(0, 16);
  lcd.setCursor(0, 0);
  lcd.print(subContent + repeat(" ", 16 - subContent.length()));
  if (content.length() > 16) {
    String subContent = content.substring(16, 32);
    lcd.setCursor(0, 1);
    lcd.print(subContent + repeat(" ", 16 - subContent.length()));
  }
  lcd.setCursor(0, 0);

  if (content.length() > 32) {
    delay(1000);
    lcd.clear();
    lcdPrint(lcd, content.substring(32, 64));
  }
}

void lcdPrintln(LiquidCrystal_I2C lcd, String content, int line = 0) {
  lcd.setCursor(0, line);
  lcd.print(content + repeat(" ", 16 - content.length()));
}

void setup() {
  Serial.begin(9600); // 初始化序列埠,波特率為 9600
  pinMode(GREEN_LED, OUTPUT); // 設定綠燈為輸出
  pinMode(RED_LED, OUTPUT);   // 設定紅燈為輸出
  lcd.begin(16, 2);
}

void loop() {
  delay(1000); // 每 2 秒讀取一次數據

  int check = dht.read(DHTPIN); // 讀取 DHT11 數據

  // 檢查讀取是否成功
  if (check == DHTLIB_OK) {
    
    Serial.println("Hum: " + String(dht.humidity) + "%\n" + 
                   "Temp: " + String(dht.temperature) + "");
    lcdPrintln(lcd, "Hum: " + String(dht.humidity) + "%");
    
    // 根據濕度控制 LED
    if (dht.humidity > 40) {
      digitalWrite(GREEN_LED, HIGH); // 打開綠燈
      digitalWrite(RED_LED, LOW);    // 關閉紅燈

      Serial.println("It's wet!");
      lcdPrintln(lcd, "It's wet!", 1);
      
    } else if (dht.humidity < 20) {
      digitalWrite(GREEN_LED, LOW);   // 關閉綠燈
      digitalWrite(RED_LED, HIGH);    // 打開紅燈

      Serial.println("It's dry!");
      lcdPrintln(lcd, "It's dry!", 1);
      
    } else {
      digitalWrite(GREEN_LED, LOW);
      digitalWrite(RED_LED, LOW); 
      lcdPrintln(lcd, "Temp: " + String(dht.temperature) + String((char)0xDF) + "C", 1);
    }
  } else {
    Serial.println("無法讀取感測器數據!");
    digitalWrite(GREEN_LED, LOW);   // 讀取失敗,關閉綠燈
    digitalWrite(RED_LED, LOW);      // 讀取失敗,關閉紅燈
  }
}

參考資料

LCD

VCC 5V
GND 接地
SDA A4
SCL A5

LED 8*8

VCC 5V 電源
GND GND 接地
DIN 11 (可以是任意數位腳) 串行數據輸入
CS(LOAD) 10 使能引腳
CLK(Clock) 13 時鐘信號

蜂鳴器

低音階的音符:do re mi fa so la si do

int sound[8] = {261, 293, 329, 349, 392, 440, 493, 523}

七段顯示器

  • a 接 Arduino 腳位 2
  • b 接 Arduino 腳位 3
  • c 接 Arduino 腳位 4
  • d 接 Arduino 腳位 5
  • e 接 Arduino 腳位 6
  • f 接 Arduino 腳位 7
  • g 接 Arduino 腳位 8
  • dp 接 Arduino 腳位 9

共陰極 (CC) 接 GND

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment