2026年2月21日 星期六

Git 2.53.0 安裝

Git 安裝過程跟很久以前有些微不同,紀錄一下安裝過程。

環境:
Windows 11、Git 2.53.0


安裝步驟:

  1. 到官網 http://git-scm.com 下載最新版 Git,我下載的是 Git-2.53.0-64-bit.exe
  2. 執行安裝檔,安裝畫面按「Next」到下一步驟

  3. 選擇安裝到那個資料夾,按「Next」。

  4. 早期安裝的時候沒有 Git LFS 和 Scalar,這兩個我都照預設勾選,進行下一步。
    Git LFShttps://git-lfs.com/
    Git Large File Storage,一個對大型檔案進行版本控制的開源 Git 擴展。將大檔案(圖片、影片...)上傳至大檔案儲存服務,而與大檔案對應的指標檔案與其他程式碼檔案推送到 Git 倉庫中,以讓 Git 倉庫空間佔用減小。
    Scalarhttps://git-scm.tw/docs/scalar
    管理大型 Git 倉庫的工具。


  5. 是否在開始選單建立資料夾,按「Next」。

  6. 預設使用什麼文字編輯器,依自己喜好選擇,這邊我用預設的 Vim


  7. 設定執行 git init 時,建立的儲存庫分支名稱。早期安裝時沒這設定,名稱是 master,不解為什麼這要設定,查了一下,原來是跟種族歧視有關(master/slave),以前還真沒想到這些用語背後隱含的文化意義。。
    避免無心造成的紛爭,建議設定個中性的名稱。
    目前 GitHub 是使用 main,所以我也設定為 main。


  8. 設定執行 Git 指令的方式,以前我習慣不動到原本系統環境變數 PATH 的設定(Git Bash only)。
    但這次看到安裝畫面建議選第二項,優點是可讓其他要使用 Git 的軟體,在環境變數 PATH 裡找到 Git 使用。所以我選預設的第二項。


  9. 使用 SSH 時,ssh.exe 指令使用 Git 自帶捆綁的 OpenSSH ,還是外部的 OpenSSH。
    我安裝過 Windows 選用功能裡的 OpenSSH (設定 --> 系統 --> 選用功能),路徑 C:\Windows\System32\OpenSSH,所以我選擇使用外部的 OpenSSH。

    相關:開始使用 Windows 版 OpenSSH 伺服器 | Microsoft Learn


  10. 使用 HTTPS 時,使用 OpenSSL library 還是 Windows 原生的安全通道 library。
    Windows 原生的安全通道 library,優點是可使用公司內部發的 CA 證書。
    我選擇 Windows 原生的安全通道 library。
    相關:在高度網路管制的企業內部如何設定 Git 連接 Azure Repos 上的儲存庫 | The Will Will Web

  11. 換行轉換處理,在 Windows 安裝選第一項,checkout LF 轉成 CRLF,commit CRLF 轉成 LF。
    這務必大家處理原則都一致,避免發生因換行轉換原則不同,誤判每行都有修改。

  12. Git Bash 使用哪種終端機操作,MinTTY 或 Windows內建終端機。
    這裡選 MinTTY,比Windows內建終端機好用。

  13. 選擇 git pull 指令的行為,早期的安裝過程也無此選項。
    我通常都是先 git fetch,再看怎麼做,所以直接保留安裝程式預設的第一項。
    第一種:git pull = git pull --no-rebase = git fetch + git merge
    第二種:git pull = git pull --rebase = git fetch + git rebase
    第三種:git pull = git pull --ff-only ,如果本機分支與遠端分支出現分歧,則會失敗。

  14. 選擇是否使用 Git Credential Manager(GCM、Git 認證管理員) 。
    一個為 Git 提供無縫的多因素 HTTP(S) 身份驗證工具,優點不用每次連到 HTTP(S) 遠端儲存庫都要輸入密碼。
    當 git push 到遠端儲存庫時,系統會自動開啟一個 GCM 窗口,引導完成登入。然後 GCM  儲存認證(儲存在 Windows  認證管理員),之後在同一儲存庫中的後續 Git 命令將重複使用 現有的認證(credentials or tokens、憑證或令牌),直到這些認證失效。

    安裝畫面上的兩個連結:Cross-platform Git Credential Managerhere

  15. 勾選 Enable file system caching:將資料快取到記憶體,供特定操作使用,此設定可顯著改善效能。

  16. 安裝完成



  17. 以上選擇安裝完後,Git 系統的設定值如下
    $ git config --list --system
    diff.astextplain.textconv=astextplain
    filter.lfs.clean=git-lfs clean -- %f
    filter.lfs.smudge=git-lfs smudge -- %f
    filter.lfs.process=git-lfs filter-process
    filter.lfs.required=true
    http.sslbackend=schannel
    core.autocrlf=true
    core.fscache=true
    core.symlinks=false
    pull.rebase=false
    credential.helper=manager
    credential.https://dev.azure.com.usehttppath=true
    init.defaultbranch=main



參考:


2026年2月15日 星期日

解決電腦設備符合 Win11 要求,卻仍顯示不符合執行 Win11 最低系統需求

問題:

主機板 BIOS 已開啟 TPM2.0、UEFI、安全開機。

執行 「tpm.msc」 ,查看目前的 TPM 資訊:


執行「msinfo32」  查看目前的 UEFI、安全開機 資訊:



以上皆已符合 Windows 11 需求,但在 Win10 的 Windows Update 裡,仍然顯示「您的電腦目前不符合執行Windows 11 的最低系統需求」,按檢查更新無法升級到 Windows 11:


當下我懷疑 Win10 在 Windows Update 裡顯示的訊息可能是快取,而不是最新的狀態。
所以去下載安裝了「電腦健康情況檢查(PC Health Check)」,
但執行後出乎意料,居然顯示「若要查看此電腦是否可以執行Windows 11,請檢查系統需求,或詢問製造您電腦的公司。」,甚至「查看結果」的按鈕都不能按。
加上「電腦健康情況檢查(PC Health Check)」執行的飛快,完全沒有檢查的感覺,讓我更覺得不符合 Win11 需求的判斷是快取。
這個畫面當時我沒有截圖,後面兩個圖是事後從網路找的。
後圖來源:https://learn.microsoft.com/zh-tw/answers/questions/4293493/question-4293493


後圖來源:https://learn.microsoft.com/zh-tw/answers/questions/4253480/windows-11?forum=windows-all&referrer=answers





解決方式:

手動讓系統立即評估檢查
後來在 reddit 看到有網友提供讓系統立即檢查的方法,手動執行工作排程器裡的 Microsoft Compatibility Appraiser。

Task Sceduler (工作排程器)-> Microsoft -> Windows -> Application Experience -> Microsoft Compatibility Appraiser

(Win10 和 Win11 有些微差異)
Win10:Microsoft Compatibility Appraiser
Win11:Microsoft Compatibility Appraiser Exp

我操作時間點,大約在傍晚,後面的圖則是在下午7點多擷取的,可發現上次執行是早上4點多,下次執行要等到隔天早上。
(註:事後我在微軟官網有找到系統大約24小時評估檢查一次。)



在 Microsoft Compatibility Appraiser 排程上,按「右鍵」-->「執行」


之後可發現 Microsoft Compatibility Appraiser 排程,處於執行中的狀態。
微軟官方是說等排程跑完,狀態變回「就緒」。
reddit 的網友是說等 10~15 分。

我是打開工作管理員,看到「Microsoft Compatibility Telemetry」占用很多 CPU,等「Microsoft Compatibility Telemetry」降下來後,就去Windows Update 看到變成符合升級 Win 11,按了檢查更新,就出現可下載 Win11 升級,
不用等 Microsoft Compatibility Appraiser 排程跑完,狀態變回「就緒」,因為不知道要等多久,也不知道是不是實際已跑完,只是狀態沒變回「就緒」。










參考:



2026年2月8日 星期日

ESP32 NODEMCU-32S 發送遙控器紅外線訊號

目的:

將之前從電風扇紅外線遙控器讀取的訊號:
ESP32 NODEMCU-32S 讀取遙控器紅外線訊號
在 Arduino IDE 的 Serial Monitor 用鍵盤輸入1~7,讓紅外線發射器發送遙控器上 7 個按鈕的訊號,控制電風扇。

環境:

Win10、Arduino IDE 2.3.7、ESP32 NODEMCU-32S、紅外線發射器(電壓:1.4V~1.6V,電流:20mA)、電阻(90 歐姆)


[關於紅外線接收]

紅外線發射器是一種 LED,發出的光是紅外線。
我看到有兩種紅外線發射器,一種是長短兩隻腳的紅外線 LED,一種是做成做成插上就可使用的電路板模組。
我想自己接電組,所以使用兩隻腳的紅外線 LED。
遙控器發出的紅外線,常用波長有 850nm、940nm 兩種,我不確定原本遙控器是哪種,所以都買來測試。
我買時看到有外觀有 3mm、5mm 兩種大小,也都買來測試。

先講測試結果

  • 850nm、940nm,兩種都可以正常發送紅外線,遙控電風扇。
    個人感覺 940nm 在我的電風扇似乎稍微好一點。
  • 3mm、5mm 兩種大小,兩種都可以正常發送紅外線,遙控電風扇。
    比較大顆的 5mm 感覺有效角度大些,比較不用對準電風扇。




引腳線路接法:

  • GPIO27 (ESP32)  ---------- 電阻(90歐姆) ---------- 正極(+)  (紅外線 LED 長腳)
  • GND (ESP32)  ----------   負極(-) (紅外線 LED 短腳)


安裝 IRremote library:

使用 IRremote 這個 library 處理紅外線訊號,
先到「Tools」->「Manage Libraries...」確認已安裝 IRremote 。


紅外線訊號:

之前讀取的紅外線訊號如後,可知是用 NEC 通訊協議。
用 IrSender.sendNEC(<aAddress>,  <aCommand>, <numberOfRepeats>) 發射訊號。

電源開關
14:32:44.974 -> EF1FEFE
14:32:44.974 -> Protocol=NEC Address=0xFEFE Command=0xF1 Raw-Data=0xEF1FEFE 32 bits LSB first Gap=3276750us Duration=75150us
14:32:45.041 -> Send with: IrSender.sendNEC(0xFEFE, 0xF1, <numberOfRepeats>);

減風量
14:23:42.992 -> FB04FEFE
14:23:42.992 -> Protocol=NEC Address=0xFEFE Command=0x4 Raw-Data=0xFB04FEFE 32 bits LSB first Gap=3276750us Duration=75100us
14:23:43.100 -> Send with: IrSender.sendNEC(0xFEFE, 0x4, <numberOfRepeats>);

加風量
14:25:02.445 -> F906FEFE
14:25:02.445 -> Protocol=NEC Address=0xFEFE Command=0x6 Raw-Data=0xF906FEFE 32 bits LSB first Gap=3276750us Duration=75150us
14:25:02.576 -> Send with: IrSender.sendNEC(0xFEFE, 0x6, <numberOfRepeats>);

指示燈開關
14:25:50.912 -> CF3FEFE
14:25:50.912 -> Protocol=NEC Address=0xFEFE Command=0xF3 Raw-Data=0xCF3FEFE 32 bits LSB first Gap=3276750us Duration=75150us
14:25:50.997 -> Send with: IrSender.sendNEC(0xFEFE, 0xF3, <numberOfRepeats>);

轉頭開關
14:27:12.477 -> DF2FEFE
14:27:12.477 -> Protocol=NEC Address=0xFEFE Command=0xF2 Raw-Data=0xDF2FEFE 32 bits LSB first Gap=3276750us Duration=75150us
14:27:12.584 -> Send with: IrSender.sendNEC(0xFEFE, 0xF2, <numberOfRepeats>);

關機定時
14:28:15.624 -> AF5FEFE
14:28:15.624 -> Protocol=NEC Address=0xFEFE Command=0xF5 Raw-Data=0xAF5FEFE 32 bits LSB first Gap=3276750us Duration=75100us
14:28:15.701 -> Send with: IrSender.sendNEC(0xFEFE, 0xF5, <numberOfRepeats>);

開機定時
14:29:05.835 -> 9F6FEFE
14:29:05.835 -> Protocol=NEC Address=0xFEFE Command=0xF6 Raw-Data=0x9F6FEFE 32 bits LSB first Gap=3276750us Duration=75150us
14:29:05.913 -> Send with: IrSender.sendNEC(0xFEFE, 0xF6, <numberOfRepeats>);


程式碼:

後面是 IRremote 4.x 版本的寫法,若版本不同,可到官網 https://github.com/Arduino-IRremote/Arduino-IRremote 查對應的寫法。
若要關閉發送紅外訊號時,開發板內建LED燈閃爍的效果,可在 #include <IRremote.hpp> 之前 #define NO_LED_SEND_FEEDBACK_CODE 或 #define NO_LED_FEEDBACK_CODE
//設定發送訊號時, LED_BUILTIN 這顆 LED 不閃爍
//#define NO_LED_SEND_FEEDBACK_CODE
//#define NO_LED_FEEDBACK_CODE
#include <IRremote.hpp>  // include the library

// 發送紅外線的 GPIO 引腳
const int IR_SEND_PIN = 27;

//要發送的紅外線訊號
int sCmdArrCnt = 7;
uint8_t sCmdArr[7] = {
  0xF1,  //1.電源開關
  0xF2,  //2.轉頭開關
  0xF3,  //3.指示燈開關
  0x4,   //4.減風量
  0xF5,  //5.關機定時
  0xF6,  //6.開機定時
  0x6    //7.加風量
};
String sCmdStrArr[7] = {
  "電源開關",
  "轉頭開關",
  "指示燈開關",
  "減風量",
  "關機定時",
  "開機定時",
  "加風量"
};


void setup() {
  Serial.begin(115200);

  pinMode(LED_BUILTIN, OUTPUT);

  //version 4.5: LED feedback is always enabled for sending.
  //It can only be disabled by using #define NO_LED_SEND_FEEDBACK_CODE or #define NO_LED_FEEDBACK_CODE.
  IrSender.begin(IR_SEND_PIN);
}

/*
 * Set up the data to be sent.
 * For most protocols, the data is build up with a constant 8 (or 16 byte) address
 * and a variable 8 bit command.
 * There are exceptions like Sony and Denon, which have 5 bit address.
 */
uint16_t sAddress = 0xFEFE;
uint8_t sCommand = 0xF1;
int_fast8_t sRepeats = 0;

void loop() {

  if (Serial.available()) {

    String readString = Serial.readStringUntil('\n');  // Read until newline
    Serial.print("[readString]:");
    Serial.println(readString);

    //轉成整數
    //若用 Serial.parseInt() 讀取整數,讀到換行,會轉成0,導致多執行一次
    int readInt = atoi(readString.c_str());
    Serial.print("[readInt]:");
    Serial.println(readInt);
    if (readInt >= 1 && readInt <= sCmdArrCnt) {
      //7個功能,分別輸入1~7代表,轉成 array index
      int idx = readInt - 1;
      //印出16進位紅外線指令
      Serial.print("0x");
      Serial.println(sCmdArr[idx], HEX);
      Serial.println(sCmdStrArr[idx]);  //文字說明
      IrSender.sendNEC(sAddress, sCmdArr[idx], sRepeats);
    }
    Serial.println("===================");
  }
}
結果



參考:





2026年2月4日 星期三

ESP32 NODEMCU-32S 讀取遙控器紅外線訊號

目的: 

電風扇遙控器的開關按鍵,越來越不靈敏,趁還未完全壞掉前,將遙控器紅外線訊號複製起來保存。


環境:

Win10、Arduino IDE 2.3.7、ESP32 NODEMCU-32S、1838 紅外線接收模組、NWT 威技電風扇(WPF-14P7)遙控器


[關於紅外線接收]
一般有三種:
  • 單純的紅外線接收,是一種光電二極體(photodiode、PD),可將接收到的光,轉換成電。
    雖然長得很像 LED,但 LED 是發光二極體(light-emitting diode),作用是將電轉換成光。
    兩者引腳雖然都用長短區分正負,但內部的PN接面剛好相反,所以從內部PN接面來看,
    發光二極體工作時,是施加順向偏壓。
    光電二極體工作時,是施加逆向偏壓。
    這形式的光電二極體,最直接的應用,是感測紅外線強弱變化,來偵測物體。

  • 一般紅外線遙控器,使用的載波頻率(Carrier Frequency、可想成背載電磁波進行傳送)是 38KHz,所以下面這種三支引腳的封裝,是將原本兩支腳的光電二極體,加上濾波取得載波頻率為 38KHz 的訊號,對訊號解調(demodulation)後,再轉成以 HIGH 或 LOW 訊號輸出。
    三支引腳分別是接正極(+)、接地(-)、輸出訊號(S)。

  • 最後一種,是做成插上就可使用的電路板模組,我使用的是這種,我用的模組上面除了有三支引腳的紅外線接收器,還接好了電阻,以及一個 LED,紅外線接收器收到訊號時,LED 會閃爍。



引腳線路接法:

  • 3.3V (ESP32)  ----------  正極(+)  (1838 IR module)
  • GND (ESP32)  ----------   負極(-) (1838 IR module)
  • GPIO33 (ESP32)  ----------  訊號(S)  (1838 IR module)


安裝 IRremote library:
  • 這邊使用 IRremote 這個 library 處理紅外線訊號
    「Tools」->「Manage Libraries...」


  • 找到 IRremote 進行安裝
    1. 安裝好的 library 會在「File」->「Preferences...」->「sketchbook location」設定路徑裡的 libraries 資料夾。
    2. sketchbook location 預設路徑
      C:\Users\%UserName%\Documents\Arduino\
    3. 安裝好 library 後,如果在設定裡改了 sketchbook location 路徑,Arduino IDE 會認為沒安裝,若之後要在「Manage Libraries...」裡移除已安裝的 library,也是 sketchbook location 設定是原本安裝的路徑下才能辨別。



程式碼:

後面是 IRremote 4.x 版本的寫法,若版本不同,可到官網 https://github.com/Arduino-IRremote/Arduino-IRremote 查對應的寫法。
#include <IRremote.h>
// 連接紅外線接收模組訊號引腳(S引腳)的 GPIO
const int IR_RECEIVE_PIN = 33;

void setup() {

  //LED_BUILTIN 是開發板內建的 LED,GPIO 2
  pinMode(LED_BUILTIN, OUTPUT);

  Serial.begin(115200);
  IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);  // Start the receiver

  delay(2000);
  Serial.println("IR Receiver Ready. Point your remote at the sensor and press buttons");
}

void loop() {
  // 檢查是否收到紅外線訊號
  if (IrReceiver.decode()) {
    Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX);  // Print "old" raw data
    IrReceiver.printIRResultShort(&Serial);                        // Print complete received data in one line
    IrReceiver.printIRSendUsage(&Serial);                          // Print the statement required to send this data
    IrReceiver.resume();                                           // Enable receiving of the next value
  }
}


遙控器須對準紅外線接收器,如果沒對準,可能每次都出現不一樣的結果。
若不確定遙控器有無送出訊號,可透過相機(手機)鏡頭,看遙控器發送端,透過鏡頭可看到紅外線。

最終輸出的結果如下:

電源開關
14:32:44.974 -> EF1FEFE
14:32:44.974 -> Protocol=NEC Address=0xFEFE Command=0xF1 Raw-Data=0xEF1FEFE 32 bits LSB first Gap=3276750us Duration=75150us
14:32:45.041 -> Send with: IrSender.sendNEC(0xFEFE, 0xF1, <numberOfRepeats>);

減風量
14:23:42.992 -> FB04FEFE
14:23:42.992 -> Protocol=NEC Address=0xFEFE Command=0x4 Raw-Data=0xFB04FEFE 32 bits LSB first Gap=3276750us Duration=75100us
14:23:43.100 -> Send with: IrSender.sendNEC(0xFEFE, 0x4, <numberOfRepeats>);

加風量
14:25:02.445 -> F906FEFE
14:25:02.445 -> Protocol=NEC Address=0xFEFE Command=0x6 Raw-Data=0xF906FEFE 32 bits LSB first Gap=3276750us Duration=75150us
14:25:02.576 -> Send with: IrSender.sendNEC(0xFEFE, 0x6, <numberOfRepeats>);

指示燈開關
14:25:50.912 -> CF3FEFE
14:25:50.912 -> Protocol=NEC Address=0xFEFE Command=0xF3 Raw-Data=0xCF3FEFE 32 bits LSB first Gap=3276750us Duration=75150us
14:25:50.997 -> Send with: IrSender.sendNEC(0xFEFE, 0xF3, <numberOfRepeats>);

轉頭開關
14:27:12.477 -> DF2FEFE
14:27:12.477 -> Protocol=NEC Address=0xFEFE Command=0xF2 Raw-Data=0xDF2FEFE 32 bits LSB first Gap=3276750us Duration=75150us
14:27:12.584 -> Send with: IrSender.sendNEC(0xFEFE, 0xF2, <numberOfRepeats>);

關機定時
14:28:15.624 -> AF5FEFE
14:28:15.624 -> Protocol=NEC Address=0xFEFE Command=0xF5 Raw-Data=0xAF5FEFE 32 bits LSB first Gap=3276750us Duration=75100us
14:28:15.701 -> Send with: IrSender.sendNEC(0xFEFE, 0xF5, <numberOfRepeats>);

開機定時
14:29:05.835 -> 9F6FEFE
14:29:05.835 -> Protocol=NEC Address=0xFEFE Command=0xF6 Raw-Data=0x9F6FEFE 32 bits LSB first Gap=3276750us Duration=75150us
14:29:05.913 -> Send with: IrSender.sendNEC(0xFEFE, 0xF6, <numberOfRepeats>);





參考:


2026年1月25日 星期日

讀取 Arduino IDE 序列埠監控窗輸入,ESP32 使用程式碼 reset (software reset)

Demo 影片:




效果:

在 Arduino IDE 序列埠監控窗(Serial Monitor)輸入字串,ESP32 開發板上的程式讀取字串,當輸入字串為 RST,則執行 Reset,重啟開發板。

  • 使用 Serial.readStringUntil() 讀取字串,並設定讀取到換行字元(\n)時停止,所以序列埠監控窗(Serial Monitor)須設定送出訊息時,加上 New Line。
    等待 serial data,預設 Timeout 為 1000ms (1秒),所以若送出訊息時,選擇 No Line Ending,過了1秒 Timeout,仍會結束讀取,繼續執行後面程式。
  • Serial Monitor 和程式的 baud rate 需相同,這邊設為 115200
  • 使用 ESP.restart() 進行 Reset
    • software reset of the chip (對晶片進行軟體重設)
    • execution of the program stops (程式執行停止)
    • both CPUs are reset (兩個 CPU 都將被重設)
    • the application is loaded by the bootloader and starts execution again (應用程式由啟動引導程式載入並重新開始執行)
  • 使用 esp_reset_reason() 取得最近一次 Reset  的原因
  • 執行結果


程式碼:

void setup() {

  Serial.begin(115200);  //設定 baud rate

  // 獲取最近一次重置的原因
  esp_reset_reason_t reason = esp_reset_reason();

  Serial.println("========================================");
  Serial.print("系統啟動... 重置原因代碼: ");
  Serial.println(reason);

  switch (reason) {
    case ESP_RST_UNKNOWN:
      Serial.println("原因: Reset reason can not be determined. (無法確定重置原因)");
      break;
    case ESP_RST_POWERON:
      Serial.println("原因: Reset due to power-on event. (因開機事件而重設)");
      break;
    case ESP_RST_EXT:
      Serial.println("原因: Reset by external pin. (透過外部引腳,不適用於 ESP32)");
      break;
    case ESP_RST_SW:
      Serial.println("原因: Software reset via esp_restart. (軟體重置:透過調用 esp_restart 觸發)");
      break;
    case ESP_RST_PANIC:
      Serial.println("原因: Software reset due to exception/panic. (異常重置:系統崩潰或程式碼運行錯誤)");
      break;
    case ESP_RST_INT_WDT:
      Serial.println("原因: Reset due to interrupt watchdog. (中斷看門狗重置:中斷服務例程 ISR 受到長時間阻斷,即 IWDT 逾時)。IWDT:Independent Watchdog Timer");
      break;
    case ESP_RST_TASK_WDT:
      Serial.println("原因: Reset due to task watchdog. (任務看門狗重置:某個 FreeRTOS 任務未及時餵狗)");
      break;
    case ESP_RST_WDT:
      Serial.println("原因: Reset due to other watchdogs. (其他看門狗重置:包括 RTC 看門狗等硬體計時器)");
      break;
    case ESP_RST_DEEPSLEEP:
      Serial.println("原因: Reset after exiting deep sleep mode. (深睡喚醒重置:系統從深度睡眠模式中恢復)");
      break;
    case ESP_RST_BROWNOUT:
      Serial.println("原因: Brownout reset (software or hardware). (欠壓重置:供電電壓不穩定導致)");
      break;
    case ESP_RST_SDIO:
      Serial.println("原因: Reset over SDIO. (SDIO 重置:透過 SDIO 接口發送的復位指令)");
      break;
    case ESP_RST_USB:
      Serial.println("原因: Reset by USB peripheral. (USB 重置:由 USB 設備接口觸發的重置)");
      break;
    case ESP_RST_JTAG:
      Serial.println("原因: Reset by JTAG. (JTAG 重置:調試器通過 JTAG 觸發)");
      break;
    case ESP_RST_EFUSE:
      Serial.println("原因: Reset due to efuse error. (eFuse 錯誤重置:檢測到硬件 eFuse 數據損壞)");
      break;
    case ESP_RST_PWR_GLITCH:
      Serial.println("原因: Reset due to power glitch detected. (電源毛刺重置:檢測到極短時間的電壓異常)");
      break;
    case ESP_RST_CPU_LOCKUP:
      Serial.println("原因: Reset due to CPU lock up (double exception). (CPU 死鎖重置:發生了嚴重的雙重異常)");
      break;
    default:
      Serial.println("原因: Undefined reset reason. (未定義的重置原因)");
      break;
  }
  Serial.println("========================================");
}

void loop() {
  //讀取 Serial Monitor 輸入
  if (Serial.available()) {

    String readString = Serial.readStringUntil('\n');  // Read until newline
    readString.toUpperCase();
    Serial.println("[readString]:" + readString);

    if (readString == "RST") {
      Serial.println("[ESP.restart]");
      ESP.restart();  //software reset
    }
  }
}




參考: