├── .gitignore ├── C02_1_1_timeControlLoop.ino ├── C02_1timeControlLoop.ino ├── C03_1_wdtTest.ino ├── C07_2_DedugMacro.ino ├── C07_DebugMacro.ino ├── C08_noinitTest.ino ├── LICENSE └── readMe.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | 31 | # Debug files 32 | *.dSYM/ 33 | -------------------------------------------------------------------------------- /C02_1_1_timeControlLoop.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Code for moreStableArduinoCode 3 | 4 | Class 2.1.1 Time control Loop 5 | 6 | Note : This version uses Serial plot to demo the task Sequence..... 7 | 8 | author : allen54a0@gmail.com 9 | compiler : arduino IDE 1.8.4 10 | lib dependience : none 11 | 12 | https://github.com/allen54a0/moreStableArduinoCode 13 | */ 14 | 15 | // 定義我們要的控制速度,每秒多少HZ , 下面的範例是每秒跑 10次 主迴圈 ---------------> 16 | #define SYS_HZ 10 17 | #define SYS_HZ_COUNT (1000 / SYS_HZ)-1 //這行不要動 18 | 19 | 20 | //硬體設定定義---------------------------------------------------------------------> 21 | 22 | #define arduinoLED 13 // Arduino LED on board 23 | 24 | //Global 變數定義---------------------------------------------------------------------> 25 | 26 | int ver_10HZ =0; 27 | int ver_1S =0; 28 | int ver_10S =0; 29 | 30 | unsigned long fast_loopTimer; // Time in miliseconds of main control loop 31 | int mainLoop_count=0; 32 | int secondCounter =0; 33 | 34 | 35 | // 控制程序 36 | 37 | 38 | //10HZ 控制程序, 每1秒被呼叫10 次 39 | 40 | void doThings_10Hz(){ 41 | 42 | //Serial.println("10Hz Loop"); 43 | digitalWrite(arduinoLED,!digitalRead(arduinoLED)); // 用LED燈來顯示 44 | 45 | ver_10HZ = ! ver_10HZ ; 46 | 47 | 48 | 49 | } 50 | // 1 Sec 控制程序,每1秒被呼叫1 次 51 | 52 | void doThings_1sec(){ 53 | 54 | //Serial.println("1 Sec Loop"); 55 | 56 | if(secondCounter%2==0) 57 | ver_1S=4; 58 | else 59 | ver_1S=3; 60 | 61 | 62 | } 63 | 64 | // 10 Sec 控制程序,每10秒被呼叫1 次 65 | 66 | void doThings_10sec(){ 67 | 68 | //Serial.println("10 Sec Loop"); 69 | if(secondCounter%20==0) 70 | ver_10S=7; 71 | else 72 | ver_10S=6; 73 | 74 | } 75 | 76 | 77 | void doUpdateStatus(){ 78 | 79 | Serial.print("Status,"); 80 | Serial.print(ver_10HZ); 81 | Serial.print(","); 82 | Serial.print(ver_1S); 83 | Serial.print(","); 84 | Serial.print(ver_10S); 85 | Serial.println(""); 86 | 87 | } 88 | 89 | 90 | // 硬體與變數初始化---------------------------------------------------------------------> 91 | void setup() { 92 | 93 | // put your setup code here, to run once: 94 | 95 | Serial.begin(115200); //用來demo 程式的serial port 96 | pinMode(arduinoLED,OUTPUT); //用來demo 程式的LED燈腳位 97 | Serial.println("C02_1timeControlLoop RUN!"); 98 | 99 | } 100 | 101 | void loop() { 102 | 103 | // put your main code here, to run repeatedly: 104 | 105 | //下面這個迴圈會每秒跑 SYS_HZ 次 , 這個範例碼是跑 SYS_HZ =10 HZ 106 | 107 | if (millis()-fast_loopTimer > SYS_HZ_COUNT) { 108 | 109 | fast_loopTimer = millis(); 110 | mainLoop_count++; 111 | 112 | //// SYS_HZ lOOP 間隔 (1/SYS_HZ) 秒會跑一次, 這個範例是1/10 秒跑一次--------------------------------> 113 | 114 | doThings_10Hz(); 115 | 116 | 117 | 118 | 119 | if(mainLoop_count% SYS_HZ ==0 ){ // 這行不要改動 120 | 121 | secondCounter++; // 每秒向上加 1 122 | 123 | //// 1 秒迴圈 , 每1 秒會跑一次 ----------------------------------------------------------------> 124 | doThings_1sec(); 125 | 126 | 127 | if(secondCounter%10==0){ // %10 就是每10秒跑進來一次 128 | 129 | //// 1 秒迴圈 , 每10 秒會跑一次 ----------------------------------------------------------------> 130 | doThings_10sec(); 131 | } 132 | 133 | 134 | 135 | 136 | } 137 | 138 | 139 | doUpdateStatus(); 140 | 141 | } 142 | 143 | 144 | 145 | } 146 | -------------------------------------------------------------------------------- /C02_1timeControlLoop.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Code for moreStableArduinoCode 3 | 4 | Class 2.1 Time control Loop 5 | 6 | author : allen54a0@gmail.com 7 | compiler : arduino IDE 1.8.4 8 | lib dependience : none 9 | 10 | https://github.com/allen54a0/moreStableArduinoCode 11 | */ 12 | 13 | // 定義我們要的控制速度,每秒多少HZ , 下面的範例是每秒跑 10次 主迴圈 ---------------> 14 | #define SYS_HZ 10 15 | #define SYS_HZ_COUNT (1000 / SYS_HZ)-1 //這行不要動 16 | 17 | 18 | //硬體設定定義---------------------------------------------------------------------> 19 | 20 | #define arduinoLED 13 // Arduino LED on board 21 | 22 | //Global 變數定義---------------------------------------------------------------------> 23 | 24 | int ver_10HZ =0; 25 | int ver_1S =0; 26 | int ver_10S =0; 27 | 28 | unsigned long fast_loopTimer; // Time in miliseconds of main control loop 29 | int mainLoop_count=0; 30 | int secondCounter =0; 31 | 32 | 33 | // 控制程序 34 | 35 | 36 | //10HZ 控制程序, 每1秒被呼叫10 次 37 | 38 | void doThings_10Hz(){ 39 | 40 | //Serial.println("10Hz Loop"); 41 | digitalWrite(arduinoLED,!digitalRead(arduinoLED)); // default to LED off 42 | 43 | } 44 | // 1 Sec 控制程序,每1秒被呼叫1 次 45 | 46 | void doThings_1sec(){ 47 | 48 | Serial.println("1 Sec Loop"); 49 | 50 | } 51 | 52 | // 10 Sec 控制程序,每10秒被呼叫1 次 53 | 54 | void doThings_10sec(){ 55 | 56 | Serial.println("10 Sec Loop"); 57 | } 58 | 59 | 60 | 61 | 62 | // 硬體與變數初始化---------------------------------------------------------------------> 63 | void setup() { 64 | 65 | // put your setup code here, to run once: 66 | 67 | Serial.begin(115200); //用來demo 程式的serial port 68 | pinMode(arduinoLED,OUTPUT); //用來demo 程式的LED燈腳位 69 | Serial.println("C02_1timeControlLoop RUN!"); 70 | 71 | } 72 | 73 | void loop() { 74 | 75 | // put your main code here, to run repeatedly: 76 | 77 | //下面這個迴圈會每秒跑 SYS_HZ 次 , 這個範例碼是跑 SYS_HZ =10 HZ 78 | 79 | if (millis()-fast_loopTimer > SYS_HZ_COUNT) { 80 | 81 | fast_loopTimer = millis(); 82 | mainLoop_count++; 83 | 84 | //// SYS_HZ lOOP 間隔 (1/SYS_HZ) 秒會跑一次, 這個範例是1/10 秒跑一次--------------------------------> 85 | 86 | doThings_10Hz(); 87 | 88 | 89 | 90 | 91 | if(mainLoop_count% SYS_HZ ==0 ){ // 這行不要改動 92 | 93 | secondCounter++; // 每秒向上加 1 94 | 95 | //// 1 秒迴圈 , 每1 秒會跑一次 ----------------------------------------------------------------> 96 | doThings_1sec(); 97 | 98 | 99 | if(secondCounter%10==0){ // %10 就是每10秒跑進來一次 100 | 101 | //// 1 秒迴圈 , 每10 秒會跑一次 ----------------------------------------------------------------> 102 | doThings_10sec(); 103 | } 104 | 105 | 106 | 107 | 108 | } 109 | 110 | 111 | 112 | 113 | } 114 | 115 | 116 | 117 | } 118 | -------------------------------------------------------------------------------- /C03_1_wdtTest.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Code for moreStableArduinoCode 3 | 4 | 5 | Class 3. Watching DOG 6 | Note : NEED UNO BOARD or MEGA Board, or had burnned the optiboot bootloader into your legecy board (mini, nano, duemilanove) 7 | author : allen54a0@gmail.com 8 | compiler : arduino IDE 1.8.4 9 | lib dependience : 10 | 11 | #include 12 | #include 13 | 14 | https://github.com/allen54a0/moreStableArduinoCode 15 | */ 16 | 17 | 18 | 19 | 20 | #include 21 | #include 22 | 23 | 24 | 25 | #define SYS_HZ 20 26 | //DOn;t Touch Variable 27 | #define SYS_HZ_COUNT (1000 / SYS_HZ)-1 28 | 29 | 30 | 31 | #define arduinoLED 13 // Arduino LED on board 32 | 33 | SerialCommand SCmd; // The demo SerialCommand object 34 | 35 | 36 | 37 | unsigned long fast_loopTimer; // Time in miliseconds of main control loop 38 | int mainLoop_count=0; 39 | int secondCounter =0; 40 | 41 | 42 | void doIOCheck(){ 43 | 44 | //Do Somethong Here ..... called SYS_HZ times per Sec.... 45 | Serial.print(":)_"); 46 | 47 | } 48 | 49 | 50 | 51 | 52 | 53 | void WDT_TEST() 54 | { 55 | Serial.println("WDT TEST"); 56 | while(1){ 57 | 58 | Serial.print("XD "); 59 | delay(500); 60 | } 61 | } 62 | 63 | 64 | 65 | 66 | // This gets set as the default handler, and gets called when no other command matches. 67 | void unrecognized() 68 | { 69 | Serial.println("What?"); 70 | } 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | void setup() 80 | { 81 | 82 | 83 | 84 | pinMode(arduinoLED,OUTPUT); // Configure the onboard LED for output 85 | digitalWrite(arduinoLED,LOW); // default to LED off 86 | 87 | 88 | Serial.begin(9600); 89 | 90 | /// Add command Here 91 | // Setup callbacks for SerialCommand commands 92 | 93 | SCmd.addCommand("WDT",WDT_TEST); //WDT TEST, go into while(1) Loop 94 | SCmd.addDefaultHandler(unrecognized); // Handler for command that isn't matched (says "What?") 95 | Serial.println("\n\n\n\n moreStableArduinoCode WDT Example\n\n\n\n\ "); 96 | 97 | 98 | 99 | 100 | //Enable WDT ------------------->>>>>> 101 | 102 | wdt_enable(WDTO_4S); 103 | 104 | } 105 | 106 | 107 | 108 | 109 | 110 | void loop() 111 | { 112 | 113 | //Reset DWT ------------------->>>>>>> 114 | wdt_reset(); 115 | 116 | 117 | 118 | SCmd.readSerial(); // We don't do much, just process serial commands 119 | 120 | 121 | // n HZ system Loop 122 | 123 | if (millis()-fast_loopTimer > SYS_HZ_COUNT) { 124 | 125 | fast_loopTimer = millis(); 126 | mainLoop_count++; 127 | 128 | 129 | doIOCheck(); 130 | 131 | 132 | 133 | //// 1 min Counter , can usd to other Hz..... 134 | 135 | 136 | 137 | if(mainLoop_count% SYS_HZ ==0 ){ 138 | 139 | // DEBUGN("DEBUG ENABLE~~~"); 140 | secondCounter++; 141 | 142 | 143 | if(secondCounter%2==0){ 144 | digitalWrite(arduinoLED,HIGH); // default to LED off 145 | }else{ 146 | digitalWrite(arduinoLED,LOW); // default to LED off 147 | } 148 | 149 | 150 | Serial.println("$"); 151 | 152 | } 153 | 154 | 155 | 156 | 157 | 158 | } 159 | 160 | 161 | 162 | } 163 | 164 | -------------------------------------------------------------------------------- /C07_2_DedugMacro.ino: -------------------------------------------------------------------------------- 1 | /* DedugMacro.ino 2 | * 除錯訊息開關範例 3 | * 使用時機 : 部分除錯訊息不想在正式執行輸出,可以用這個小技巧 4 | * 使用方法 : 設定 " #define DEBUG X " , X ==0 不印出訊息,X==1 印出訊息 5 | * 6 | * 引用來源 : C 教科書衍生 7 | * 8 | * Author : allen54a0 9 | * DATE: 2015 1229 10 | * 11 | */ 12 | 13 | 14 | 15 | // 16 | //#define DEBUG 0 // 藉由定義 0 或 1 來關閉或開啟除錯訊息 17 | //#define DEBUGP(x) if (DEBUG == 1) { x ; } 18 | 19 | 20 | #define DEBUG 0 21 | #if(DEBUG) 22 | #define DEBUGP(x) Serial.println(x) 23 | #else 24 | #define DEBUGP(x) 25 | #endif 26 | 27 | 28 | void setup() { 29 | // put your setup code here, to run once: 30 | 31 | Serial.begin(9600); 32 | 33 | Serial.println("DEBUG_MACRO_TEST_02"); 34 | 35 | } 36 | 37 | void loop() { 38 | // 39 | 40 | 41 | //do something, 一般的程式操作 42 | 43 | 44 | 45 | //Normal Dump ,一般需要輸出的訊息 46 | Serial.println("Status DUMP"); 47 | 48 | //dump debug Message , 僅有除錯時要印出輸出的訊息,正式執行時不輸出 49 | DEBUGP("DEBUG02 DUMP000"); 50 | DEBUGP("DEBUG02 DUMP001"); 51 | DEBUGP("DEBUG02 DUMP002"); 52 | DEBUGP("DEBUG02 DUMP003"); 53 | DEBUGP("DEBUG02 DUMP004"); 54 | 55 | 56 | delay(1000); 57 | 58 | 59 | 60 | } 61 | -------------------------------------------------------------------------------- /C07_DebugMacro.ino: -------------------------------------------------------------------------------- 1 | /* DedugMacro.ino 2 | * 除錯訊息開關範例 3 | * 使用時機 : 部分除錯訊息不想在正式執行輸出,可以用這個小技巧 4 | * 使用方法 : 設定 " #define DEBUG X " , X ==0 不印出訊息,X==1 印出訊息 5 | * 6 | * 引用來源 : C 教科書衍生 7 | * 8 | * Author : allen54a0 9 | * DATE: 2015 1229 10 | * 11 | */ 12 | 13 | 14 | 15 | 16 | #define DEBUG 1 // 藉由定義 0 或 1 來關閉或開啟除錯訊息 17 | #define DEBUGP(x) if (DEBUG == 1) { x ; } 18 | 19 | 20 | void setup() { 21 | // put your setup code here, to run once: 22 | 23 | Serial.begin(9600); 24 | 25 | Serial.println("Program Start"); 26 | 27 | } 28 | 29 | void loop() { 30 | // 31 | 32 | 33 | //do something, 一般的程式操作 34 | 35 | 36 | 37 | //Normal Dump ,一般需要輸出的訊息 38 | Serial.println("Status DUMP"); 39 | 40 | //dump debug Message , 僅有除錯時要印出輸出的訊息,正式執行時不輸出 41 | DEBUGP(Serial.println("DEBUG DUMP")); 42 | 43 | 44 | delay(1000); 45 | 46 | 47 | 48 | } 49 | -------------------------------------------------------------------------------- /C08_noinitTest.ino: -------------------------------------------------------------------------------- 1 | /* C08_noinitTest.ino 2 | * noinit Section 使用範例 3 | * 使用時機 : 系統Reset 或是當機之後,需要取得當機前的一些特定數值 4 | * 使用方法 : 可以用來維護一些隨時間改變,但是不方便放在EEPROM的變數,例如 軟體時間,系統執行狀態等.... 5 | * 加上 __attribute__ ((section(".noinit"))); 來宣告特定變數在硬體初始化時不被清除 6 | 7 | * 引用來源 : This code is from http://forum.arduino.cc/index.php?topic=41088.0 by mem 8 | * 9 | * Author : allen54a0 10 | * DATE: 2016 0107 11 | * 12 | */ 13 | 14 | 15 | 16 | int savedFlag __attribute__ ((section(".noinit"))); 17 | 18 | int i =0; 19 | 20 | void setup() { 21 | Serial.begin(9600); 22 | Serial.print("Old: "); 23 | Serial.println(savedFlag,DEC); // note this prints the decimal value of the integer 24 | 25 | i++; 26 | Serial.print("Local Variable: "); 27 | Serial.println(i,DEC); // note this prints the decimal value of the integer 28 | 29 | savedFlag = savedFlag+i; 30 | Serial.print("New: "); 31 | Serial.println(savedFlag,DEC); 32 | } 33 | 34 | void loop() { 35 | } 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | CC0 1.0 Universal 2 | 3 | Statement of Purpose 4 | 5 | The laws of most jurisdictions throughout the world automatically confer 6 | exclusive Copyright and Related Rights (defined below) upon the creator and 7 | subsequent owner(s) (each and all, an "owner") of an original work of 8 | authorship and/or a database (each, a "Work"). 9 | 10 | Certain owners wish to permanently relinquish those rights to a Work for the 11 | purpose of contributing to a commons of creative, cultural and scientific 12 | works ("Commons") that the public can reliably and without fear of later 13 | claims of infringement build upon, modify, incorporate in other works, reuse 14 | and redistribute as freely as possible in any form whatsoever and for any 15 | purposes, including without limitation commercial purposes. These owners may 16 | contribute to the Commons to promote the ideal of a free culture and the 17 | further production of creative, cultural and scientific works, or to gain 18 | reputation or greater distribution for their Work in part through the use and 19 | efforts of others. 20 | 21 | For these and/or other purposes and motivations, and without any expectation 22 | of additional consideration or compensation, the person associating CC0 with a 23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright 24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work 25 | and publicly distribute the Work under its terms, with knowledge of his or her 26 | Copyright and Related Rights in the Work and the meaning and intended legal 27 | effect of CC0 on those rights. 28 | 29 | 1. Copyright and Related Rights. A Work made available under CC0 may be 30 | protected by copyright and related or neighboring rights ("Copyright and 31 | Related Rights"). Copyright and Related Rights include, but are not limited 32 | to, the following: 33 | 34 | i. the right to reproduce, adapt, distribute, perform, display, communicate, 35 | and translate a Work; 36 | 37 | ii. moral rights retained by the original author(s) and/or performer(s); 38 | 39 | iii. publicity and privacy rights pertaining to a person's image or likeness 40 | depicted in a Work; 41 | 42 | iv. rights protecting against unfair competition in regards to a Work, 43 | subject to the limitations in paragraph 4(a), below; 44 | 45 | v. rights protecting the extraction, dissemination, use and reuse of data in 46 | a Work; 47 | 48 | vi. database rights (such as those arising under Directive 96/9/EC of the 49 | European Parliament and of the Council of 11 March 1996 on the legal 50 | protection of databases, and under any national implementation thereof, 51 | including any amended or successor version of such directive); and 52 | 53 | vii. other similar, equivalent or corresponding rights throughout the world 54 | based on applicable law or treaty, and any national implementations thereof. 55 | 56 | 2. Waiver. To the greatest extent permitted by, but not in contravention of, 57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and 58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright 59 | and Related Rights and associated claims and causes of action, whether now 60 | known or unknown (including existing as well as future claims and causes of 61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum 62 | duration provided by applicable law or treaty (including future time 63 | extensions), (iii) in any current or future medium and for any number of 64 | copies, and (iv) for any purpose whatsoever, including without limitation 65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes 66 | the Waiver for the benefit of each member of the public at large and to the 67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver 68 | shall not be subject to revocation, rescission, cancellation, termination, or 69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work 70 | by the public as contemplated by Affirmer's express Statement of Purpose. 71 | 72 | 3. Public License Fallback. Should any part of the Waiver for any reason be 73 | judged legally invalid or ineffective under applicable law, then the Waiver 74 | shall be preserved to the maximum extent permitted taking into account 75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver 76 | is so judged Affirmer hereby grants to each affected person a royalty-free, 77 | non transferable, non sublicensable, non exclusive, irrevocable and 78 | unconditional license to exercise Affirmer's Copyright and Related Rights in 79 | the Work (i) in all territories worldwide, (ii) for the maximum duration 80 | provided by applicable law or treaty (including future time extensions), (iii) 81 | in any current or future medium and for any number of copies, and (iv) for any 82 | purpose whatsoever, including without limitation commercial, advertising or 83 | promotional purposes (the "License"). The License shall be deemed effective as 84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the 85 | License for any reason be judged legally invalid or ineffective under 86 | applicable law, such partial invalidity or ineffectiveness shall not 87 | invalidate the remainder of the License, and in such case Affirmer hereby 88 | affirms that he or she will not (i) exercise any of his or her remaining 89 | Copyright and Related Rights in the Work or (ii) assert any associated claims 90 | and causes of action with respect to the Work, in either case contrary to 91 | Affirmer's express Statement of Purpose. 92 | 93 | 4. Limitations and Disclaimers. 94 | 95 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 96 | surrendered, licensed or otherwise affected by this document. 97 | 98 | b. Affirmer offers the Work as-is and makes no representations or warranties 99 | of any kind concerning the Work, express, implied, statutory or otherwise, 100 | including without limitation warranties of title, merchantability, fitness 101 | for a particular purpose, non infringement, or the absence of latent or 102 | other defects, accuracy, or the present or absence of errors, whether or not 103 | discoverable, all to the greatest extent permissible under applicable law. 104 | 105 | c. Affirmer disclaims responsibility for clearing rights of other persons 106 | that may apply to the Work or any use thereof, including without limitation 107 | any person's Copyright and Related Rights in the Work. Further, Affirmer 108 | disclaims responsibility for obtaining any necessary consents, permissions 109 | or other rights required for any use of the Work. 110 | 111 | d. Affirmer understands and acknowledges that Creative Commons is not a 112 | party to this document and has no duty or obligation with respect to this 113 | CC0 or use of the Work. 114 | 115 | For more information, please see 116 | 117 | 118 | -------------------------------------------------------------------------------- /readMe.md: -------------------------------------------------------------------------------- 1 | 這個文件主要是提供Arduino 使用者一個簡單易用的 Arduino運用程式架構概念。 2 | 3 | 本文件主要是給Arduino 初中階使用者參考,歡迎大家一起提供實際的開發問題與經驗。 4 | 5 | 只要參考這些準則與技巧進行程式撰寫,可以協助Arduino 使用者寫出可以執行24-365(每天跑24小時,一年365天)都不中斷服務的超級穩定程式。 6 | 7 | 大家可以根據這個流程圖來選擇需要使用的技巧。 8 | 9 | 比較詳細的說明請參考wiki 10 | https://github.com/allen54a0/moreStableArduinoCode/wiki 11 | --------------------------------------------------------------------------------