Here is a useful bit of code to help debugging such things:
float target = 0;
char printVariable = 0;
void loop() {
unsigned long loopTime = _micros();
motor.loopFOC();
motor.move(target);
loopTime = _micros() - loopTime;
static unsigned long lastPrintTime = 0;
unsigned long t = millis();
if (printVariable && t >= lastPrintTime + 50)
{
lastPrintTime = t;
char string[256];
switch(printVariable)
{
case 's': sprintf(string, "%i\n", (int)(motor.shaft_velocity*1000)); break;
case 'a': sprintf(string, "%i\n", (int)(motor.shaft_angle*1000)); break;
case 'l': sprintf(string, "%i\n", loopTime); break;
case 't': sprintf(string, "%i\n", (int)target); break;
default: string[0] = 0;
}
if(string[0]) Serial.print(string);
}
switch(Serial.read())
{
case '!': delay(2); printVariable = Serial.available() ? Serial.read() : 0; break;
case 'N': motor.controller = (MotionControlType)(int)Serial.parseInt(); Serial.print("Set ");
case 'n': Serial.print("controller "); Serial.println(motor.controller); break;
case 'U': motor.foc_modulation = (FOCModulationType)Serial.parseInt(); Serial.print("Set ");
case 'u': Serial.print("foc_modulation "); Serial.println(motor.foc_modulation); break;
case 'Q': motor.torque_controller = (TorqueControlType)Serial.parseInt(); Serial.print("Set ");
case 'q': Serial.print("torque_controller "); Serial.println(motor.torque_controller); break;
case 'K': motor.KV_rating = Serial.parseFloat(); Serial.print("Set ");
case 'k': Serial.print("KV_rating "); Serial.println(motor.KV_rating); break;
case 'R': motor.phase_resistance = Serial.parseFloat(); Serial.print("Set ");
case 'r': Serial.print("phase_resistance "); Serial.println(motor.phase_resistance); break;
case 'L': motor.phase_inductance = Serial.parseFloat(); Serial.print("Set ");
case 'l': Serial.print("phase_inductance "); Serial.println(motor.phase_inductance); break;
case 'Z': motor.zero_electric_angle = Serial.parseFloat(); Serial.print("Set ");
case 'z': Serial.print("zero_electric_angle "); Serial.println(motor.zero_electric_angle); break;
case 'T': target = Serial.parseFloat(); Serial.print("Set target "); Serial.println(target); break;
case 't': Serial.print("target "); Serial.println(target); break;
case 'V': motor.voltage_limit = motor.P_angle.limit = motor.PID_current_q.limit = motor.PID_current_d.limit = Serial.parseFloat(); Serial.print("Set ");
case 'v': Serial.print("voltage_limit "); Serial.println(motor.voltage_limit); break;
case 'C': motor.current_limit = motor.PID_velocity.limit = Serial.parseFloat(); Serial.print("Set ");
case 'c': Serial.print("current_limit "); Serial.println(motor.current_limit); break;
case 'O': motor.PID_velocity.output_ramp = Serial.parseFloat(); Serial.print("Set ");
case 'o': Serial.print("PID_velocity.output_ramp "); Serial.println(motor.PID_velocity.output_ramp); break;
case 'F': motor.LPF_velocity.Tf = Serial.parseFloat(); Serial.print("Set ");
case 'f': Serial.print("LPF_velocity.Tf "); Serial.println(motor.LPF_velocity.Tf); break;
case 'E': motor.LPF_angle.Tf = Serial.parseFloat(); Serial.print("Set ");
case 'e': Serial.print("LPF_angle.Tf "); Serial.println(motor.LPF_angle.Tf); break;
case 'P': motor.PID_velocity.P = Serial.parseFloat(); Serial.print("Set ");
case 'p': Serial.print("PID_velocity.P "); Serial.println(motor.PID_velocity.P); break;
case 'I': motor.PID_velocity.I = Serial.parseFloat(); Serial.print("Set ");
case 'i': Serial.print("PID_velocity.I "); Serial.println(motor.PID_velocity.I); break;
case 'D': motor.PID_velocity.D = Serial.parseFloat(); Serial.print("Set ");
case 'd': Serial.print("PID_velocity.D "); Serial.println(motor.PID_velocity.D); break;
}
}
You can add more variables as needed, although eventually you run out of letters to represent them ![]()
In serial monitor, you type things like V1.5 to set voltage limit 1.5, or v to print out the current voltage limit, and !s to print velocity to the serial monitor 20 times per second, and ! alone to cancel the continuous printing.
The continuous printing is done with a single call to Serial.print, which as I said before will not block the CPU. And you can close serial monitor and open serial plotter to see the variable in graphical form.
Note: STM32’s implementation of sprintf does not support floating point, so you have to multiply by 1000 and cast to int to see the decimal portion.
You might try adding a printVariable case for motor.voltage.Ua to see what voltage it thinks it’s outputting, and compare the shape of the wave to what you see on the oscilloscope when probing phase A.