Arduino 的OO寫作方式

範例程式
https://github.com/MarcoYang21/stepMotor/tree/master

//stepMotor.ino
// 此版本是用Arduino Uno R4 WiFi撰寫
// 用物件的寫法來控制步進馬達
// 這個範例只是轉動33度,不間斷往反運動。
#include "StepMotor.h"  // 引入自定義的步進馬達控制頭文件

int rotateTime = 100;    // 旋轉運動時間,單位毫秒
float targetAngle = 33;  // 目標旋轉角度

const int PUL = 11;  // 步進腳位
const int DIR = 12;  // 正反轉控制腳位
const int EN = 13;   // 致能腳位

StepMotor myMotor(DIR, EN, PUL);  // 創建名為 myMotor 的 StepMotor 物件並初始化引腳

void setup() {
  // 執行初始化
  pinMode(PUL, OUTPUT);     // 設定步進腳位為輸出模式
  pinMode(DIR, OUTPUT);     // 設定正反轉控制腳位為輸出模式
  pinMode(EN, OUTPUT);      // 設定致能腳位為輸出模式
  myMotor.enable();         // 最初啟用電機
  Serial.begin(115200);     // 開啟串列通信
  Serial.println("Ready");  // 顯示訊息,表示程式已就緒
}

void loop() {
  myMotor.run();  // 啟動步進馬達運動

  if (myMotor.isFinished()) {
    // 旋轉後到設定位置後,才執行的程式碼
    delay(200);                               // 延遲 200 毫秒
    myMotor.reverseRotation();                // 反轉旋轉方向
    myMotor.rotate(targetAngle, rotateTime);  // 以指定角度和時間旋轉
  }
  // 其它需要一直被執行的工作
}
\\stepMotor.h
#ifndef StepMotor_h
#define StepMotor_h

#include <Arduino.h>  // 引入 Arduino 標準庫

class StepMotor {
public:
  StepMotor(int dirPin, int enaPin, int stpPin);  // 類別建構函數,用於初始化步進馬達的引腳

  void setDirection(int dir);                              // 設定步進馬達的運動方向
  void enable();                                           // 啟用步進馬達
  void disable();                                          // 停用步進馬達
  void rotate(float degrees, unsigned long rotationTime);  // 控制步進馬達旋轉到指定角度和時間
  void reverseRotation();                                  // 反轉步進馬達的運動方向
  bool isFinished();                                       // 檢查步進馬達是否已完成運動
  void run();                                              // 開始步進馬達的運動

private:
  int directionPin;       // 步進馬達的方向控制引腳
  int enablePin;          // 步進馬達的啟用/停用控制引腳
  int stepPin;            // 步進馬達的步進引腳
  int stepsPerRev;        // 一個完整旋轉(360度)所需的步數
  int targetSteps;        // 目標步數
  int currentStep;        // 目前的步數
  int stepDelay;          // 步進間的時間延遲
  int lastStepTime;       // 最後一次輸出步進脈衝的時間
  int rotationDirection;  // 1 表示正向旋轉,-1 表示反向旋轉
  bool pulseDirection;    // 控制步進脈衝方向
  bool isRunning;         // 步進馬達是否正在運行
};

#endif
//stepMotor.cpp
#include "StepMotor.h"

#include <Arduino.h>
StepMotor::StepMotor(int dirPin, int enaPin, int stpPin) {
  directionPin = dirPin;  // 設定方向控制腳的引腳
  enablePin = enaPin;     // 設定啟用/停用控制腳的引腳
  stepPin = stpPin;       // 設定步進腳的引腳
  isRunning = false;      // 初始化為非運行狀態
  rotationDirection = 1;  // 初始為正向旋轉
  stepsPerRev = 1600;     // 一個完整旋轉(360度)所需的步數,看微步器的設定隨之改變
  pulseDirection = true;  // 起始脈衝方向為真(正向)

  pinMode(directionPin, OUTPUT);  // 設定方向控制腳為輸出模式
  pinMode(enablePin, OUTPUT);     // 設定啟用/停用控制腳為輸出模式
  pinMode(stepPin, OUTPUT);       // 設定步進腳為輸出模式
}

void StepMotor::setDirection(int dir) {
  digitalWrite(directionPin, dir);             // 設定方向控制腳的電位高低
  rotationDirection = (dir == HIGH) ? 1 : -1;  // 根據電位高低設定旋轉方向
}

void StepMotor::enable() {
  digitalWrite(enablePin, LOW);  // 啟用馬達
}

void StepMotor::disable() {
  digitalWrite(enablePin, HIGH);  // 停用馬達
}

void StepMotor::rotate(float degrees, unsigned long rotationTime) {
  targetSteps = int((degrees / 360.0) * stepsPerRev);                  // 計算所需的步數
  stepDelay = static_cast<double>(rotationTime) / targetSteps * 1000;  // 計算每步之間的時間延遲
  currentStep = 0;                                                     // 初始化當前步數
  isRunning = true;                                                    // 設定為運行狀態
  enable();                                                            // 啟用馬達
}

void StepMotor::reverseRotation() {
  rotationDirection = -rotationDirection;                             // 反轉旋轉方向
  digitalWrite(directionPin, (rotationDirection == 1) ? HIGH : LOW);  // 根據反轉方向設定方向控制腳
}

bool StepMotor::isFinished() {
  return !isRunning;  // 檢查是否完成運行
}

void StepMotor::run() {
  if (isRunning) {
    unsigned long currentTime = micros();  // 取得當前時間(微秒)
    if (currentStep > targetSteps) {
      isRunning = false;  // 如果已完成所有步數,則設定為非運行狀態
    } else {
      if (currentTime - lastStepTime >= stepDelay) {
        digitalWrite(enablePin, LOW);           // 啟用馬達
        digitalWrite(stepPin, pulseDirection);  // 輸出步進脈衝
        pulseDirection = !pulseDirection;       // 切換脈衝方向
        currentStep++;                          // 增加當前步數
        lastStepTime = currentTime;             // 更新最後一次輸出脈衝的時間
      }
    }
  }
}