讀取串列埠輸入的資料、自定義函式

讀取串列埠輸入資料:

void setup() {
  Serial.begin(9600);    //啟用串列埠監看視窗
  Serial.println("Please enter:");  //提示輸入
}

void loop() {
  if (Serial.available()) //若串列埠有輸入資料,則執行下列程式區塊
  {
    //-----------------------------------------------------------------------------------------
    String input = Serial.readStringUntil('\n');    //讀取一行的輸入資料,直到換行符號為止(按下enter鍵)
    input.trim();                     //去除輸入字串前後的空白字元
    Serial.println(input);            //印出輸入字串
    //-----------------------------------------------------------------------------------------
    Serial.println("Please enter:");  //提示輸入
  }
}

可將串列埠輸入文字進行條件判斷,再賦予相對應的動作:

void setup() {
  Serial.begin(9600);    //啟用串列埠監看視窗
  Serial.println("Enter operation (add, subtract, multiply, divide):");  //提示輸入運算符號
}

void loop() {
  if (Serial.available()) //若串列埠有輸入資料,則執行下列程式區塊
  {
    //-----------------------------------------------------------------------------------------
    String input = Serial.readStringUntil('\n');    //讀取一行的輸入資料,直到換行符號為止(按下enter鍵)
    input.trim();             //去除輸入字串前後的空白字元
    Serial.println(input);    //印出輸入字串
    //-----------------------------------------------------------------------------------------
    if (input == "add" || input == "subtract" || input == "multiply" || input == "divide")
    {
      // 若輸入字串有效(add, subtract, multiply, divide)
      // 根據輸入的字串,執行相對應的函式
      if (input == "add")
      {
        Serial.println("加法運算");
      }
      else if (input == "subtract")
      {
        Serial.println("減法運算");
      }
      else if (input == "multiply")
      {
        Serial.println("乘法運算");
      }
      else if (input == "divide")
      {
        Serial.println("除法運算");
      }
      //-----------------------------------------------------------------------------------------
    }
    else
    {
      //若輸入字串無效(其他)
      Serial.println("Unknown operation. Use 'add', 'subtract', 'multiply' or 'divide'.");
    }
    //-----------------------------------------------------------------------------------------
  Serial.println("Enter operation (add, subtract, multiply, divide):");  //提示輸入運算符號 
  }
}

讀取串列埠輸入「整數」資料的函式:(如果要返回「浮點數」,資料型態 int 要改成 float ,文字轉換數值 .toInt 要改成 .toFloat )

// 讀取一個整數
int readNumber()
{
  while (!Serial.available());  // 等待串列埠輸入
  //-----------------------------------------------------------------------------------------
  String input = Serial.readStringUntil('\n');  //讀取一行的輸入資料,直到換行符號為止(按下enter鍵)
  input.trim();                 //去除輸入字串前後的空白字元
  Serial.println(input);        //印出輸入字串
  //-----------------------------------------------------------------------------------------
  return input.toInt();         //轉換為整數
}

例:利用while (!Serial.available());,可等待每一筆輸入完成後,再進行下一步:

void setup() {
  Serial.begin(9600);    //啟用串列埠監看視窗
}

void loop() {
  Serial.println("Enter first number:");  // 提示輸入第一個數字
  int num1 = readNumber();
  
  Serial.println("Enter second number:"); // 提示輸入第二個數字
  int num2 = readNumber();

  Serial.print("You entered:");
  Serial.print(num1);
  Serial.print(", ");
  Serial.println(num2);
}

自定義函式:

// 加法
int add(int a, int b)
{
  return a + b;
}

// 減法
int subtract(int a, int b)
{
  return a - b;
}

// 乘法
int multiply(int a, int b)
{
  return a * b;
}

// 除法
float divide(float a, float b)
{
  if (b != 0.0)
  {
    return a / b;
  } 
  else 
  {
    Serial.println("Error: Division by zero!");
    return NAN;  // 返回 NaN (Not a Number) 來表示錯誤
  }
}

串列埠雙層輸入範例:
第1層:輸入運算子(加、減、乘、除)
第2層:輸入運算元(數值)

void setup() {
  Serial.begin(9600);    //啟用串列埠監看視窗
  Serial.println("Enter operation (add, subtract, multiply, divide):");  //提示輸入運算符號
}

void loop() {
  if (Serial.available()) //若串列埠有輸入資料,則執行下列程式區塊
  {
    //-----------------------------------------------------------------------------------------
    String input = Serial.readStringUntil('\n');    //讀取一行的輸入資料,直到換行符號為止(按下enter鍵)
    input.trim();             //去除輸入字串前後的空白字元
    Serial.println(input);    //印出輸入字串
    //-----------------------------------------------------------------------------------------
    if (input == "add" || input == "subtract" || input == "multiply" || input == "divide")
    {
      //若輸入字串有效(add, subtract, multiply, divide)

      //-----------------------------------------------------------------------------------------
      // 提示輸入第一個數字
      Serial.println("Enter first number:");
      int num1 = readNumber();

      // 提示輸入第二個數字
      Serial.println("Enter second number:");
      int num2 = readNumber();

      // 根據輸入的字串,執行相對應的函式
      if (input == "add")
      {
        int result = add(num1, num2);
        Serial.print(num1);
        Serial.print(" + ");
        Serial.print(num2);
        Serial.print(" = ");
        Serial.println(result);
      }
      else if (input == "subtract")
      {
        int result = subtract(num1, num2);
        Serial.print(num1);
        Serial.print(" - ");
        Serial.print(num2);
        Serial.print(" = ");
        Serial.println(result);
      }
      else if (input == "multiply")
      {
        int result = multiply(num1, num2);
        Serial.print(num1);
        Serial.print(" * ");
        Serial.print(num2);
        Serial.print(" = ");
        Serial.println(result);
      }
      else if (input == "divide")
      {
        float result = divide(num1, num2);
        Serial.print(num1);
        Serial.print(" / ");
        Serial.print(num2);
        Serial.print(" = ");
        Serial.println(result);
      }
      //-----------------------------------------------------------------------------------------
    }
    else
    {
      //若輸入字串無效(其他)
      Serial.println("Unknown operation. Use 'add', 'subtract', 'multiply' or 'divide'.");
    }
    //-----------------------------------------------------------------------------------------
  Serial.println("Enter operation (add, subtract, multiply, divide):");  //提示輸入運算符號 
  }
}

作業練習1:解電晶體輸出方程式 VCC = IC ( RC + RE ) + VCE

  1. 請輸入VCC (參考值10V)
  2. 請輸入RC (參考值2.2kΩ)
  3. 請輸入RE (參考值1kΩ)
  4. 請輸入VCE (參考值5V)
  5. 計算出IC (代入上述參考值,可得約1.5625mA)

(本練習無須使用到串列埠雙層輸入判斷,使用單層即可)

作業練習2:雙層選單(主選單採數字1,2,3,0、子選單採字母a,b,0)

  • 攝氏溫度= 5/9 * (華氏溫度-32) 
  • 華氏溫度= 9/5 * (攝氏溫度)+32
  • BMI指數 = 體重(公斤) / 身高(公尺)的平方,參考指標如下:
    • BMI < 18.5 (過輕)
    • 18.5 < BMI < 24 (正常)
    • 24 < BMI < 27 (過重)
    • BMI > 27 (肥胖)
《主選單》
1. 溫度轉換 (°C ↔ °F)
2. BMI 計算

主選單輸入 1
子選單:溫度轉換
a. 攝氏轉華氏 (°C → °F)
b. 華氏轉攝氏 (°F → °C)
0. 返回主選單

子選單輸入 a
請輸入攝氏溫度 (°C):90.00
90.00 °C = 194.00 °F

子選單輸入 b
請輸入華氏溫度 (°F):180.00
180.00 °F = 82.22 °C

子選單輸入 0
回到主選單

主選單輸入 2
子選單:BMI 計算
a. 開始計算 BMI
0. 返回主選單

子選單輸入 a
請輸入身高 (cm):180.00
請輸入體重 (kg):50.00
您的 BMI = 15.4
→ 過輕

子選單輸入 a
請輸入身高 (cm):180.00
請輸入體重 (kg):75.00
您的 BMI = 23.1
→ 正常

請輸入身高 (cm):180.00
請輸入體重 (kg):80.00
您的 BMI = 24.7
→ 過重

子選單輸入 a
請輸入身高 (cm):180.00
請輸入體重 (kg):90.00
您的 BMI = 27.8
→ 肥胖

子選單輸入 0
回到主選單
int menuState = 0;      // 選單位置:(0)主選單, (1)溫度轉換, (2)BMI計算

void setup() {
  Serial.begin(9600);   // 啟用串列埠監看視窗
  mainMenu();           // 顯示主選單
}

void loop() {
  if (Serial.available()) //若串列埠有輸入資料,則執行下列程式區塊
  {
    String input = readText();    // 讀取輸入文字

    //-----------------------------------------------------------------------------------------
    if (menuState == 0)   // 主選單
    {
      if (input == "1")       // 子選單1:溫度轉換
      {
        menuState = 1;
        subMenu1();           // 顯示子選單1
      }
      else if (input == "2")  // 子選單2:BMI計算
      {
        menuState = 2;
        subMenu2();           // 顯示子選單2
      }
      else                    // 以上皆非
      {
        Serial.println("輸入字串無效,請輸入'1', '2' 或 '0'.");
      }
    }
    //-----------------------------------------------------------------------------------------
    else if (menuState == 1)   // 子選單1:溫度轉換
    {
      if (input == "a")
      {
        Serial.println("--------------------");
        Serial.println("攝氏轉華氏 (°C → °F)");
        Serial.println("請自行完成");
        Serial.println("--------------------");
        subMenu1();     // 顯示子選單1
      }
      else if (input == "b")
      {
        Serial.println("--------------------");
        Serial.println("華氏轉攝氏 (°F → °C)");
        Serial.println("請自行完成");
        Serial.println("--------------------");
        subMenu1();     // 顯示子選單1
      }
      else if (input == "0")
      {
        menuState = 0;  // 返回主選單
        mainMenu();     // 顯示主選單
      }
      else        //若輸入字串無效
      {
        Serial.println("輸入字串無效,請輸入'a', 'b' 或 '0'.");
      }
    }
    //-----------------------------------------------------------------------------------------
    else if (menuState == 2)   // 子選單2:BMI計算
    {
      Serial.println("請自行完成");
      menuState = 0;  // 返回主選單
      mainMenu();     // 顯示主選單
    }
    //-----------------------------------------------------------------------------------------
  }
}

void mainMenu()   // 顯示主選單
{
  Serial.println("");
  Serial.println("《主選單》");
  Serial.println("1. 溫度轉換 (°C ↔ °F)");
  Serial.println("2. BMI 計算");
}

void subMenu1()   // 顯示子選單1
{
  Serial.println("");
  Serial.println("子選單:溫度轉換");
  Serial.println("a. 攝氏轉華氏 (°C → °F)");
  Serial.println("b. 華氏轉攝氏 (°F → °C)");
  Serial.println("0. 返回主選單");
}

void subMenu2()    // 顯示子選單2
{
  Serial.println("");
  Serial.println("子選單:BMI 計算");
  Serial.println("a. 開始計算 BMI");
  Serial.println("0. 返回主選單");
}

String readText()   // 讀取輸入文字
{
  //-----------------------------------------------------------------------------------------
  String input = Serial.readStringUntil('\n');  // 讀取一行的輸入資料,直到換行符號為止(按下enter鍵)
  input.trim();                                 // 去除輸入字串前後的空白字元
  Serial.println(input);                        // 印出輸入字串
  //-----------------------------------------------------------------------------------------
  return input;                                 // 回傳文字
}

float readNumber()  // 讀取輸入數字
{
  while (!Serial.available());  // 等待串列埠輸入
  //-----------------------------------------------------------------------------------------
  String input = Serial.readStringUntil('\n');  // 讀取一行的輸入資料,直到換行符號為止(按下enter鍵)
  input.trim();                                 // 去除輸入字串前後的空白字元
  Serial.println(input);                        // 印出輸入字串
  //-----------------------------------------------------------------------------------------
  return input.toFloat();                       // 轉換為浮點數,回傳數值
}