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

We've already exercised the procedure to get the right calibration factors for the battery current measurement successfully! :)
https://endless-sphere.com/forums/viewtopic.php?p=1352618#p1352618

This can be easily repeated for different shunt/OP-gain values of any controller...

regards
stancecoke
 
stancecoke said:
We are not controlling the max value of the phase current. The phase current is only used for doing the simplyfied FOC.

Well I think original firmware does limit it or atleast cuts when over limit. Will do some tests...

I think that it will be needed, or if not possible, a ramp-up of max battery current linear with erps up to like 20 should do the job.

Problem is even when casainho has 12fet with 1000w direct hub, it can ask for too much phase amps from standstill and blow the mosfets.
 
honya96 said:
stancecoke said:
We are not controlling the max value of the phase current. The phase current is only used for doing the simplyfied FOC.

Well I think original firmware does limit it or atleast cuts when over limit. Will do some tests...

I think that it will be needed, or if not possible, a ramp-up of max battery current linear with erps up to like 20 should do the job.

Problem is even when casainho has 12fet with 1000w direct hub, it can ask for too much phase amps from standstill and blow the mosfets.
Master branch also cuts if you block the motor for some seconds. The current is ALWAYS being limited to max configured current!!
 
casainho said:
I am not motivated to test/develop for controllers I don't use... like that of 40A.

I dont understand how can you not be motivated to run 2kw ~65kph when your bike can handle it :lol: maybe just my mind set... your s12s is not 40A? Or you have it and dont use?

Is 2. Needed to run the FOC correctly?
S12S phase current sensor is 50A and 18fet is 100A

I believe stock 2 shunt 18fet will work the same as 2 shunt 12fet..

To your last post: stock fw cuts when you floor it too fast from dead stop, (when asking for too high phase current)
 
honya96 said:
casainho said:
I am not motivated to test/develop for controllers I don't use... like that of 40A.

I dont understand how can you not be motivated to run 2kw ~65kph when your bike can handle it :lol: maybe just my mind set... your s12s is not 40A? Or you have it and dont use?
Unfortunately I am not riding bicycle lately and just using car.
Also I don't have the firmware ready to run my ebike: direct drive motor and torque sensor. I am currently working on torque sensor.

honya96 said:
Is 2. Needed to run the FOC correctly?
S12S phase current sensor is 50A and 18fet is 100A

I believe stock 2 shunt 18fet will work the same as 2 shunt 12fet..
On our firmware, currently, it is used only for FOC (as Stancecoke told before and did show the only piece of code that uses phase B current sensor signal, that only looks for 2.5V (127 value) and increase or decrease ui8_angle_correction:

Code:
      // read here the phase B current: FOC Id current
      ui8_adc_id_current = UI8_ADC_PHASE_B_CURRENT;

      if (ui8_adc_id_current > 127) { ui8_angle_correction++; }
      else if (ui8_adc_id_current < 125) { ui8_angle_correction--; }

The ui8_angle_correction variable is the green line on this image -- read more here: https://opensourceebikefirmware.bitbucket.io/development/Datasheets_and_application_notes--Endless-sphere.com_forum_messages--2017.10.23_-_FOC_and_no_FOC_comparison.html
91-2.png


honya96 said:
To your last post: stock fw cuts when you floor it too fast from dead stop, (when asking for too high phase current)
No point in talk about phase current to protect the motor as the hardware only has 1 phase current sensor, while we would need to have the 3 phase currents -- so we are using instead the motor current(the current that flows from the battery).

I want to understand what you mean by: "you floor it too fast from dead stop".
 
stancecoke said:
Read the throttle value, the direct torque-signal and the human power (human power averaged over one, or at least a half crank revolution) and give the highest value to the motor. With this, the support will start from zero speed, it will oszillate at startup, but it will be smooth from the point, where the human power value is higher than the simple torque value, the thumb throttle as highest priority and overrides the other values...
I think I got it, more or less as you suggested:


- the direct torque sensor value always has the oscillation, as expected and we can see on second line
- the processing algorithm:
-- when cadence is lower than 15RPM, the direct torque sensor value is used, as can be seen at left side of graph, the third line has the same oscilation when cadence (first line) is bellow 15 RPM
-- the filtered/processed signal is almost flat while the input signal has oscilation
-- this torque sensor, outputs a signal value when I am resting my feet on the pedals - as can be seen when there is an output value and cadence = 0 (this can be problematic, let's see how it goes in real testing ride)
-- I used 1 cadence RPM and output the max value

Now I need to test this on a real ride and see if I like it. Also I can test processing over 1/2 * 1 cadence RPM.
 
I am now happy with torque sensor, I tested on direct drive motor Q85, 24V battery, S06S controller.
The answer from torque sensor is reasonably fast and I don't feel any oscillation on the motor. Next I want to test with the direct drive motor as last time I was very unhappy with the oscillations...

The torque sensor is very sensitive but the value is after divided by 4 and multiplied by assist levels, so at assist level 5, the final torque sensor signal is multiplied by 1.25 and at assist level 1, the final torque sensor signal is multiplied by 0.25:
Code:
void ebike_throttle_type_torque_sensor (void)
{
...
  // divide the torque sensor throttle value by 4 as it is very sensitive and multiply by assist level
  f_temp = (float) ((ui8_throttle_value_filtered >> 2) * lcd_configuration_variables.ui8_assist_level);
}

Also found 2 bugs that were solved by resetting PI controllers I term while we break, so when we release brakes, motor will not suddenly start:
Code:
  // set PWM duty_cycle target value only if we are not braking
  if (!motor_controller_state_is_set (MOTOR_CONTROLLER_STATE_BRAKE))
  {
    // now use the lowest value from the PI controllers outputs
    motor_set_pwm_duty_cycle_target (ui8_min (
      motor_current_pi_controller_state.ui8_controller_output_value,
      wheel_speed_pi_controller_state.ui8_controller_output_value));
  }
  else
  {
    // keep reseting PI controllers so the I term will not increase while we are braking!
    pi_controller_reset (&motor_current_pi_controller_state);
    pi_controller_reset (&wheel_speed_pi_controller_state);
  }
 
Hmm, I don't understand your latest code in detail...
I can't see the typical sinusoidal shape in the torque-curve?!
Why don't you average the torque signal over a crank revolution? This would avoid the scatter.

I think you are doing many things much more complicated than necessary, e.g. a reset of the integral part of the controller should not be done to avoid sudden changes in the setpoint which could cause the motor to stutter. The control loop will decrease the integral part fast enough automatically, if you choose proper parameters ...



Regards
stancecoke
 
stancecoke said:
Hmm, I don't understand your latest code in detail...
I can't see the typical sinusoidal shape in the torque-curve?!
It is inline what I measured some time ago: https://opensourceebikefirmware.bitbucket.io/development/Torque_sensors--BMSBattery_torque_sensor.html
Maybe that is the effect of the low pass filter on the motor controller??

If you need some clarification, please ask.

stancecoke said:
Why don't you average the torque signal over a crank revolution? This would avoid the scatter.
I can't imagine being less scatter using the average. Do you have a link were I can read more about it for a similar situation?

stancecoke said:
I think you are doing many things much more complicated than necessary, e.g. a reset of the integral part of the controller should not be done to avoid sudden changes in the setpoint which could cause the motor to stutter. The control loop will decrease the integral part fast enough automatically, if you choose proper parameters ...
I am sure others ways can work. For instance, keep resetting the target value instead of resetting the I term.
It works for now, in future can be rewritten if needed or such.
I am now more worried about direct drive motor.
 
casainho said:
I can't imagine being less scatter using the average. Do you have a link were I can read more about it for a similar situation?

I had a closer look to you code now. As far as I understand, you are averaging the torque-signal over four AD-conversions, in the fixed frequency of the slow loop. So you have no reference to the pedal position.

Code:
 // low pass filter the torque sensor to smooth the signal
  ui16_throttle_value_accumulated -= ui16_throttle_value_accumulated >> 2;
  ui16_throttle_value_accumulated += ((uint16_t) ui8_throttle_value);
  ui8_throttle_value_filtered = ui16_throttle_value_accumulated >> 2;

The slow loop frequency seems to be very slow (only 10 Hz ?!)

Code:
ui16_TIM2_counter = TIM2_GetCounter ();
    if ((ui16_TIM2_counter - ui16_motor_controller_counter) > 781) // every 100ms
    {
      ui16_motor_controller_counter = ui16_TIM2_counter;
      motor_controller ();
      ebike_app_controller ();
      continue;
}

So as an example: if you are pedaling with a cadence of 60/min you will get 10 AD-conversions per crank revolution, if you are averaging over four points, you will get an low-resolution sine-curve for the ui8_throttle_value_filtered values. I marked four red dots on the sine-curve to make it more transparent.

Torque-Signals whithin one crank revolution.png

In the "forumscontroller"-code and in my fork, we are reading the torque-value at every PAS-interrupt, and average the torque over one crank revolution. In this way you get a stable torque-value with no oszillation.

Code:
#if defined(TORQUESENSOR) || defined(TORQUE_SIMULATION)
    //	Update cadence, torque and battery current after PAS interrupt occurrence
    if (ui8_PAS_Flag == 1)
    {
      ui16_PAS=ui16_PAS_Counter; 		//save recent cadence
      ui16_PAS_High=ui16_PAS_High_Counter;
      
      ...

      ui8_PAS_Flag =0; 			//reset interrupt flag

      ui8_temp = ui8_adc_read_throttle (); //read in recent torque value
      ui16_torque[ui8_torque_index]= (uint8_t) map (ui8_temp , ADC_THROTTLE_MIN_VALUE, ADC_THROTTLE_MAX_VALUE, 0, SETPOINT_MAX_VALUE); //map throttle to limits
      ui16_sum_torque = 0;
      for(a = 0; a < NUMBER_OF_PAS_MAGS; a++) {			// sum up array content
	   ui16_sum_torque+= ui16_torque[a];
	   }
      ui8_torque_index++;
      if (ui8_torque_index>NUMBER_OF_PAS_MAGS-1){ui8_torque_index=0;} //reset index counter
}

This may be a bit sluggish at low cadence, but therefore the "forumscontroller" overwrites the target value from human power with the direct read torque if this value is higher. Then you get direct response to the pedal force...

regards
stancecoke
 
stancecoke said:
I had a closer look to you code now. As far as I understand, you are averaging the torque-signal over four AD-conversions, in the fixed frequency of the slow loop. So you have no reference to the pedal position.
Seems you missed my new code -- you can see on the commits diffs:
- https://github.com/OpenSource-EBike-firmware/BMSBattery_S_controllers_firmware/commit/3d6a958e917db19eb90e1dc56382ab90a6b4db90
- https://github.com/OpenSource-EBike-firmware/BMSBattery_S_controllers_firmware/commit/aa5989ea3015eeef40ca5013536c3e42905c8609

The new code I added to PAS code, at every signal change:
Code:
  if (ui8_pas_state != ui8_pas_state_old) // PAS signal did change
  {
    ui8_pas_state_old = ui8_pas_state;

    (...)
	
    ui8_torque_sensor_throttle_value = UI8_ADC_THROTTLE;
    ui8_torque_sensor_pas_signal_change_counter++;
    if (ui8_torque_sensor_pas_signal_change_counter > (PAS_NUMBER_MAGNETS << 1)) // ui8_pas_signal_change_counter = (PAS_NUMBER_MAGNETS*2) means 1 pedal rotation
    {
      ui8_torque_sensor_pas_signal_change_counter = 1; // this is the first cycle
      ui8_torque_sensor_throttle_processed_value = ui8_torque_sensor_throttle_max_value; // store the max value on the output variable of this algorithm
      ui8_torque_sensor_throttle_max_value = 0; // reset the max value
    }
    else
    {
      // store the max value
      if (ui8_torque_sensor_throttle_value > ui8_torque_sensor_throttle_max_value)
      {
	ui8_torque_sensor_throttle_max_value = ui8_torque_sensor_throttle_value;
      }
    }
  }
As you can see, it reads the max value of the signal every 1 pedal rotation and outputs that value to the global variable ui8_torque_sensor_throttle_processed_value.

Then on ebike_app.c, running at 10Hz:
Code:
void read_torque_sensor_throttle (void)
{
  read_throttle (); // so we get regular processing of throttle signal

  // if cadence is over 15 RPM, use the processed torque sensor value, otherwise, use ui8_throttle_value_filtered
  if (ui8_pas_cadence_rpm <= 15)
  {
    ui8_throttle_value_filtered = ui8_throttle_value;
  }
  else
  {
    ui8_throttle_value_filtered = (uint8_t) (map (
	  ui8_torque_sensor_throttle_processed_value,
	  (uint8_t) ADC_THROTTLE_MIN_VALUE,
	  (uint8_t) ADC_THROTTLE_MAX_VALUE,
	  (uint8_t) THROTTLE_MIN_VALUE,
	  (uint8_t) THROTTLE_MAX_VALUE));
  }
}
ui8_throttle_value (unfiltered value!!) is used when cadence <= 15 and when over, ui8_torque_sensor_throttle_processed_value is used instead, as I did show before with real values on the graph.

Note that
Code:
ui8_throttle_value_filtered
is the same variable with output value from either:
- read_throttle (); (used for thumb throttle and PAS)
- read_torque_sensor_throttle (); (used for torque sensor)
I am using the S06S Bluetooth version and I think I will stick with that version, for later use with our mobile app. This means I connected the torque sensor signals to the thumb throttle connector and PAS and so I can't use in parallel a thumb throttle with this controller.
 
casainho said:
Seems you missed my new code -- you can see on the commits diffs:

Ah, yes, I didn't recognize the changes in the motor.c :)
You will get less scatter with the averaged values, but of course it will work with the single maximum value of one crank revolution also. But you get a new torque value only once per revolution and not at every PAS event...

casainho said:
I am using the S06S Bluetooth version and I think I will stick with that version, for later use with our mobile app. This means I connected the torque sensor signals to the thumb throttle connector and PAS and so I can't use in parallel a thumb throttle with this controller.

Is the X4 pad used for somethings else with the BT-version?

regards
stancecoke
 
stancecoke said:
Ah, yes, I didn't recognize the changes in the motor.c :)
You will get less scatter with the averaged values, but of course it will work with the single maximum value of one crank revolution also. But you get a new torque value only once per revolution and not at every PAS event...
Go ahead an show the results on a similar graph as I don't believe will be a big difference.

stancecoke said:
Is the X4 pad used for somethings else with the BT-version?
I don't know, I wish someone could see the hardware differencies...
 
casainho said:
Go ahead an show the results on a similar graph as I don't believe will be a big difference.

OK, I'll do some logging of the raw ADC-values on a real ride, but this will take at least two weeks to prepare. I can try the "thumb-brake" with the BionX in "real life" then, too :wink:

regards
stancecoke
 
stancecoke said:
OK, I'll do some logging of the raw ADC-values on a real ride, but this will take at least two weeks to prepare. I can try the "thumb-brake" with the BionX in "real life" then, too :wink:
About 1 month up to start spring season, so right on time (at least for me) to have the bicycles ready for family fun :)
I have 2 ebikes using S06S, geared Q85 motors and 24V batteries (for young son of 8 years old + girlfriend). My other ebike, that I use, has the S12S, direct drive Q11 motor and 48V battery - on this one I need to work the firmware for this direct drive motor, as I was not happy last time I tested. All this ebikes has torque sensor only.
So, that is my plan up to spring and summer.
Who knows if on next year we can prepare the Mobile bluetooth app??
 
casainho said:
I want to understand what you mean by: "you floor it too fast from dead stop".

I mean turning throttle to full position at standstill.
As it is now, Iam sure it will blow s12s mosfets with fast direct motor at 40A.

Pwm rise value may help but it will affect reaction at higher rpm.

As I understand, there is a current going through phase sensor 2/3 of time? So limiting it, in combination with pwm rise value should be ok?

Or the other way as I mentioned before, limiting battery current up to set erps should also do the job, maybe better.

Having "startup Amps" and "Max current eprs" values in java app will limit phase current and allow users to get higher battery amps without blowing the controller at startup.
 
I went for a real test drive with the geared Q85 motor, 24V battery, S06S controller, LCD5 and torque sensor only. I am very happy with the result and I don't feel the need to change anything on the firmware. I really like the feeling of pedaling stronger and felling higher support from the motor. Also adapting the motor support from LCD, using the assist level, works well and is very useful.
Some notes:
1. I wasn't using an external wheel speed sensor so on LCD5 I was seeing the motor speed. On situations like small downhills (here, all is almost flat, no real downhills), I wanted to rest my feet and verified that torque sensor outputs some throttle value, keeping the motor rotating at a lower speed than bicycle wheel thanks to motor internal clutch.
2. I wounder what should be the correct algorithm for a direct drive motor, as when downhill and resting my feet, I don't want that motor stops/brakes...

 
honya96 said:
I mean turning throttle to full position at standstill.
As it is now, Iam sure it will blow s12s mosfets with fast direct motor at 40A.
So you mean the S12S can't withstand his max current of 40A for a period of 2.5 seconds?

honya96 said:
As I understand, there is a current going through phase sensor 2/3 of time? So limiting it, in combination with pwm rise value should be ok?
We can measure only twice per ERPs (at Id and -Id points on the image), but even like that didn't worked well when I tested:
80-3.png

https://opensourceebikefirmware.bitbucket.io/development/nd_application_notes--Endless-sphere.com_forum_messages--2017.09.02_-_How_to_do_FOC_on_the_BMSBattery_S06S-Kunteng_STM8_motor_controllers.html

Also that would work with motor rotating at least medium speed, not at startup. So we just can use current value from the shunt(motor total current).

honya96 said:
Or the other way as I mentioned before, limiting battery current up to set erps should also do the job, maybe better.

Having "startup Amps" and "Max current eprs" values in java app will limit phase current and allow users to get higher battery amps without blowing the controller at startup.
Can you please make a graph with example values? (you can draw on paper and take a photo).
Maybe you mean a current ramp, so the max controller current is not available at startup?
 
casainho said:
So you mean the S12S can't withstand his max current of 40A for a period of 2.5 seconds?

Yes, actually not even 0.5 second with really fast motor, because 40A from battery can be 200A to motor. (=at mofets)

casainho said:
Maybe you mean a current ramp, so the max controller current is not available at startup?
Not exactly, it has to be available when the wheel is spinning allready, and has to be limited when at speed and terrain slows your motor under the set speed, or something blocks your wheel.
 

Attachments

  • 20180216_185607-1536x864_crop_345x345.jpg
    20180216_185607-1536x864_crop_345x345.jpg
    9.3 KB · Views: 1,859
honya96 said:
Yes, actually not even 0.5 second with really fast motor, because 40A from battery can be 200A to motor. (=at mofets)
Didn't know about that!! Now I recall Stancecoke and others telling that "motor current" on firmware is instead battery current but I always thought they were equal.
I need to read more about it and I found this one shunt used on this controllers, is referred as "DC-Link Current Sensor".

casainho said:
Not exactly, it has to be available when the wheel is spinning allready, and has to be limited when at speed and terrain slows your motor under the set speed, or something blocks your wheel.
I think I got it. I hope to get back to this later.
 
casainho said:
I think I got it. I hope to get back to this later.

Thank you, I really need this.

I know I am the only one (for now) trying higher powers but It will be important function for anyone who wants fast motor response from standstill without risking mosfets.. :wink:
 
honya96 said:
casainho said:
I think I got it. I hope to get back to this later.

Thank you, I really need this.

I know I am the only one (for now) trying higher powers but It will be important function for anyone who wants fast motor response from standstill without risking mosfets.. :wink:
Can be other way, simple, to indirectly measure the motor current?
 
stancecoke said:
I think, that can be only done by a mathematical model.

Or hardware modification, which I will like the best, but is really hard.

A)
Adding 1 more hall current sensor to the last free AIN pin. (Sensor can be on wire, so not that hard do do for me) adding 2 more will be best but we dont have enough free pins?

Or

B) Using mosfets as shunts (is done on some controllers) but then we need amplifier?

Then even true FOC will be possible.. but I saw somewhere Casainho whote stm8 doesnt have enough processing power.
 
stancecoke said:
I think, that can be only done by a mathematical model.
If that math model works, it can be done easily on slow loop (and maybe we can increase slow loop frequency for this feature).
I think I read that FOC controllers can read only(optional) the phase currents and then do the math to get the battery current... (so they limit motor and battery currents) so the other way back may also work. Let's try and understand how to implement, test and do the validation.
 
Back
Top