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
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 …
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:
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:
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…
@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)
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?
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()
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)
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
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} )