Skip to content

Commit e0cceab

Browse files
author
Richard Unger
committed
Merge branch 'dev' of https://github.com/simplefoc/Arduino-FOC into driver_refactor
2 parents 7f02b8a + ecd1c25 commit e0cceab

File tree

7 files changed

+236
-118
lines changed

7 files changed

+236
-118
lines changed

README.md

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,27 @@ Therefore this is an attempt to:
1818
- See also [@byDagor](https://github.com/byDagor)'s *fully-integrated* ESP32 based board: [Dagor Brushless Controller](https://github.com/byDagor/Dagor-Brushless-Controller)
1919

2020

21+
2122
<blockquote class="info">
22-
<p class="heading">FUTURE RELEASE 📢: <span class="simple">Simple<span class="foc">FOC</span>library</span> v2.2.1 </p>
23+
<p class="heading">NEW RELEASE 📢: <span class="simple">Simple<span class="foc">FOC</span>library</span> v2.2.1 <a href="https://github.com/simplefoc/Arduino-FOC/releases/tag/v2.2.1">see release</a></p>
2324
<ul>
24-
<li>Sensor class init bugfix #121</li>
25-
<li>Added the new motion control interface to the commander- possible to set the position, velocity and torque target at once</li>
26-
<li>NRF52 series mcus support by <a href="https://github.com/Polyphe">@Polyphe</a></li>
27-
<li>Voltage/current limit handling bugs #118</li>
28-
<li>Generic position and current sense classes - to implement a new sensor only implement one function</li>
29-
<li>Initial support for esp32s2 and esp32s3 - separation of the esp32 mcpwm and led implementation</li>
30-
<li><b>esp32 arduino package transfer to v2.0.1+</b> - helpful PR#149 by <a href="https://github.com/samguns">samguns</a></li>
31-
</ul>
25+
<li>Sensor class init bugfix <a href="https://github.com/simplefoc/Arduino-FOC/issues/121">#121</a></li>
26+
<li>Voltage/current limit handling bugs <a href="https://github.com/simplefoc/Arduino-FOC/issues/118">#118</a></li>
27+
<li>Added the new motion control interface to the commander <a href="https://docs.simplefoc.com/commander_target">see docs</a>
28+
<ul>
29+
<li>New target setting - possible to set the position, velocity and torque target at once</li>
30+
<li>Separated the motion control interface from full motor callback - only motion control and torque control type, enable disable and target setting</li>
31+
</ul>
32+
</li>
33+
<li>New MCU support <a href="https://docs.simplefoc.com/microcontrollers">see docs</a>
34+
<ul>
35+
<li>NRF52 series mcus support by <a href="https://github.com/Polyphe">@Polyphe</a></li>
36+
<li><b>esp32 arduino package transfer to v2.0.1+</b> - helpful <a href="https://github.com/simplefoc/Arduino-FOC/pull/92/149">PR#149</a> by <a href="https://github.com/samguns">samguns</a></li>
37+
<li>Initial support for esp32s2 and esp32s3 - separation of the esp32 mcpwm and led implementation</li>
38+
</ul>
39+
</li>
40+
<li>Generic sensor class - to implement a new sensor only implement one function <a href="https://docs.simplefoc.com/generic_sensor">see docs</a></li>
41+
</ul>
3242
</blockquote>
3343

3444
## Arduino *SimpleFOClibrary* v2.2

examples/hardware_specific_examples/SimpleFOCShield/version_v2/single_full_control_example/single_full_control_example.ino

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ InlineCurrentSense current_sense = InlineCurrentSense(0.01, 50.0, A0, A2);
1717

1818
// commander communication instance
1919
Commander command = Commander(Serial);
20-
void doTarget(char* cmd){ command.scalar(&motor.target, cmd); }
20+
void doMotion(char* cmd){ command.motion(&motor, cmd); }
2121
// void doMotor(char* cmd){ command.motor(&motor, cmd); }
2222

2323
void setup() {
@@ -74,7 +74,7 @@ void setup() {
7474
motor.target = 2;
7575

7676
// subscribe motor to the commander
77-
command.add('T', doTarget, "target");
77+
command.add('T', doMotion, "motion control");
7878
// command.add('M', doMotor, "motor");
7979

8080
// Run user commands to configure and the motor (find the full command list in docs.simplefoc.com)

examples/utils/calibration/find_pole_pair_number/encoder/find_pole_pairs_number/find_pole_pairs_number.ino

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ void setup() {
7373
while(motor_angle <= pp_search_angle){
7474
motor_angle += 0.01f;
7575
motor.move(motor_angle);
76+
_delay(1);
7677
}
7778
_delay(1000);
7879
// read the encoder value for 180

examples/utils/calibration/find_pole_pair_number/magnetic_sensor/find_pole_pairs_number/find_pole_pairs_number.ino

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ void setup() {
7373
motor_angle += 0.01f;
7474
sensor.update(); // keep track of the overflow
7575
motor.move(motor_angle);
76+
_delay(1);
7677
}
7778
_delay(1000);
7879
// read the sensor value for 180

keywords.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ pullup KEYWORD2
122122
quadrature KEYWORD2
123123
foc_modulation KEYWORD2
124124
target KEYWORD2
125+
motion KEYWORD2
125126
pwm_frequency KEYWORD2
126127
dead_zone KEYWORD2
127128
gain_a KEYWORD2

src/communication/Commander.cpp

Lines changed: 151 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,7 @@ void Commander::motor(FOCMotor* motor, char* user_command) {
101101

102102
// if target setting
103103
if(isDigit(user_command[0]) || user_command[0] == '-' || user_command[0] == '+'){
104-
printVerbose(F("Target: "));
105-
motor->target = atof(user_command);
106-
println(motor->target);
104+
target(motor, user_command);
107105
return;
108106
}
109107

@@ -177,65 +175,9 @@ void Commander::motor(FOCMotor* motor, char* user_command) {
177175
}
178176
break;
179177
case CMD_MOTION_TYPE:
180-
printVerbose(F("Motion:"));
181-
switch(sub_cmd){
182-
case SCMD_DOWNSAMPLE:
183-
printVerbose(F(" downsample: "));
184-
if(!GET) motor->motion_downsample = value;
185-
println((int)motor->motion_downsample);
186-
break;
187-
default:
188-
// change control type
189-
if(!GET && value >= 0 && (int)value < 5) // if set command
190-
motor->controller = (MotionControlType)value;
191-
switch(motor->controller){
192-
case MotionControlType::torque:
193-
println(F("torque"));
194-
break;
195-
case MotionControlType::velocity:
196-
println(F("vel"));
197-
break;
198-
case MotionControlType::angle:
199-
println(F("angle"));
200-
break;
201-
case MotionControlType::velocity_openloop:
202-
println(F("vel open"));
203-
break;
204-
case MotionControlType::angle_openloop:
205-
println(F("angle open"));
206-
break;
207-
}
208-
break;
209-
}
210-
break;
211178
case CMD_TORQUE_TYPE:
212-
// change control type
213-
printVerbose(F("Torque: "));
214-
if(!GET && (int8_t)value >= 0 && (int8_t)value < 3)// if set command
215-
motor->torque_controller = (TorqueControlType)value;
216-
switch(motor->torque_controller){
217-
case TorqueControlType::voltage:
218-
println(F("volt"));
219-
// change the velocity control limits if necessary
220-
if( !_isset(motor->phase_resistance) ) motor->PID_velocity.limit = motor->voltage_limit;
221-
break;
222-
case TorqueControlType::dc_current:
223-
println(F("dc curr"));
224-
// change the velocity control limits if necessary
225-
motor->PID_velocity.limit = motor->current_limit;
226-
break;
227-
case TorqueControlType::foc_current:
228-
println(F("foc curr"));
229-
// change the velocity control limits if necessary
230-
motor->PID_velocity.limit = motor->current_limit;
231-
break;
232-
}
233-
break;
234179
case CMD_STATUS:
235-
// enable/disable
236-
printVerbose(F("Status: "));
237-
if(!GET) (bool)value ? motor->enable() : motor->disable();
238-
println(motor->enabled);
180+
motion(motor, &user_command[0]);
239181
break;
240182
case CMD_PWMMOD:
241183
// PWM modulation change
@@ -384,6 +326,80 @@ void Commander::motor(FOCMotor* motor, char* user_command) {
384326
}
385327
}
386328

329+
void Commander::motion(FOCMotor* motor, char* user_cmd, char* separator){
330+
char cmd = user_cmd[0];
331+
char sub_cmd = user_cmd[1];
332+
bool GET = isSentinel(user_cmd[1]);
333+
float value = atof(&user_cmd[(sub_cmd >= 'A' && sub_cmd <= 'Z') ? 2 : 1]);
334+
335+
switch(cmd){
336+
case CMD_MOTION_TYPE:
337+
printVerbose(F("Motion:"));
338+
switch(sub_cmd){
339+
case SCMD_DOWNSAMPLE:
340+
printVerbose(F(" downsample: "));
341+
if(!GET) motor->motion_downsample = value;
342+
println((int)motor->motion_downsample);
343+
break;
344+
default:
345+
// change control type
346+
if(!GET && value >= 0 && (int)value < 5) // if set command
347+
motor->controller = (MotionControlType)value;
348+
switch(motor->controller){
349+
case MotionControlType::torque:
350+
println(F("torque"));
351+
break;
352+
case MotionControlType::velocity:
353+
println(F("vel"));
354+
break;
355+
case MotionControlType::angle:
356+
println(F("angle"));
357+
break;
358+
case MotionControlType::velocity_openloop:
359+
println(F("vel open"));
360+
break;
361+
case MotionControlType::angle_openloop:
362+
println(F("angle open"));
363+
break;
364+
}
365+
break;
366+
}
367+
break;
368+
case CMD_TORQUE_TYPE:
369+
// change control type
370+
printVerbose(F("Torque: "));
371+
if(!GET && (int8_t)value >= 0 && (int8_t)value < 3)// if set command
372+
motor->torque_controller = (TorqueControlType)value;
373+
switch(motor->torque_controller){
374+
case TorqueControlType::voltage:
375+
println(F("volt"));
376+
// change the velocity control limits if necessary
377+
if( !_isset(motor->phase_resistance) ) motor->PID_velocity.limit = motor->voltage_limit;
378+
break;
379+
case TorqueControlType::dc_current:
380+
println(F("dc curr"));
381+
// change the velocity control limits if necessary
382+
motor->PID_velocity.limit = motor->current_limit;
383+
break;
384+
case TorqueControlType::foc_current:
385+
println(F("foc curr"));
386+
// change the velocity control limits if necessary
387+
motor->PID_velocity.limit = motor->current_limit;
388+
break;
389+
}
390+
break;
391+
case CMD_STATUS:
392+
// enable/disable
393+
printVerbose(F("Status: "));
394+
if(!GET) (bool)value ? motor->enable() : motor->disable();
395+
println(motor->enabled);
396+
break;
397+
default:
398+
target(motor, user_cmd, separator);
399+
break;
400+
}
401+
}
402+
387403
void Commander::pid(PIDController* pid, char* user_cmd){
388404
char cmd = user_cmd[0];
389405
bool GET = isSentinel(user_cmd[1]);
@@ -445,57 +461,91 @@ void Commander::scalar(float* value, char* user_cmd){
445461
}
446462

447463

448-
void Commander::target(FOCMotor* motor, char* user_cmd){
449-
bool GET = isSentinel(user_cmd[0]);
450-
if(!GET){
451-
float pos, vel, torque;
452-
switch(motor->controller){
453-
case MotionControlType::torque: // setting torque target
454-
torque= atof(strtok (user_cmd," "));
455-
motor->target = torque;
456-
break;
457-
case MotionControlType::velocity: // setting velocity target + torque limit
458-
vel= atof(strtok (user_cmd," "));
459-
torque= atof(strtok (NULL," "));
460-
motor->target = vel;
464+
void Commander::target(FOCMotor* motor, char* user_cmd, char* separator){
465+
// if no values sent
466+
if(isSentinel(user_cmd[0])) return;
467+
468+
float pos, vel, torque;
469+
char* next_value;
470+
switch(motor->controller){
471+
case MotionControlType::torque: // setting torque target
472+
torque = atof(strtok (user_cmd, separator));
473+
motor->target = torque;
474+
break;
475+
case MotionControlType::velocity: // setting velocity target + torque limit
476+
// set the target
477+
vel= atof(strtok (user_cmd, separator));
478+
motor->target = vel;
479+
480+
// allow for setting only the target velocity without chaning the torque limit
481+
next_value = strtok (NULL, separator);
482+
if (next_value){
483+
torque = atof(next_value);
461484
motor->PID_velocity.limit = torque;
462485
// torque command can be voltage or current
463486
if(!_isset(motor->phase_resistance) && motor->torque_controller == TorqueControlType::voltage) motor->voltage_limit = torque;
464487
else motor->current_limit = torque;
465-
break;
466-
case MotionControlType::angle: // setting angle target + torque, velocity limit
467-
pos= atof(strtok (user_cmd," "));
468-
vel= atof(strtok (NULL," "));
469-
torque= atof(strtok (NULL," "));
470-
motor->target = pos;
488+
}
489+
break;
490+
case MotionControlType::angle: // setting angle target + torque, velocity limit
491+
// setting the target position
492+
pos= atof(strtok (user_cmd, separator));
493+
motor->target = pos;
494+
495+
// allow for setting only the target position without chaning the velocity/torque limits
496+
next_value = strtok (NULL, separator);
497+
if( next_value ){
498+
vel = atof(next_value);
471499
motor->velocity_limit = vel;
472500
motor->P_angle.limit = vel;
473-
motor->PID_velocity.limit = torque;
474-
// torque command can be voltage or current
475-
if(!_isset(motor->phase_resistance) && motor->torque_controller == TorqueControlType::voltage) motor->voltage_limit = torque;
476-
else motor->current_limit = torque;
477-
break;
478-
case MotionControlType::velocity_openloop: // setting velocity target + torque limit
479-
vel= atof(strtok (user_cmd," "));
480-
torque= atof(strtok (NULL," "));
481-
motor->target = vel;
501+
502+
// allow for setting only the target position and velocity limit without the torque limit
503+
next_value = strtok (NULL, separator);
504+
if( next_value ){
505+
torque= atof(next_value);
506+
motor->PID_velocity.limit = torque;
507+
// torque command can be voltage or current
508+
if(!_isset(motor->phase_resistance) && motor->torque_controller == TorqueControlType::voltage) motor->voltage_limit = torque;
509+
else motor->current_limit = torque;
510+
}
511+
}
512+
break;
513+
case MotionControlType::velocity_openloop: // setting velocity target + torque limit
514+
// set the target
515+
vel= atof(strtok (user_cmd, separator));
516+
motor->target = vel;
517+
// allow for setting only the target velocity without chaning the torque limit
518+
next_value = strtok (NULL, separator);
519+
if (next_value ){
520+
torque = atof(next_value);
482521
// torque command can be voltage or current
483522
if(!_isset(motor->phase_resistance)) motor->voltage_limit = torque;
484523
else motor->current_limit = torque;
485-
break;
486-
case MotionControlType::angle_openloop: // setting angle target + torque, velocity limit
487-
pos= atof(strtok (user_cmd," "));
488-
vel= atof(strtok (NULL," "));
489-
torque= atof(strtok (NULL," "));
490-
motor->target = pos;
524+
}
525+
break;
526+
case MotionControlType::angle_openloop: // setting angle target + torque, velocity limit
527+
// set the target
528+
pos= atof(strtok (user_cmd, separator));
529+
motor->target = pos;
530+
531+
// allow for setting only the target position without chaning the velocity/torque limits
532+
next_value = strtok (NULL, separator);
533+
if( next_value ){
534+
vel = atof(next_value);
491535
motor->velocity_limit = vel;
492-
// torque command can be voltage or current
493-
if(!_isset(motor->phase_resistance)) motor->voltage_limit = torque;
494-
else motor->current_limit = torque;
495-
break;
496-
}
497-
}
498-
//println(*value);
536+
// allow for setting only the target velocity without chaning the torque limit
537+
next_value = strtok (NULL, separator);
538+
if (next_value ){
539+
torque = atof(next_value);
540+
// torque command can be voltage or current
541+
if(!_isset(motor->phase_resistance)) motor->voltage_limit = torque;
542+
else motor->current_limit = torque;
543+
}
544+
}
545+
break;
546+
}
547+
printVerbose(F("Target: "));
548+
println(motor->target);
499549
}
500550

501551

0 commit comments

Comments
 (0)