bipropellant / bipropellant-hoverboard-firmware

OpenSource Hoverboard firmware based on Niklas Fauth's one https://github.com/NiklasFauth/hoverboard-firmware-hack
GNU General Public License v3.0
175 stars 74 forks source link

BLDC Control Optimization 2 #32

Closed btsimonh closed 5 years ago

btsimonh commented 5 years ago

New thread.....

EFeru commented 5 years ago

a, yes for the hoverborad mode in your repo you mean? Because in my repo, I calculate the phases commands and return within the same DMA interrupt. With the new commit that I will make, the BLDC_controller is more light, so maybe it can run faster even in your firmware.

EFeru commented 5 years ago

@btsimonh @lalalandrus I just commited the new BLDC control.

lalalandrus commented 5 years ago

Yay! Been waiting for the next iteration.

Everything runs properly. Tested during high dynamic and direction change. Motors spin without issues.

I see that for sin3 lookup the highest number is +/- 996 we should normalize it so that the max is still 1000 that way we get an extra 0.5% of power :)

  • There is one thing on this branch... Code compiles and builds. However does not spin the wheel on my Denver hoverboard. The init melody does not play. I tried with previous commits and the same behavior. Normally, it should run better, this code is lighter and also separates control for each motor LEFT and RIGHT.

@EmanuelFeru This is beacuse that code was changed again to run at 16khz which over subscribes that interrupt on the older STM uC. If you find the line that says 'return' and the associated 'if' statement it will run every other time, thus 8khz and the code works again. EDIT: Line 91 in BLDC.C

EFeru commented 5 years ago

I see that for sin3 lookup the highest number is +/- 996 we should normalize it so that the max is still 1000 that way we get an extra 0.5% of power :)

It is better that I fine tune to peak exactly at 1000. I will do it now and do a pull request.

EFeru commented 5 years ago

@lalalandrus , done. I preferred that I do it by regenerating it, so the 3rd harmonic is consistent everywhere.

lalalandrus commented 5 years ago

@lalalandrus , done. I preferred that I do it by regenerating it, so the 3rd harmonic is consistent everywhere.

Thanks ill look in a bit when i am beside some hardware to test with. As per my edit above, un-comment line 91 in the bldc.c

EFeru commented 5 years ago

For some reason, it still doesn't want to run, even with the "return" un-commented. Have a look when you have time if it works for you.

lalalandrus commented 5 years ago

@EmanuelFeru i am using that code in my hoverboard right now, it is the code that i achieved 30kph with. the only change i made was with the return uncommented. are the lights and sensors working?

EFeru commented 5 years ago

The lights do blink, but more red than green.

EDIT: I don't know what is different, because I had an old commit (the one that you sent me last time) And that one worked. But then I updated to last one and this one does not work for me. I cannot see the difference because I removed the old one which worked... maybe I should have keep that one to see the differences.

lalalandrus commented 5 years ago

you double tapped the sensors to active hoverboard mode? the lights stay red until you doubel tap then it goes yellow

EFeru commented 5 years ago

Yes. but still no success.. and I cannot turn off the board by the button, only by disconnecting the battery.

lalalandrus commented 5 years ago

Ill have a look again later guess it will have to wait until i get to some hardware later in the day.

EFeru commented 5 years ago

Ill have a look again later guess it will have to wait until i get to some hardware later in the day.

No problem. Take your time. I have to go to bed now anyway, it is quite late here in The Netherlands :)

lalalandrus commented 5 years ago

Ill have a look again later guess it will have to wait until i get to some hardware later in the day.

No problem. Take your time. I have to go to bed now anyway, it is quite late here in The Netherlands :)

I just did a diff between the fork that btsimonh has in his repo and my folder. it turns out i commented also the buzzer code (ln 140-149) in bldc.c but i didnt think that should matter, try that to see if helps your motor run. in the meanwhile i will test out your new motor code and report back

UPDATE: I have tried the new code and nothing i do can get it to work. I think the new algorthim is even slower than the first one and the interrupt is overrunning. I even coded it to calculate the left and then right with each alternate interrupt and it still does not work.

EFeru commented 5 years ago

Too bad, not very good news... Did you try running just one motor? (one call only in bldc.c) Because for me even with one motor it doesn't want to run for the hoverboard branch. And one motor is definetely lighter than the previous control.

EDIT: And also try with

define CTRL_TYP_SEL 0 (commutation method)

This I didn't try. I think we should make this the first test, If that doesn't run then is something with the code, variables, definitions, interrutps..etc

btsimonh commented 5 years ago

@EmanuelFeru "By the way, what do you say of adding an integrator to the controller in hoverboard mode? Because then it will behave like the manufacturer firmware. At the moment, we need to keep feets angled to move forward with a constant speed, while in the original firmware it integrates the angle so by instinct you put the feets straight again and speed is maintained. The integral part should only be apllied when both angles have the same sign. If they are different, just do what you do now (so spinning in place does not need integral part)."

It kind of does that, because angle demands torque not speed....? We can certainly experiment with options - that's what tapping and flash is for :). Did you try angle^2 yet? I have not, but you may find this is the key. My 2nd board is without sensor boards at the moment, but with original firmware. My first board lost it's original firmware pretty quickly... so I have little experience with the original behaviour....

EFeru commented 5 years ago

I will give it a try tomorrow because I have more time and see how it feels.

btsimonh commented 5 years ago

ok, first cut. Based on current master branch. Builds, but untested (see wiki changes today for why I can't test tonight...). https://github.com/btsimonh/hoverboard-firmware/tree/sinusoidalbldc

please let me have feedback. I've tried to keep it to essential fixes and the new BLDC. I've not removed the original BLDC, will add a config to choose....

btsimonh commented 5 years ago

ok, more information. When DMA1_Channel1_IRQHandler is called, it really should complete within the time before the next DMA is completed. The DMA completes at 16khz, so we have 62.5us. On my GD32 based board, doing left and right takes ~90-100us, and so the routine is overrunning. If I do Left and Right separately, i'm at 50-60us (measured to 10us resolution), and no overruns (measured by looking at the DMA complete flag for DMA1). For an STM32 based board, it would seem that 16khz is too quick, or we need to be much more efficient. Note that by returning every other interrupt, we are not actually allowing ourselves more time to run the code. It MUST complete within the 62.5us on all platforms. I'm going to see what can be pruned :).

EFeru commented 5 years ago

Nice investigations and thanks for the info. I am currently running the bldc control at 16 kHz on Stm32 without problems but does not include any hoverboard functionality, only the motor control. I see that the stm32 is a bit limited, I think this is the reason why manufacture also went for a different microcontroller in the newer boards. To cover both platforms we need an interrupt every 100us so 10kHz frequency to be sure. ( if this can be implemented )

btsimonh commented 5 years ago

On GD32, I'm down at 50-60us for L+R, and 30us for L then R (effectively 8khz, using alternate interrupts). Will push soon, but would like to slim a bit more first. Are there any more saving to be had in the actual routines? (e.g. additional pre-calculation & lookup tables, etc.)? I have not looked at or modified the new controller code yet.

lalalandrus commented 5 years ago

I spent last night coming to the same conclusions. Also the gd chip architecture has a zero wait state flash whereas the stm does not. This would impact lookup tables as well. I also implemented alternate left and right and it doesn't seem to work for the stm either unless you trimmed some code

We should try compiler directives or declarations to load the lookup tables and main bldc controller functions in ram. We have 50 percent remaining.

I think a lot of the measurements made in that interrupt is also slowing things down.

EFeru commented 5 years ago
btsimonh commented 5 years ago

ok, try https://github.com/btsimonh/hoverboard-firmware/tree/sinusoidalbldc with https://github.com/btsimonh/bipropellant-protocol/tree/sinusoidalbldc

IF the measurements are right from new immediate command 'V': Main loop interval_us 4999; lates 2, processing_us 642, interval by tick 4, bldc freq 8035, bldc_us 14, bldc overruns 0, bldc cycles 949, bld100k 3, cpu freq 64000000

Then we're down to 14us, measured from CPU cycles, although the cpu freq seems strange for a GD32. I've seen as many as 1200 cpu cycles, so I assume there are other interrupts occuring during our processing.

would be VERY interested in results from a real STM32....

btsimonh commented 5 years ago

just a small wrinkle - last commit broke double tap! before that it was working nicely! give me a few more minutes...

btsimonh commented 5 years ago

no, it's ok. I was in a non-hoverboard mode triggered from ascii protocol.

btsimonh commented 5 years ago

just pushed one more change; a little essential, now checks that the duplicate angles are the same before accepting the buffer. Now need to add a few more screws before riding the hoverboard to see if the clicking etc. goes away. Still have bad performance at manually held and twisted high speed - but more in one direction than the other. But I'm not ruling out bearings yet!!!

lalalandrus commented 5 years ago

ok, try https://github.com/btsimonh/hoverboard-firmware/tree/sinusoidalbldc

I dont have any access to serial ports so I can load the code but I cannot get any serial outputs

@btsimonh i thought about the comparing the two values before and it is a good idea but perhaps we should do something like this and average 4 numbers (2 readings from current and 2 readings from previous) i was going to implement this when i got around implementing the integration

#define FILTER_SHIFT = 4 filter_temp += Angle - (filter_temp >> FILTER_SHIFT); filter_temp += Angle2 - (filter_temp >> FILTER_SHIFT); Angle_output = filter_temp >> FILTER_SHIFT;

btsimonh commented 5 years ago

I left a test in the code which would log if a resulting angle was more than 200 different than the last valid read. Not seen the log come out yet.... so I don't think we need to filter.

p.s. I tested my 2nd hoverboard (still has original firmware), ref integration and behaviour with angle: https://photos.app.goo.gl/YBUv1e4Y9qGLN1gS9 Notes: Reducing the angle to zero brakes the wheel quickly, just like our implementation (not shown in video). Unloaded speed seems relatively proportional to angle; i.e. there is no integration.

lalalandrus commented 5 years ago

In that case a simple expo like a square is sufficient.

EFeru commented 5 years ago

Unloaded speed seems relatively proportional to angle; i.e. there is no integration.

@btsimonh, that is only true when you run one wheel or both wheels in opposite direction (turning in place motion). Try running both wheels in the same direction and then you will see the integration. The integration happens only when both wheels are spinning in the same direction (forward driving motion).

lalalandrus commented 5 years ago

I tested the new code on a atm and it doesn't work still.

EFeru commented 5 years ago

I will test it tomorrow as well and see.

lalalandrus commented 5 years ago

I dont know if there is something else going on with the STM. If i line by line uncomment BLDC_controller_step the first line that hits a snag is

Ln 222 in bldc_controller.c rtDW->UnitDelay1 = rtDW->Switch2;

Which is pretty early on. At that spot I inserted two nested 1000 count for loops and the code runs fine. but if I add that one line everything breaks.

btsimonh commented 5 years ago

just pushed on the same two repos (you need both on this one). Now you should be able to build 'hoverboard' - USART2_BAUD = 0 -> auto sense of sensor baud rate. Also solved some of my ticking - I think I had bad reads of 'Roll' angle, and it was briefly disabling because if that. Now I only disable if I get 5 high values in a row. However, this should not affect you as you don't have those bytes in the sensor data?

Ln 222 in bldc_controller.c I hate evil ones like that. You could try exercising it outside of the interrupt. Try being explicit about structure packing (go for 4, then the STM won't be shuffling things about to get at the char values). Make sure it does a complete rebuild. e.g. modify platformio.ini.

lalalandrus commented 5 years ago

Leaning more towards a memory access bug now, even commutation type = 0 will not work.

btsimonh commented 5 years ago

@btsimonh, that is only true when you run one wheel or both wheels in opposite direction (turning in place motion). Try running both wheels in the same direction and then you will see the integration. The integration happens only when both wheels are spinning in the same direction (forward driving motion).

haha! this hoverboard only has one functional sensor board, so can't test that :(. Looking at another board but it's 40 miles away :(.

EFeru commented 5 years ago

Now I understand why it was not integrating... If you see a kid with a hoverboard maybe you can ask him to let you check the integration... haha, just joking.

lalalandrus commented 5 years ago

I picked up 3 hoverboards the other day for 50cdn. Yes all three.

EFeru commented 5 years ago

All 3 with 50? That is good deal :)

EFeru commented 5 years ago

Back to the basics, @btsimonh does sinusoidal BLDC control run on your Gd32 board? I just tried on my STM32 and no method works from the ones that I provide (the original blockPWM works though). I tried running only one motor with CTRL_TYP_SEL = 0 and still it gets stuck (board cannot be shut down).

lalalandrus commented 5 years ago

I agree with your observations. If you comment the entire controller step and slowly uncomment each line. I thi m you will crash at line 222 it is not just an overrun issue.

If you go this route use ifdef to comment out the code as your autogeneration scripts have too many '*/'

I have tried initializing the packaged motor state variable but it still crashes.

btsimonh commented 5 years ago

yes, working fine. It works in your repo, yes? One thing i did which is a 'little unusual' are these lines in main.c:

  // enable the DWT counter for cycle timing
  CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
  DWT->CYCCNT = 0;
  DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;

enabling something in the debug part of the chip to allow counting of the CPU cycles. That could be different in the different chip designs? If you disable this, be sure not to use sensor baud estimation, as it will tight loop.

EFeru commented 5 years ago

I can remove the comments from autocode on the next generation. I have to check if reusable setting did not mess up some things.

btsimonh commented 5 years ago

Note on debug registers from STM32 manual: Important: these registers are not reset by a system reset. They are only reset by a poweron reset So, if you suspect them, remove, flash, and power cycle.

EFeru commented 5 years ago

So, if you suspect them, remove, flash, and power cycle.

Just checked... no effect

It works in your repo, yes?

I could not clone the repo with the right protocol folder in it. When cloning the protocol folder was empty. So I cloned from the website as a zip and unzip. And cloned the protocol as zip separately.

btsimonh commented 5 years ago

you can run under ODB, maybe it will tell you what it's doing? Another idea: I increased the speed of the PWM pins in Setup.c line 512: GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; Try going back to GPIO_SPEED_FREQ_LOW. Maybe it is as simple as the board is more susceptible to interference from the switching? (but then you would not expect it to reliably hit a specific line of code...)

Does it die on flash, or only when motors become enabled?

(the original blockPWM works though)

you did this by setting the type to -1 with no other changes?

most likely culprit:

   rtb_Sum2_h = (int8_T)(rtConstP.vec_hallToPos_Value[rtb_Sum] -
                          rtDW->UnitDelay2_DSTATE_i);

if rtb_Sum > size of array -> invalid access? rtb_Sum is made from hall, so if hall values are not 0/1, it would die?

EFeru commented 5 years ago

Does it die on flash, or only when motors become enabled?

Flash is ok. When motor gets enabled (actually they don't because the melody does not play at all).

you did this by setting the type to -1 with no other changes?

Yes. Option -1 only (and my baud rate of course)

EFeru commented 5 years ago

if rtb_Sum > size of array -> invalid access?

Here i do the same operation like in original repo: halll = hall_ul 1 + hall_vl 2 + hall_wl * 4

For me rtbSum = halll. So it should not go outside the size of array.

I see in your repo this was changed to

  hall[0] = (~(LEFT_HALL_U_PORT->IDR & (LEFT_HALL_U_PIN | LEFT_HALL_V_PIN | LEFT_HALL_W_PIN))/LEFT_HALL_U_PIN) & 7;
  hall[1] = (~(RIGHT_HALL_U_PORT->IDR & (RIGHT_HALL_U_PIN | RIGHT_HALL_V_PIN | RIGHT_HALL_W_PIN))/RIGHT_HALL_U_PIN) & 7;

Is there a reason for this?

btsimonh commented 5 years ago

so, no melody -> dies in first few interrupts, no PWM going on at that point, because enable should b e 0. When it's dead, are the motors driven at all? (i.e. compared to power off, or normal disabled, do they have any drag)