Git Product home page Git Product logo

Comments (27)

RoboDurden avatar RoboDurden commented on August 28, 2024 1
LowPassFilter LPF_target(0.5);  //  the higher the longer new values need to take effect

void loop()
{
...
    motor.move(LPF_target(target));

from split_hoverboard_simplefoc.

Candas1 avatar Candas1 commented on August 28, 2024

[Moving the message here]
Some signs were wrong in my case:
image

The extrapolation seems to work at constant speed at least now.
image

I need to do more tests this evening.

from split_hoverboard_simplefoc.

Candas1 avatar Candas1 commented on August 28, 2024

I did some tests, it seems the zero_electrical_angle was still off by 0.17 something (should be 1.92 instead of 2.09), it needed to be tweaked.
The way the sensor alignment procedure is done in simplefoc, it cannot be precise, it's meant for encoders mainly, so for hall sensors it has to be tweaked by hand. I believe you also played around with this parameter.
That's what I meant when I said the hoverboard firmware are already tweaked for hoverboard wheels, those aspects are probably hardcoded or baked into the firmware.

I might have to work on a better sensor alignment for hall sensor.
With bad alignment, FOC will probably be bad even if the current sensing is done right.

from split_hoverboard_simplefoc.

RoboDurden avatar RoboDurden commented on August 28, 2024

With my 2.0 board the sensor alignment procedure never did work at all. Only with the Gen1 stm32F103 did it succeed.
That is why i never understood how you obtained the 2.09.
Yes i did try to optimize your 2.09 but did not find a better value:

unsigned long iOptimize = 0;
float fOptimize = 0;
..
  OUT2T(fOptimize*1000, motor.zero_electric_angle*1000)
  fOptimize = -0.2  * (ABS(	(float)((iOptimize++ + 20) % 80) - 40) - 20)/20;
  motor.zero_electric_angle = 2.09 + fOptimize;

I might have to work on a better sensor alignment for hall sensor.

Might be good if you would be more prescise. We have used the word "alignment" in so many contexts by now, so i do not really understand what you mean with "better sensor alignment".
Only parameter is this zero_electric_angle. So you want to write a better auto zero_electric_angle detection ?

from split_hoverboard_simplefoc.

Candas1 avatar Candas1 commented on August 28, 2024

Sensor alignment is what happens here.

This will work well with an encoder, but with a hall sensor it just gives you a hint.

I need to try this as well.

from split_hoverboard_simplefoc.

Candas1 avatar Candas1 commented on August 28, 2024

the motor is blocking in the other direction if I am using 1.92.
I need to investigate more.

from split_hoverboard_simplefoc.

Candas1 avatar Candas1 commented on August 28, 2024

Ok I think I found the solution, and I have learned more, I summarized it all here
I am curious how Eferu compares with those number but I wouldn't be able to check before this weekend.
Eferu doesn't have such compensation (or I couldn't find it in the model), probably it's optimized only for some of the speed range.

from split_hoverboard_simplefoc.

RoboDurden avatar RoboDurden commented on August 28, 2024

Nice. I do not really understand a lot of your post over there.
But i am working with my Arduino-FOC that i forkerd from your Arduino-FOC.
So if you publish your local code changes to your repo, i can sync my fork to test your work with my test setup :-)

(today i worked on a 20A 80V ESP32 OLED mppt charger..)

from split_hoverboard_simplefoc.

Candas1 avatar Candas1 commented on August 28, 2024

I updated the dev branch.

from split_hoverboard_simplefoc.

RoboDurden avatar RoboDurden commented on August 28, 2024

Now that is a bit confusing (for me). You seem to work on three different branches and the latest _configure6PWM is in main but smoothedSensor in another branch ?

from split_hoverboard_simplefoc.

Candas1 avatar Candas1 commented on August 28, 2024

I am talking about the dev branch of this repository:
image

It uses the dev-gd32 branch of my Arduino-foc fork, and the dev branch of my arduino-foc-drivers fork.

from split_hoverboard_simplefoc.

Candas1 avatar Candas1 commented on August 28, 2024

I did a pull request to simplefoc dev branch with the direction fix and they accepted it.
So I think the smoothing is complete.
I will work on improving the autodetect only after the current sensing.

from split_hoverboard_simplefoc.

RoboDurden avatar RoboDurden commented on August 28, 2024

Okay @Candas1 here my test comparison between EFeru and your firmware here on a Gen1 board:

  driver.voltage_power_supply = 26; // 3.6 * BAT_CELLS; // power supply voltage [V]
  motor.voltage_limit = driver.voltage_power_supply * 0.58; // should be half the power supply

STM32 Gen1 board:

bin	target	[rpm/V]	[A]

smFOC	T5+E	-5.4	0.17
smFOC	T-5+E	+5.3	0.17
EFeru	+390	-5.4	0.25
EFeru	390	+5.4	0.23

smFOC	T15+E	-11.4	0.31
smFOC	T-15+E	+11.1	0.30
EFeru	+760	-11.3	0.38
EFeru	-760	+11.3	0.37

smFOC	T26	-13.9	0.68
smFOC	T-26	+12.9	0.48
EFeru	1000	-14.6	0.50
EFeru	-1000	+15.0	0.51

no SmoothingSensor:

smFOC	T5+E0	-5.5	0.19
smFOC	T-5+E0	+5.3	0.19
smFOC	T15+E0	-11.8	0.49
smFOC	T-15+E0	+11.1	0.38

This inital nasty "push" might be because some class variable is not initialized to 0..

To make the Commander class work nicely with the short uart cable of the gen1 board, it would be nice if you would update your config.h to

// Define to prevent recursive inclusion
#ifndef CONFIG_H
#define CONFIG_H


#if defined(PLATFORMIO)
  #ifdef STM32F103RC
    #define HOVER_GEN   1
    #define HOVER_LAYOUT	0

    // too late here, has to be a build flag #define SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH false

    // call motor.initFOC() without parameters to auto align sensor and copy values from debug log
    #define MOTOR_zero_electric_offset  4.19  
    #define MOTOR_sensor_direction  Direction::CCW

    // log debug output over master/slave uart
    //#define DEBUG_UART  Serial
    HardwareSerial oSerialSteer(PB11, PB10);  // short cable 5VT EFeru USART3 GPIO Configuration
    #define DEBUG_UART oSerialSteer

  #else
    #define HOVER_GEN   2
    #define HOVER_LAYOUT	0

    // call motor.initFOC() without parameters to auto align sensor and copy values from debug log
    #define MOTOR_zero_electric_offset  2.09
    #define MOTOR_sensor_direction  Direction::CCW

    // SEGGER RTT Debug
    #define DEBUG_STLINK rtt              // Uncomment to enable DEBUG over stlink dongle

  #endif
#else
  // LAYOUT_x_y is used in defines.h
  #define HOVER_GEN   2
  #define HOVER_LAYOUT 0
  //  2_0	// https://github.com/flo199213/Hoverboard-Firmware-Hack-Gen2
  //  2_1	// https://github.com/krisstakos/Hoverboard-Firmware-Hack-Gen2.1
  //  2_2	// 2023/05/11 only MASTER and TEST_SPEED: motor is spinning but needs a push to startup :-/
  //  2_4	// NOT READY !!! https://github.com/RoboDurden/Hoverboard-Firmware-Hack-Gen2.x/issues/3
  //  2_5	// NOT READY !!! https://github.com/RoboDurden/Hoverboard-Firmware-Hack-Gen2.x/issues/11

  //  1_0	// old Gen 1 boards with two motors

    // call motor.initFOC() without parameters to auto align sensor and copy values from debug log
    #define MOTOR_zero_electric_offset  2.09
    #define MOTOR_sensor_direction  Direction::CCW

    // SEGGER RTT Debug
    #define DEBUG_STLINK rtt              // Uncomment to enable DEBUG over stlink dongle
    // log debug output over master/slave uart
    //#define DEBUG_UART  Serial2

#endif


#define BLDC_POLE_PAIRS   15    // all hoverboard motors have 15 pole pairs ?
#define BAT_CELLS         7     // battery number of cells. mostly 10 = 10s = 36V. Sometimes 7 = 7s = 25V

#ifdef DEBUG_UART
  #define DEBUG_UART_BAUD   115200    // [-] Baud rate for HoverSerial (used to communicate with the hoverboard)
#endif

#define TIME_SEND           10000         // [ms] Sending time interval


#endif //  CONFIG_H

https://github.com/Candas1/Split_Hoverboard_SimpleFOC/blob/dev/src/main.cpp#L88 would be changed to

Commander command = Commander(SERIALDEBUG);
The auto calibration did again not work for me.
I got this MOTOR_zero_electric_offset 4.19 from an older version of our code when the auto calibration did work.
By now i have the same identical bldc motors installed in the gen1 test setup and the gen2.0 setup.

Lower case comands were more suitable for me:

  command.add('t', doTarget, "target voltage");
  // add smoothing enable/disable command E (send E0 to use hall sensor alone, or E1 to use smoothing)
  command.add('e', enableSmoothing, "enable smoothing");
  command.add('p', doPhaseCorrection, "phase correction");
  command.add('z', doZero, "zero electrical angle");
  command.add('f', doLPF, "LPF");

I also added a low pass to target:

    fSpeed = 0.999 * fSpeed + 0.001 * target;

    //GPIO_BOP(GPIOB) = (uint32_t)GPIO_PIN_7;
    motor.move(fSpeed);
    //GPIO_BC(GPIOB) = (uint32_t)GPIO_PIN_7;

maybe this line is missing your main.cpp:

driver.voltage_limit = motor.voltage_limit; // stupid bug to have two voltage_limit in different places

from split_hoverboard_simplefoc.

Candas1 avatar Candas1 commented on August 28, 2024

Thank you.
Great so SFOC is more efficient, but not as fast.

It could be the inductance value has to be tweaked on different motors. I am using one with 5 coil wires and 30mm magnets. I am thinking about buying a LCR meter to measure it.

I tried the low pass filter class from SFOC some time ago but couldn't get it to work for the target.

No driver and voltage limit are equal by default.

from split_hoverboard_simplefoc.

RoboDurden avatar RoboDurden commented on August 28, 2024

I don't think so:

void BLDCMotor::init() {
...
  // sanity check for the voltage limit configuration
  if(voltage_limit > driver->voltage_limit) voltage_limit =  driver->voltage_limit;

motor::voltage_limit can be smaller than driver::voltage_limit

But i do no longer want to think about that stupidity to have two different voltage_limit
and on top both (seemingly to me) being used at random in BLDCMotor.cpp :-(

from split_hoverboard_simplefoc.

Candas1 avatar Candas1 commented on August 28, 2024

https://github.com/simplefoc/Arduino-FOC/blob/05954cb9691534dd478407505d810a68f1673a5e/src/drivers/BLDCDriver6PWM.cpp#L61

from split_hoverboard_simplefoc.

Candas1 avatar Candas1 commented on August 28, 2024

If you uncommented the curent sense, maybe the current sense alignment is running

from split_hoverboard_simplefoc.

RoboDurden avatar RoboDurden commented on August 28, 2024

Your last update to Candas1/Arduino-FOC/tree/dev-gd32 was two weeks ago.
So i do not understand what you mean with "... maybe the current sense alignment is running"

from split_hoverboard_simplefoc.

RoboDurden avatar RoboDurden commented on August 28, 2024

I have tested the smoothed sensor with 25V sine (stm Gen1 board):
stmstudio smooth Sine25V

    float fTarget = LPF_target(target) * (ABS((float)(((millis()-iLoopStart)/10 + 250) % 1000) - 500) - 250)/250;
    motor.move(fTarget);

    fAnglePred = fmod(smooth.angle_prev * 57.295779513082320876798154814105 + 360.0 , 360.0);
    fAngleReal = fmod(sensor.angle_prev * 57.295779513082320876798154814105 + 360.0 , 360.0);

Looks like i need to also set an optimized phase correction for SmoothingSensor::update():

  // Apply phase correction if needed
  if (phase_correction != 0) {
    if (_motor.shaft_velocity < -0) angle_prev -= _motor.sensor_direction * phase_correction / _motor.pole_pairs;
    else if (_motor.shaft_velocity > 0) angle_prev += _motor.sensor_direction * phase_correction / _motor.pole_pairs;
  }

I am not too happy with this more general SmoothingSensor approach that can wrap any kind of rotation-position sensor as it can not make use of the interrupt driven HallSensor method HallSensor::updateState().
Instead it must rely on the Sensor:.update() function which is called in motor.loopFOC() far more often (every single blue dot in the curve of fAnglePred) than HallSensor::updateState() (the coarse 4° steps of the grey curve fAngleReal).
And SmoothingSensor does not implement its own lowpass but cleverly uses _motor.shaft_velocity which has a lowpass:

float FOCMotor::shaftVelocity() {
  // if no sensor linked return previous value ( for open loop )
  if(!sensor) return shaft_velocity;
  return sensor_direction*LPF_velocity(sensor->getVelocity());
}

This method is called in void BLDCMotor::move(float new_target) and therefore motor.move(target) has to be called at the same rate as motor.loopFOC().

I think this is NOT intuitive as people might want to call motor.move only a few times per second to update a new target speed.

So yes, SmoothingSensor is working but all it basically does is adding a low pass to the angle and does a linear prediction

  float dt = (_micros() - angle_prev_ts) * 1e-6f;
  angle_prev += _motor.sensor_direction * _constrain(_motor.shaft_velocity * dt, -_PI_3 / _motor.pole_pairs, _PI_3 / _motor.pole_pairs);

Implement that "two lines" directly into HallSensor might be the better way...

from split_hoverboard_simplefoc.

RoboDurden avatar RoboDurden commented on August 28, 2024

SmoothingSensor.h

    // For hall sensors, the predicted angle is always 0 to 60 electrical degrees ahead of where it would be without
    // smoothing, so offset it backward by 30 degrees (set this to -PI_6) to get the average in phase with the rotor
    float phase_correction = 0;

Setting it to +0.1 already had a bad effect.
Setting it to -0.52 = -Pi/6 was okay but does not really help:
stmstudio smooth Sine25V with phase correction

from split_hoverboard_simplefoc.

RoboDurden avatar RoboDurden commented on August 28, 2024

here the downside of a low pass: it takes some time the direction change is noticed:

stmstudio smooth Sine25V 0 5Hz with phase correction

from split_hoverboard_simplefoc.

Candas1 avatar Candas1 commented on August 28, 2024

I already discussed with the contributor, I told him it's not optimal for hall sensors. But that's the best solution we have now and it works most of the time.

EFeru would stop predicting at slow speed or direction change, this is easy to do.

from split_hoverboard_simplefoc.

RoboDurden avatar RoboDurden commented on August 28, 2024

I guess i will spend half a day to test my direct HallSensor impelementation against these SmoothedSensor results here :-)

from split_hoverboard_simplefoc.

Candas1 avatar Candas1 commented on August 28, 2024

You could have checked already weeks ago.
Feel free to talk to him. I don't want to be a proxy between you and him.

from split_hoverboard_simplefoc.

RoboDurden avatar RoboDurden commented on August 28, 2024

Again, i do not want to pose problems when i can not offer solutions.

And i already figured out that linear prediction with a speed average is sufficient.
The inaccuracies i showed in the pics above are only at direction changes, so low speed an we do not really have to care for.

It is possible to give SmoothingSensor.h its own speed low pass

    float shaft_velocity;//!< current motor velocity 
    LowPassFilter LPF_velocity{DEF_VEL_FILTER_Tf};//!<  parameter determining the velocity Low pass filter configuration     

but as the speed will not change when motor.move() is not called, it is okay to use the lowpass filtered motor.shaft_velocity which gets updated by motor.move().

And when i only call motor.move at 10 Hz and some heave torque on the motor affects the shaft_velocity we have a lowpass anyway and do not see that when smoothing.

So everything is okay with SmoothingSensor :-)

from split_hoverboard_simplefoc.

Candas1 avatar Candas1 commented on August 28, 2024

OK then we are aligned.
I know it's not a perfect solution but it's good enough for now.
When all works we can check what is worth improving.

from split_hoverboard_simplefoc.

RoboDurden avatar RoboDurden commented on August 28, 2024

I think it is already perfect for us.
In the beginning i thought that a higher grade polynomial would better predict future speed changes like in my screenshots..
(That is why i did not want to wait for SmoothingSensor...)

But this is only needed at very slow speeds and we do not need to care for that.
At normal speed when noise and efficiency is important, the refresh rate is so high that a linear prediction is sufficient.
(That is why i stopped with my HallSensor-prediction.)

Now seeing that SmoothedSensor is more silent than my linear prediction, i happily close that chapter.

I guess when you have finished your channel3 timer0 adc, you have successfully ported SFOC to GD32F130.

I would still like to have a callback when adc has finished to trigger motor.loopFOC() every second call :-)

from split_hoverboard_simplefoc.

Related Issues (10)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.