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
174 stars 74 forks source link

BLDC Control Optimization 3 #41

Open btsimonh opened 5 years ago

btsimonh commented 5 years ago

Continuation of https://github.com/bipropellant/bipropellant-hoverboard-firmware/issues/32

Concrete information can be added here: https://github.com/bipropellant/bipropellant-hoverboard-firmware/wiki/Notes-on-BLDC-Drive-and-Hoverboard-motors or as additional pages on the wiki :).

TomTinkering commented 5 years ago

Not necessarily that we need to go above 90%, but even at 80% I get spikes sometimes. Above 80% data is rubish. And this is on the 1st sampled motor. I don't even want to look on the 2nd sampled motor. I fear that is much worse.

Hmm ok, that's worse than I thought. I'm not sure how much of this can be contributed to ADC timing. Since the first motor is already sampled directly in the centre of the PWM pulse, you won't get any improvement on this motor. The timing will only affect the second motor (see image)

Capture

I will check the exact ADC sampling time again when I get the chance, if 80% is already giving problems, then maybe we should sample faster (if possible).

What I want to say is that we are very limited because of this measurement and filtering... I tried and is hard. It helps but is hard to removed the spikes, especially when they are consecutive :)

What kind of filters have you tried? Do you maybe have a capture of the motor currents you get. Maybe I can dig up my matlab skills and try out some filters.

EFeru commented 5 years ago

What kind of filters have you tried? Do you maybe have a capture of the motor currents you get. Maybe I can dig up my matlab skills and try out some filters.

The filtering I did was always in 2 stages:

Even with all this, spikes goes through if I go above 80%. Bellow 80% is decent... Again for the 1st sampled motor. I haven't try the 2nd motor. I just did some logging some time ago and I saw it was worse, so I said I leave that motor for later.

I can give you some data, just have I have to log it first, because the filtering I applied was directly on the motor (online, on the running motor). I did not do offline filtering on Raw data. But that should be possible I just need to log some Raw data.

TomTinkering commented 5 years ago

Ok, quick update:

Motor ADC settings:

This means:

So maximum duty cycles for which this should work for both motors = 12/62.5 = 20%~80%

What we can 'improve' Reduce sample-time and improve timing

The result would be a minimum LO-Fet ON time of around 4us/62.5us = 7%-93% It won't get faster than that with this MCU, the rest will have to come from filtering. Also by lowering the sample time, probably the measurements will see more noise

TomTinkering commented 5 years ago

second, I applied low pass filtering or moving average. I tryied both, they both behave fairly similar in terms of filtering the output.

Did you try second-order low pass filters as well? And do you have an estimate of the "frequency" of the spikes?

btsimonh commented 5 years ago

sorry to bang on; but we do know when the samples will be wrong, and can just ignore the samples which we know will be incorrect? @EmanuelFeru - Have you tried rejecting samples or retaining the last good sample based on the last PWM value? With this, we should be able to go up to 99% duty cycle with no issues?

TomTinkering commented 5 years ago

@btsimonh The motor currents are typically a sine wave. Going this way would basically mean you cut the top of all the motor currents above 80% duty cycle, and below 20% duty cycle with this approach.

That being said, you only need a few samples on a sine wave to reconstruct it, so a more complicated solution could maybe be to only measure currents in the lower duty cycle regions, and the reconstruct the expected sine wave from these measurement (which is a form of filtering :) ).

btsimonh commented 5 years ago

theory says the current and PWM are not aligned, at least when driving hard :). The 'missing bits' are not near the peaks: image

TomTinkering commented 5 years ago

True, sorry, you don't cut the peaks of the current, but the PWM output does follow a sine wave. I think the same argument holds (keeping the old value when the PWM goes above/below a certain duty cycle would mean you ignore a lot of consecutive measurements), right?

Actually, looking at that plot, if this was ADC timing related, wouldn't we expect to see that here too? (lot's of consecutive peaks in the same places?).

TomTinkering commented 5 years ago

Also, I still don't understand why the spikes go towards 0, when sampling outside of the "window" should in my understanding result in spikes towards the maximum measureable current. Or am I missing something there?

TomTinkering commented 5 years ago

@EmanuelFeru Does your setup allow logging the PWM values along with the current measurements? With that data we can verify if the PWM duty cycle is actually causing the spikes

lalalandrus commented 5 years ago
  1. The 'missing bits' are not near the peaks:

Because the one interrupt fires for all three phases one phase current could be spiking while another is at 90% own.

  1. Filtering introduces group delay for a foc this is no good

  2. I agree if this is adc sampling we should see consistent behaviours. Are we not accounting for the adc dma copy cycle? Or do we have a memory issue. We can do the reads with the adc at speed and pwm max to a known value but removing the op amp to set the pin at a known voltage.

  3. We could do kalman filter or a basterdized state observer using lookup tables and plls if we really can't solve the reading issue.

EFeru commented 5 years ago

Sorry for delayed response. @btsimonh

we do know when the samples will be wrong, and can just ignore the samples which we know will be incorrect? @EmanuelFeru - Have you tried rejecting samples or retaining the last good sample based on the last PWM value? With this, we should be able to go up to 99% duty cycle with no issues?

I am not sure if I understand how to do this. I mean how do you know that last PWM value caused wrong reading just based on PWM value? I need an example to understand how do you see this implemented.

@TomTinkering

Does your setup allow logging the PWM values along with the current measurements? With that data we can verify if the PWM duty cycle is actually causing the spikes

Do you mean the PWM values as pulses and not the Duty Cycle? If yes, I need to assign it to a variable and then it should be possible to log it in STM Studio. I just need form you to tell me how to access the PWM values (as pulses)?

EFeru commented 5 years ago

I did one logging at 90% Duty cycle. Where I change one thing:

sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5; --> Spikes are there

image

sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5; --> Spikes are NOT there

image

In my opinion, this clearly says that we have little time for ADC sample.

NOTE: The Duty Cycle commands shapes are not perfect. That is because the STM Studio is missing some points. It cannot log all and every point.

EFeru commented 5 years ago

I tried the TIM_CHANNEL_4 interrupt trigger, but no melody and the wheels are stiff, very hard to move by hand. I think the interrupt does not trigger at all. Do you have an idea what am I doing wrong?

setup.c Line 515: HAL_TIM_PWM_Start(&htim_left, TIM_CHANNEL_4); HAL_TIMEx_PWMN_Start(&htim_left, TIM_CHANNEL_4); Line 538: hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGINJECCONV_T8_CC4; // instead of ADC_EXTERNALTRIGCONV_T8_TRGO bldc.c LEFT_TIM->CCR4 = (uint16_t)(950 + pwm_res / 2);

btsimonh commented 5 years ago

I am not sure if I understand how to do this. I mean how do you know that last PWM value caused wrong reading just based on PWM value? I need an example to understand how do you see this implemented.

If the last PWM value for the phase (0-2000) is > (0.8*2000), then the last ADC value was taken in a 'danger zone', so ignore it.

EFeru commented 5 years ago

Functionally, isn't this exactly as clamping the PWM between 20 - 80 %?

TomTinkering commented 5 years ago

Do you mean the PWM values as pulses and not the Duty Cycle? If yes, I need to assign it to a variable and then it should be possible to log it in STM Studio. I just need form you to tell me how to access the PWM values (as pulses)?

Just the values that are written to the timer channels, this should show something like if PWM value is bigger than 1900 -> spikes appear.

In my opinion, this clearly says that we have little time for ADC sample.

Does the second motor still show spikes if you do this?

I think the interrupt does not trigger at all. Do you have an idea what am I doing wrong?

You also need to set the output trigger of TIM8 from : sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE; to sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC4REF;

Also, I am not sure you need to enable channel 4. I think this is more related to the IO pin attached to that channel, although I'm not 100% sure. If you do need to enable the channel, we definetly have to set it to a different mode than TIM_OCMODE_PWM1. All channels are compared with the same timer value, what you want is to generate a trigger when OCR4 is the same value as the timer value. I might be enough just to set the OCR4 registers and set the output trugger to TIM_TRGO_OC4REF.

However, we do need to look into how to configure it to generate only one trigger, and not 2. Should not be too hard, but some datasheet digging is required. Look at chapter 14.4 TIM1 and TIM8 registers of the reference manual for this

Functionally, isn't this exactly as clamping the PWM between 20 - 80 %?

It's a little different.

TomTinkering commented 5 years ago

@EmanuelFeru If setting the sample rate to 1.5 helps you for now, I can look into changing the timer settings appropriatly somewhere this week and send you a patch/update. That way you can keep working of FOC using lower duty cycles?

EFeru commented 5 years ago

Just the values that are written to the timer channels, this should show something like if PWM value is bigger than 1900 -> spikes appear.

They are already ploted in the figures I show in my previouse comment. The Duty Cycle (top plot) are the values that are written to the 3 time channels. And indeed, you see that around 1900 we get spikes.

Does the second motor still show spikes if you do this?

This is exactly what I will try next. If that one does not give spikes at 90% duty cycle with ADC_SAMPLETIME_1CYCLE_5 then I call it a success.

sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC4REF

Aa, ok. I will try tonight.

However, we do need to look into how to configure it to generate only one trigger, and not 2. Should not be too hard, but some datasheet digging is required. Look at chapter 14.4 TIM1 and TIM8 registers of the reference manual for this

I see in the documentation for TIM1 and TIM8 this image And in setup.c we have this Line 523 So, I was thinking that maybe we are lucky and the UEV(Update Event) happens when we want.

By ignoring measurements when PWM > 80%, you pretend like the current doesn't change above a certain di/dt

Hmm.. doesn't feel like an elegant solution. Of course a try does not hurt.

If setting the sample rate to 1.5 helps you for now, I can look into changing the timer settings appropriatly somewhere this week and send you a patch/update. That way you can keep working of FOC using lower duty cycles?

That would be nice. What settings will you update? (just curious). I have to try 2nd motor and let you know.

TomTinkering commented 5 years ago

So, I was thinking that maybe we are lucky and the UEV(Update Event) happens when we want.

The update event is the one we are using now, if we change to OCR4, this does not apply anymore.

That would be nice. What settings will you update? (just curious). I have to try 2nd motor and let you know.

I will:

EFeru commented 5 years ago

The update event is the one we are using now, if we change to OCR4, this does not apply anymore.

You are right. I just noticed :)

For the ADC updates you mentioned, it would be really nice if you can look into it. I prefer this path rather then trying to remove spikes which will require computational time. Time that we can use for other better purposes in FOC.

EFeru commented 5 years ago

@TomTinkering Short remark, I think the interrupt on Channel 4 should only triggger when counting down (as expected) due to this line in config.c htim_right.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED1; image

EDIT: By the way, I forgot say, I cannot test the 2nd motor tonight because of an appointment. I hope tomorrow I can find some time.

TomTinkering commented 5 years ago

@EmanuelFeru Ah nice, I knew I had seen it somewhere when looking into the current configuration, but I could not find it anymore. Good, so we just need to double-check if we need mode 1 or mode 2. In that case the OCR4 method is definitely the nicest.

I also realized that we want to center around the end of the sample-time of Motor 1, and the end of sample-time of Motor 2. Not the conversion complete times. Once the ADC is converting the samples are kept constat (sample->hold..)

So

EFeru commented 5 years ago

I also realized that we want to center around the end of the sample-time of Motor 1, and the end of sample-time of Motor 2. Not the conversion complete times. Once the ADC is converting the samples are kept constat (sample->hold..)

► That is true. However, it does not hurt if we start earlier, so the DMA interrupts earlier, immediately after ADC conversion is finished. It is actually a good thing, because we minimise the delay between measurement -> actuation. EDIT: What we want here is to trigger ADC as soon as the Last Low FET turns on + the DeadTime. So, maybe using the max/min (depends) of the values of all phases is a good thing to minimize delay time measurement -> actuation even further, instead of using a fixed value for OCR4. Because for most of the time we will not operate at full torque / full PWM. This is for the future. For now let's first try with a fixed value.

assuming 14MHz ADC clock, and 1us margin on both sides, we should be able to go up to 95% duty cycle

► That would be just perfect! :)

TomTinkering commented 5 years ago

EDIT: What we want here is to trigger ADC as soon as the Last Low FET turns on + the DeadTime. So, maybe using the max/min (depends) of the values of all phases is a good thing to minimize delay time measurement -> actuation even further, instead of using a fixed value for OCR4. Because for most of the time we will not operate at full torque / full PWM. This is for the future. For now let's first try with a fixed value.

Not sure if this is true. I think you want so sample as close around the center as possible. In the higher duty cycles, this is the same as sampling directly after FET turn-on. For lower duty cycles the center is a more stable point of measurement = less noise.

Also, the center is always at the same time, so you don't introduce unnecessary jitter

ADC conversion is finished. It is actually a good thing, because we minimize the delay between measurement -> actuation.

I think as long as you finish your control calculation before the counter loads the next PWM value, it doesn't matter how long it takes, or how fast you process the value after you sample it.

Actually with center-aligned PWM this is a bit tricky, because if the BLDC controller times vary a lot, it can happen that the timer sometimes updates when downcounting, sometimes when upcounting. That would probably give some weir behavior.

EFeru commented 5 years ago

For lower duty cycles the center is a more stable point of measurement = less noise.

This is also true. I was still in the "getting rid of the sipkes mood" :D

Actually with center-aligned PWM this is a bit tricky, because if the BLDC controller times vary a lot, it can happen that the timer sometimes updates when downcounting, sometimes when upcounting. That would probably give some weir behavior.

We have to see. I think it should be ok. Prbably it will limit the how high can we put the gains on the controller. We will see...

btsimonh commented 5 years ago

For lower duty cycles the center is a more stable point of measurement = less noise.

actually, read some of the sites on FOC. The current is changing during the PWM cycle, and we always want to sample at the same point in the cycle. so not just more stable; more accurate & predictable.

it can happen that the timer sometimes updates when downcounting, sometimes when upcounting

in my humble opinion, the values should ONLY be changed in the DMA routine (they may have been calculated previously, or at a slower rate....)

TomTinkering commented 5 years ago

actually, read some of the sites on FOC. The current is changing during the PWM cycle, and we always want to sample at the same point in the cycle. so not just more stable; more accurate & predictable.

Yes exactly, although there are many ways to interpret this. Could you provide an image of what you mean? Sampling at the center will give a constant sample frequency, but not a contant sample point with regards to the PWM-period. Sampling at the flank will not give you either (both sample frequency and sample point will change). Sampling using edge-aligned mode can do both, but then then time between the on-flank and the sample will vary.

in my humble opinion, the values should ONLY be changed in the DMA routine (they may have been calculated previously, or at a slower rate....)

Yes, but right now the PWM values are written whenever the BLDC controller is done calculating. If this is sometimes just before the timer updates itself, and sometimes just after, your update frequency is not constant. In edge-aligned mode this is not an issue, as the BLDC controller will always be done before a timer update, but in center-aligned mode, there are two updates per PWM period, and we need to take care that we always use the same one.

EFeru commented 5 years ago

I forgot to tell you.. I posted a question to the STM community regarding our issue on current sensing few days ago and someone from ST replied. You can follow it here Custom FOC control: Current measurement / DMA Timer interrupt needs review Feel free to comment if you wish.

lalalandrus commented 5 years ago

@EmanuelFeru It is hard to track with all these messages, are the errors confined to ADC1 or ADC2?

Since we have the whole motor current can we implement something as mentioned in this very detailed article, Section 5.3.2. This would reduce the channels of conversion but needs synchronization with the respective phase pulses.

https://www.nxp.com/docs/en/reference-manual/DRM102.pdf

Finally, I dont know if anyone mentioned, but even thought our PWM output frequency is 16khz, because we are utilizing center aligned with up down counter, our pulses are actually the same as 8khz PWM. Dont know if this will affect the controller stablilty.

EFeru commented 5 years ago

@lalalandrus In both ADCs. Because they are used in parallel. However, it is not that the ADCs are not doing their job. It is more a timing issue. For high PWM values we have too little time to sample the values. And what happens is that, from the 5 Conversion that we do, few of them are taken when the lower FETs are opened and not closed. As a result, this leads to spikes or wrong readings.

As action points, together with @TomTinkering, we want to:

Since we have the whole motor current can we implement something as mentioned in this very detailed article, Section 5.3.2. This would reduce the channels of conversion but needs synchronization with the respective phase pulses.

► In short.. too much effort. For FOC, we need a minimum of 2 phase currents to be measured. It is hard with a look-up table to extrapolate. Not that is not possible, guys from ST/NXP did it with 1 current sensor only (Phase current or DC Link current), but that requires a motor model or some sort of estimator. From experience, if you have a measurement it is better to used it... simple is better in 90% of the cases :) To conclude, we have these measurements and we don't need to model them, we just need to read them. And read them well without artifacts.

lalalandrus commented 5 years ago

I understand that it is the timing.

If we are to trigger on OCR4 then we need to distinguish when it it crosses the level on the downcount.
Whats the hesitation on changing the ADC to 14MHz?

EDIT: looks like 64 and 14 dont play nice, but we can move the div to 6, that should give us ~11 mhz

On that tangent, I mentioned this before, why dont we increase the uC frequency to 72mhz?

EFeru commented 5 years ago

Whats the hesitation on changing the ADC to 14MHz?

I don't know :) Temperature sensor sampling? I haven't tried so I don't know what is the effect. Did you try changing PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV8; // 8 MHzto any of this?

RCC_ADCPCLK2_DIV2
RCC_ADCPCLK2_DIV4
RCC_ADCPCLK2_DIV6

On that tangent, I mentioned this before, why dont we increase the uC frequency to 72mhz?

I think for this we need an external oscillator. And personally, I prefer not to modify the board because we loose flexibility if other people want to use it.

lalalandrus commented 5 years ago

I dont have or know how to setup the software to sample the currents like you have, try a DIV6 and that should be able to get you a ~11Mhz adc sample freq.

EFeru commented 5 years ago

I thought that you have tried, just to see that it is working as before with no issues and that other readings (Temperature, Vbat, ...etc) are still ok. Can you try? Because I am busy with some FOC work and I don't have the time.

lalalandrus commented 5 years ago

I will try later today, dont have the hardware.

EFeru commented 5 years ago

That is ok. Let me know when you have some results. I just need to know that the rest is ok. The impact on current measurements I will check later.

EFeru commented 5 years ago

And 2nd sampled motor (Right motor / short wired motor) measurement at at 90% Duty cycle.

sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5; --> Spikes are there

image

sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5; --> Spikes are there

image

It makes sense to have spikes on both cases because this motor is sampled 2nd. What I don't understand is why are there more spikes at 1.5 Cycles (which is faster) than 7.5 Cycles (slower)?

Conclusions:

                        SPIKES
                7CYCLES_5    1CYCLE_5
Motor A:          Yes           No
Motor B:          Yes           Yes (more spikes than for 7CYCLES_5)
TomTinkering commented 5 years ago

@lalalandrus

~11Mhz adc sample freq.

It is not the sample frequency, but the ADC clock. The sample frequency is determined by the PWM frequency, and the sample time by a combination of the ADC clock and sample-time settings. I don't think there is a real disadvantage in increasing the ADC clock other than power consumption and maybe some more non-linearity

@EmanuelFeru

What I don't understand why are there more spikes at 1.5 Cycles (which is faster) than 7.5 Cycles (slower)?

Good question, although the second motor still has to wait for the first motor to complete, so setting the sample time to 1.5 Cycles won't have that much effect. Maybe it is just unlucky timing, or it is not timing related...?

lalalandrus commented 5 years ago

@TomTinkering Perhaps my terminology is wrong, what i meant is the ADC sampling frequency of which it performs the successive approximations, right now we require 7.5 cycles of 8mhz whereas if we increase it to 11mhz we should be able to do the the adc capture in less time. This would still more more linear than performing 1.5 cycles at 8mhz.

Perhaps the reason why the 1.5 cycles has more spikes is because the ADC is succesive summation, and in order to achieve the sampling in 1.5 cycles, there has to be either saving of the previous value or some sort of pre-emption as without this approximating a value in 1.5 cycles is pretty tight.

TomTinkering commented 5 years ago

@lalalandrus

Perhaps the reason why the 1.5 cycles has more spikes is because the ADC is succesive summation, and in order to achieve the sampling in 1.5 cycles, there has to be either saving of the previous value or some sort of pre-emption as without this approximating a value in 1.5 cycles is pretty tight.

The sample-time term is confusing, but in this sense it just means the amount of ADC clock cycles that are used to charge the sample-capacitor. After this amount of time, the capacitor (or I should say hold-circuit) is disconnected from the input, and kept constant. The successive ADC can then sample the value.

The effect of a shorter sample time is that less time is spent charging the capacitor. Longer sample time does not necessarily get different results, as the capacitor is quite small. The capacitor will form a simple low-pass filter together with any series input resistance. In our case there is no series resistance other than copper tracks so the low-pass effect will be negligible and longer sample times will not give much different results.

However, it could be possible that there is a settling time of internal circuits that introduce noise. If we sample very shortly, we might see the effects of this in our signal, and get more spikes.

lalalandrus commented 5 years ago

@TomTinkering I just was about to edit my comment as I came to the same conclusion. Given that the approximation still happens regardless of the sample time, chaning the clk from 8mhz to 11mhz will improve the overal sample period by quite a bit.

TomTinkering commented 5 years ago

@lalalandrus You say 11MHz, 14 is not possible? I was planning on looking into this tonight or tomorrow.

lalalandrus commented 5 years ago

Not with the divisors available. (64 / 2,4,6,8 this is also why I wanted to revisit the 72Mhz byt looking at the clock tree this is impossible with the HSI as mentioned by @EmanuelFeru)

Also since we up down counting, the pwm clamp is X+/-10 (or 100) but in reality, we only need the time AFTER the downcount reset so the clamp could be only X-100?

TomTinkering commented 5 years ago

@lalalandrus

Also since we up down counting, the pwm clamp is X+/-10 (or 100) but in reality, we only need the time AFTER the downcount reset so the clamp could be only X-100?

Well you never want 0% or 100% duty cycle, but yes it does not have to be symmetrical. We could do 2% - 95% or so. But honestly, pulses shorter than ~5% or longer than 95% duty cycle really should not be necessary. They introduce more noise than anything else.

lalalandrus commented 5 years ago

@TomTinkering The OCRx has a direction option, I am looking at how to use this but the wording is confusing as it is not consistent.

TomTinkering commented 5 years ago

Yes, @EmanuelFeru found the right setting. Depending on the center-aligned mode, it will either trigger only on upcounting, downcounting or both

TomTinkering commented 5 years ago

Wow, so much that can go wrong, it's a miracle it even works at all :P en.CD00211314.pdf

lalalandrus commented 5 years ago

Yea i was reading that paper and a lot of it we cant do anything about.

TomTinkering commented 5 years ago

WAIT!

The STM guys had a great comment. There is no reason for us to run the two motor timers synchronously right? If we offset one timer by half a period, then we can sample one motor first, and the second motor half a period later. That way both can be sampled in the middle of the lower FET ON time.

That makes it way faster, without having to increase the ADC clock.