Problem with going from openloop to closed using hall sensors

I am now getting consistant values e.g:

Pole pairs (PP) estimator
-

Estimated PP : -5
PP = Electrical angle / Encoder angle 
1080.00/-232.65 = -4.64

PP number cannot be negative
 - Try changing the search_voltage value or motor/sensor configuration.

I have tried changing the search voltage to no avail, does a negative value mean I have to change the phases on the motor (reverse) to match the sensor?

Maybe this thread can help someone else, even if I am only taking to myself :slight_smile:
So, I changed the DIR on the sensor to GND instead of VCC and now sensor matches motor direction.

However even with that the motor does not start. Even at low voltage:
1v draws 0.02A, motor still
2v draws 0.6 motor still
3v draws 3A motor does not move, at current limit…
4v draws 3A 24v supply sags to 15 …

I am having no joy with closed loop at all, can someone please HELP …

I’ve not used the AS5600 for years.
Maybe try:

MagneticSensorI2C sensor = MagneticSensorI2C(AS5600_I2C);

void setup() {
  Wire.setClock(400000);
  sensor.init();
}

instead of

MagneticSensorAS5600 sensor;
Wire.begin(33, 32, (uint32_t)400000);
sensor.init()

The sensor class calls begin() internally during sensor.init() so you shouldn’t need to call begin() unless you want to use non standard pins. In which case you might need to do:

Wire1.begin(33, 32, (uint32_t)400000);
sensor.init(&Wire1);

Until you can do a reliable sensor_test then I wouldn’t try a closed loop example. With the sensor test you manually turn the motor and hope to see the angle change 2*PI with a single rotation.
Here is the example for a sensor test with and i2c sensor:

Hi Owen,

With my original code I can do the sensor test fine, I get approx 6 radians per full turn, turning it by hand. It’s getting it going closed loop that is the issue.
Open loop works fine …

I tried your code using wire1, but that does not work, get error messages about not talking to the sensor, just “wire” works. I don’t think pins 33 and 32 are standard, but I can’t see reference anywhere in your docs of what the default pins are for different boards.

Anyway my setup with the sensor works fine. Any suggestions on how to get it to run in closed loop, it tries to turn maybe a half turn or so, but then stalls drawing current limit on my power supply.

I presume open loop works fine. Maybe you can try open loop whilst printing out angle from sensor. I’m wondering whether noise from motor is messing up your i2c. Maybe sda and scl need to be supported by external pull-ups to deal with noise.

Might be worth pasting your code too so we get a clear idea of what you are doing

Thanks, I will look at noise on I2C and beef up the resistors (they are standard 10k, will try 4k7 or 3k3).

Attached is the code:

/**
 * 
 * Torque control example using voltage control loop.
 * 
 * Most of the low-end BLDC driver boards doesn't have current measurement therefore SimpleFOC offers 
 * you a way to control motor torque by setting the voltage to the motor instead of the current. 
 * 
 * This makes the BLDC motor effectively a DC motor, and you can use it in a same way.
 */
#include <SimpleFOC.h>
#include "encoders/as5600/MagneticSensorAS5600.h"

// BLDC motor & driver instance
BLDCMotor motor = BLDCMotor(4, 1.2, 100, 0.0013365);  
//BLDCDriver3PWM driver = BLDCDriver3PWM(25, 26, 27, 13, 15, 2);  
BLDCDriver3PWM driver = BLDCDriver3PWM(26, 27, 14, 13, 15, 2); 

// MagneticSensorAS5600 sensor;
MagneticSensorI2C sensor = MagneticSensorI2C(AS5600_I2C);

// voltage set point variable
float target_voltage = 0;
// instantiate the commander
Commander command = Commander(Serial);
void doTarget(char* cmd) { command.scalar(&target_voltage, cmd); }

void setup() { 
  
  //Wire.begin(33, 32, (uint32_t)400000);
  //AS5600Conf conf;
  //conf.fth = 0b111; conf.sf = 0b11; // Slow filter 2x, Fast filter 10LSB's
  // initialize encoder sensor hardware
  Wire.begin(33, 32, (uint32_t)400000);
  sensor.init(&Wire);

  //sensor.setConf(conf);

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

  // driver config
  // power supply voltage [V]
  driver.voltage_power_supply = 24;
  driver.voltage_limit = 12;

  driver.init();
  // link driver
  motor.linkDriver(&driver);

  // aligning voltage
  motor.voltage_sensor_align = 3;

  motor.motion_downsample = 20;
  
  // choose FOC modulation (optional)
  //motor.foc_modulation = FOCModulationType::SpaceVectorPWM;

  // set motion control loop to be used
  motor.controller = MotionControlType::torque;

  // 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.sensor_direction = Direction::CCW;
  //motor.zero_electric_angle = 3.56;
  motor.initFOC();
  //motor.disable();
  //while (true);


  // add target command T
  command.add('t', doTarget, "target voltage");

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


void loop() {

  // main FOC algorithm function
  // the faster you run this function the better
  // Arduino UNO loop  ~1kHz
  // Bluepill loop ~10kHz 
  motor.loopFOC();

  // Motion control function
  // velocity, position or voltage (defined in motor.controller)
  // this function can be run at much lower frequency than loopFOC() function
  // You can also use motor.move() and set the motor.target in the code
  motor.move(target_voltage);

  // user communication
  command.run();
}

EDIT: It was noise on the I2C lines, changed pullups to 3k3 and shielded the lines worked. Thanks for the help.

EDIT2: Also running very well in velocity closed loop, once I tuned the PID.

NOTE: With these AS5600 sensors they are critical in distance from magnet. 1mm is too close 1.5mm…2.5mm seemed ideal, at least for me…

1 Like

@Owen_Williams I have just re-introduced the bluetooth classic code back into the closed lopp velocity code and find that my timer interrupt conflicts with timers used by motor.loopFOC()

I used timer0, is there any other channels free, that you are not using?
(Using ESP32 Dev Board)

I did not have this issue with openloop.

Cheers

I see the following in the code:

typedef struct hw_timer_s
{
    uint8_t group;
    uint8_t num;
} hw_timer_t;

// Works for all chips
static hw_timer_t timer_dev[4] = {
    {0,0}, {1,0},  {0,1},  {1,1}
};

I presume you are using the first three, however I tried index 3, but that did not work either.

You might need to give us a refresher as to what pins you are using for what and when things stop working. You mentioned Bluetooth classic - does that mean you are using an external bluetooth module (e.g. hc-05)? And your communicating to this over serial rx/tx?

Still using esp32, right?

I am using the internal Classic bluetooth module in the ESP32. i.e#include "BluetoothSerial.h"
However I am using a timer interrupt to send data back to my phone, that interrupt no longer works in
closed loop, worked fine in openloop. I have tracked down the conflick to the use of motor.loopFOC() as mentioned earlier.
My interrupt code is:

uint8_t timer_id = 0;
uint16_t prescaler = 80; // Between 0 and 65 535
  int threshold = 200000; // 64 bits value (limited to int size of 32bits)

  timer = timerBegin(timer_id, prescaler, true);
  timerAttachInterrupt(timer, &timer_isr, true);
  timerAlarmWrite(timer, threshold, true);
  timerAlarmEnable(timer); 

I am presuming the timer I am using is conflicting with ones used by motor.loopFOC()

The exception I am getting when that interrupt is enabled is:

MOT: Align sensor.
MOT: Skip dir calib.
MOT: Skip offset calib.
MOT: No current sense.
MOT: Ready.
Motor ready.
Set the target velocity using serial terminal:
Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.

Core  1 register dump:
PC      : 0x40084ec8  PS      : 0x00050131  A0      : 0x80090712  A1      : 0x3ffbf67c  
A2      : 0x00000010  A3      : 0x00018010  A4      : 0x000637ff  A5      : 0x3ffbf65c  
A6      : 0x00000000  A7      : 0x3ffbded0  A8      : 0x00000000  A9      : 0x00000000  
A10     : 0x00030d40  A11     : 0x00000000  A12     : 0x800818cd  A13     : 0x3ffbf63c  
A14     : 0x3ffc41e8  A15     : 0xfffffbff  SAR     : 0x00000015  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x8009071e  LBEG    : 0x400029ac  LEND    : 0x400029cb  LCOUNT  : 0x00000000  


Backtrace: 0x40084ec5:0x3ffbf67c |<-CORRUPTED




ELF file SHA256: b70a77292ea133d5

Probably need the help of someone more familiar with esp32.

What does the timer_isr def look like?

void IRAM_ATTR timer_isr() {
  // ISR code here
}

It’s possible that if you’ve missed the IRAM_ATTR you might get that error.

No, my interrupt function is fine. You are not understanding correctly though. The Interrupt is working fine in openloop mode. I can control and read back rpm from the motor. In closed loop (with motor.loopFOC() in the loop) I can control the motor with bluetooth, but cannot send data back via my interrupt.
For reference, the interrupt code is:

// Interrupt to send data to phone.
void IRAM_ATTR timer_isr() {
    // This code will be executed every 1000 ticks, 200ms
    if (motor.shaft_velocity != lastVelocity) {
      //ftoa(motor.shaft_velocity*9.5492968,buffer, 0);
      dtostrf(motor.shaft_velocity*9.5492968,4,0,buffer);
      if(SerialBT.connected()) {
        SerialBT.println(buffer);
      }
      lastVelocity = motor.shaft_velocity;
    }  
}

The above is not the issue, it works fine. The issue is I don’t know what timer channels you use in motor.loopFOC(), can you not tell me what you have used? I am having issues finding it in the code. Then I can avoid using that timer for my interrupt function (if one is available still)

Hey,

The motor driver in SimpleFOC uses either the LEDC peripheral or the MCPWM peripheral, depending on what your ESP32 supports.

It does not use the general purpose timers.

Also, the open loop and closed loop modes use the MCPWM or LEDC timers in the same way, there’s no additional configuration or interrupts used in closed loop mode.

So I don’t see any reason for the motor control to be causing your problems, we’ll have to find out what’s going on. Are you trying to use current sensing also?

Are you sure you can write to Bluetooth serial from inside of an interrupt handler? I have my doubts.
It might be better to just set a flag in the interrupt handler and do the actual Bluetooth communication from the main loop

@runger

Are you trying to use current sensing also?
No.

You might be right about writing to bluetooth in the handler, I was just trying to get it out of the main loop, as I found putting it there causes issues with smooth running.

It doesn’t explain why bluetooth including the timer interrupt works fine with openloop, I can smoothly control the motor with my phone, and receive RPM info, but when I switch to velocity closed loop I get the crash.

I am not sure how to go forward with this, it seems bluetooth(classic) and sinpleFOC just won’t play nice together …BLE is even worse …

As mentioned above, it works fine for controlling the motor, just can’t use that interrupt to send data back to the phone.

It’s a good question why it crashes in closed loop but not in open loop. I can’t really say.

Using BLE or WiFi at the same time as SimpleFOC is difficult. SimpleFOC, at least in closed loop mode, will need most of your MCU time, and doesn’t like it if it gets interrupted for a long time (more than 1ms is definately too long).

So to use Bluetooth or WiFi along with SimpleFOC you need to do the communications asynchronously to SimpleFOC running. On a 2-core ESP32 this is possible, but not with just Arduino framework. You will need to use the FreeRTOS layer to handle multiple tasks running in parallel, and manage the allocation of the tasks to the MCU cores.

Thanks for the response. I am happy to just not have the RPM feedback at present. It does work ok with sending commands from my phone to enable/disable motor, FWD/REV, and a slider to control speed. This it does with a 250us loop time, so I am happy with that. (especially as I am running an AS5600 sensor
{but I2C at 1mhz and configured for fast filter} )

1 Like