TL;DR
I have linked a working sensor (writes to serial fine). The angle varible in the motor class is not updating even after linking, init
, initFOC
and motor.move
in the loop. However, the velocity is updating…(see Motor Class section below).
System details:
IDE: Platform IO (MacOS)
MCU:STM32 F401CC
Board: We Act BlackPill
Motor: Portescap 16ECP36 Ultra EC + 30:1 planetary gear head (this is niche)
Encoder: 3 hall effects on motor, placed by manufacturer.
Deep Dive
I am using a hall effect encoder to control a motor.
(I know hall effects have limitations)
The encoder is working.
(I used the example)
I get output which looks like the following, this updates as I drive the motor by hand:
18.85 0.00
18.85 0.00
18.85 0.00
17.80 -29.73
17.80 -29.73
17.80 -29.73
17.80 -29.73
Commander
However, when I link the sensor to the motor and monitor the motor I dont get position updates!
motor.linkSensor(&sensor);
I am using the commander to monitor the motor.
However, when I call MMG6
(to get the angle) it always gives 0.
Telemetery
I have tried usin telemetery instead of the commander.
motor.useMonitoring(Serial);
motor.monitor_variables = _MON_TARGET | _MON_VEL | _MON_ANGLE;
motor.monitor_downsample = 100; // default 10
and then in the loop:
motor.monitor();
I get the following:
0.0000 0.0000 0.0000
0.0000 0.0000 0.0000
0.0000 0.0000 0.0000
0.0000 0.0000 0.0000
Global variables
Finally I have used the raw motor variables to monitor what the motor thinks is happening:
Serial.println(motor.shaft_angle);// print current motor position to the serial terminal
This also reads zero.
Motor class
This appears to be linked to various motor methods not reading/updating appropriately.
When I add motor.move()
for instance the velocity seems to update appropriately but still not the position.
In this case the velocity is correct for commander, telemetery and global vars
main.cpp:
This should demonstrate my issue
(this is Platform IO code, Arduino will need to remove the `#include <Arduino.h>)
The output should show the following:
- The motor position increments continuously (steps of 0.01 rads) from 0 - 2pi before returning to 0:
Motor class angle (rads): 6.28, Sensor class angle (rads): -12.57
Motor class angle (rads): 0.00, Sensor class angle (rads): -12.57
- The sensor position increments in large steps related to the wide (120 degree) hall sensor placement:
Motor class angle (rads): 0.39, Sensor class angle (rads): -12.57
Motor class angle (rads): 0.39, Sensor class angle (rads): -13.61
- The senor position reacts to me backdriving the motor, the motor position does not.
#include <Arduino.h>
#include <SimpleFOC.h>
BLDCMotor motor = BLDCMotor(1, 4.05, 1200);
BLDCDriver3PWM driver = BLDCDriver3PWM(PA7, PA6, PA5, PA4);
HallSensor sensor = HallSensor(PA1, PA2, PA3, 1);
// Interrupt routine initialization (3 sensors = 3 callbacks)
void doA(){sensor.handleA();}
void doB(){sensor.handleB();}
void doC(){sensor.handleC();}
// instantiate the commander
Commander commander = Commander(Serial);
void onMotor(char* cmd){ commander.motor(&motor,cmd); }
void setup() {
Serial.begin(115200);
SimpleFOCDebug::enable();
// Hall sensor working!
sensor.pullup = Pullup::USE_INTERN;
sensor.init();
sensor.enableInterrupts(doA, doB, doC);
motor.linkSensor(&sensor);
// Diver (20kHz PWM)
driver.pwm_frequency = 20000;
driver.voltage_power_supply = 24;
driver.voltage_limit = 3;
driver.init();
// Link sensor and driver to motor
motor.linkDriver(&driver);
motor.voltage_sensor_align = 3;
motor.foc_modulation = FOCModulationType::SinePWM;
motor.controller = MotionControlType::velocity_openloop;
motor.voltage_limit = 3; // Volts
// or current - if phase resistance provided
motor.current_limit = 0.5; // Amps
//motor.useMonitoring(Serial);
motor.monitor_variables = _MON_TARGET | _MON_VEL | _MON_ANGLE;
motor.monitor_downsample = 100; // default 10
motor.voltage_sensor_align = 3;
motor.init();
motor.initFOC();
motor.target = 1;
// add target command T
commander.add('M',onMotor,"target setting");
}
void loop() {
motor.monitor();
motor.loopFOC();
motor.move();
Serial.print("Motor class angle (rads): ");
Serial.print(motor.shaft_angle); // Print current motor position to the serial terminal
sensor.update();
Serial.print(", Sensor class angle (rads): ");
Serial.println(sensor.getAngle()); // Print current sensor position to the serial terminal
commander.run();
}