SimpleFOClibrary  2.1
Commander.cpp
Go to the documentation of this file.
1 #include "Commander.h"
2 
3 
4 Commander::Commander(Stream& serial){
5  com_port = &serial;
6 }
8  // do nothing
9 }
10 
11 
12 void Commander::add(char id, CommandCallback onCommand, char* label ){
13  call_list[call_count] = onCommand;
14  call_ids[call_count] = id;
15  call_label[call_count] = label;
16  call_count++;
17 }
18 
19 
21  if(!com_port) return;
22  // a string to hold incoming data
23  while (com_port->available()) {
24  // get the new byte:
25  received_chars[rec_cnt] = (char)com_port->read();
26  // end of user input
27  if (received_chars[rec_cnt++] == '\n') {
28  // execute the user command
29  run(received_chars);
30 
31  // reset the command buffer
32  received_chars[0] = 0;
33  rec_cnt=0;
34  }
35  }
36 }
37 
38 void Commander::run(Stream& serial){
39  Stream* tmp = com_port; // save the serial instance
40  // use the new serial instance to output if not available the one linked in constructor
41  if(!tmp) com_port = &serial;
42 
43  // a string to hold incoming data
44  while (serial.available()) {
45  // get the new byte:
46  received_chars[rec_cnt] = (char)serial.read();
47  // end of user input
48  if (received_chars[rec_cnt++] == '\n') {
49  // execute the user command
50  run(received_chars);
51 
52  // reset the command buffer
53  received_chars[0] = 0;
54  rec_cnt=0;
55  }
56  }
57 
58  com_port = tmp; // reset the instance to the internal value
59 }
60 
61 void Commander::run(char* user_input){
62  // execute the user command
63  char id = user_input[0];
64  switch(id){
65  case CMD_SCAN:
66  for(int i=0; i < call_count; i++){
67  print(call_ids[i]);
68  print(":");
69  if(call_label[i]) println(call_label[i]);
70  else println("");
71  }
72  break;
73  case CMD_VERBOSE:
74  if(user_input[1] != '\n') verbose = (VerboseMode)atoi(&user_input[1]);
75  printVerbose(F("Verb:"));
76  switch (verbose){
78  println(F("off!"));
79  break;
82  println(F("on!"));
83  break;
84  }
85  break;
86  case CMD_DECIMAL:
87  if(user_input[1] != '\n') decimal_places = atoi(&user_input[1]);
88  printVerbose(F("Decimal:"));
89  println(decimal_places);
90  break;
91  default:
92  for(int i=0; i < call_count; i++){
93  if(id == call_ids[i]){
94  call_list[i](&user_input[1]);
95  break;
96  }
97  }
98  break;
99  }
100 }
101 
102 void Commander::motor(FOCMotor* motor, char* user_command) {
103  // parse command letter
104  char cmd = user_command[0];
105  char sub_cmd = user_command[1];
106  int value_index = (sub_cmd >= 'A' && sub_cmd <= 'Z') ? 2 : 1;
107  // check if get command
108  bool GET = user_command[value_index] == '\n';
109  // parse command values
110  float value = atof(&user_command[value_index]);
111 
112  // a bit of optimisation of variable memory for Arduino UNO (atmega328)
113  switch(cmd){
114  case CMD_C_Q_PID: //
115  printVerbose(F("PID curr q| "));
116  if(sub_cmd == SCMD_LPF_TF) lpf(&motor->LPF_current_q, &user_command[1]);
117  else pid(&motor->PID_current_q,&user_command[1]);
118  break;
119  case CMD_C_D_PID: //
120  printVerbose(F("PID curr d| "));
121  if(sub_cmd == SCMD_LPF_TF) lpf(&motor->LPF_current_d, &user_command[1]);
122  else pid(&motor->PID_current_d, &user_command[1]);
123  break;
124  case CMD_V_PID: //
125  printVerbose(F("PID vel| "));
126  if(sub_cmd == SCMD_LPF_TF) lpf(&motor->LPF_velocity, &user_command[1]);
127  else pid(&motor->PID_velocity, &user_command[1]);
128  break;
129  case CMD_A_PID: //
130  printVerbose(F("PID angle| "));
131  if(sub_cmd == SCMD_LPF_TF) lpf(&motor->LPF_angle, &user_command[1]);
132  else pid(&motor->P_angle, &user_command[1]);
133  break;
134  case CMD_LIMITS: //
135  printVerbose(F("Limits| "));
136  switch (sub_cmd){
137  case SCMD_LIM_VOLT: // voltage limit change
138  printVerbose(F("volt: "));
139  if(!GET) {
140  motor->voltage_limit = value;
141  motor->PID_current_d.limit = value;
142  motor->PID_current_q.limit = value;
143  // change velocity pid limit if in voltage mode and no phase resistance set
144  if( !_isset(motor->phase_resistance) && motor->torque_controller==TorqueControlType::voltage) motor->PID_velocity.limit = value;
145  }
146  println(motor->voltage_limit);
147  break;
148  case SCMD_LIM_CURR: // current limit
149  printVerbose(F("curr: "));
150  if(!GET){
151  motor->current_limit = value;
152  // if phase resistance is set, change the voltage limit as well.
153  if(_isset(motor->phase_resistance)) motor->voltage_limit = value*motor->phase_resistance;
154  // if phase resistance specified or the current control is on set the current limit to the velocity PID
155  if(_isset(motor->phase_resistance) || motor->torque_controller != TorqueControlType::voltage ) motor->PID_velocity.limit = value;
156  }
157  println(motor->current_limit);
158  break;
159  case SCMD_LIM_VEL: // velocity limit
160  printVerbose(F("vel: "));
161  if(!GET){
162  motor->velocity_limit = value;
163  motor->P_angle.limit = value;
164  }
165  println(motor->velocity_limit);
166  break;
167  default:
168  printError();
169  break;
170  }
171  break;
172  case CMD_MOTION_TYPE:
173  printVerbose(F("Motion: "));
174  switch(sub_cmd){
175  case SCMD_DOWNSAMPLE:
176  printVerbose(F("downsample: "));
177  if(!GET) motor->motion_downsample = value;
178  println((int)motor->motion_downsample);
179  break;
180  default:
181  // change control type
182  if(!GET && value >= 0 && (int)value < 5)// if set command
183  motor->controller = (MotionControlType)value;
184  switch(motor->controller){
186  println(F("torque"));
187  break;
189  println(F("vel"));
190  break;
192  println(F("angle"));
193  break;
195  println(F("vel open"));
196  break;
198  println(F("angle open"));
199  break;
200  }
201  break;
202  }
203  break;
204  case CMD_TORQUE_TYPE:
205  // change control type
206  printVerbose(F("Torque: "));
207  if(!GET && (int8_t)value >= 0 && (int8_t)value < 3)// if set command
208  motor->torque_controller = (TorqueControlType)value;
209  switch(motor->torque_controller){
211  println(F("volt"));
212  break;
214  println(F("dc curr"));
215  break;
217  println(F("foc curr"));
218  break;
219  }
220  break;
221  case CMD_STATUS:
222  // enable/disable
223  printVerbose(F("Status: "));
224  if(!GET) (bool)value ? motor->enable() : motor->disable();
225  println(motor->enabled);
226  break;
227  case CMD_RESIST:
228  // enable/disable
229  printVerbose(F("R phase: "));
230  if(!GET){
231  motor->phase_resistance = value;
232  if(motor->torque_controller==TorqueControlType::voltage){
233  motor->voltage_limit = motor->current_limit*value;
234  motor->PID_velocity.limit= motor->current_limit;
235  }
236  }
237  if(_isset(motor->phase_resistance)) println(motor->phase_resistance);
238  else println(0);
239  break;
240  case CMD_SENSOR:
241  // Sensor zero offset
242  printVerbose(F("Sensor | "));
243  switch (sub_cmd){
244  case SCMD_SENS_MECH_OFFSET: // zero offset
245  printVerbose(F("offset: "));
246  if(!GET) motor->sensor_offset = value;
247  println(motor->sensor_offset);
248  break;
249  case SCMD_SENS_ELEC_OFFSET: // electrical zero offset - not suggested to touch
250  printVerbose(F("el. offset: "));
251  if(!GET) motor->zero_electric_angle = value;
252  println(motor->zero_electric_angle);
253  break;
254  default:
255  printError();
256  break;
257  }
258  break;
259  case CMD_MONITOR: // get current values of the state variables
260  printVerbose(F("Monitor | "));
261  switch (sub_cmd){
262  case SCMD_GET: // get command
263  switch((uint8_t)value){
264  case 0: // get target
265  printVerbose(F("target: "));
266  println(motor->target);
267  break;
268  case 1: // get voltage q
269  printVerbose(F("Vq: "));
270  println(motor->voltage.q);
271  break;
272  case 2: // get voltage d
273  printVerbose(F("Vd: "));
274  println(motor->voltage.q);
275  break;
276  case 3: // get current q
277  printVerbose(F("Cq: "));
278  println(motor->voltage.q);
279  break;
280  case 4: // get current d
281  printVerbose(F("Cd: "));
282  println(motor->voltage.q);
283  break;
284  case 5: // get velocity
285  printVerbose(F("vel: "));
286  println(motor->shaft_velocity);
287  break;
288  case 6: // get angle
289  printVerbose(F("angle: "));
290  println(motor->shaft_angle);
291  break;
292  default:
293  printError();
294  break;
295  }
296  break;
297  case SCMD_DOWNSAMPLE:
298  printVerbose(F("downsample: "));
299  if(!GET) motor->monitor_downsample = value;
300  println((int)motor->monitor_downsample);
301  break;
302  case SCMD_CLEAR:
303  motor->monitor_variables = (uint8_t) 0;
304  println(F("clear"));
305  break;
306  case SCMD_SET:
307  if(!GET) motor->monitor_variables = (uint8_t) 0;
308  for(int i = 0; i < 7; i++){
309  if(user_command[value_index+i] == '\n') break;
310  if(!GET) motor->monitor_variables |= (user_command[value_index+i] - '0') << (6-i);
311  print( (user_command[value_index+i] - '0') );
312  }
313  println("");
314  break;
315  default:
316  printError();
317  break;
318  }
319  break;
320  default: // target change
321  printVerbose(F("Target: "));
322  motor->target = atof(user_command);
323  println(motor->target);
324  }
325 }
326 
327 void Commander::pid(PIDController* pid, char* user_cmd){
328  char cmd = user_cmd[0];
329  bool GET = user_cmd[1] == '\n';
330  float value = atof(&user_cmd[1]);
331 
332  switch (cmd){
333  case SCMD_PID_P: // P gain change
334  printVerbose("P: ");
335  if(!GET) pid->P = value;
336  println(pid->P);
337  break;
338  case SCMD_PID_I: // I gain change
339  printVerbose("I: ");
340  if(!GET) pid->I = value;
341  println(pid->I);
342  break;
343  case SCMD_PID_D: // D gain change
344  printVerbose("D: ");
345  if(!GET) pid->D = value;
346  println(pid->D);
347  break;
348  case SCMD_PID_RAMP: // ramp change
349  printVerbose("ramp: ");
350  if(!GET) pid->output_ramp = value;
351  println(pid->output_ramp);
352  break;
353  case SCMD_PID_LIM: // limit change
354  printVerbose("limit: ");
355  if(!GET) pid->limit = value;
356  println(pid->limit);
357  break;
358  default:
359  printError();
360  break;
361  }
362 }
363 
364 void Commander::lpf(LowPassFilter* lpf, char* user_cmd){
365  char cmd = user_cmd[0];
366  bool GET = user_cmd[1] == '\n';
367  float value = atof(&user_cmd[1]);
368 
369  switch (cmd){
370  case SCMD_LPF_TF: // Tf value change
371  printVerbose(F("Tf: "));
372  if(!GET) lpf->Tf = value;
373  println(lpf->Tf);
374  break;
375  default:
376  printError();
377  break;
378  }
379 }
380 
381 void Commander::scalar(float* value, char* user_cmd){
382  bool GET = user_cmd[0] == '\n';
383  if(!GET) *value = atof(user_cmd);
384  println(*value);
385 }
386 
387 
388 void Commander::print(const int number){
389  if( !com_port || verbose == VerboseMode::nothing ) return;
390  com_port->print(number);
391 }
392 void Commander::print(const float number){
393  if(!com_port || verbose == VerboseMode::nothing ) return;
394  com_port->print((float)number,(int)decimal_places);
395 }
396 void Commander::print(const char* message){
397  if(!com_port || verbose == VerboseMode::nothing ) return;
398  com_port->print(message);
399 }
400 void Commander::print(const __FlashStringHelper *message){
401  if(!com_port || verbose == VerboseMode::nothing ) return;
402  com_port->print(message);
403 }
404 void Commander::print(const char message){
405  if(!com_port || verbose == VerboseMode::nothing ) return;
406  com_port->print(message);
407 }
408 
409 void Commander::println(const int number){
410  if(!com_port || verbose == VerboseMode::nothing ) return;
411  com_port->println(number);
412 }
413 void Commander::println(const float number){
414  if(!com_port || verbose == VerboseMode::nothing ) return;
415  com_port->println((float)number, (int)decimal_places);
416 }
417 void Commander::println(const char* message){
418  if(!com_port || verbose == VerboseMode::nothing ) return;
419  com_port->println(message);
420 }
421 void Commander::println(const __FlashStringHelper *message){
422  if(!com_port || verbose == VerboseMode::nothing ) return;
423  com_port->println(message);
424 }
425 void Commander::println(const char message){
426  if(!com_port || verbose == VerboseMode::nothing ) return;
427  com_port->println(message);
428 }
429 
430 
431 void Commander::printVerbose(const char* message){
432  if(verbose == VerboseMode::user_friendly) print(message);
433 }
434 void Commander::printVerbose(const __FlashStringHelper *message){
435  if(verbose == VerboseMode::user_friendly) print(message);
436 }
437 void Commander::printError(){
438  print(F("err"));
439 }
SCMD_PID_I
#define SCMD_PID_I
PID gain I.
Definition: commands.h:27
velocity_openloop
@ velocity_openloop
Definition: FOCMotor.h:31
TorqueControlType
TorqueControlType
Definition: FOCMotor.h:38
SCMD_CLEAR
#define SCMD_CLEAR
Clear all monitored variables.
Definition: commands.h:41
SCMD_GET
#define SCMD_GET
Get variable only one value.
Definition: commands.h:42
FOCMotor
Definition: FOCMotor.h:58
Commander::add
void add(char id, CommandCallback onCommand, char *label=nullptr)
Definition: Commander.cpp:12
CMD_C_Q_PID
#define CMD_C_Q_PID
current d PID & LPF
Definition: commands.h:8
CMD_C_D_PID
#define CMD_C_D_PID
current d PID & LPF
Definition: commands.h:7
voltage
@ voltage
Torque control using voltage.
Definition: FOCMotor.h:39
CMD_RESIST
#define CMD_RESIST
motor phase resistance
Definition: commands.h:17
MotionControlType
MotionControlType
Definition: FOCMotor.h:27
CMD_A_PID
#define CMD_A_PID
angle PID & LPF
Definition: commands.h:10
angle
@ angle
Position/angle motion control.
Definition: FOCMotor.h:30
_isset
#define _isset(a)
Definition: foc_utils.h:11
CMD_LIMITS
#define CMD_LIMITS
limits current/voltage/velocity
Definition: commands.h:12
VerboseMode
VerboseMode
Definition: Commander.h:11
Commander::Commander
Commander()
Definition: Commander.cpp:7
SCMD_LPF_TF
#define SCMD_LPF_TF
LPF time constant.
Definition: commands.h:31
velocity
@ velocity
Velocity motion control.
Definition: FOCMotor.h:29
torque
@ torque
Torque control.
Definition: FOCMotor.h:28
user_friendly
@ user_friendly
Definition: Commander.h:14
SCMD_SENS_ELEC_OFFSET
#define SCMD_SENS_ELEC_OFFSET
Sensor electrical zero offset.
Definition: commands.h:38
SCMD_PID_LIM
#define SCMD_PID_LIM
PID limit.
Definition: commands.h:30
CMD_V_PID
#define CMD_V_PID
velocity PID & LPF
Definition: commands.h:9
foc_current
@ foc_current
torque control using dq currents
Definition: FOCMotor.h:41
Commander::decimal_places
uint8_t decimal_places
number of decimal places to be used when displaying numbers
Definition: Commander.h:90
dc_current
@ dc_current
Torque control using DC current (one current magnitude)
Definition: FOCMotor.h:40
CMD_MOTION_TYPE
#define CMD_MOTION_TYPE
motion control type
Definition: commands.h:13
on_request
@ on_request
Definition: Commander.h:13
SCMD_SENS_MECH_OFFSET
#define SCMD_SENS_MECH_OFFSET
Sensor offset.
Definition: commands.h:37
CMD_TORQUE_TYPE
#define CMD_TORQUE_TYPE
torque control type
Definition: commands.h:14
Commander.h
CMD_STATUS
#define CMD_STATUS
motor status enable/disable
Definition: commands.h:11
Commander::run
void run()
Definition: Commander.cpp:20
SCMD_LIM_VEL
#define SCMD_LIM_VEL
Limit velocity.
Definition: commands.h:35
CMD_VERBOSE
#define CMD_VERBOSE
command setting output mode - only for commander
Definition: commands.h:21
Commander::verbose
VerboseMode verbose
flag signaling that the commands should output user understanable text
Definition: Commander.h:89
Commander::lpf
void lpf(LowPassFilter *lpf, char *user_cmd)
Definition: Commander.cpp:364
SCMD_PID_D
#define SCMD_PID_D
PID gain D.
Definition: commands.h:28
SCMD_DOWNSAMPLE
#define SCMD_DOWNSAMPLE
Monitoring downsample value.
Definition: commands.h:40
Commander::pid
void pid(PIDController *pid, char *user_cmd)
Definition: Commander.cpp:327
CommandCallback
void(* CommandCallback)(char *)
command callback function pointer
Definition: Commander.h:19
SCMD_LIM_VOLT
#define SCMD_LIM_VOLT
Limit voltage.
Definition: commands.h:34
CMD_DECIMAL
#define CMD_DECIMAL
command setting decimal places - only for commander
Definition: commands.h:22
SCMD_PID_P
#define SCMD_PID_P
PID gain P.
Definition: commands.h:26
Commander::scalar
void scalar(float *value, char *user_cmd)
Definition: Commander.cpp:381
PIDController
Definition: pid.h:12
CMD_MONITOR
#define CMD_MONITOR
monitoring
Definition: commands.h:16
SCMD_PID_RAMP
#define SCMD_PID_RAMP
PID ramp.
Definition: commands.h:29
CMD_SENSOR
#define CMD_SENSOR
sensor offsets
Definition: commands.h:15
nothing
@ nothing
Definition: Commander.h:12
angle_openloop
@ angle_openloop
Definition: FOCMotor.h:32
Commander::com_port
Stream * com_port
Serial terminal variable if provided.
Definition: Commander.h:93
SCMD_SET
#define SCMD_SET
Set variables to be monitored.
Definition: commands.h:43
Commander::motor
void motor(FOCMotor *motor, char *user_cmd)
Definition: Commander.cpp:102
LowPassFilter
Definition: lowpass_filter.h:12
CMD_SCAN
#define CMD_SCAN
command scaning the network - only for commander
Definition: commands.h:20
SCMD_LIM_CURR
#define SCMD_LIM_CURR
Limit current.
Definition: commands.h:33