B-G431-ESC Current Sensing Working with I2C Encoder

Hi Folks,

I just wanted to make a quick post regarding the B-G431-ESC board and using closed loop control with current sensing. Since upgrading to SimpleFOC v2.2.3 (thank you all!), I’ve been able to control my gimbal motor torque using current sensing. The only thing I had to add was:

build_flags =
-DHAL_OPAMP_MODULE_ENABLED

to my .ini file in PlatformIO.

I am using an AS5600 and I2C to do position sensing, and followed the instructions here to get started: B-G431B-ESC1: Beginner guide + I2C guide

One question for the community - since I am now using the existing broken out pins for I2C, does anyone know if there are other broken out pins (UART maybe?) that could be used for an incremental encoder like the AMT103? I would need 2 digital pins for it, since i already have 5V and GND available.

Cheers all!

2 Likes

I would venture a guess and say yes. The uart pins are just digital pins. Let’s see if anyone else provides feedback.

Cheers,
Valentine

Cheers! Looks like I should try it out and report back!

If you are using two of the hall sensor pins for I2C, then you are left actually with 4 free digital pins. The tx/rx for uart, the third hall pin and the pwm pin next to the uart pins.

Using the UART pins is convenient because they are next to each other, however, if you need uart debugging you can keep them for serial and use the third hall pin and the PWM pin as digital i/o pins. I believe. Give it a try. You will need a lot of patience and some extra-fine soldering skills however. Whoever designed that board was some kind of engineering sadist.

Cheers,
Valentine

Lol yeah, really! The G4 is such a powerful MCU, it’s such a shame they crippled this demo board with so few IOs…

In terms of attaching an encoder, it can work on the Hall Sensor Inputs, I think.
Any digital pins that support interrupts can be used with our Encoder class…
To use the STM32HardwareEncoder class from our drivers repository the pins all have to be on the same timer…

If they broke out an SPI channel this board could have been a big winner, even with the overheating problem. UART, Hall/I2C, SPI and CAN. Users can always add a good heatsink to control the temperature.

Hi.

@wrcman555 Could you share your setup code. For some reason driver.init() returns zero.

@HoeckDK Sure! See below.

#include <SimpleFOC.h>

// Motor instance
BLDCMotor motor = BLDCMotor(11);
BLDCDriver6PWM driver = BLDCDriver6PWM(A_PHASE_UH, A_PHASE_UL, A_PHASE_VH, A_PHASE_VL, A_PHASE_WH, A_PHASE_WL);
LowsideCurrentSense currentSense = LowsideCurrentSense(0.003, -64.0/7.0, A_OP1_OUT, A_OP2_OUT, A_OP3_OUT);

// encoder instance
MagneticSensorI2C sensor = MagneticSensorI2C(AS5600_I2C);

// instantiate the commander
Commander command = Commander(Serial);
void onMotor(char* cmd){ command.motor(&motor, cmd); }

void setup() {
  
  // configure i2C
  Wire.setClock(400000);
  
  // 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 the motor and the driver
  motor.linkDriver(&driver);
  
  // link current sense and the driver
  currentSense.linkDriver(&driver);

  currentSense.init();
  // no need for aligning
  currentSense.skip_align = true;
  motor.linkCurrentSense(&currentSense);
  
  // aligning voltage [V]
  motor.voltage_sensor_align = 2;
  // index search velocity [rad/s]
  //motor.velocity_index_search = 3;

  // control loop type and torque mode 
  motor.torque_controller = TorqueControlType::foc_current;
  motor.controller = MotionControlType::velocity;
  motor.motion_downsample = 0.0;

  // velocity loop PID
  motor.PID_velocity.P = 0.1;
  motor.PID_velocity.I = 3.0;
  // Low pass filtering time constant 
  motor.LPF_velocity.Tf = 0.005;
  
  // angle loop PID
  motor.P_angle.P = 16.0;
  // Low pass filtering time constant 
  motor.LPF_angle.Tf = 0.0;
  
  // current q loop PID 
  motor.PID_current_q.P = 1.0;
  motor.PID_current_q.I = 200.0;
  // Low pass filtering time constant 
  motor.LPF_current_q.Tf = 0.001;
  
  // current d loop PID
  motor.PID_current_d.P = 1.0;
  motor.PID_current_d.I = 200.0;
  // Low pass filtering time constant 
  motor.LPF_current_d.Tf = 0.001;

  // Limits 
  motor.velocity_limit = 35.0; // 100 rad/s velocity limit
  motor.voltage_limit = 6.0;   // 12 Volt limit 
  motor.current_limit = 0.5;    // 2 Amp current limit

  // use monitoring with serial 
  Serial.begin(115200);

  // comment out if not needed
  motor.useMonitoring(Serial);
  
  // downsampling
  motor.monitor_downsample = 10; // default 10
  
  // initialize motor
  motor.init();
  
  // align encoder and start FOC
  motor.initFOC();

  // add target command T
  command.add('M', onMotor, "motor");

  Serial.println(F("Motor ready."));
  
  _delay(1000);
}

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

  // function intended to be used with serial plotter to monitor motor variables
  // significantly slowing the execution down!!!!
  motor.monitor();
  
  // user communication
  command.run();

}
1 Like

Update - I was successfully able to use an AMT102 encoder with the B-G431. I used the PWM and Hall 1 pin (PA15, PB6). I set the internal pullups to be used in the SimpleFOC code. The only issue I found was that with high sensor resolution (2048 ppr) and speeds above 25 rad/s, there was some jitter in velocity mode. Decreasing the ppr to 1024 via the dip switches alleviated the issue. So now, I can control my motor using the AMT encoder, and have the AS5600 sensor on I2C for sensing another angle in my project. Thanks for help folks!

2 Likes

Fantastic! It’s always very educational to see what others are doing. Thank you for the update.

Cheers,
Valentine

Hi wrcman555

I tried your code… Except changing pole pairs to 8 and request it to align sensor.

I can see the sensor is working, if I manually turn the motor.

My ini file:
[env:disco_b_g431b_esc1]
platform = ststm32
board = disco_b_g431b_esc1
framework = arduino
monitor_speed = 115200
debug_tool = stlink
upload_protocol = stlink

lib_deps =
askuric/Simple FOC @ 2.2.3

build_flags =
-DHAL_OPAMP_MODULE_ENABLED

Any ideas?

Hi @HoeckDK,

Please add a line:

lib_archive = false

to your platformio.ini

Let us know if this helps :slight_smile:

That helped. Thanks a lot.

Hi,
I’m grateful to the community and all the efforts you guys have put in this.
I am able to run open-loop motion control without any issues on the B-G431 board (running through the Arduino IDE). But running into issues when working with Closed Loop. I’m using the AS5600 in I2C mode (and the sensor is working fine by itself). I’m trying to see if @wrcman555 's suggestion to set the build_flags would work for me (not sure, but just trying to troubleshoot). How do I set this up in the Arduino IDE?
I’m using boards-manager library from stm32duino’s github.
Any ideas?

Hi @mizzi_labs , welcome to SimpleFOC!

Setting build flags in ArdunioIDE is a bit of a pain. You’d have to edit the platform files, there are instructions for this you can find online.

But the OPAMP build flag won’t help in this case, if this were missing then you would be getting compile errors and would not be able to build any SimpleFOC code for the board.

Hi @runger - thank you for the quick response. Yes, you are right. I followed this suggestion and it worked fine! update boards.txt

1 Like