本文參(zhao)考(chao)至官方文檔https://docs.simplefoc.com/docs_chinese/commander_interface
Commander 接口
Commander是一個簡單而靈活的監控,配置和控制接口,使用類似G代碼的通信協議。由於是基於“ASCII”字符命令ID,從而在任何mcu上解析都簡單高效。接收到命令ID后,將調用綁定到此命令的函數,並接收到命令字符后面的剩余字符串。
| 命令1 | 命令2 |
|---|---|
![]() |
![]() |
此類似於G代碼的接口提供回調來配置和調整:
- 無刷直流或步進電機
- PID控制器
- 低通濾波器
- 運動控制
- 監測
- 約束
- 啟用/禁用
- 傳感器偏移
- 相電阻
- ...
- PID控制器
- 低通濾波器
- 浮點變量
此外,利用commander接口可以輕松創建自己的命令,並以可能需要的任何方式擴展此接口。
當用戶發送命令時會發生什么?
commander收到字符串MVD0.765時:
它首先檢查命令ID,發現是'M',則將剩余字符串發送給電機回調函數處理。電機的回調函數進一步檢查命令ID是什么,發現是'V',則將剩余字符串發送到速度PID回調函數。然后速度PID回調函數掃描命令ID並發現它是'D',因此會設置D環數值。
| 指令 | 電機回調(cmd idM) |
PID回調(cmd idV) |
|---|---|---|
![]() |
![]() |
![]() |
另一個例子是,如果Commander收到:OE
它找到的第一個ID是'O',比如是motor,則將剩余的字符串發送給此命令的回調函數(本例中為電機的回調函數)。然后,電機的回調函數發現是命令“E”,並獲知這個命令是要獲取還是設置其所指示的狀態(已啟用/已禁用)。它檢查剩余的字符值是否為空,如果為空則意味着用戶發送的是get請求。
| 指令 | 電機回調 (cmd id O ) |
|---|---|
![]() |
![]() |
使用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-此模式不會向串口終端輸出任何內容-例如,當Commander與 monitoring 結合使用時,它就有效避免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類的命令 - PID命令 -
PIDController類的命令 - Low pass filter 命令 -
LowPassFilter類的命令 - Motor 命令 -
FOCMotor類的命令
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
電機指令
當對BLDCMotor和StepperMotor類使用標准回調函數時:commander.motor(&motor,cmd)用戶將擁有一組可用的命令:
- Q - I_Q的PID控制器和低通濾波器(有關命令,請參見pid和lpf)
- D - I_DPID控制器和低通濾波器(有關命令,請參見pid和 lpf)
- V - 速度PID控制器和低通濾波器(有關命令,pid和 lpf)
- A - 角度PID控制器和低通濾波器-(有關命令,請參見pid和 lpf )
- 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 - 獲取變量值
- '' - 目標獲取/設置

例如,如果在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.







