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

Configurator now working very nicely, thanks to Xnyle for all his work on that.. :)

On a slightly different subject, I've recently received another torque sensor (sempu gen3, one that actually works this time..!) and after a few config tweaks is now working well on stancecoke's fw. It's a great feeling to be able to attack hills and headwinds now without having to constantly alter assist level or add throttle.

I suppose the only thing I miss is the ability to throttle away from a standstill, something my ageing legs seem to appreciate. It would be fairly straightforward to connect a hand throttle in parallel with the torquesensor input (via a couple of blocking diodes) but it would also entail removing the need for PAS input to start the motor - just wondered if there's any way I can do this?

Just daydreaming really, for me everything works really sweetly now.. :wink:
 
stancecoke said:
Set speedsensor to extern or set the right gear ratio!

Regards
stancecoke
I measure the speed by a speedometer that stands alone.
How can the gear ratio affect the number of revolutions per second? I have in my motor wheel 20 magnets, the motor inside is small, the gear ratio for the original controller is 20X4 = 80.
In the open firmware I put 45, then it began to show the real speed value in comparison with the external speedometer
Maybe I do not understand that correctly. Can the controller program take as a basis the number of magnets to calculate RPM?
 
I ask the question: who will be able to respond as best they can. About the translation into Russian do not worry, I'll understand.
How does the program start the engine from zero speed?
Based only on the position of the rotor relative to the hall sensors?
 
Romantas said:
Based only on the position of the rotor relative to the hall sensors?
Yes.
 
geofft said:
after a few config tweaks is now working well on stancecoke's fw. It's a great feeling to be able to attack hills and headwinds now without having to constantly alter assist level or add throttle.

Great, the support of a torquesensor is the main advantage of the open source firmware vs. the stock firmware!!1

geofft said:
I suppose the only thing I miss is the ability to throttle away from a standstill, something my ageing legs seem to appreciate.

You don't need an additional throtte, as your legs operate the "throttle". But we would have to adapt the code as you wrote, we have to disable the PAS timeout and override the calculated human power assistance (factor*torque*cadence) with the pure torque signal. We could combine that with a walk assistance function (up to 6km/h the throttle works without pedaling) It's a lot of work to be done (and I'm not motivated to do that at the moment.... :shock: ).

regards
stancecoke
 
casainho said:
Romantas said:
Based only on the position of the rotor relative to the hall sensors?
Yes.
this means, when the engine is standing, the controller can not determine the normal direction of rotation, which was shown by the practice when my engine was running.
There is a suggestion, to add to the program a forced function of the initial turn-on of switching on transistors, starting from the trigger voltage of one of the sensors in the hall. Add the direction of rotation to the tool in this case. Thus, when the throttle, or the PAS system is switched on, the controller will always start to untwist the engine in the specified direction, making corrections for opening the transistors according to the location of the hall sensors.
this is very important for engines with a reducer.
to my disappointment, I understand the algorithm of work well, but I understand very poorly in programming :(
 
Romantas said:
In the open firmware I put 45, then it began to show the real speed value in comparison with the external speedometer
Maybe I do not understand that correctly. Can the controller program take as a basis the number of magnets to calculate RPM?

In speedsensor-->intern mode the wheel speed is calculated from the erps (electric revolutions per sencond), the wheel circumference and the gear ratio (number of pole pairs * mechanical gear ratio). So if the speed is displayed correctly, you can reach higer speeds only with higher voltage or with field weakening....

regards
stancecoke
 
stancecoke said:
Romantas said:
I set the value of the checksum until I got a working display :)

so what was the right XOR number for your display?
Once I left home and after some kms I changed some options on LCD3 and the firmware stopped working :-( :-( It only worked again after resetting the LCD3 options... it was very bad because I was far from home...

I think the XOR is not working as expected because once we change some options, that xors values will stop to work so something is wrong for sure -- I think we don't know yet how to calculate.
 
stancecoke said:
geofft said:
I suppose the only thing I miss is the ability to throttle away from a standstill, something my ageing legs seem to appreciate.

You don't need an additional throtte, as your legs operate the "throttle". But we would have to adapt the code as you wrote, we have to disable the PAS timeout and override the calculated human power assistance (factor*torque*cadence) with the pure torque signal. We could combine that with a walk assistance function (up to 6km/h the throttle works without pedaling) It's a lot of work to be done (and I'm not motivated to do that at the moment.... :shock: ).
It is very straightforward, I did that on TSDZ2 firmware. Here it is:

Code:
IF (pedal_cadence < 25)
{
  value = torque_sensor_value * assist_level;
} 
ELSE
{
  human_power = pedal_cadence * torque_sensor_value;
  value = human_power * assist_level;
}

value = max(value, throttle_value); // use the max value of both, for instance, throttle will override if has higher value
That works very well!!

BUT, recently (it took me some days) I implemented the BOOST feature on TSDZ2 firmware where at startup there is a different assist_level, typically user will choose a value that will get a boost at startup.

On LCD3 user can configure the startup duration, fade out duration and assist_level for boost and assist_level on regular use (it is a factor that multiplies to the torque sensor signal/human power).
So, user can setup like 3 seconds for boost time and get a power peak of like 800W and after the power fades during another 3 second (or any other user configured value) to the regular value of human_power * assist_level that can be something like 300W. This way the user still has control with the torque on pedals for the amount of boost at startup (it is not a constant value!! yes, I started to implement boost as being a constant value and the result was not very good).

You know, the code is OpenSource, you can use it but I suggest you to implement the first example as it is very simple and fast to implement, also with very low risk to have a bug.
 
casainho said:
It is very straightforward, I did that on TSDZ2 firmware. Here it is:

Code:
IF (pedal_cadence < 25)
{
  value = torque_sensor_value * assist_level;
} 
ELSE
{
  human_power = pedal_cadence * torque_sensor_value;
  value = human_power * assist_level;
}

value = max(value, throttle_value); // use the max value of both, for instance, throttle will override if has higher value

This can't work with my fork, as if PAS has timed out, you will never come to the part of the code you described...

I described the solution above, but I'm not motivated to implement it, as I personally don't like the motor pushing at standstill, sorry.

regards
stancecoke
 
casainho said:
stancecoke said:
Romantas said:
I set the value of the checksum until I got a working display :)

so what was the right XOR number for your display?
Once I left home and after some kms I changed some options on LCD3 and the firmware stopped working :-( :-( It only worked again after resetting the LCD3 options... it was very bad because I was far from home...

I think the XOR is not working as expected because once we change some options, that xors values will stop to work so something is wrong for sure -- I think we don't know yet how to calculate.

I added a value of 3 to the code.

Code:
   // see if CRC is ok
   if (((ui8_crc ^ 10) == ui8_rx_buffer [7]) 	|| // some versions of CRC LCD5 (??)
	((ui8_crc ^ 5) == ui8_rx_buffer [7]) 	|| // CRC LCD3 (tested with KT36/48SVPR, from PSWpower)
	((ui8_crc ^ 9) == ui8_rx_buffer [7]) 	|| // CRC LCD5
	((ui8_crc ^ 3) == ui8_rx_buffer [7]) 	|| // CRC LCD5 romantas added for his LSD5
	((ui8_crc ^ 2) == ui8_rx_buffer [7])) 	   // CRC LCD3
   { //printf("message valid \r\n");


I think that in the display settings you should not change the communication protocol with the controller
 
stancecoke said:
This can't work with my fork, as if PAS has timed out, you will never come to the part of the code you described...
Hmmm, I am not seeing what you mean by PAS time out. My approach is to always calculate pedal_cadence at begin of the slow loop so I can use it right after. If the PAS timing is over a max limit value, I do pedal_cadence = 0 and if it is under a min limit value like for (150 RPM), I do pedal_cadence = 150. This seems to be bullet prof and I can always count/use pedal cadence all over the firmware.

stancecoke said:
I described the solution above, but I'm not motivated to implement it, as I personally don't like the motor pushing at standstill, sorry.
I understand you as I moved away from development of this project. I wish other developers could join, as there are a lot of potential to be realized, like: I did discover torque sensor on this project, with you and I love them!! I always looked for motor pushing at standstill and that is only possible with torque sensors... also, now my kid is bigger but I remember 2 and 1 year ago where he could not push the bicycle from standstill (yes, it is a kid of city that uses to much time sit down watching TV and being transported by car, but he needed to start in someway and now he asks me to go out and ride his now bigger wheel bicycle).
 
casainho said:
I always looked for motor pushing at standstill and that is only possible with torque sensors... also, now my kid is bigger but I remember 2 and 1 year ago where he could not push the bicycle from standstill (yes, it is a kid of city that uses to much time sit down watching TV and being transported by car, but he needed to start in someway and now he asks me to go out and ride his now bigger wheel bicycle).

Casainho, I did try your KT fw with the Sempu (in 'torquesensor' mode) but found I was getting strong forward drive with the torquesensor at rest. I thought this was possibly due to the high rest voltage of the sempu (o/p is 1.5 - 4.0v, 76-204 ADC)) and that I probably needed to increase the 'Throttle min ADC' in the code.

I couldn't find where to do this though. I don't want to put you to a lot of trouble, but if this is fairly straightforward, could you point me in the right direction... :)
 
geofft said:
casainho said:
I always looked for motor pushing at standstill and that is only possible with torque sensors... also, now my kid is bigger but I remember 2 and 1 year ago where he could not push the bicycle from standstill (yes, it is a kid of city that uses to much time sit down watching TV and being transported by car, but he needed to start in someway and now he asks me to go out and ride his now bigger wheel bicycle).

Casainho, I did try your KT fw with the Sempu (in 'torquesensor' mode) but found I was getting strong forward drive with the torquesensor at rest. I thought this was possibly due to the high rest voltage of the sempu (o/p is 1.5 - 4.0v, 76-204 ADC)) and that I probably needed to increase the 'Throttle min ADC' in the code.

I couldn't find where to do this though. I don't want to put you to a lot of trouble, but if this is fairly straightforward, could you point me in the right direction... :)
First, on my KT code I am not calculating human power, I just us the torque sensor value.

Code:
void torque_sensor_read (void)
{
  // map value from 0 up to 255
  // map value from 0 up to 255
  ui8_torque_sensor_raw = (uint8_t) (map (
      UI8_ADC_TORQUE_SENSOR,
      (uint8_t) ui8_adc_torque_sensor_min_value,
      (uint8_t) ui8_adc_torque_sensor_max_value,
      (uint8_t) 0,
      (uint8_t) 255));

Exchange ui8_adc_torque_sensor_min_value and ui8_adc_torque_sensor_max_value for the fixed values you need.
 
Stancecoke, reading from the German forum, could Romantas' problem be related to the zero point adjustment you talked about lower down this page of the thread..?

https://endless-sphere.com/forums/viewtopic.php?f=30&t=87870&hilit=pushing&start=2850

..I always now change this to 3 (from 1) and no longer get the pushing problem.... :)

Edit: Hmm..I think I misunderstood the issue, so probably not relevent..
 
casainho said:
Exchange ui8_adc_torque_sensor_min_value and ui8_adc_torque_sensor_max_value for the fixed values you need.

Thanks! Will try tomorrow.. :)
 
casainho said:
Hmmm, I am not seeing what you mean by PAS time out.

there is a priority order depending on the boundary conditions in the update_setpoint.c

from highest priority to lowest:

1. linear regen (if activated) --> control duty cyle to get wanted regen current
2. undervoltage protection --> switch off pwm
3. brake/digital regen --> control duty cyle to zero battery current (or regen current, if activated)
4. erps limitig --> control duty cycle to maximum erps
5. PAS timeout --> control duty cyle to zero battery current

6. Power the motor according to the selected ride mode

So if PAS has timed out (PAS_counter>PAS_timeout) you will not reach the part of the code, where Torque/Throttle signals are processed.

regards
stancecoke
 
Isn't there a way to make that whole "how much power to output based on input variables" code part reusable among either branch.

Also I'd like to have the possibility to play around with all the variables at runtime (through an App) which is not possible with the current rather static approach.

What I have in mind is:

You have those inputs that are always gathered:

PAS direction
PAS activity
Throttle
Torquesensorinput
Brake set
Current current target
Regen rate

Derived from that:

PAS activity Sliding window
Throttle Sliding Window
Torquesensorinput Sliding Window
Current target Sliding Window

You can change the following variables at runtime:

Sliding Window Size (x4)
Assist Level
PAS / Torquesensor needed
Digital regen (brake vs. switched)
PAS/ Torquesensor sensitivity
Max speed
Max speed without PAS
Throttle response (linear/cubic, etc.)
- maybe more, just an idea -

Output:

New Current target.

I don't even consider designing that reusable function very complicated, nothing compared to that PWM rocket science :)
 
Code:
void torque_sensor_read (void)
{
  // map value from 0 up to 255
  // map value from 0 up to 255
  ui8_torque_sensor_raw = (uint8_t) (map (
      UI8_ADC_TORQUE_SENSOR,
      (uint8_t) ui8_adc_torque_sensor_min_value,
      (uint8_t) ui8_adc_torque_sensor_max_value,
      (uint8_t) 0,
      (uint8_t) 255));
Exchange ui8_adc_torque_sensor_min_value and ui8_adc_torque_sensor_max_value for the fixed values you need.

Casainho, I'm struggling to find those precise line of code - which file are they located in..?
 
geofft said:
Code:
void torque_sensor_read (void)
{
  // map value from 0 up to 255
  // map value from 0 up to 255
  ui8_torque_sensor_raw = (uint8_t) (map (
      UI8_ADC_TORQUE_SENSOR,
      (uint8_t) ui8_adc_torque_sensor_min_value,
      (uint8_t) ui8_adc_torque_sensor_max_value,
      (uint8_t) 0,
      (uint8_t) 255));
Exchange ui8_adc_torque_sensor_min_value and ui8_adc_torque_sensor_max_value for the fixed values you need.

Casainho, I'm struggling to find those precise line of code - which file are they located in..?
ebike_app.c file
 
Casainho, I'm struggling to find those precise line of code - which file are they located in..?
ebike_app.c file

..odd, we seem to be looking at different ebike_app.c files.

The nearest I can find to the code you have quoted is:-

void throttle_read (void)
{
// read torque sensor signal
ui8_throttle_value = UI8_ADC_THROTTLE;

throttle_value_remove_offset (&ui8_throttle_value);

// map throttle value from 0 up to 255
ui8_throttle_value = (uint8_t) (map (
ui8_throttle_value,
(uint8_t) 0,
(uint8_t) ADC_THROTTLE_MAX_VALUE,
(uint8_t) 0,
(uint8_t) 255));

...which is very similar, but inputting the ADC values here (77,204) hasn't helped. Am I on the correct section of code?
 
geofft said:
Casainho, I'm struggling to find those precise line of code - which file are they located in..?
ebike_app.c file

..odd, we seem to be looking at different ebike_app.c files.

The nearest I can find to the code you have quoted is:-

void throttle_read (void)
{
// read torque sensor signal
ui8_throttle_value = UI8_ADC_THROTTLE;

throttle_value_remove_offset (&ui8_throttle_value);

// map throttle value from 0 up to 255
ui8_throttle_value = (uint8_t) (map (
ui8_throttle_value,
(uint8_t) 0,
(uint8_t) ADC_THROTTLE_MAX_VALUE,
(uint8_t) 0,
(uint8_t) 255));

...which is very similar, but inputting the ADC values here (77,204) hasn't helped. Am I on the correct section of code?
You need to do this:
Code:
void throttle_read (void)
{
  // read torque sensor signal
  ui8_throttle_value = UI8_ADC_THROTTLE;

  // map throttle value from 0 up to 255
  ui8_throttle_value = (uint8_t) (map (
      ui8_throttle_value,
      (uint8_t) 77,
      (uint8_t) 204,
      (uint8_t) 0,
      (uint8_t) 255));

I deleted throttle_value_remove_offset (&ui8_throttle_value); on purpose.
 
casainho said:
You need to do this:
Code:
void throttle_read (void)
{
  // read torque sensor signal
  ui8_throttle_value = UI8_ADC_THROTTLE;

  // map throttle value from 0 up to 255
  ui8_throttle_value = (uint8_t) (map (
      ui8_throttle_value,
      (uint8_t) 77,
      (uint8_t) 204,
      (uint8_t) 0,
      (uint8_t) 255));

I deleted throttle_value_remove_offset (&ui8_throttle_value); on purpose.

Many thanks Casainho, that seems to have fixed the problem. Just had a very quick test ride, seems ok, maybe a little inconsistent in it's operation at the moment but I'll play around with settings, etc, over the next few days, no doubt there are improvements to be made... :wink:
 
Back
Top