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

geofft said:
honya96 said:
I wish I was a programmer to be able to work on these things. :cry:

...yep, me too, I'm working at the extreme edge of my abilities here :shock:

You obviously have a good grasp on how these things work, why not have a go, get a spare controller and try flashing this firmware? It's not as daunting as it first appears and, as you can see, these guys give fantastic help if you run into problems.

I am just waiting for st-link to arrive, then I have 2 broken controllers 6fet and 12 fet (bad mosfet driver but will show the basic functionality). And one good but old 6 fet, so I want to try them first on my 10s test bike, then I need to run it on 18fet, 14s battery at 70+ amps 8). And If it will work well then also on my 20s 10kw+ bike (maybe will buy 24fet or mod 18fet to extreme) but I don't expect it to be that good, because I need high phase amperage and it does not measure all 3.

I hope I can get it working without much struggle and bothering :?
 
honya96 said:
I am just waiting for st-link to arrive, then I have 2 broken controllers 6fet and 12 fet (bad mosfet driver but will show the basic functionality). And one good but old 6 fet, so I want to try them first on my 10s test bike, then I need to run it on 18fet, 14s battery at 70+ amps 8). And If it will work well then also on my 20s 10kw+ bike (maybe will buy 24fet or mod 18fet to extreme) but I don't expect it to be that good, because I need high phase amperage and it does not measure all 3.

I hope I can get it working without much struggle and bothering :?

Good to hear you intend to experiment with this. You have much deeper hardware knowledge than myself, so should be able to give our friends some useful feedback. Good luck with the various 'projects'.. :)
 
casainho said:
This is the diff of changes I did on main.h (where user should not change). On config.h, user selects the BATTERY_LI_ION_CELLS_NUMBER, like BATTERY_LI_ION_CELLS_NUMBER = 7.

Next thing that need to be updated is the configuration tool. Let's see if I can do it soon.

And the final code (no tested but it is on master branch as I am confident about it):
Casainho, I think there's a bug in this somewhere, whatever battery config (7s,12s, etc) I put in config.h I get a flashing empty battery signal and no motor functions... :(
 
geofft said:
casainho said:
This is the diff of changes I did on main.h (where user should not change). On config.h, user selects the BATTERY_LI_ION_CELLS_NUMBER, like BATTERY_LI_ION_CELLS_NUMBER = 7.

Next thing that need to be updated is the configuration tool. Let's see if I can do it soon.

And the final code (no tested but it is on master branch as I am confident about it):
Casainho, I think there's a bug in this somewhere, whatever battery config (7s,12s, etc) I put in config.h I get a flashing empty battery signal and no motor functions... :(
Solved.

Looking at the diff image, I saw that I forgot the << 6 operation on ADC_BATTERY_VOLTAGE_MED:
Code:
#define ADC_BATTERY_VOLTAGE_MED  ((COMMUNICATIONS_BATTERY_VOLTAGE / ADC_BATTERY_VOLTAGE_PER_ADC_STEP)) << 6

 
@geofft,

Can you please test the power on the LCD3? because I changed this, in the hope it will improve (do not left shift signed ints, as I think will not make the result we are looking for):
Code:
- ui8_tx_buffer [8] = (uint8_t) (i8_motor_current_filtered_10b << 1);
+ ui8_tx_buffer [8] = ((uint8_t) (i8_motor_current_filtered_10b)) << 1;
 
I'm not completely sure what you're asking for here but LCD3 powers up ok, everything seems to work and I get 3 battery bars with cell voltage 3.80. Is that what you would expect?
 
geofft said:
I'm not completely sure what you're asking for here but LCD3 powers up ok, everything seems to work and I get 3 battery bars with cell voltage 3.80. Is that what you would expect?
Motor power readings, that depends on the motor current readed -- firmware reads the current and send to display; display multiplies after reading the battery voltage directly.
Let's see if now motor power is correct...
 
Yes, motor power looks correct with a quick test on the stand, around 50-100w at 25kph unloaded, about what you would expect.

Slightly strange display behaviour on power up (without any load), display shows 2 battery bars (correct for 3.80v?) and 2000w, the 2000w slowly decays to 0w after around 10 secs, then the battery bars increase to 3. This is not new behaviour, (the 2000-0w thing), it has always done this, it's just the first time I've mentioned it.
 
geofft said:
Yes, motor power looks correct with a quick test on the stand, around 50-100w at 25kph unloaded, about what you would expect.

Slightly strange display behaviour on power up (without any load), display shows 2 battery bars (correct for 3.80v?) and 2000w, the 2000w slowly decays to 0w after around 10 secs, then the battery bars increase to 3. This is not new behaviour, (the 2000-0w thing), it has always done this, it's just the first time I've mentioned it.
The battery readings have a low pass filter that slows down and filters fast change on the signal. And the filter starts from ADC_BATTERY_VOLTAGE_MED otherwise starting from 0, would trigger the fault/undervoltage (as just did before when ADC_BATTERY_VOLTAGE_MED value was wring and very low).

ui16_adc_battery_voltage_accumulated is just like a big accumulator (think as a water accumulator, to absorb fast changes on the water input while maintain a constant output of water).
Code:
uint16_t ui16_adc_battery_voltage_accumulated = (uint16_t) ADC_BATTERY_VOLTAGE_MED;

void do_battery_voltage_protection (void)
{
  // low pass filter the voltage readed value, to avoid possible fast spikes/noise
  ui16_adc_battery_voltage_accumulated -= ui16_adc_battery_voltage_accumulated >> 6;
  ui16_adc_battery_voltage_accumulated += ((uint16_t) ui8_adc_read_battery_voltage ());
  ui8_adc_battery_voltage_filtered = ui16_adc_battery_voltage_accumulated >> 6;

  if (ui8_adc_battery_voltage_filtered < ((uint8_t) ADC_BATTERY_VOLTAGE_MIN))
  {
    // motor will stop and battery symbol on LCD will be empty and flashing
    motor_controller_set_state (MOTOR_CONTROLLER_STATE_UNDER_VOLTAGE);
    motor_disable_PWM ();
    motor_controller_set_error (MOTOR_CONTROLLER_ERROR_91_BATTERY_UNDER_VOLTAGE);
  }
}

The code for battery bars is here:
Code:
  // calc battery pack state of charge (SOC)
  ui16_battery_volts = motor_get_ADC_battery_voltage_filtered () * ADC_BATTERY_VOLTAGE_K;
  if (ui16_battery_volts > BATTERY_PACK_VOLTS_100) { ui16_battery_soc = 16; } // 4 bars | full
  else if (ui16_battery_volts > BATTERY_PACK_VOLTS_80) { ui16_battery_soc = 12; } // 3 bars
  else if (ui16_battery_volts > BATTERY_PACK_VOLTS_40) { ui16_battery_soc = 8; } // 2 bars
  else if (ui16_battery_volts > BATTERY_PACK_VOLTS_20) { ui16_battery_soc = 4; } // 1 bar
  else { ui16_battery_soc = 3; } // empty
  
  // Considering the follow voltage values for each li-ion battery cell
// State of charge 		| voltage
#define LI_ION_CELL_VOLTS_MAX 	4.2
#define LI_ION_CELL_VOLTS_100 	4.05
#define LI_ION_CELL_VOLTS_80 	3.93
#define LI_ION_CELL_VOLTS_60 	3.78
#define LI_ION_CELL_VOLTS_40 	3.60
#define LI_ION_CELL_VOLTS_20 	3.38
#define LI_ION_CELL_VOLTS_0 	3.20
#define LI_ION_CELL_VOLTS_MIN 	3.0

#define BATTERY_PACK_VOLTS_100	(LI_ION_CELL_VOLTS_100 * BATTERY_LI_ION_CELLS_NUMBER) * 256
#define BATTERY_PACK_VOLTS_80 	(LI_ION_CELL_VOLTS_80 * BATTERY_LI_ION_CELLS_NUMBER) * 256
#define BATTERY_PACK_VOLTS_60	(LI_ION_CELL_VOLTS_60 * BATTERY_LI_ION_CELLS_NUMBER) * 256
#define BATTERY_PACK_VOLTS_40	(LI_ION_CELL_VOLTS_40 * BATTERY_LI_ION_CELLS_NUMBER) * 256
#define BATTERY_PACK_VOLTS_20	(LI_ION_CELL_VOLTS_20 * BATTERY_LI_ION_CELLS_NUMBER) * 256
#define BATTERY_PACK_VOLTS_0	(LI_ION_CELL_VOLTS_0 * BATTERY_LI_ION_CELLS_NUMBER) * 256

The motor current value, at start may have some incorrect value (??)....
 
Unfortunately I am not able to read the code, but I fully understand the 'damping' control you describe. I would add that this power-up display behaviour is only a detail, it's only because the motor power (on power up) starts at 2000w (not 0w) that the effect is noticeable, it doesn't really affect operation in any important way. It's because the bigger things are now working so well I'm starting to pay attention to the details... :D

Just out of interest can I ask what programming langauge you're using here, is it Java, C, C++, or something else?
 
geofft said:
Just out of interest can I ask what programming langauge you're using here, is it Java, C, C++, or something else?
C and the compiler is: http://sdcc.sourceforge.net/mediawiki/index.php/Stm8_code_size
 
in the main.h the value of ADC_MOTOR_CURRENT_MAX_MED_10B is set to constant value, [strike]that may not fit to the max motor current chosen from the user[/strike].

Edit: that may not fit to the zero amps reading of the certain controller. That should be easy to fix!

Code:
#define ADC_MOTOR_CURRENT_MAX_MED_10B 10144 // ADC_MOTOR_CURRENT_MAX_ZERO_VALUE_10B << 5
#define ADC_MOTOR_CURRENT_MAX_10B (ADC_MOTOR_CURRENT_MAX << 2)



regards
stancecoke
 
stancecoke said:
in the main.h the value of ADC_MOTOR_CURRENT_MAX_MED_10B is set to constant value, that may not fit to the max motor current chosen from the user. That should be easy to fix!

Code:
#define ADC_MOTOR_CURRENT_MAX_MED_10B 10144 // ADC_MOTOR_CURRENT_MAX_ZERO_VALUE_10B << 5
#define ADC_MOTOR_CURRENT_MAX_10B (ADC_MOTOR_CURRENT_MAX << 2)
Good find!!
Maybe this initial values of the filters could be real values, measured at startup of the system. Something for future.
 
Ok, my fault. This value doesn't refer to the max motor current, but to the zero amps value. And this value we read in already.

Code:
  // read and average a few values of ADC
  ui16_motor_total_current_offset_10b = 0;
  for (ui8_i = 0; ui8_i < 16; ui8_i++)
  {
    ui16_counter = TIM2_GetCounter () + 78; // delay ~10ms
    adc_trigger ();
    while (!ADC1_GetFlagStatus (ADC1_FLAG_EOC)) ; // wait for end of conversion
    ui16_motor_total_current_offset_10b += ui16_adc_read_motor_total_current_10b ();
  }
  ui16_motor_total_current_offset_10b >>= 4;
  ui8_motor_total_current_offset = ui16_motor_total_current_offset_10b >> 2;
}

So we should write in the motor.c, somewhere in the motor init procedure, making sure, that ui16_motor_total_current_offset_10b was read already at this time:

Code:
ui16_adc_motor_current_accumulated_10b = ui16_motor_total_current_offset_10b<<4;

I think, this can fix the thing with the high power values displayed at startup.

regards
stancecoke
 
another finding:
the avaraging in the code is done by shift right 4.

Code:
void calc_motor_current_filtered (void)
{
  // low pass filter the current readed value, to avoid possible fast spikes/noise
  ui16_adc_motor_current_accumulated_10b -= ui16_adc_motor_current_accumulated_10b >> 4;
  ui16_adc_motor_current_accumulated_10b += ui16_adc_read_motor_total_current_10b ();
  ui16_adc_motor_current_filtered_10b = ui16_adc_motor_current_accumulated_10b >> 4;
  i8_motor_current_filtered_10b = ui16_adc_motor_current_filtered_10b - ui16_motor_total_current_offset_10b;
}

The initial value in the main.h was calculated with shift left 5, so the initial value is too high by factor two!

regards
stancecoke
 
Done!
 
Firmware configuration tool is now updated to support variable cells number.
 
So I have received the st-link and I have first "dumb user" problem. I don't see where to connect 4 pins from header to 10pins on stlink. I am able to find it somewhere maybe but It should be added.

Edit: ok its at stacecoke's page, so they should be all 4 connected?
 
See here also: https://opensourceebikefirmware.bitbucket.io/INSTALL_FIRMWARE--Hardware_tools_flash_firmware--Open_controller_and_solder_programming_header.html
 
casainho said:

That's much better now, powers up dead on zero, maybe starts to drift a little after around 20 secs and eventually settles drifting slightly around 22 watts. Not perfect but probably near enough.

Battery meter starts at 2 bars (looks correct for current cell voltage of 3.80v ?) but after about 10 secs jumps to 3 bars, (maybe too high?)

Did have a play with FOC motor angle, tried various angles measuring battery current at fixed (limited) speed/full throttle but difficult to get meaningful results with no load. If anything a slightly higher angle may work on my setup (around 145-150 degrees) but I've little confidence in this result. Would need to find some way of providing a fixed controlled load, not easy on the stand.

Looking forward now to trying a road test, have some time tomorrow morning and weather looks better, will let you know how it goes.
 
honya96 said:
Edit: ok its at stacecoke's page, so they should be all 4 connected?
If you connect all four wires, you don't have to power the controller with the battery for flashing. It's powered from the STLink then.

it looks like we're making a lot of progress today! :D

regards
stancecoke
 
Casainho, at your link I cant see connection to st-link pins.

Thanks stancecoke :wink:

So first things done.
 

Attachments

  • 20180109_170730-1024x576.jpg
    20180109_170730-1024x576.jpg
    131.5 KB · Views: 2,690
  • 20180109_165218-580x1031.jpg
    20180109_165218-580x1031.jpg
    61.9 KB · Views: 2,690
honya96 said:
Casainho, at your link I cant see connection to st-link pins.
Then I will update with stancecoke pictures and maybe even your picutres.
 
So, I have it connected and light is up still.

but looks like you are working on the website right?
 

Attachments

  • 20180109_174146-864x1536.jpg
    20180109_174146-864x1536.jpg
    98.2 KB · Views: 2,687
  • 20180109_174239-1024x576.jpg
    20180109_174239-1024x576.jpg
    68.7 KB · Views: 2,687
geofft said:
That's much better now, powers up dead on zero, maybe starts to drift a little after around 20 secs and eventually settles drifting slightly around 22 watts. Not perfect but probably near enough.
I also got on my ebike around that value. I think i8_motor_current_filtered_10b = 1, that is multiplied by two before sent to LCD. Each unit is 0.25A. So, in your case: 38V( 10S * 3.8V), 22W --> I = P / U; 22/38 = 0.58A

Maybe we could always decrement i8_motor_current_filtered_10b by 1 or 2 units, before sent to LCD.

I wounder it that 22W will not increase after you run the motor for some time, if the shunt on the controller will not change his value considerable...
 
Back
Top