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

I just made a little java tool for setting up the main parameters. It edits the config.h-file and starts the compiling process. I think I have to read about the command-line flash tool from ST to add the flashing process to the batch-file ;). The tool needs Java Runtime.

In this way any user without progamming skills can use our firmware project :)



Regards
stancecoke
 

Attachments

  • OSEC.JPG
    OSEC.JPG
    32.5 KB · Views: 3,575
stancecoke said:
I just made a little java tool for setting up the main parameters. It edits the config.h-file and starts the compiling process. I think I have to read about the command-line flash tool from ST to add the flashing process to the batch-file ;). The tool needs Java Runtime.

In this way any user without progamming skills can use our firmware project :)
Thank you for the video and this software -- I will now write a note to hackaday.

I am being working on the 6 steps <--> sine wave transition. They both work but the transition mostly fails or is jerky :-( --- but I am pretty sure the original firmware o the same 6 steps <--> sine wave -- I need to figure out better this thing.

Good to see that you can develop software!! The way you are going for the configurations seems different from the other controllers. I think the other way may be better, where that variables can be changed in real-time, no need to configure and flash a new firmware. But sure, we have the limitation of the flash memory so we will not be able to accommodate many features in the same firmware file...
So, the original firmware stores some variable values on the EEPROM memory inside the microcontroller (1k bytes), and the user interface is on mobile app or the physical LCD. I think users will like to have the bluetooth module + mobile app (BMSBattery do not sell the bluetooh module at unit, just when we buy S09P controller, so I think would be great if we could do our own module DIY since I believe it should be simple). So the configuration would happen by UART PC or mobile app.
Maybe we could extend the LCD protocol do accommodate new commands for this new features configurations and this way keeping the compatibility with the original LCD. For the advanced features, user would need to use the bluetooth module instead of the LCD (but still we can always develop hardware to have both at the same time).

What do you think?
 
Of course it would be fine to adjust the parameters at runtime with UART (e.g. Bluetooth-module + Cellphone-app) later, but first the user has to flash the firmware. Perhaps I can even add a Button to the Java tool for setting the option bytes :).

Regards
stancecoke
 
stancecoke said:
Of course it would be fine to adjust the parameters at runtime with UART (e.g. Bluetooth-module + Cellphone-app) later, but first the user has to flash the firmware. Perhaps I can even add a Button to the Java tool for setting the option bytes :).
Ok I think I see now -- you are improving the process to configure and flash the firmware for the users without programming skills - everyone will need to do this step.
 
While contacting BMSBattery on Skype to put some questions about parts I want to buy next time, I sent them the videos and links about this project and I got some words of thanks :)
Sherry Zou: ok tank you for your supporting.
me: What you mean by my supporting?
Sherry Zou: ahh, your supporting to our company
me: Ah, okok. As long you guys keep selling good and cheap products for EBikes
 
I now want to implement battery current limiting and undervoltage protection. Therefore I want to read in throttle, battery current, and battery voltage in the acd_read_throttle.
Is there an easy way to return all three values from the function? I don't know how to deal with arraypointers etc. I would use globals instead otherwise....
Sorry this question was discussed in several programming forums thousand times, but i just don't understand how it works, to return an array from a function....

regards
stancecoke
 
stancecoke said:
I now want to implement battery current limiting and undervoltage protection. Therefore I want to read in throttle, battery current, and battery voltage in the acd_read_throttle.
Is there an easy way to return all three values from the function? I don't know how to deal with arraypointers etc. I would use globals instead otherwise....
Sorry this question was discussed in several programming forums thousand times, but i just don't understand how it works, to return an array from a function....
For me is ok to use global vars, I would do like that. I am not sure, but it may even reduce processing time. Also, we just have 32 kbytes of flash programming memory so the firmware will not be extensive... so not much need of a very good structure I think.
 
stancecoke said:
OK, then i'll try it with global variables.
Why do you map the throttle value to a maximum of 237?
That is a way to limit max duty_cycle as SVM should not have the max amplitude but I don't know which max value should be. When having the motor working correctly we can try and find this max value.
Processing is very limited so don't want to calc the limits other time again -- bad structure code I think but processing power and memory is very limited -- I am afraid we can't pack all the original features..... we will need to optimise the max. My current code with debug features goes in 30kbytes!!
 
Whats the best place to buy Kunteng controllers? I can't find them on aliexpress/baba and their web has no webshop http://www.szktdz.com
 
vex_zg said:
Whats the best place to buy Kunteng controllers? I can't find them on aliexpress/baba and their web has no webshop http://www.szktdz.com
See here links to some online shops: https://opensourceebikefirmware.bitbucket.io/Motor_controllers.html
 
OK, it works now. Some remarks:

You mixed up pins 23 and 24 in you documentation, Battery Voltage is on pin 24 (PE7 AIN9). The schematic gives the right information :)
• pin 23: BATTERY VOLTAGE
• pin 24: seems to stay always at 2V

There is very much scatter on the battery current signal, I think we have to average over many samples to get a reliable value.

I added a linear function "y=a*x+b" to calculate the correction value from the inverse speed.

Code:
ui8_position_correction_value = 135-(ui16_speed_inverse/19);

The only problem is the initial Value (0xffff) of the inverse speed, can we set it to 254 or something?!

Code:
    ui16_PWM_cycles_counter = 0;
    ui16_PWM_cycles_counter_total = 0xffff; //(SVM_TABLE_LEN_x1024) / PWM_CYCLES_COUNTER_MAX;
    ui16_speed_inverse = 0xffff;

    // next code is need for motor startup correctly
    ui8_interpolation_angle = 0;
    motor_state = MOTOR_STATE_COAST;
    hall_sensors_read_and_action ();

I wonder why the motor stops that apruptly when duty cycle is set to zero. Aren't the phases floating at this state?!

Regards
Stancecoke
 
stancecoke said:
OK, it works now. Some remarks:

You mixed up pins 23 and 24 in you documentation, Battery Voltage is on pin 24 (PE7 AIN9). The schematic gives the right information :)
• pin 23: BATTERY VOLTAGE
• pin 24: seems to stay always at 2V
Thanks. I think I will delete that part on documentation and leave only the schematic. Also that info is on the firmware source files.

stancecoke said:
There is very much scatter on the battery current signal, I think we have to average over many samples to get a reliable value.
Good idea. Low pass filter, maybe just loose resolution with right shifts or maybe this:
Code:
      ui16_PWM_cycles_counter_angle_track_accumulated -= ui16_PWM_cycles_counter_angle_track_accumulated >> 6;
      ui16_PWM_cycles_counter_angle_track_accumulated += ui16_PWM_cycles_counter;
      ui16_PWM_cycles_counter_angle_track_filtered = ui16_PWM_cycles_counter_angle_track_accumulated >> 6;

stancecoke said:
I added a linear function "y=a*x+b" to calculate the correction value from the inverse speed.
Code:
ui8_position_correction_value = 135-(ui16_speed_inverse/19);
I would say that values may only work for your specific motor, so we need defines for each motor.
Question: did you saw if at max speed, your motor have a phase B current sinewave?

stancecoke said:
The only problem is the initial Value (0xffff) of the inverse speed, can we set it to 254 or something?!

Code:
    ui16_PWM_cycles_counter = 0;
    ui16_PWM_cycles_counter_total = 0xffff; //(SVM_TABLE_LEN_x1024) / PWM_CYCLES_COUNTER_MAX;
    ui16_speed_inverse = 0xffff;

    // next code is need for motor startup correctly
    ui8_interpolation_angle = 0;
    motor_state = MOTOR_STATE_COAST;
    hall_sensors_read_and_action ();
Why not consider that initial value as invalid and also low pass filter the final value??

stancecoke said:
I wonder why the motor stops that apruptly when duty cycle is set to zero. Aren't the phases floating at this state?!
With power supply, it even increases the voltage!! That's braking and regen!! The duty_cycle at stop is 50%!! this is not the same PWM scheme as original firmware... I found this as having motor lower noise and will for sure help us implement regen/braking.
 
stancecoke said:
OK, it works now. Some remarks:
I added a linear function "y=a*x+b" to calculate the correction value from the inverse speed.

Code:
ui8_position_correction_value = 135-(ui16_speed_inverse/19);

You'll get better precision (due to correct rounding, to nearest value) by doing

Code:
ui8_position_correction_value = 135 - ((ui16_speed_inverse + 19/2) / 19);

More details here: https://endless-sphere.com/forums/viewtopic.php?f=30&t=87870&start=50#p1298214
 
casainho said:
Question: did you saw if at max speed, your motor have a phase B current sinewave?

I have not tested it yet, I still haven't identified the via on the ciruit board (I never searched for it :))

casainho said:
That's braking and regen!! ... and will for sure help us implement regen/braking.

OK, we have to make that switchable, the recent behavior is not suitable for riding a bike with a direct drive (as I do ;))

Regards
stancecoke
 
stancecoke said:
casainho said:
That's braking and regen!! ... and will for sure help us implement regen/braking.
OK, we have to make that switchable, the recent behavior is not suitable for riding a bike with a direct drive (as I do ;))
First, I can't run the original PWM scheme as I tried a few times to have the table values of duty_cycle but I always found that makes more noise than the original firmware...

Regen/braking: I think that for regen we just need to lower duty_cycle to happen regen/brake, when doing so, we need to make a PWM ramp (already done on current firmware) and look at current, to control max PWM slope and this wat controlling the max current allowed -- for regen or for accelerating -- and at least for regen, we need to look also at battery voltage as it should not pass the max allowed value (for regen and for accelerating).

So, we need to implement phase B current control!!

To disable regen, we simple disable PWM signals when decrementing throttle value.

But there are some missing bits: let's say motor is rotating freewheel at some speed where duty_cycle would be 90% but I don't know this duty_cycle value. If my throttle is at 0 and I have that ramp and current control, I can't start the ramp at duty_cycle = 0, I would need to start at 90%... but how do I know at which duty_cycle should I start?? -- I don't know this but I saw code on VESC firmware to do this... but was complicated and for FOC... maybe I will start by looking at Shane Colton firmware that is a simpler firmware.
 
[strike]<low voltage protection configuration post moved to motor tech section>[/strike]
 
casainho said:
To disable regen, we simple disable PWM signals when decrementing throttle value.
Where in the code you can disable PWM?

casainho said:
... but how do I know at which duty_cycle should I start??
Shoudn't that be easy for a direct drive, as we know the mechanical rpm from the speed signal?

I updated the feature_torque_sensor branch, I added ifdefs for three modes:
Throttle: motor runs just with throttle
Throttle and PAS: motor runs with throttle only if you are pedaling
Torquesensor: motor is driven by torquesensor

The source code of the Java-tool can be found in the /tools -folder, if someone wants to improve it ;)

index.php


Regards
stancecoke
 
vex_zg said:
sorry if I am polluting the thread - I can move to separate if it's out of scope
Yes, please. Put under Motor Technology section (I think is the correct one).
 
stancecoke said:
casainho said:
To disable regen, we simple disable PWM signals when decrementing throttle value.
Where in the code you can disable PWM?
TIM1_CtrlPWMOutputs(DISABLE); // main Output Disable

stancecoke said:
casainho said:
... but how do I know at which duty_cycle should I start??
Shoudn't that be easy for a direct drive, as we know the mechanical rpm from the speed signal?
Yes!!
I think I remember that:
- if we put higher voltage on the motor phases than BEMF, will work as motor
- if we put lower voltage on the motor phases than BEMF, will work as brake/regen
- if we equal voltage on the motor phases as BEMF, will keep the same speed and no current flowing <--- we want this!!

Calc the motor phase voltage we can put: duty_cycle (0 to 100%) * battery voltage
Calc the motor BEMF: eRPM (motor speed) * motor constant Kv (volts per RPM)

So we just need to equal both values to get the desired PWM duty_cycle value, when we need to apply a throttle value when the motor is rotating already.

stancecoke said:
I updated the feature_torque_sensor branch, I added ifdefs for three modes:
Great!! And is up to you to update master branch with your feature.
 
casainho said:
stancecoke said:
casainho said:
To disable regen, we simple disable PWM signals when decrementing throttle value.
Where in the code you can disable PWM?
TIM1_CtrlPWMOutputs(DISABLE); // main Output Disable
Seems I didn't understand your question.

For throttle, I would disable always when user decrements throttle and enable again (including calculation new needed duty_cycle value based on need voltage to equal BEMF) when user increments throttle.

On a speed controller, I would disable when the speed controller reduces the ducty_cycle value and vice-versa.
 
Hmm, now I looked up the via for phase B current. I'm a little confused. It seems that I have an older version of board layout. There is no ACS711 (EX Package) as shown on KingQueenWong's schematic on my board. There is a space for a ACS712, but it's left empty. On the board of a (defect) S06ST the ACS712 is mounted.

So, sorry, I can't show the phase B current on the osziloscope :-(
And of course can't do anything with a code that uses the phase B current signal....

Regards
stancecoke

ACS712_S06ST.jpgACS712_missing.jpgACS711_EX_Package.JPG
 
stancecoke said:
There is a space for a ACS712, but it's left empty.
So, is your controller a SxxS or SxxP??

Can you please share your controller reference and board reference?
 
Here are some photos of the labeles and the boards of the KT36 and the S06ST

So it seems the S06ST is board version KTE-6S3-B, my KT36 is KTE-6S3-D and yours is KTE-6S3-D3 ....

I bought the KT36 from ebay.
It has a little additional board for switching bikes lights.

regards
stancecoke

KT36 label.JPGKT36 board.JPGS06ST label.JPGS06ST board.JPG
 
So, what is the phase current sensor for?? why that current sensor integrated circuit on a so dirty cheap motor controller??

Maybe your controller don't do sinewave and so don't need automatic angle adjustment?? At least the ones on BMSBattery that don't have the phase current sensor, don't do sinewave and vice-versa. And sinewave/more silent motor is something that sells (Customer Perceived Value) and so can justify the added cost to the dirty cheap controller.
 
Back
Top