Cant get good data from sensor/can't turn the motor

Hi guys, it 's a great discussion in here! :smiley:

@Owen_Williams thanks for the fix for the find_pole_pairs example I have included it to the new version of the code.

@breef Unfortunately, both of your motors are a bit to much for the shield. The board is designed for the motors closer to resistance of 10 ohms, and for currents under 5A peak. And if you would be planning to run this motor with 2A+ you should consider cooling, a heat sink or something similar.

I will try to document this better when I am back, but for now I would like to provide you guys with an example code of the open motor control and one example of how exactly to limit the voltages.

Open loop motor control - motor test

 // Open loop motor control example 
 #include <SimpleFOC.h>

// motor instance
BLDCMotor motor = BLDCMotor(3, 10, 6, 11, 7);

void setup() {
  
  // power supply voltage
  // default 12V
  motor.voltage_power_supply = 12;
  
  // choose FOC modulation (optional)
  motor.foc_modulation = FOCModulationType::SpaceVectorPWM;

  // init motor hardware
  motor.init();

  Serial.begin(115200);
  Serial.println("Motor ready!");
  _delay(1000);
}

// target voltage to be set to the motor
float target_voltage = 2;
// target voltage to be set to the motor
float target_angle = 2;

void loop() {
  // integratiing the angle in real time
  // the larger the constant added the faster the movement
  target_angle += 0.001;
  
  // set open loop voltage
  motor.setPhaseVoltage(target_voltage, target_angle);
}

With this code you can test your driver and you can easily set the limiting voltage you are setting to the motor. Just make sure you change the target_voltage value. (this value can be negative as well).
In case of your motors you can start form 0.1V and then grow the values.

If you wish to change the velocity of the movement you just add a larger number instead of 0.001. You can put something like:
target_angle += 0.1;

Voltage limiting

Now when you want to limit the voltage there are 4 things you should know:

  1. First thing you should make sure to change is set is the motor.voltage_power_supply if you don’t put the real power supply voltage (doesn’t have to be dead on, but at least close) then all of your limiting in future steps will have an error proportional to the error of the motor.voltage_power_supply .

  2. First thing to limit is the variable motor.PI_velocity.voltage_limit = yourVoltageLimit; as suggestedd by @David_Gonzalez. This is very important.

  3. When you are running the voltage control then you don’t need any other limits, other than not setting the target voltage higher than you limit.

  4. When running position/velocity motion control then you need to set the
    motor.PI_velocity.voltage_limit = yourVoltageLimit; this variable is only used for position and velocity control, not for open loop and voltage control. You can see this on the diagrams in the Motion Control | Arduino-FOC

Here is a voltage control code with voltage limiting:

#include <SimpleFOC.h>

// Magnetic sensor
MagneticSensorI2C sensor = MagneticSensorI2C(0x36, 12, 0x0E, 4);

// Motor instance
BLDCMotor motor = BLDCMotor(9, 5, 6, 11, 8);

void setup() {

  // initialise magnetic sensor hardware
  sensor.init();
  // link the motor to the sensor
  motor.linkSensor(&sensor);

  // power supply voltage
  // default 12V
  motor.voltage_power_supply = your power supply;     
  // aligning voltage
  motor.voltage_sensor_align = your limit; 
  
  // choose FOC modulation (optional)
  motor.foc_modulation = FOCModulationType::SpaceVectorPWM;

  // set motion control loop to be used
  motor.controller = ControlType::voltage;

  // use monitoring with serial 
  Serial.begin(115200);
  // comment out if not needed
  motor.useMonitoring(Serial);

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

  Serial.println("Motor ready.");
  Serial.println("Set the target voltage using serial terminal:");
  Serial.println("But dont exceed your limit");
  _delay(1000);
}

// target voltage to be set to the motor
float target_voltage = 0;

void loop() {

  // main FOC algorithm function
  motor.loopFOC();

  target_voltage = 

  // Motion control function
  motor.move(target_voltage);
  
  // communicate with the user
  serialReceiveUserCommand();
}


// utility function enabling serial communication with the user to set the target values
// this function can be implemented in serialEvent function as well
void serialReceiveUserCommand() {
  
  // a string to hold incoming data
  static String received_chars;
  
  while (Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read();
    // add it to the string buffer:
    received_chars += inChar;
    // end of user input
    if (inChar == '\n') {
      
      // change the motor target
      target_voltage = constrain(received_chars.toFloat();, -your limit, your limit)
      Serial.print("Target voltage: ");
      Serial.println(target_voltage);
      
      // reset the command buffer 
      received_chars = "";
    }
  }
}

And here is a simple example of a velocity control (the limiting part is the same as for the position loop):

// Voltage motion control will placeholders for voltage limit
#include <SimpleFOC.h>

// magnetic sensor instance
MagneticSensorI2C sensor = MagneticSensorI2C(0x36, 12, 0x0E, 4);

// Motor instance
BLDCMotor motor = BLDCMotor(9, 5, 6, 11, 8);

void setup() {
 
  // initialise magnetic sensor hardware
  sensor.init();
  // link the motor to the sensor
  motor.linkSensor(&sensor);

  // power supply voltage
  // default 12V
  motor.voltage_power_supply = your power supply;
  // aligning voltage
  motor.voltage_sensor_align = your limit; 

  // set motion control loop to be used
  motor.controller = ControlType::velocity;

  // velocity PI controller parameters
  motor.PI_velocity.P = 0.2;
  motor.PI_velocity.I = 20;
  // default voltage_power_supply
  motor.PI_velocity.voltage_limit = your limit;

  // use monitoring with serial 
  Serial.begin(115200);
  // comment out if not needed
  motor.useMonitoring(Serial);

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

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

// velocity set point variable
float target_velocity = 0;

void loop() {
  // main FOC algorithm function
  motor.loopFOC();

  // Motion control function
  motor.move(target_velocity);
  
  // user communication
  serialReceiveUserCommand();
}

// utility function enabling serial communication with the user to set the target values
// this function can be implemented in serialEvent function as well
void serialReceiveUserCommand() {
  
  // a string to hold incoming data
  static String received_chars;
  
  while (Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read();
    // add it to the string buffer:
    received_chars += inChar;
    // end of user input
    if (inChar == '\n') {
      
      // change the motor target
      target_velocity = received_chars.toFloat();
      Serial.print("Target velocity: ");
      Serial.println(target_velocity);
      
      // reset the command buffer 
      received_chars = "";
    }
  }
}

I hope it helps, let me know how it goes!

I have released the new version of the library 1.4.1 which has a bit smaller memory footprint so please make sure to use the newest version. This might help with the find_pole_pairs issue.

I also have one quesstion

@Juxo, you say you are running the i2c sensor with the Nucleo boards, did you need to use pull-ups.

1 Like