It turns out there is a problem with the lepton’s waveform generation, even in open loop. There appears to be a thump about once per revolution. The waveform flakes out, I confirmed it in a couple different ways. I thought it was some kind of mechanical defect in my fan at first, that’s why I didn’t realize what was going on.
It appears to be worse when I compile code on my desktop. I reset the libraries, and it still is. I noticed my desktop gives the following error when compiling and uploading on arduino, after following the board install proceedure:
Warning: Board simplefoc:stm32:build doesn’t define a ‘build.board’ preference. Auto-set to: STM32_BUILD
In orange letters. I think maybe some peripheral is configured slightly differently and this has something to do with the thumping noise.
The G431 board doesn’t do it as far as I can tell. I hypothesize some calculation occurs when things wrap around and this causes the thump. Either I have to try to get in there and fix the problem with the code or I have to use the G431 board and can’t use the Lepton. I will have a look at the code but… This is a real downturn for me because I really don’t want to have to go through designing my own G431 based board.
The thump occurs even when I restrain the fan from actually moving or put the voltage down so low it can’t move on it’s own. So it’s definitely an interruption in the waveform.
edit: ok, looking at the code, I think it might be when the shaft_angle = _normalizeAngle(shaft_angle + target_velocity*Ts); happens on line 677 of BLDCmotor.cpp. Normalize calls fmod, floating point modulo.
The noise takes a while to build up when I start rotation, I think this may be because the division takes longer when the angle is larger? I think shaft_angle accumulates, rather than wrapping around.
Thus, perhaps the floating point hardware is not working properly on the Lepton? Man, I haz no clue how to solve such a problem :(. If only I can get open loop mode working at least.
Oh geeze it’s an M-0 cortex, right? they don’t even have floating point hardware? https://ww1.microchip.com/downloads/en/DeviceDoc/90003178A.pdf
Yeah the G431 thing has floating point hardware https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwii1v2Zg-n9AhUcmYkEHY5LBA4QFnoECBEQAQ&url=https%3A%2F%2Fwww.st.com%2Fen%2Fmicrocontrollers-microprocessors%2Fstm32g431cb.html&usg=AOvVaw1IG0vpnrQS1R11KanU9eqJ
Ah shit.
Update: well I don’t see how I could make the code in the library work any better, which is no surprise. It doesn’t look like there is much stuff that could take time. There is just a handful of floating point modulo things and I don’t see anything that could explain the increase over time, shaft angle doesn’t increase in perpetuity in openloop mode apparently, it does appear as though it would wrap around and the cycle just begin again. it happens just as well with trapezoidal drive, so it’s not the stuff in setphasevoltage or whatever. I follow the flow of the program and don’t see how it could flake out or stall like that.
Edit: ok, I realized the G431 board also does it, it’s just not as loud. Oh shit. Ok so not a floating point issue. Just a bunch of code that takes too long once per revolution… I really don’t see anything.
edit: I made a last ditch effort, and it actually worked. I figured something else is messing with shaft_angle at some point, and just replaced it with a static variable that stays inside the velocityopenloop function.
it now reads:
// Function (iterative) generating open loop movement for target velocity
// - target_velocity - rad/s
// it uses voltage_limit variable
float BLDCMotor::velocityOpenloop(float target_velocity){
// get current timestamp
static float other_shaft_angle = 0;
unsigned long now_us = _micros();
// calculate the sample time from last call
float Ts = (now_us - open_loop_timestamp) * 1e-6f;
// quick fix for strange cases (micros overflow + timestamp not defined)
if(Ts <= 0 || Ts > 0.5f) Ts = 1e-3f;
// calculate the necessary angle to achieve target velocity
other_shaft_angle = _normalizeAngle(other_shaft_angle + target_velocity*Ts);
// for display purposes
shaft_velocity = target_velocity;
// use voltage limit or current limit
float Uq = voltage_limit;
if(_isset(phase_resistance)){
Uq = _constrain(current_limit*phase_resistance + fabs(voltage_bemf),-voltage_limit, voltage_limit);
// recalculate the current
current.q = (Uq - fabs(voltage_bemf))/phase_resistance;
}
// set the maximal allowed voltage (voltage_limit) with the necessary angle
setPhaseVoltage(Uq, 0, _electricalAngle(other_shaft_angle, pole_pairs));
// save timestamp for next call
open_loop_timestamp = now_us;
return Uq;
}
Man, what a roller coaster. So stressful. Progress is possible, it just always takes so long. Only open source makes this kind of rectification of issues possible.
Probably the above modification broke all kinds of stuff, idk.