I have gotten started with simpleFOC and so far it seems like a fantastic project.
I am running a simpleFOCMini controlled from raspberry pi pico. I use the commander to control the motor by sending default commands and monitor interfaces to read data back.
When I control the motor from my m1 macbook pro it runs completely smooth either using a serial terminal or a python script to send commands. However when I run the same unit from a Raspberry Pi 5 AND monitor is used the movement jerks seemingly in time with the reporting from monitor. If I disable monitoring in the program running on the pico the movement is smooth also when run from the Pi5. The result is the same wether I use a serial terminal or python script on the PI.
I have attempted to downsample monitoring and it then became clear that it jerks for every reporting point.
The pico is connected to the Pi using USB, and the Pi is running Ubuntu 24.04
I have now tried all baud rates between 9600 - and 460800. I can see no discernible difference. Though I must report that the jerking in time with the monitor reports also happens on my m1, just much more subtly.
For this project I really only need the motor position, is there possibly a “lighter” way to read this?
In the future to be able to use the monitor telemetry solution is naturally preferable.
I include the code here just in case.
Thank you again!
Thor
#include <Arduino.h>
#include <SimpleFOC.h>
// Define board type here - uncomment the board you're using
//#define BOARD_TYPE_SHIELD
#define BOARD_TYPE_MINI
#ifdef BOARD_TYPE_SHIELD
const int pwmPin1 = 0;
const int pwmPin2 = 1;
const int pwmPin3 = 2;
const int enablePin = 3;
#elif defined(BOARD_TYPE_MINI)
const int pwmPin1 = 10;
const int pwmPin2 = 11;
const int pwmPin3 = 12;
const int enablePin = 13;
#else
#error "Please define either BOARD_TYPE_SHIELD or BOARD_TYPE_MINI"
#endif
// magnetic sensor instance - SPI
MagneticSensorSPI sensor = MagneticSensorSPI(17, 14, 0x3FFF);
float filteredAngle = 0.0;
const float alpha = 0.001; // Low-pass filter coefficient
// BLDC motor & driver instance
BLDCMotor motor = BLDCMotor(11);
BLDCDriver3PWM driver = BLDCDriver3PWM(pwmPin1, pwmPin2, pwmPin3, enablePin);
// commander interface
Commander command = Commander(Serial);
//Commander command = Commander(Serial1);
void doMotor(char* cmd) { command.motor(&motor, cmd); }
//void onMotor(char* cmd){ command.motor(&motor, cmd); }
//void doTarget(char* cmd){command.scalar(&motor.target, cmd);}
void setup() {
// monitoring port
Serial.begin(115200);
// enable the debugging output
SimpleFOCDebug::enable(&Serial);
// initialise magnetic sensor hardware
sensor.init();
// link the motor to the sensor
motor.linkSensor(&sensor);
// driver config
// power supply voltage [V]
driver.voltage_power_supply = 12;
driver.init();
// link driver
motor.linkDriver(&driver);
// set control loop type to be used
motor.controller = MotionControlType::angle;
// contoller configuration based on the control type
motor.PID_velocity.P = 0.4;
motor.PID_velocity.I = 5;
motor.PID_velocity.D = 0;
// default voltage_power_supply
motor.voltage_limit = 3;
// velocity low pass filtering time constant
motor.LPF_velocity.Tf = 0.01;
// angle loop controller only deceleration on lower values.
motor.P_angle.P = 20;
// angle loop velocity limit
motor.velocity_limit = 50;
// initialise motor
motor.init();
// align encoder and start FOC
motor.initFOC();
// set the inital target value
motor.target = 0;
// define the motor id
//command.add('A', onMotor, "motor");
//command.add('T',doTarget,"target");
char motor_id = 'M';
command.add(motor_id,doMotor,"motor");
// use monitoring with serial for motor init
// comment out if not needed
motor.useMonitoring(Serial);
motor.monitor_downsample = 250; // default 10
motor.monitor_start_char = motor_id; // the same latter as the motor id in the commander
motor.monitor_end_char = motor_id; // the same latter as the motor id in the commander
command.verbose = VerboseMode::machine_readable;
// Run user commands to configure and the motor (find the full command list in docs.simplefoc.com)
Serial.println(F("Motor commands sketch | Initial motion control > torque/voltage : target 2V."));
_delay(1000);
}
void loop() {
// Regularly update the sensor reading
sensor.update();
// iterative setting of the FOC phase voltage
motor.loopFOC();
// iterative function setting the outter loop target
// velocity, position or voltage
// if target not set in parameter uses motor.target variable
motor.move();
// user communication
command.run();
/*
static unsigned long lastMonitorTime = 0;
if (millis() - lastMonitorTime > 10) { // Adjust the interval as needed
motor.monitor();
lastMonitorTime = millis();
}
*/
motor.monitor();
}
// Print the filtered angle
Hi, is this with the mbed core from Arduino or the earlephilhower core? If using the mbed core, I’d try the other one…
If it doesn’t improve then it’s probably an issue of unbuffered serial writes. You’ll have to change the monitoring implementation to not cause blocking IO. One way to do this would be to use the Telemetry code from our drivers repo. In this code base I’ve already solved that issue.
The code is compiled using PlatformIO in Vscode I assume this is using the mbed core. I think that my Arduino IDE has the Arduino mbed core. I will investigate switching and see if that changes things.
Then I will investigate the telemetry code, that sounds good.