KT motor controllers -- Flexible OpenSource firmware for BMSBattery S/Kunteng KT motor controllers (0.25kW up to 5kW)

daffy99 said:
Funny enough, stancecoke writing "144 W (4A@36V) is the highest power I can put on the motor actually." is something where I'd immediately stop tinkering.
This limitation is given by my power supply, if you connect your battery to the controller, you can get much more power for your motor of course. The code includes battery current limitation and undervoltage protection already, the current is set to maximum in the config.h actually, as I don't know the right calibration function at the moment.

Code:
#define BATTERY_CURRENT_MAX_VALUE 254

I'll try to figure out the linear function coefficients
Code:
Current (A) = a * ui8_BatteryCurrent + b

Regards
stancecoke
 
stancecoke said:
I'll try to figure out the linear function coefficients
Code:
Current (A) = a * ui8_BatteryCurrent + b

Excellent!

My intent is to have a hard static limit to, well, statically protect the motor. Basically "beyond this point, nothing good will come by pushing more into the motor".

I have no idea whether current (A) or total energy (V*A=W) is the best means to accomplish this.

Additionally, and eventually, a dynamic limit could be interesting as a feature. Something like

Code:
  magic_limiter := f(energy into motor over 60 seconds with geometric average, observed motor rpm, ambient temperature, motor temperature)

  if magic_limiter > motor_limit then throttle_energy_into_motor

Is it possible to limit on the battery side, independently? E.g. "only extract at most x Amps, ever"? That would protect the battery pack (and its fuse, and BMS, and ...), and take care of battery pack aging. That also could be combined with ambient temperature, when available, again to protect the battery pack. LCD3 displays show temperature, but I am not sure which temperature, and https://endless-sphere.com/forums/viewtopic.php?t=73475 seems to indicate that this flows from the controller to the display, so it would be "something" temperature, if at all.

All this energy flow limiting would then offer a great, safe envelope in which it is possible to experiment with minimal risk to the hardware?

In case the firmware does not have battery low voltage protection yet, that would be another protective feature. I'd rather have control via firmware than depending on the battery BMS, in case there is one.

Again, for me "protection" and thus creating a safe zone to operate is the first step; after that, funky features could be added, such as overdrive mode or so :D
 
Today I got ADC readings correctly and I was able to read motor total current. After I went to disable current PWM cycle and also decrese duty_cycle variable: it kind of works well, at least I could see the limiting current working and this time the motor can run even faster before hitting the short-circuit protection of the power supply. But there are some bugs that I need take care of.

I tested again the SVM 7 segment (without motor max current control) on this 26'' wheel and without load the wheel could run at 33km/h, using 2.5A and at 3.12ms hall sensor period (320 eRPS), on my Q85 24V motor 328 RPM. This SVM 7 segment seems to provide the best performance. I think I will go with this SVM and try to implement motor total max current to it, will try tomorrow.

 
I've implemented a linear function for Battery current, but I'm not satisfied yet. I've taken the moving average of 16 adc values alreacdy, but there is still very much scatter.
The adc-value is not proportional to the battery current. Hm....
I tested the system with my battery today, the generator makes the motor draw about 7 A at load level 3 with full throttle.

regards
stancecoke
 
stancecoke said:
I've implemented a linear function for Battery current, but I'm not satisfied yet. I've taken the moving average of 16 adc values alreacdy, but there is still very much scatter.
The adc-value is not proportional to the battery current. Hm....

Per the S06S schematics in the project's site, the bulk capacitance is [strike]after[/strike] before the battery current measurement resistor (capacitors are connected to GND and not to MGND), so you're actually not seeing the battery current but the sum of the ("instantaneous") currents pulled by the phases (part from the capacitors, part from the battery), therefore it will jump around. I guess you'll have to consider other variables (such as the PWM's duty cycle?) to estimate battery current or perform some other "averaging" algorithm (seems more complex, time dependent).


update: I meant to say "before" and not "after"
 
I think there is a bug in the schematic, I'll try to read in the battery current from ADC8. I've read from ADC6 up to now.

file.php


Regards
stancecoke
 

Attachments

  • Bug in Schematic.JPG
    Bug in Schematic.JPG
    97.9 KB · Views: 2,301
stancecoke said:
I think there is a bug in the schematic, I'll try to read in the battery current from ADC8. I've read from ADC6 up to now.
I am trying to read also from ADC6. I didn't look with care to the schematic... and so we have 3 signals about the shunt current??
- OC: seems to be over current
Opamp as comparator (U2A):
R2/(R2+R1) * Vin = Vout
2.2 / (2.2 + 20) * 5V = 0.099 * 5V = 0.5v (on 2B + pin 3)
If R6 = 0.001R; OC will be active (low) when I = U / R; I = 0.5 / 0.001 = 500 amps (??)

Opamp as diferential amplifier (U2B):
- ISHUNT is the amplified signal
- AN8 is the previous signal but low pass filtered

Gain = (R3/R1) * (V2-V1) = 10/1.8 * (V R6 - 0) --> gain = 5.56
Vout = 1.59V with motor stopped. For each 1A, Vout will increase:
V R6 = 0.001 * 1 = 0.001V; 0.001 * 5.56 (gain) = 5.6mV

Are all this calc correct??

And how should we use the direct current value and the filtered value??



85-3.png


https://opensourceebikefirmware.bitbucket.io/Various--Endless-sphere.com_forum_messages--2017.09.14_-_measuring_motor_current.html
 
I just measured the ISHUNT signal and ISHUNT filtered signal. I also did the calculations using the resistor values of the circuit, calculating the amplifier gains and measuring the real current values, seems to me the shunt is more like 0.01 and not 0.001. Please see here all the information I gathered: https://opensourceebikefirmware.bitbucket.io/Various--Endless-sphere.com_forum_messages--2017.09.19_-_measuring_motor_current.html
Njay said:
I guess you'll have to consider other variables (such as the PWM's duty cycle?) to estimate battery current or perform some other "averaging" algorithm (seems more complex, time dependent).
So, to me the ISHUNT filtered signal seems to be that averaging value and I will now use it and should simplify a lot what I am looking to do -- many thanks to KingQueenWong for writing the schematic and NJay to point this out!!

85-3.png
 
So, there is no bug in the schematic!
I tried to read in the battery current at ADC8 now and as casainho showed in the oszilograph already, the signal is low pass filtered here and therefore much easier to handle in the code.
In the linear approximation factor a is 3.8 and factor b is -295 to get current*10 ("deziAmpere") from the adc values.

I think in this case it is better to use full 10bit ADC resolution.

Regards
stancecoke
 

Attachments

  • linear approximation battery current.JPG
    linear approximation battery current.JPG
    22.5 KB · Views: 2,549
The bulk capacitance is still before (I meant to write before on my other post, sorry) the current measuring resistor, so it's not measuring battery current directly, it's measuring the sum of phase currents (then filtered and presented at AN8 for the average value), what you're seeing in the scopeshots at ISHUNT is phase currents: when a phase turns on (FET -> ON), current rises to phase current "instantaneously", then ramps up slowly while the phase is on (pumping "battery" current to the phase), then the phase turns off (FET -> OFF) and current "instantaneously" goes back to zero (then recirculates on the motor, slowly ramping down, until next phase turn on, ramp up, and on and on...). That's the typical phase current trapezoidal waveform, and you can actually measure phase current with this scheme, but you have to trigger the ADC to sample at the right time (at the same point during the PWN ON cycle).
 
stancecoke said:
So, there is no bug in the schematic!
I tried to read in the battery current at ADC8 now and as casainho showed in the oszilograph already, the signal is low pass filtered here and therefore much easier to handle in the code.
In the linear approximation factor a is 3.8 and factor b is -295 to get current*10 ("deziAmpere") from the adc values.
And I went and implemented the current limit and now works ok. Maybe it should have a PI controller... (??)

What I found is that this limit is not a help for motor max eRPM. Maybe we need to stick with a value like 18000 eRPM and control the motor max speed to that limit.

Limiting to 1A, see the value on the power supply and the the speed in km/h:
[youtube]NSu50f-cxA8[/youtube]

Limiting to 2A, see the value on the power supply and the the speed in km/h:
[youtube]Fqj0TESFOHQ[/youtube]
 
casainho said:
And I went and implemented the current limit and now works ok. Maybe it should have a PI controller... (??)

Which current signal do you use?!
The battery current limitation was already implemented in the update_setpoint.c?!

regards
stancecoke
 
I have just the same question: basic question motor controllers -- max current
https://endless-sphere.com/forums/viewtopic.php?f=30&t=90609

casainho said:
timmy66 said:
Sorry for basic question:

I understand how the motor controllers, when they're rated for say 20A, will PWM the current coming from the battery pack to make an "average" current rating not to exceed the 20A.

But if you're looking at the more instantaneous current demand : how is that being limited?

Because in general, for a short period of time while a motor is in a specific position, there is a short circuit over the windings -- is that amount findable in the specifications somewhere?

And how do you ensure that these sudden bursts are never too bad for the battery pack? eg, for the BMS that may be watching the pack's output current closely? Is it because their (BMS) response time is mostly averaged over a second's window, too, that it doesn't kill the peak demands?

And deeper -- where to see the capabilities of batteries to see how they respond to those very rapid pulses?

Thanks
This is something I want to implement on our OpenSource firmware for Kunteng/BMSBAttery S controllers. I was able to limit the max current but only the average value but I would like also to limit the instantaneous current... if is possible and if makes sense, and if the hardware permits.
 
stancecoke said:
casainho said:
And I went and implemented the current limit and now works ok. Maybe it should have a PI controller... (??)
Which current signal do you use?!
The battery current limitation was already implemented in the update_setpoint.c?!
Just pushed to SVM_7. I used ADC1_CHANNEL_8.

I must say I didn't looked at your code yet, I must do it and I will today. I wanted to play myself because I think this code may be tied tightly with the motor code.

So here is the code. It reads the MOTOR_TOTAL_CURRENT_FILTERED value and signals the ui8_motor_total_current_flag. Later on void pwm_duty_cycle_controller (void), that flag is checked and will decrease the duty_cycle. For what I saw on the oscilloscope, a PI controller could be nice however there is very low resolution on the values and on the other side, I don't know if when running on the bicycle with the rider, it will be necessary.
Code:
void TIM1_UPD_OVF_TRG_BRK_IRQHandler(void) __interrupt(TIM1_UPD_OVF_TRG_BRK_IRQHANDLER)
{
  if (ui8_motor_state == MOTOR_STATE_RUNNING_INTERPOLATION_360_DEGREES)
  {
    adc_select_channel (ADC1_CHANNEL_MOTOR_TOTAL_CURRENT_FILTERED);
    ui8_temp = adc_read_channel () >> 2;
    if (ui8_temp > ADC_MOTOR_TOTAL_CURRENT_MAX_POSITIVE)
    {
//      TIM1->BKR &= (uint8_t)(~TIM1_BKR_MOE);
      ui8_motor_total_current_flag = 1;
    }
  }
  else
  {
    ui8_motor_total_current_flag = 0;
  }

I played with TIM1->BKR &= (uint8_t)(~TIM1_BKR_MOE); that immediately disables the duty_cycle value until next PWM period but the result was worst...

And then on void pwm_duty_cycle_controller (void):

Code:
  if (ui8_motor_total_current_flag == 0)
  {
    if (ui8_counter++ > PWM_DUTY_CYCLE_CONTROLLER_COUNTER)
    {
      ui8_counter = 0;

      // increment or decrement duty_cycle
      if (ui8_duty_cycle_target > ui8_duty_cycle) { ui8_duty_cycle++; }
      else if (ui8_duty_cycle_target < ui8_duty_cycle) { ui8_duty_cycle--; }
    }
  }
  else
  {
    ui8_motor_total_current_flag = 0;

    if (ui8_duty_cycle > 0)
    {
      ui8_duty_cycle--;
    }
  }
 
casainho said:
Just pushed to SVM_7. I used ADC1_CHANNEL_8.

OK, then we have done some work in parallel. I'm reading battery current and battery voltage in the slow main loop 10 times a second. I think for normal riding this should be fast enough, as the changes of the analog values shouldn't be that fast. For short curcuit protection this could be to slow, but for this we could better use an interrupt on the OC pin. (edit: NJAY just had the same idea while I was editing this post :D )

Njay said:
The bulk capacitance is still before (I meant to write before on my other post, sorry) the current measuring resistor, so it's not measuring battery current directly,
I don't understand that thing with the "bulk capacitance". As far as I read the schematic, each terminal of the shunt is connected to the Opamp just over a resistor....
Of course you don't get the current that is drawn by the LDO for the 5V supply but this is negligible, I think.

Regards
stancecoke
 
Using OC the controller/motor is protected by limiting maximum motor current (controller is frequently the weaker of the 2). On OC going active, terminate the PWM ON phase regardless of the currently desired duty cycle. This is the kind of thing to do in hw or in an interrupt on OC change.

Using ISHUNT the motor current is measured, if the sw is fast enough. The motor current can also be controlled by terminating the PWM ON phase when the desired current is reached, thus providing some kind of torque control (or just providing a motor current reading to the user).

Using AN8 the battery current is measured. This is "slow moving" measurement, that can be used to limit battery current (protect the battery) or provide a reading to the user; can also be used to estimate motor current but can't be used to provide a precise control over it.

Regarding motor current limiting versus battery current limiting, I see it this way (besides the protection functions): limit motor current => motor torque is limited; limit battery current => motor power is limited.
 
stancecoke said:
Njay said:
The bulk capacitance is still before (I meant to write before on my other post, sorry) the current measuring resistor, so it's not measuring battery current directly,
I don't understand that thing with the "bulk capacitance". As far as I read the schematic, each terminal of the shunt is connected to the Opamp just over a resistor....
Of course you don't get the current that is drawn by the LDO for the 5V supply but this is negligible, I think.

The bulk capacitance is C19 and C20, it's the "DC link capacitors" or other names you can see - sometimes I just call it "decoupling caps", but they actually perform several functions. They are connected to GND, and the shunt resistor is between these caps and the power circuit (half bridges), thus measuring the current that circulates between them and the circuit; the current circulating between said caps and the battery can and is often different, and could only be seen with a shunt between the battery and the caps. The power circuit pulls current in a very "peaky way" (like in the ISHUNT scopeshots! Zero on the PWM OFF period, then some high ramp on the ON period); the caps smooth that usage such that the battery sees a more regular/constant current being pulled (this is not the reason why the caps are there, just "consequence").
 
Njay said:
Using OC the controller/motor is protected by limiting maximum motor current (controller is frequently the weaker of the 2). On OC going active, terminate the PWM ON phase regardless of the currently desired duty cycle. This is the kind of thing to do in hw or in an interrupt on OC change.

Using ISHUNT the motor current is measured, if the sw is fast enough. The motor current can also be controlled by terminating the PWM ON phase when the desired current is reached, thus providing some kind of torque control (or just providing a motor current reading to the user).

Using AN8 the battery current is measured. This is "slow moving" measurement, that can be used to limit battery current (protect the battery) or provide a reading to the user; can also be used to estimate motor current but can't be used to provide a precise control over it.

Regarding motor current limiting versus battery current limiting, I see it this way (besides the protection functions): limit motor current => motor torque is limited; limit battery current => motor power is limited.
I have one big question: which signal use to find current motor torque?? so we can use it to finally implement the throttle using mode "torque + speed"!!

I can try read Id from the very low resolution FOC but looking at oscilloscope I can see it will be very noise, because the phase B current signal is not a perfect sinewave (always changing) -- but on the FOC algorithm, the Id is the torque!! And there are people saying this: Most of the sinewave controllers have torque throttle, which is easier for them since they need to measure motor current as part of the sinewave control algorithm.

Or should we use AN8/MOTOR_TOTAL_CURRENT_FILTERED signal??

Hmmm, this controller is common to 6 steps and sinewave/low res FOC. On 6 steps, there is no phase B current signal, so the torque control must be done with AN8/MOTOR_TOTAL_CURRENT_FILTERED signal, right??
And with low res FOC, should we use Id value for torque control?? -- maybe I should try and see :) :)
 
Njay said:
the caps smooth that usage such that the battery sees a more regular/constant current being pulled

OK, now I got you, but I think there's no big difference between real battery current and the current you get from reading AD8, (as you wrote before :D ....)

Regards
stancecoke
 
casainho said:
I can try read Id from the very low resolution FOC but looking at oscilloscope I can see it will be very noise, because the phase B current signal is not a perfect sinewave (always changing) -- but on the FOC algorithm, the Id is the torque!! And there are people saying this: Most of the sinewave controllers have torque throttle, which is easier for them since they need to measure motor current as part of the sinewave control algorithm.

Or should we use AN8/MOTOR_TOTAL_CURRENT_FILTERED signal??

Hmmm, this controller is common to 6 steps and sinewave/low res FOC. On 6 steps, there is no phase B current signal, so the torque control must be done with AN8/MOTOR_TOTAL_CURRENT_FILTERED signal, right??
And with low res FOC, should we use Id value for torque control?? -- maybe I should try and see :) :)
Hmmm, seems we have 3 times more resolution on phase B current signal... and also the controller characteristics says "Maximum current: 15+-1A" which is the max value measured on phase B current signal while MOTOR_TOTAL_CURRENT_FILTERED should be able to go up to 26 amps (at least in the negative direction). Maybe Id current is the way to go to have torque control...

// Phase current: max of +-15.5 amps
// 512 --> 15.5 amps
// 1 ADC increment --> 0.030A

// Total motor current filtered
// Each 1A should increase the signal about 53mV
// 1 ADC increment --> 0.092A
 
Battery current (Ibat) alone isn't what you want because Ibat != Imotor. Older controllers apparently combined Ibat with the PWM duty cycle to estimate motor current (Ibat / duty, duty in [0;1]). In the case of FOC I guess you would want the RMS value of a phase current? Take the peak and divide by 1.41? I don't know.
 
stancecoke said:
Njay said:
the caps smooth that usage such that the battery sees a more regular/constant current being pulled

OK, now I got you, but I think there's no big difference between real battery current and the current you get from reading AD8, (as you wrote before :D ....)

See this illustration. (the S06S controller has R2: R6 on the shcematics)
 

Attachments

  • PowerTrainCurrents.png
    PowerTrainCurrents.png
    7.3 KB · Views: 2,538
Njay said:
Using ISHUNT the motor current is measured, if the sw is fast enough. The motor current can also be controlled by terminating the PWM ON phase when the desired current is reached, thus providing some kind of torque control (or just providing a motor current reading to the user).
I tried this and I heard a motor noise I never did with original firmware. But also I saw the phase B current signal with much more noise... and I think:
- if we disable/terminate PWM ON phase, we will be reshaping the sinewave
- we need to decrease duty_cycle, that will decrease the PWM ON time but also keeping the sinewave shape and we need to maintain the shape to keep doing FOC.

Njay said:
Battery current (Ibat) alone isn't what you want because Ibat != Imotor. Older controllers apparently combined Ibat with the PWM duty cycle to estimate motor current (Ibat / duty, duty in [0;1]). In the case of FOC I guess you would want the RMS value of a phase current? Take the peak and divide by 1.41? I don't know.
Ok, and Ibat / duty isn't the same as AN8/MOTOR_TOTAL_CURRENT_FILTERED?
Maybe we should use AN8/MOTOR_TOTAL_CURRENT_FILTERED while the motor startup and after being running using FOC, switch to use Id.
 
casainho said:
Njay said:
Using ISHUNT the motor current is measured, if the sw is fast enough. The motor current can also be controlled by terminating the PWM ON phase when the desired current is reached, thus providing some kind of torque control (or just providing a motor current reading to the user).
I tried this and I heard a motor noise I never did with original firmware. But also I saw the phase B current signal with much more noise... and I think:
- if we disable/terminate PWM ON phase, we will be reshaping the sinewave
- we need to decrease duty_cycle, that will decrease the PWM ON time but also keeping the sinewave shape and we need to maintain the shape to keep doing FOC.
Ahh, when I wrote that I totally forgot you were using FOC on a 3 phase motor. I'm not familiar with FOC.

casainho said:
Njay said:
Battery current (Ibat) alone isn't what you want because Ibat != Imotor. Older controllers apparently combined Ibat with the PWM duty cycle to estimate motor current (Ibat / duty, duty in [0;1]). In the case of FOC I guess you would want the RMS value of a phase current? Take the peak and divide by 1.41? I don't know.
Ok, and Ibat / duty isn't the same as AN8/MOTOR_TOTAL_CURRENT_FILTERED?
I don't know what MOTOR_TOTAL_CURRENT_FILTERED is...
 
Njay said:
casainho said:
Njay said:
Battery current (Ibat) alone isn't what you want because Ibat != Imotor. Older controllers apparently combined Ibat with the PWM duty cycle to estimate motor current (Ibat / duty, duty in [0;1]). In the case of FOC I guess you would want the RMS value of a phase current? Take the peak and divide by 1.41? I don't know.
Ok, and Ibat / duty isn't the same as AN8/MOTOR_TOTAL_CURRENT_FILTERED?
I don't know what MOTOR_TOTAL_CURRENT_FILTERED is...
AN8 and I am not sure if it is the same as motor total current filtered, I can change the name if it is different.
 
Back
Top