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