|
Re:Re:abc(2024/10/22 下午 01:24:02 )
https://wokwi.com/projects/412250875969771521
※請生成一完整的程式碼,利用arduino 設計一個模擬紅綠燈控制其周邊接腳定義如下:
南北向路口: 綠燈:GPIO2 黃燈:GPIO3 紅燈:GPIO4 東西向路口: 綠燈:GPIO5 黃燈:GPIO6 紅燈:GPIO7
動作要求: 各路口紅綠燈各停留5秒,綠燈轉紅燈前,先切至黃燈閃爍5次,每次亮暗各0.2S 停留5秒時間請依序倒數計數5 4 3 2 1 0輸出至 serial port 監控視窗中,0不顯示。 Copilot 這聽起來像是一個很有趣的項目。讓我們來編寫Arduino程式碼來實現這個模擬紅綠燈控制系統。
cpp
複製 const int greenNS = 2; const int yellowNS = 3; const int redNS = 4; const int greenEW = 5; const int yellowEW = 6; const int redEW = 7;
void setup() { pinMode(greenNS, OUTPUT); pinMode(yellowNS, OUTPUT); pinMode(redNS, OUTPUT); pinMode(greenEW, OUTPUT); pinMode(yellowEW, OUTPUT); pinMode(redEW, OUTPUT); Serial.begin(9600); }
void loop() { // 南北向路口綠燈,東西向路口紅燈 digitalWrite(greenNS, HIGH); digitalWrite(redEW, HIGH); countDown(5);
// 南北向路口綠燈轉黃燈閃爍,東西向路口紅燈 digitalWrite(greenNS, LOW); for (int i = 0; i < 5; i++) { digitalWrite(yellowNS, HIGH); delay(200); digitalWrite(yellowNS, LOW); delay(200); } digitalWrite(redNS, HIGH);
// 東西向路口綠燈,南北向路口紅燈 digitalWrite(redEW, LOW); digitalWrite(greenEW, HIGH); countDown(5);
// 東西向路口綠燈轉黃燈閃爍,南北向路口紅燈 digitalWrite(greenEW, LOW); for (int i = 0; i < 5; i++) { digitalWrite(yellowEW, HIGH); delay(200); digitalWrite(yellowEW, LOW); delay(200); } digitalWrite(redEW, HIGH); digitalWrite(redNS, LOW); }
void countDown(int seconds) { for (int i = seconds; i > 0; i--) { Serial.println(i); delay(1000); } Serial.println(); } 這段程式碼將控制南北向和東西向的紅綠燈,並按照你的要求執行動作。紅綠燈各停留5秒,綠燈轉紅燈前會先閃爍黃燈5次,每次亮暗各0.2秒。同時,倒數計數將會輸出到Serial監控視窗中。確保你已經將正確的LED燈接到Arduino板上的對應引腳上。祝你實驗成功!
您 ※上述功能正確,我想新增功能將倒數計數數值同步顯示在OLED中以字型大小為3輸出,輸出位置在OLED畫面的右半邊 Copilot 好的,我們需要使用OLED顯示屏來顯示倒數計數。首先,我們將使用SSD1306 OLED顯示器和Adafruit GFX庫來實現這個功能。請確保你已經安裝了Adafruit SSD1306和Adafruit GFX庫。
這是更新的Arduino程式碼,包括OLED顯示功能:
cpp
複製 #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_RESET -1 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
const int greenNS = 2; const int yellowNS = 3; const int redNS = 4; const int greenEW = 5; const int yellowEW = 6; const int redEW = 7;
void setup() { pinMode(greenNS, OUTPUT); pinMode(yellowNS, OUTPUT); pinMode(redNS, OUTPUT); pinMode(greenEW, OUTPUT); pinMode(yellowEW, OUTPUT); pinMode(redEW, OUTPUT); Serial.begin(9600); if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { Serial.println(F("SSD1306 allocation failed")); for(;;); } display.display(); delay(2000); display.clearDisplay(); display.setTextSize(3); // 設定字型大小為3 display.setTextColor(SSD1306_WHITE); }
void loop() { // 南北向路口綠燈,東西向路口紅燈 digitalWrite(greenNS, HIGH); digitalWrite(redEW, HIGH); countDown(5);
// 南北向路口綠燈轉黃燈閃爍,東西向路口紅燈 digitalWrite(greenNS, LOW); for (int i = 0; i < 5; i++) { digitalWrite(yellowNS, HIGH); delay(200); digitalWrite(yellowNS, LOW); delay(200); } digitalWrite(redNS, HIGH);
// 東西向路口綠燈,南北向路口紅燈 digitalWrite(redEW, LOW); digitalWrite(greenEW, HIGH); countDown(5);
// 東西向路口綠燈轉黃燈閃爍,南北向路口紅燈 digitalWrite(greenEW, LOW); for (int i = 0; i < 5; i++) { digitalWrite(yellowEW, HIGH); delay(200); digitalWrite(yellowEW, LOW); delay(200); } digitalWrite(redEW, HIGH); digitalWrite(redNS, LOW); }
void countDown(int seconds) { for (int i = seconds; i > 0; i--) { Serial.println(i); display.clearDisplay(); display.setCursor(64, 0); // 設定顯示位置為OLED畫面的右半邊 display.print(i); display.display(); delay(1000); } display.clearDisplay(); display.display(); Serial.println(); } 在這段更新的程式碼中,我們使用Adafruit SSD1306庫來控制OLED顯示屏,並在倒數計時期間將數值顯示在OLED的右半邊。希望這能滿足你的需求!1
1 github.com
您 可否將字形大小放大到5 且顯示於OLED的畫面正中間的位置 Copilot 當然可以!讓我們來修改程式碼將字型大小放大到5,並將倒數計數顯示在OLED畫面的正中間。
cpp
複製 #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_RESET -1 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
const int greenNS = 2; const int yellowNS = 3; const int redNS = 4; const int greenEW = 5; const int yellowEW = 6; const int redEW = 7;
void setup() { pinMode(greenNS, OUTPUT); pinMode(yellowNS, OUTPUT); pinMode(redNS, OUTPUT); pinMode(greenEW, OUTPUT); pinMode(yellowEW, OUTPUT); pinMode(redEW, OUTPUT);
Serial.begin(9600); if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { Serial.println(F("SSD1306 allocation failed")); for(;;); } display.display(); delay(2000); display.clearDisplay(); display.setTextSize(5); // 設定字型大小為5 display.setTextColor(SSD1306_WHITE); }
void loop() { // 南北向路口綠燈,東西向路口紅燈 digitalWrite(greenNS, HIGH); digitalWrite(redEW, HIGH); countDown(5);
// 南北向路口綠燈轉黃燈閃爍,東西向路口紅燈 digitalWrite(greenNS, LOW); for (int i = 0; i < 5; i++) { digitalWrite(yellowNS, HIGH); delay(200); digitalWrite(yellowNS, LOW); delay(200); } digitalWrite(redNS, HIGH);
// 東西向路口綠燈,南北向路口紅燈 digitalWrite(redEW, LOW); digitalWrite(greenEW, HIGH); countDown(5);
// 東西向路口綠燈轉黃燈閃爍,南北向路口紅燈 digitalWrite(greenEW, LOW); for (int i = 0; i < 5; i++) { digitalWrite(yellowEW, HIGH); delay(200); digitalWrite(yellowEW, LOW); delay(200); } digitalWrite(redEW, HIGH); digitalWrite(redNS, LOW); }
void countDown(int seconds) { for (int i = seconds; i > 0; i--) { Serial.println(i); display.clearDisplay(); int16_t x1, y1; uint16_t w, h; display.getTextBounds(String(i), 0, 0, &x1, &y1, &w, &h); display.setCursor((SCREEN_WIDTH - w) / 2, (SCREEN_HEIGHT - h) / 2); // 將文字顯示在正中間 display.print(i); display.display(); delay(1000); } display.clearDisplay(); display.display(); Serial.println(); } 這段程式碼將字型大小設為5,並將倒數計數顯示於OLED畫面的正中間。希望這能滿足你的需求! 1
1 github.com
您 除此之外,我想在OLED上顯示東西南北路口的狀態,南北向用NS:東西用EW: 在:後面就同步呈現目前LED所亮的燈號。 Copilot 明白,讓我們來更新程式碼以顯示東西南北路口的燈號狀態。這裡是更新後的程式碼:
cpp
複製 #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_RESET -1 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
const int greenNS = 2; const int yellowNS = 3; const int redNS = 4; const int greenEW = 5; const int yellowEW = 6; const int redEW = 7;
String nsStatus = "RED"; String ewStatus = "RED";
void setup() { pinMode(greenNS, OUTPUT); pinMode(yellowNS, OUTPUT); pinMode(redNS, OUTPUT); pinMode(greenEW, OUTPUT); pinMode(yellowEW, OUTPUT); pinMode(redEW, OUTPUT);
Serial.begin(9600); if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { Serial.println(F("SSD1306 allocation failed")); for(;;); } display.display(); delay(2000); display.clearDisplay(); display.setTextSize(5); // 設定字型大小為5 display.setTextColor(SSD1306_WHITE); }
void loop() { // 南北向路口綠燈,東西向路口紅燈 digitalWrite(greenNS, HIGH); digitalWrite(redEW, HIGH); nsStatus = "GREEN"; ewStatus = "RED"; updateDisplay(); countDown(5);
// 南北向路口綠燈轉黃燈閃爍,東西向路口紅燈 digitalWrite(greenNS, LOW); for (int i = 0; i < 5; i++) { digitalWrite(yellowNS, HIGH); delay(200); digitalWrite(yellowNS, LOW); delay(200); } digitalWrite(redNS, HIGH); nsStatus = "RED"; ewStatus = "RED"; updateDisplay();
// 東西向路口綠燈,南北向路口紅燈 digitalWrite(redEW, LOW); digitalWrite(greenEW, HIGH); nsStatus = "RED"; ewStatus = "GREEN"; updateDisplay(); countDown(5);
// 東西向路口綠燈轉黃燈閃爍,南北向路口紅燈 digitalWrite(greenEW, LOW); for (int i = 0; i < 5; i++) { digitalWrite(yellowEW, HIGH); delay(200); digitalWrite(yellowEW, LOW); delay(200); } digitalWrite(redEW, HIGH); nsStatus = "RED"; ewStatus = "RED"; updateDisplay(); digitalWrite(redNS, LOW); }
void countDown(int seconds) { for (int i = seconds; i > 0; i--) { Serial.println(i); display.clearDisplay(); display.setTextSize(5); int16_t x1, y1; uint16_t w, h; display.getTextBounds(String(i), 0, 0, &x1, &y1, &w, &h); display.setCursor((SCREEN_WIDTH - w) / 2, (SCREEN_HEIGHT - h) / 2); display.print(i); display.display(); delay(1000); } display.clearDisplay(); display.display(); Serial.println(); }
void updateDisplay() { display.clearDisplay(); display.setTextSize(1); // 設定字型大小為1 display.setCursor(0, 0); display.print("NS: "); display.println(nsStatus); display.print("EW: "); display.println(ewStatus); display.display(); } 這段程式碼在OLED上顯示東西南北路口的燈號狀態,並將倒數計數顯示於正中間。希望這能滿足你的需求!1
1 github.com
您 倒數計數的字型改回2的大小且置於OLED的右下角,NS: 與 EW: 的狀態也是大小為2的字型 Copilot 沒問題,我們來調整程式碼,使倒數計數的字型大小為2,且顯示在OLED的右下角,同時將NS和EW的狀態字型大小設置為2。
cpp
複製 #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_RESET -1 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
const int greenNS = 2; const int yellowNS = 3; const int redNS = 4; const int greenEW = 5; const int yellowEW = 6; const int redEW = 7;
String nsStatus = "RED"; String ewStatus = "RED";
void setup() { pinMode(greenNS, OUTPUT); pinMode(yellowNS, OUTPUT); pinMode(redNS, OUTPUT); pinMode(greenEW, OUTPUT); pinMode(yellowEW, OUTPUT); pinMode(redEW, OUTPUT);
Serial.begin(9600); if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { Serial.println(F("SSD1306 allocation failed")); for(;;); } display.display(); delay(2000); display.clearDisplay(); display.setTextSize(2); // 設定字型大小為2 display.setTextColor(SSD1306_WHITE); }
void loop() { // 南北向路口綠燈,東西向路口紅燈 digitalWrite(greenNS, HIGH); digitalWrite(redEW, HIGH); nsStatus = "GREEN"; ewStatus = "RED"; updateDisplay(); countDown(5);
// 南北向路口綠燈轉黃燈閃爍,東西向路口紅燈 digitalWrite(greenNS, LOW); for (int i = 0; i < 5; i++) { digitalWrite(yellowNS, HIGH); delay(200); digitalWrite(yellowNS, LOW); delay(200); } digitalWrite(redNS, HIGH); nsStatus = "RED"; ewStatus = "RED"; updateDisplay();
// 東西向路口綠燈,南北向路口紅燈 digitalWrite(redEW, LOW); digitalWrite(greenEW, HIGH); nsStatus = "RED"; ewStatus = "GREEN"; updateDisplay(); countDown(5);
// 東西向路口綠燈轉黃燈閃爍,南北向路口紅燈 digitalWrite(greenEW, LOW); for (int i = 0; i < 5; i++) { digitalWrite(yellowEW, HIGH); delay(200); digitalWrite(yellowEW, LOW); delay(200); } digitalWrite(redEW, HIGH); nsStatus = "RED"; ewStatus = "RED"; updateDisplay(); digitalWrite(redNS, LOW); }
void countDown(int seconds) { for (int i = seconds; i > 0; i--) { Serial.println(i); display.clearDisplay(); display.setTextSize(2); int16_t x1, y1; uint16_t w, h; display.getTextBounds(String(i), 0, 0, &x1, &y1, &w, &h); display.setCursor(SCREEN_WIDTH - w, SCREEN_HEIGHT - h); // 將文字顯示在右下角 display.print(i); display.display(); delay(1000); } display.clearDisplay(); display.display(); Serial.println(); }
void updateDisplay() { display.clearDisplay(); display.setTextSize(2); // 設定字型大小為2 display.setCursor(0, 0); display.print("NS: "); display.println(nsStatus); display.print("EW: "); display.println(ewStatus); display.display(); } 這段程式碼將倒數計數的字型大小設為2,並顯示在OLED的右下角,同時NS和EW的狀態字型大小也是2。希望這樣能滿足你的需求!1
1 github.com
您 目前只有顯示倒數計數,NS和EW的狀態幾乎沒有正常顯示 Copilot 明白了,我們來調整一下程式碼,確保倒數計數和NS、EW狀態都能顯示在OLED上。讓我們來更新程式碼,使其顯示正確的內容:
cpp
複製 #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_RESET -1 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
const int greenNS = 2; const int yellowNS = 3; const int redNS = 4; const int greenEW = 5; const int yellowEW = 6; const int redEW = 7;
String nsStatus = "RED"; String ewStatus = "RED";
void setup() { pinMode(greenNS, OUTPUT); pinMode(yellowNS, OUTPUT); pinMode(redNS, OUTPUT); pinMode(greenEW, OUTPUT); pinMode(yellowEW, OUTPUT); pinMode(redEW, OUTPUT);
Serial.begin(9600); if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { Serial.println(F("SSD1306 allocation failed")); for(;;); } display.display(); delay(2000); display.clearDisplay(); display.setTextSize(2); // 設定字型大小為2 display.setTextColor(SSD1306_WHITE); }
void loop() { // 南北向路口綠燈,東西向路口紅燈 digitalWrite(greenNS, HIGH); digitalWrite(redEW, HIGH); nsStatus = "GREEN"; ewStatus = "RED"; updateDisplay(); countDown(5);
// 南北向路口綠燈轉黃燈閃爍,東西向路口紅燈 digitalWrite(greenNS, LOW); for (int i = 0; i < 5; i++) { digitalWrite(yellowNS, HIGH); delay(200); digitalWrite(yellowNS, LOW); delay(200); } digitalWrite(redNS, HIGH); nsStatus = "RED"; ewStatus = "RED"; updateDisplay();
// 東西向路口綠燈,南北向路口紅燈 digitalWrite(redEW, LOW); digitalWrite(greenEW, HIGH); nsStatus = "RED"; ewStatus = "GREEN"; updateDisplay(); countDown(5);
// 東西向路口綠燈轉黃燈閃爍,南北向路口紅燈 digitalWrite(greenEW, LOW); for (int i = 0; i < 5; i++) { digitalWrite(yellowEW, HIGH); delay(200); digitalWrite(yellowEW, LOW); delay(200); } digitalWrite(redEW, HIGH); nsStatus = "RED"; ewStatus = "RED"; updateDisplay(); digitalWrite(redNS, LOW); }
void countDown(int seconds) { for (int i = seconds; i > 0; i--) { Serial.println(i); display.clearDisplay(); display.setTextSize(2); int16_t x1, y1; uint16_t w, h; display.getTextBounds(String(i), 0, 0, &x1, &y1, &w, &h); display.setCursor(SCREEN_WIDTH - w, SCREEN_HEIGHT - h); // 將文字顯示在右下角 display.print(i); display.setTextSize(2); // 確保NS和EW狀態文字大小為2 display.setCursor(0, 0); // 設定顯示位置 display.print("NS: "); display.println(nsStatus); display.print("EW: "); display.println(ewStatus); display.display(); delay(1000); } display.clearDisplay(); display.display(); Serial.println(); }
void updateDisplay() { display.clearDisplay(); display.setTextSize(2); // 設定字型大小為2 display.setCursor(0, 0); display.print("NS: "); display.println(nsStatus); display.print("EW: "); display.println(ewStatus); display.display(); } 這段程式碼將確保倒數計數的字型大小為2,並顯示在OLED的右下角,同時NS和EW的狀態字型大小也設為2,並顯示在螢幕的左上角。這樣應該能夠同時正確顯示倒數計數和燈號狀態了。希望這能幫助到你!1
1 github.com
您 NS和EW的狀態不用關閉顯示,且加上黃燈亮的狀態 Copilot 明白,我們來更新程式碼以在整個計數過程中持續顯示NS和EW的狀態,並加入黃燈的狀態顯示。
cpp
複製 #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_RESET -1 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
const int greenNS = 2; const int yellowNS = 3; const int redNS = 4; const int greenEW = 5; const int yellowEW = 6; const int redEW = 7;
String nsStatus = "RED"; String ewStatus = "RED";
void setup() { pinMode(greenNS, OUTPUT); pinMode(yellowNS, OUTPUT); pinMode(redNS, OUTPUT); pinMode(greenEW, OUTPUT); pinMode(yellowEW, OUTPUT); pinMode(redEW, OUTPUT);
Serial.begin(9600); if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { Serial.println(F("SSD1306 allocation failed")); for(;;); } display.display(); delay(2000); display.clearDisplay(); display.setTextSize(2); // 設定字型大小為2 display.setTextColor(SSD1306_WHITE); }
void loop() { // 南北向路口綠燈,東西向路口紅燈 digitalWrite(greenNS, HIGH); digitalWrite(redEW, HIGH); nsStatus = "GREEN"; ewStatus = "RED"; countDown(5);
// 南北向路口綠燈轉黃燈閃爍,東西向路口紅燈 digitalWrite(greenNS, LOW); nsStatus = "YELLOW"; updateDisplay(); for (int i = 0; i < 5; i++) { digitalWrite(yellowNS, HIGH); delay(200); digitalWrite(yellowNS, LOW); delay(200); } digitalWrite(redNS, HIGH); nsStatus = "RED"; ewStatus = "RED"; updateDisplay();
// 東西向路口綠燈,南北向路口紅燈 digitalWrite(redEW, LOW); digitalWrite(greenEW, HIGH); nsStatus = "RED"; ewStatus = "GREEN"; countDown(5);
// 東西向路口綠燈轉黃燈閃爍,南北向路口紅燈 digitalWrite(greenEW, LOW); ewStatus = "YELLOW"; updateDisplay(); for (int i = 0; i < 5; i++) { digitalWrite(yellowEW, HIGH); delay(200); digitalWrite(yellowEW, LOW); delay(200); } digitalWrite(redEW, HIGH); nsStatus = "RED"; ewStatus = "RED"; updateDisplay(); digitalWrite(redNS, LOW); }
void countDown(int seconds) { for (int i = seconds; i > 0; i--) { Serial.println(i); display.clearDisplay(); display.setTextSize(2); int16_t x1, y1; uint16_t w, h; display.getTextBounds(String(i), 0, 0, &x1, &y1, &w, &h); display.setCursor(SCREEN_WIDTH - w, SCREEN_HEIGHT - h); // 將文字顯示在右下角 display.print(i); display.setTextSize(2); // 確保NS和EW狀態文字大小為2 display.setCursor(0, 0); // 設定顯示位置 display.print("NS: "); display.println(nsStatus); display.print("EW: "); display.println(ewStatus); display.display(); delay(1000); } Serial.println(); }
void updateDisplay() { display.clearDisplay(); display.setTextSize(2); // 設定字型大小為2 display.setCursor(0, 0); display.print("NS: "); display.println(nsStatus); display.print("EW: "); display.println(ewStatus); display.display(); } 這段程式碼會持續顯示NS和EW的狀態,並在黃燈閃爍時顯示對應的狀態。希望這樣能滿足你的需求!1
1 github.com
您 功能正確 Copilot 太棒了!很高興聽到這樣的好消息。如果還有其他需要或想要新增功能,隨時告訴我。Keep creating and coding! 🚦💡
|
|