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();
}