Simple FOC內置通信接口學習(二):電機命令接口


本文參(zhao)考(chao)至官方文檔https://docs.simplefoc.com/docs_chinese/commander_interface

Commander 接口

Commander是一個簡單而靈活的監控,配置和控制接口,使用類似G代碼的通信協議。由於是基於“ASCII”字符命令ID,從而在任何mcu上解析都簡單高效。接收到命令ID后,將調用綁定到此命令的函數,並接收到命令字符后面的剩余字符串。

命令1 命令2
img img

此類似於G代碼的接口提供回調來配置和調整:

  • 無刷直流或步進電機
    • PID控制器
    • 低通濾波器
    • 運動控制
    • 監測
    • 約束
    • 啟用/禁用
    • 傳感器偏移
    • 相電阻
    • ...
  • PID控制器
  • 低通濾波器
  • 浮點變量

此外,利用commander接口可以輕松創建自己的命令,並以可能需要的任何方式擴展此接口。

當用戶發送命令時會發生什么?

commander收到字符串MVD0.765時:
它首先檢查命令ID,發現是'M',則將剩余字符串發送給電機回調函數處理。電機的回調函數進一步檢查命令ID是什么,發現是'V',則將剩余字符串發送到速度PID回調函數。然后速度PID回調函數掃描命令ID並發現它是'D',因此會設置D環數值。

指令 電機回調(cmd idM PID回調(cmd idV
img img img

另一個例子是,如果Commander收到:OE

它找到的第一個ID是'O',比如是motor,則將剩余的字符串發送給此命令的回調函數(本例中為電機的回調函數)。然后,電機的回調函數發現是命令“E”,並獲知這個命令是要獲取還是設置其所指示的狀態(已啟用/已禁用)。它檢查剩余的字符值是否為空,如果為空則意味着用戶發送的是get請求。

指令 電機回調 (cmd id O )
img img

使用Commander接口

命令接口在Commander 類中實現。

// Commander 接口構型
// - serial  - 可選擇接收 HardwareSerial 或 Stream 實例
// - eol     - 可選擇接收 eol 字符 - 默認另起一行: "\n" 
// - echo    - 可選的 echo 行結束符(命令行反饋)  - 默認 false
Commander commander = Commander(Serial, "\n", false);

行結束符EOL是Commander類的可選輸入,表示命令字符的結束。用戶可以在此處定義自己的命令結束字符,但默認情況下使用的字符是換行符\n。比如

注意:EOL行結束符

不同的操作系統有不同的默認行結束符。而換行符可能是最常見的字符,linux用戶也有回車符'\r'。如果你希望用的是換行符作為命令字符的結束,請確保將它傳給Commander類的構造函數中。

echo標志位可用作調試功能,但不建議用於實時電機控制和配置!

下一步是添加commander函數,該函數將讀取所綁定的Serial實例到Arduinoloop()

void loop(){
  ...
  commander.run(); // 從 constructor 讀取 Serial 實例
}

如果沒有將Serial實例傳給Commander構造函數,則可以將其綁定給 run() 函數。

void loop(){
  ...
  commander.run(Serial); // 從 run 讀取 Serial 實例
}

或者,如果你希望使用不帶 Serial 且僅使用字符串變量的commander,則可以向 run()函數提供和 char* 變量:

char* my_string = "user command";
commander.run(my_string); // 讀取字符串

串口輸出

Commander 類會嘗試將輸出打印到構造函數中提供的串口實例。如果在構造函數中沒串口實例,則會始終在 run() 函數中的串口實例。如果以上都沒有,則不會在任何地方輸出,但用戶仍然能夠使用它。

配置

Commander有兩個配置參數:

  • verbose-串口輸出模式
  • decimal_places-浮點數的小數位數

通過設置參數decimal_places,可以輕松更改浮點數的小數位數:

commander.decimal_places = 4; // 默認為3位小數

通過設置參數verbose,可以輕松更改串口輸出模式

// VerboseMode::nothing        - 不顯示任何信息 - 適用於與監視器結合使用時
// VerboseMode::on_request     - 僅顯示用戶請求的信息
// VerboseMode::user_friendly  - 向用戶顯示文本信息(默認)
commander.verbose = VerboseMode::user_friendly;

有三種類型的輸出模式:

  • VerboseMode::nothing-此模式不會向串口終端輸出任何內容-例如,當Commandermonitoring 結合使用時,它就有效避免Arduino的串口繪圖儀中出現未知值
  • VerboseMode::on_request-此模式僅輸出get和set命令的結果,不會輸出任何其他不必要的(可讀的)文本。
  • VerboseMode::user_friendly-此模式是默認模式,適用於由用戶使用串口監視器發送命令的情況。除了所有必要的get和set值外,該模式還將輸出額外的文本,以便於用戶理解。

添加命令

你可以用add()來添加給定的命令字符的回調函數,該函數接收命令字符、函數指針和命令標簽:

// 在 commander 中創建 command A 
// - command id - 字符串
// - 回調   - 函數指針 - 返回 void (char* cmd)
// - 標簽      - 命令標簽 (可選)
commander.add('A',doSomething,"do something");

對於可以用作回調函數的函數類型,唯一的實際要求是它們需要返回void,並且必須接收char*字符串:

void doSomething(char* cmd){ ... }

使用這個簡單的接口,你可以非常簡單地創建自己的命令,並使用一行代碼將它們訂閱到Commander

除了此用於添加通用回調的靈活接口之外,Commander類還為以下對象實現了標准化回調:

  • 無刷直流電動機 (BLDCMotor) - commander.motor(&motor, cmd)
  • 步進電機 (StepperMotor) - commander.motor(&motor, cmd)
  • PID控制器(PIDController) - commander.pid(&pid, cmd)
  • 低通濾波器 (LowPassFilter) - commander.lpf(&lpf, cmd)
  • 任何數值變量(float) - commander.scalar(&variable, cmd)

例如,如果你想完整配置一個motor,你的代碼可能如下所示:

BLDCMotor motor = .....
Commander commander = ....

// 定義封裝通用回調
void onMotor(char* cmd){commander.motor(&motor, cmd);}

void setup(){
  ...
  commander.add('m',onMotor,"my motor");
  ...
}
void loop(){
  ...
  commander.run();
}

如果希望調整速度PID,更改電機的目標值,同時希望消除由於不需要的其他功能而產生的不必要的內存開銷,那么你的代碼可能如下所示:

BLDCMotor motor = .....
Commander commander = ....

// 定義封裝通用回調
void onPid(char* cmd){commander.pid(&motor.PID_velocity, cmd);}
void onLpf(char* cmd){commander.lpf(&motor.LPF_velocity, cmd);}
void onTarget(char* cmd){commander.scalar(&motor.tagret, cmd);}

void setup(){
  ...
  commander.add('C',onPid,"PID vel");
  commander.add('L',onLpf,"LPF vel");
  commander.add('T',onTarget,"target vel");
  ...
}
void loop(){
  ...
  commander.run();
}

這個接口為用戶提供了一種簡單的方式,可以同時通信和配置多個電機、PID控制器、低通濾波器、標量變量或者自定義命令。它還能使自定義控制回路的調整更加容易,因為你可以非常輕松地使用pid控制器PIDController關閉回路,只需將其添加到commander即可實時調整。

你可以在庫examplesexamples/utils/communication\u test/commander文件夾中找到更多示例。

命令列表

所有內置命令和子命令都在庫源文件src/communication/commands.h中定義。如果你希望更改某個命令的字符id,則可以在此進行操作。😄

通常,我們可以將命令分為:

Commander命令

在你的程序中使用 Commander時,用戶可以使用三個內置的默認命令:

  • ? - 列出所有可用的命令
  • # - 獲取/設置小數點位數
    • 示例:
      • 小數點位數 #
      • 設置小數點精確到后5位: #5
  • @ - 獲取/設置Commander的輸出模式
    • 示例:
      • 獲取當前模式: @
      • 設置user frinedly模式:@3
      • 設置nothing模式:@0
      • 設置on request模式: @1

list命令?會顯示所有添加到Commander的命令和他的標簽。比如如果我們添加了如下命令:

void setup(){
  ...
  commander.add('M',doSomeMotor,"some motor");
  commander.add('P',doSomePID,"some pid");
  commander.add('R',doSomeOtherMotor,"some other motor");
  ...
}

以下是以 user-friendly模式輸出 ? 的示例:

$ ?
M: some motor
P: some pid
R: some other motor

PID命令

當對 PIDController 類:commander.pid(&pid,cmd)使用標准回調函數時,用戶擁有一組可用的命令:

  • P: PID控制器P增益
  • I: PID控制器I增益
  • D: PID控制器D增益
  • R: PID控制器輸出斜率
  • L:PID控制器輸出約束

例如,如果在commander中添加了PID控制器:

PIDController pid = ....
Commander commander = ...

void onPid(char* cmd){ commander.pid(&pid,cmd); }
void setup(){
  ...
  commander.add('C',onPid,"my pid");
  ...
}
void loop(){
  ...
  commander.run();
}

你將能夠從串口監視器配置 (set 和 get) 其參數:

$ CP           # 獲取 P 增益
P: 1.0
$ CD0.05       # 設置 D 增益
D: 0.05
$ CO           # 未知命令
err
$ CL3.25       # 設置輸出限制
limit: 3.25

低通濾波器命令

使用 LowPassFilter 類的標准回調函數時:commander.lpf(&lpf,cmd)用戶有一個可用的命令:

  • F: 低通濾波器時間常數

例如,如果在commander中添加了低通濾波器:

LowPassFilter filter = ....
Commander commander = ...

void onLpf(char* cmd){ commander.lpf(&filter,cmd); }
void setup(){
  ...
  commander.add('A',onLpf,"my lpf");
  ...
}
void loop(){
  ...
  commander.run();
}

你將能夠從串口監視器配置(set 和 get)其參數:

$ AF           # 獲取時間常數
Tf: 1.0
$ AF0.05       # 設置時間常數
Tf: 0.05
$ AW           # 未知命令
err

電機指令

當對BLDCMotorStepperMotor類使用標准回調函數時:commander.motor(&motor,cmd)用戶將擁有一組可用的命令:

  • Q - I_Q的PID控制器和低通濾波器(有關命令,請參見pidlpf
  • D - I_DPID控制器和低通濾波器(有關命令,請參見pidlpf
  • V - 速度PID控制器和低通濾波器(有關命令,pidlpf
  • A - 角度PID控制器和低通濾波器-(有關命令,請參見pidlpf
  • L -約束
    • C - 電流
    • U - 電壓
    • V - 速度
  • C - 運動控制模式配置
    • D - 運動控制的下采樣頻率
    • 0 - 力矩
    • 1 - 速度
    • 2 - 角度
    • 3 - 速度開環
    • 4 - 角度開環
  • T - 力矩控制模式
    • 0 - 電壓
    • 1 - 直流電流
    • 2 - FOC電流
  • E - 電機狀態 (啟用/禁用)
    • 0 - 啟用
    • 1 - 禁用
  • R - 電機相電阻
  • S - 傳感器偏移
    • M - 傳感器偏移
    • E - 傳感器電氣零點
  • W - PWM設置
    • T - pwm 調制類型
    • C - pwm 波形中心布爾
  • M - 監控
    • D - 監測的下采樣頻率
    • C - 清除監視器
    • S - 設置監控變量
    • G - 獲取變量值
  • '' - 目標獲取/設置

img

例如,如果在commander中添加了無刷直流電機:

BLDCMotor motor = ....
Commander commander = ...

void onMotor(char* cmd){ commander.motor(&motor,cmd); }
void setup(){
  ...
  commander.add('M',onMotor,"my motor");
  ...
}
void loop(){
  ...
  commander.run();
}

你將能夠從串口監視器配置(set and get)其參數:

$ MVP                 # 獲取 PID 速度 P 增益
PID vel| P: 0.20
$ MVP1.2              # 設置 PID 速度 P 增益
PID vel| P: 1.20
$ MAI                 # 獲取 PID 角度 I 增益
PID angle| I: 0.00 
$ MAF                 # 獲取 LPF 角度時間常數
LPF angle| Tf: 0.00
$ MLV50.4             # 設置速度限制
Limits| vel: 50.4
$ MLC                 # 獲取電流限制
Limits| curr: 0.5
$ MT                  # 獲取力矩控制模式
Torque: volt
$ MT1                 # 設置力矩控制模式
Torque: dc curr
$ MT2                 # 設置力矩控制模式
Torque: foc curr
$ ME                  # 獲取電機狀態:啟用/禁用
Status: 1
$ MSM                 # 獲取傳感器偏移
Sensor| offset: 0.0
$ MSM1.2              # 設置傳感器偏移
Sensor| offset: 1.2
$ MC                  # 獲取運動控制模式
Motion: torque
$ MC3                 # 設置運動控制模式
Motion: vel open
$ MC2                 # 設置運動控制模式
Motion: angle
$ MCD100              # 獲取運動控制下采樣
Motion: downsample: 100
$ MMG0                # 獲取變量 target
Monitor | target: 0.0
$ MMG1                # 獲取變量 voltage q
Monitor | Vq: 1.4
$ MMG6                # 獲取變量 angle(角度)
Monitor | angle: 23.5 
$ MMG6                # 獲取變量 angle(角度)
Monitor | angle: 24.6 
$ MMG6                # 獲取變量 angle(角度)
Monitor | angle: 25.5 
$ M0                  # 設置 target
Target: 0.0
$ M0.4                # 設置 target
Target: 0.4
$ @1                  # 設置verbose模式: on_request
Verb | on! 
$ MMG6                # 獲取變量 angle(角度)
26.5
$ MMG5                # 獲取變量 velocity(速度)
2.57
$ #6                  # 設置保留小數點后六位
Decimal: 6
$ MMG6                # 獲取變量 angle(角度)
27.732821
$ @0                  # 設置verbose模式: nothing
Verb: off!
$ MMG6                # 獲取變量 angle(角度)
$ MMG6                # 獲取變量 angle(角度)
$ @2                  # 設置verbose模式: user_friendly
Verb: on!
$ MMG6                # 獲取變量 angle(角度)
Monitor | angle: 25.532131 

電機監控命令

Commander接口使用戶能夠控制 monitoring功能的輸出。兩者的結合使用戶能夠自由控制電機配置和調參,以及自由控制所輸出的變量。為了使用其功能,用戶需要啟用對電機的監控,代碼如下所示:

BLDCMotor motor = ....
Commander commander = ...

void onMotor(char* cmd){ commander.motor(&motor,cmd); }
void setup(){
  ...
  motor.useMonitoring(Serial);
  commander.add('M',onMotor,"my motor");
  ...
}
void loop(){
  ...
  motor.monitor();
  commander.run();
}

最后,一旦電機添加到commander接口,用戶將能夠使用以下命令配置監控:

  • M - 監控
    • D - 監測的下采樣頻率
    • C - 清除監視器
    • S - 設置監控變量

使用這些命令,你可以更改 monitor() 函數的下采樣頻率(motor.monitor_downsampling),該函數將確定輸出采樣頻率。例如,如果 loop 時間約為1ms,motor.monitor_downsampling為100,則每100ms輸出一次電機變量。
如果motor.monitor_downsampling為0, monitor() 函數將被禁用。如果motor.monitor_variables為空(等於0),則同樣 monitor() 函數被禁用。因此,命令C有效地執行以下操作:

// 回調 command MC
motor.monitor_variables = 0;

最后,命令MS用於獲取/設置 motor.monitor_variables

因此,通信可如下所示:

$ MMD                 # 獲取監視器下采樣率
Monitor | downsample: 10 
$ MMD1000             # 設置監視器下采樣率
Monitor | downsample: 1000 
$ MMS                 # 獲取監視器變量
Monitor | 0000000
$ MMS1000001          # 設置監視器變量 (target and angle)
Monitor | 1000001
1.000 0.999
1.000 0.985
1.000 1.064
.....
1.000 1.040
$ MMS0100000          # 設置監視器變量 (voltage q)
Monitor | 0100000
1.234
-0.345
...
0.772
$ MMC                 # 清除監視變量
Monitor | clear
$ MMS                 # 獲取監視變量
Monitor | 0000000

📈 Good practice for visualization

如果用monitor來調整運動控制函數或者只是為了對不同變量進行可視化的話,有必要禁用掉commander的輸出,這樣以來串口監視器中就只有monitor的輸出。為此,可以發送命令 @0使用模式 VerboseMode::nothing。詳見 [Commander命令](#commander命令)

使用motor命令的示例代碼

這是在代碼中使用motor命令進行監控的一個簡單示例。有關更多示例,請瀏覽庫示例,尤其是examples/utils/communication_tes/commander文件夾。

#include <SimpleFOC.h>

// 無刷直流電機和驅動器實例
BLDCMotor motor = BLDCMotor(11);
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8);

// 編碼器實例
Encoder encoder = Encoder(2, 3, 500);
// 通道 A 和 B 回調
void doA(){encoder.handleA();}
void doB(){encoder.handleB();}


// commander接口
Commander command = Commander(Serial);
void onMotor(char* cmd){ command.motor(&motor, cmd); }

void setup() {

  // 初始化編碼傳感器硬件
  encoder.init();
  encoder.enableInterrupts(doA, doB); 
  // 連接電機和傳感器
  motor.linkSensor(&encoder);

  // 配置驅動器
  // 電源電壓 [V]
  driver.voltage_power_supply = 12;
  driver.init();
  // 連接電機
  motor.linkDriver(&driver);

  // 設置控制環類型
  motor.controller = MotionControlType::torque;

  // 使用串口監視電機初始化
  // 監視端口
  Serial.begin(115200);
  // 如無必要,可注釋掉
  motor.useMonitoring(Serial);
  motor.monitor_downsample = 0; // 初始化禁用實時監視

  // 初始化電機
  motor.init();
  // 校准編碼器,啟動FOC
  motor.initFOC();

  // 設置初始目標值
  motor.target = 2;

  // 定義電機 id
  command.add('A', onMotor, "motor");

  // 運行用戶命令配置電機(完整命令列表見docs.simplefoc.com)
  Serial.println(F("Motor commands sketch | Initial motion control > torque/voltage : target 2V."));
  
  _delay(1000);
}


void loop() {
  // 設置FOC相電壓迭代
  motor.loopFOC();

  // 設置外部環目標迭代函數
  motor.move();

  // 監視
  motor.monitor();
  // 用戶通信
  command.run();
}

SimpleFOCStudio

SimpleFOCStudio是由@JorgeMaker 構建的一個很棒的應用程序我們會盡量在沒有庫的情況下保持最新。它是一個python應用程序,使用commander接口來調試和配置電機。

有關如何安裝和使用此應用程序的更多信息,請訪問 docs.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM