Next Steps for Tuning: Studio, WebController

New user here. Using simpleFOC example code I have a BLDC running. The goal is to run a motor at constant speed, with the ability to change the target speed via serial.

I’ve looked at the lowest and highest speeds I can go by changing the code. Now I would like to look at the performance and tune the various parameters, PID, etc… What is the best approach:

  1. Get simpleFOCstudio running? This was a challenge to get installed, but I can’t get any traces or get the motor to run. Unable to find documentation or trouble shooting info.
  2. Get simpleFOCwebcontroller running? Following the limited info on github, I connect, then it freezes with “waiting for motors list from controller…”. There is very limited discussion here about this tool. Perhaps it is too new to be used by a newbie, or there are still issues?

For either tool, I am unable to find step by step examples, online videos, or other guides that have been helpful for getting started on other hardware/software projects. Am I missing something?

Hi @aminer2k ,

Both tools basically do the same thing, they offer a graphical user interface to send commands using the serial port interface. Neither both should disturb the operation of your BLDC.

These two links give instructions on what to do to get the tools working:

Maybe if you show us the code you’re running we can see what might be wrong.

Thank you, yes, those are the main resources and starting points I’ve been using. I’ll look at it some more and paste some code here if I continue to struggle getting them to plot data.

2 Likes

As a new user, I’ll provide my 2 cents on SimpleFOCStudio (SFS). I think the Arduino code is quite confusing which makes it all confusing at first.

My initial impression was that SFS was more like the evaluation boards made by Trinamic. You plug them into your computer and control the driver directly from your computer, no firmware required whatsoever. So I assumed that I would just plug the Arduino board into my computer and begin to control it. But it does look like it requires a sketch to be uploaded to the board first.

The confusing part is that it’s not made noticeably clear in the GitHub repo, and the section about Arduino code is at the very bottom of the page which makes it hard to see because the order is not logical (Arduino code needs be uploaded before using the application).

I think the Arduino section should just get moved to the top of the page and provide slightly more info on it.

2 Likes

After looking into it more, I have code, and a process for opening simplefocstudio that looks like it is communicating with the system.

Board: Due with a simpleFOCminiboard v1
Motor: single pole pair BLDC, ~20W motor

First, the code I’ve had for a while that runs the system at constant velocity (no simpleFOCstudio). I can change the PIDs, or target velocity, and is spins as I would expect. Pulls up to 0.4 amps.

#include <SimpleFOC.h>

// define BLDC motor
//  BLDCMotor(int pp, (optional R, KV))
//  - pp  - pole pair number
//  - R   - phase resistance value - optional
//  - KV  - motor KV rating [rpm/V] - optional
BLDCMotor motor = BLDCMotor( 1,1.35,341 );
//  BLDCDriver3PWM( int phA, int phB, int phC, int en)
//  - phA, phB, phC - A,B,C phase pwm pins
//  - enable pin    - (optional input)
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 10, 11, 8);

//  Encoder(int encA, int encB , int cpr, int index)
//  - encA, encB    - encoder A and B pins
//  - ppr           - impulses per rotation  (cpr=ppr*4)
//  - index pin     - (optional input)
Encoder encoder = Encoder(2, 3, 512);
// channel A and B callbacks
void doA(){encoder.handleA();}
void doB(){encoder.handleB();}

// velocity set point variable
// RPM = Rad/s * 9.54
//
//
float target_velocity_RPM = 300; // RPM
float target_velocity = target_velocity_RPM/9.549296; // rad/s
//float target_velocity = 31.4159; // rad/s

// commander interface
Commander command = Commander(Serial);
void onTarget(char* cmd){ command.scalar(&target_velocity, cmd); }

void setup() {
  
  // initialize encoder hardware
  encoder.init();
  // hardware interrupt enable
  encoder.enableInterrupts(doA, doB);

  // power supply voltage
  // default 12V
  driver.voltage_power_supply = 10; // what your external power supply is set to
  driver.init();
  // link the motor to the driver
  motor.linkDriver(&driver);

  // set control loop type to be used
  motor.controller = MotionControlType::velocity;

  // velocity PI controller parameters
  // default P=0.2 I = 20
  motor.PID_velocity.P = 0.3;
  motor.PID_velocity.I = 10;
  //default voltage_power_supply
  motor.voltage_limit = 10;  //The voltage_limit parameter is intended if, for some reason, you wish to limit the voltage that can be sent to your motor.
  
  // velocity low pass filtering
  // default 5ms - try different values to see what is the best. 
  // the lower the less filtered
  //motor.LPF_velocity.Tf = 0.01; // orignal value
  motor.LPF_velocity.Tf = 0.005;

  // link the motor to the sensor
  motor.linkSensor(&encoder);

  // initialize motor
  motor.init();
  // align encoder and start FOC
  motor.initFOC();

  // add target command T
  //command.add('T', doTarget, "target velocity");
  command.add('M',onTarget,"my motor");

  // monitoring port
  Serial.begin(115200);
  Serial.println("Motor ready.");
  Serial.println("Set the target velocity using serial terminal:");
  _delay(1000);
}


void loop() {
  // iterative foc function 
  motor.loopFOC();

  // iterative function setting and calculating the velocity loop
  // this function can be run at much lower frequency than loopFOC function
  motor.move(target_velocity);

  // user communication
  command.run();
}

Starting from the online code generator, the code I have that simpleFOCstudio will communicate with:

#include <SimpleFOC.h>

// BLDC motor instance BLDCMotor(polepairs, (R), (KV))
BLDCMotor motor = BLDCMotor(1, 1.35, 341);

// BLDC driver instance BLDCDriver3PWM(phA, phB, phC, (en))
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 10, 11);

// position / angle sensor instance Encoder(encA, encB , cpr, (index))
Encoder sensor = Encoder(2, 3, 512);
void doA(){sensor.handleA();}
void doB(){sensor.handleA();}

float target_velocity_RPM = 300; // RPM
float target_velocity = target_velocity_RPM/9.549296; // rad/s


// commander instance
Commander command = Commander(Serial);
void doMotor(char* cmd) { command.motor(&motor, cmd); }

void setup() {
    // start serial
    Serial.begin(115200);

    // initialize sensor
    sensor.init();
    // enable encoder interrupts
    sensor.enableInterrupts(doA, doB);
    // link sensor to motor
    motor.linkSensor(&sensor);

    // set power supply voltage
    driver.voltage_power_supply = 10;
    // set driver voltage limit, this phase voltage
    driver.voltage_limit = 10;
    // initialize driver
    driver.init();
    // link driver to motor
    motor.linkDriver(&driver);

    // set motion control type to velocity
    motor.controller = MotionControlType::velocity;

    // set torque control type to voltage (default)
    //motor.torque_controller = TorqueControlType::voltage;

    // set FOC modulation type to sinusoidal
    motor.foc_modulation = FOCModulationType::SinePWM;

    // velocity PID controller
    motor.PID_velocity.P = .3;
    motor.PID_velocity.I = 10;
    //motor.PID_velocity.D = 0;
    // angle / position P controller
    //motor.P_angle.P = ;
    // set motor voltage limit, this limits Vq
    motor.voltage_limit = 10;
    // set motor velocity limit
    motor.velocity_limit = 100;

    //motor.LPF_velocity.Tf = 0.005;
    // link the motor to the sensor
    //motor.linkSensor(&sensor);
  
    // initialize motor
    motor.init();

    // align sensor and start FOC
    motor.initFOC();


    // add the motor to the commander interface
    // The letter (here 'M') you will provide to the SimpleFOCStudio
    command.add('M',doMotor,"motor");
    // tell the motor to use the monitoring
    motor.useMonitoring(Serial);
    motor.monitor_downsample = 0; // disable monitor at first - optional
  

    _delay(1000);
}

void loop() {
    // main FOC algorithm function
    // the faster you run this function the better
    motor.loopFOC();

    // this function can be run at much lower frequency than loopFOC()
    motor.move();

    // real-time monitoring calls
    motor.monitor();
    // real-time commander calls
    command.run();
  
}

simpleFOCstudio will connect, however:

  1. it will not spin. I send commands such as “M10”, changing the target velicity to 10, but it does not move. If I spin the shaft by hand the plot changes. The current on the supply is always 0.
  2. on connecting, it appears to import the parameters from the code, but the integral value is always 0, even though in the code it is 10.
  3. it looks like unless I change the output ramp and output limit, the current Q does not change (on the screen, the actually current draw is always zero, no movement)
  4. If i add certain things to the code, like motor.LPF_velocity.Tf, it seems to crash studio.

please advise on what I am missing, on how to get this to spin in studio, and be able to then optimize it (which I think it one of the purposes of simpleFOCstudio…)

Hi @aminer2k

The use of SimpleFOCStduido should not affect the way the device behaves, since it is nothing more than an application with a graphical environment that sends commands in response to user interaction and graphically displays the information sent by the device.

To try and solve your problem, what I would do is: first try using your sketch using the serial line interface with a console that connects via the serial port. Try sending commands by typing directly. Once you’ve gotten it to work correctly by issuing the commands in a shell, test if it works using SimpleFOCStduido.