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

-dg said:
stancecoke said:
-dg said:
Stancecoke, how should I send you a patch for Makefile_linux to update it?

You can post it as a txt file here, or make your own fork and send a pull request at github.

It seems a small change to make a fork for. I'm attaching the updated Makefile_linux, not a diff. Just replace the old one. It changes two things:

- update to add new files to build
- Turn off debug symbols to work around sdcc bug #2772 sdasstm8 seg faults on null pointer deref

I did not attempt to flash this or test it on hardware, just verified that it did produce a bin and ihex file. So it builds, no idea if it works. I'll look into some of the warnings when I get some time.
There is an important issue: we can't use static variables with initial values, liker 5 for instance, other way compilation fails. Because of this I am using a lot of global variables and this makes the code hard to read/understand.
 
-dg said:
I'm attaching the updated Makefile_linux, not a diff. Just replace the old one. It changes two things:

- update to add new files to build
- Turn off debug symbols to work around sdcc bug #2772 sdasstm8 seg faults on null pointer deref

Done. :D thank you very much for your efforts!

I've increased the tolerance for the offroad procedere also and made it settable in the main.h (not in the config.h/JavaTool)

regards
stancecoke
 
casainho said:
There is an important issue: we can't use static variables with initial values, liker 5 for instance, other way compilation fails. Because of this I am using a lot of global variables and this makes the code hard to read/understand.

Can you explain more about this so I understand the issue better? I'll try to test with newer sdcc and since I'm giving them bug reports already, maybe I can get them to look at that too.

The one kind of bad thing about using Modbus the way I am proposing is that the easy way to do it is to gather all the variables into one giant struct or array. I think. I'm still researching this and still learning my way around STM8 and sdcc etc. Give me a bit of time to explore this.

Are we currently using the EEPROM? Because I think that might be a neat way to deal with writable configuration. Just build it pre-initialized from the Modbus map definition and then let Modbus updates maintain it from there. However, I'm really unclear on this yet, need to do more research.

I noticed some people posting settings.ini type files that contain just raw data items. Is that format documented or coded somewhere I can look at it? I might use it to make an example Modbus map to help show what it would look like.

A favor to ask, I have asked several questions in the recent flurry of posts, could you (and also stancecoke) please go back and look at the questions and try to give me some clues. Thanks!
 
stancecoke said:
I've increased the tolerance for the offroad procedere also and made it settable in the main.h (not in the config.h/JavaTool)

Thanks for that, seems to work ok, It sometimes takes 2 or 3 tries but I always can trigger it, so not a problem. I still think that the (previously suggested) idea of 5 quick presses within, say, 2 secs would be easier for users and unlikely to be 'discovered', but for now this is ok.. :wink:
 
-dg said:
Are we currently using the EEPROM?

In my fork, we don't use the EEPROM, in casainhos, the EEPROM is used to save the latest LCD-Settings.

-dg said:
I noticed some people posting settings.ini type files that contain just raw data items.
This are the values that are defined in the GUI of the JavaTool that creates the config.h. For the order of the parameters you have to look at the sourcecode of the java-tool.
https://github.com/stancecoke/BMSBattery_S_controllers_firmware/blob/Master/tools/OSEC.java

My preference is a controller that can run "stand alone" without the need of any "master" device.... Driven "by wire" is the whole system already. There is no mechanical lever to the controller for the throttle e.g. :wink:
You should consider that the whole environment of the ebike is massively contaminated with electrosmog, due to the PWM in the motor-wires. Therefore, increased attention must be paid to the electromagnetic compatibility for a stable data transmission.

regards
stancecoke
 
-dg said:
casainho said:
There is an important issue: we can't use static variables with initial values, liker 5 for instance, other way compilation fails. Because of this I am using a lot of global variables and this makes the code hard to read/understand.

Can you explain more about this so I understand the issue better? I'll try to test with newer sdcc and since I'm giving them bug reports already, maybe I can get them to look at that too.

The one kind of bad thing about using Modbus the way I am proposing is that the easy way to do it is to gather all the variables into one giant struct or array. I think. I'm still researching this and still learning my way around STM8 and sdcc etc. Give me a bit of time to explore this.

Are we currently using the EEPROM? Because I think that might be a neat way to deal with writable configuration. Just build it pre-initialized from the Modbus map definition and then let Modbus updates maintain it from there. However, I'm really unclear on this yet, need to do more research.

I noticed some people posting settings.ini type files that contain just raw data items. Is that format documented or coded somewhere I can look at it? I might use it to make an example Modbus map to help show what it would look like.

A favor to ask, I have asked several questions in the recent flurry of posts, could you (and also stancecoke) please go back and look at the questions and try to give me some clues. Thanks!
// Sometimes I got the following error when compiling the firmware: motor.asm:750: Error: <r> relocation error
// when I have this code inside a function: "static uint8_t ui8_cruise_counter = 0;"
// and the solution was define the variable as global instead

This are the variables stored on EEPROM on the motor controller KT, this way it can run without LCD and being previous configure with the LCD connected:

DEFAULT_VALUE_ASSIST_LEVEL,
DEFAULT_VALUE_MOTOR_CHARACTARISTIC,
DEFAULT_VALUE_WHEEL_SIZE,
DEFAULT_VALUE_MAX_SPEED,
DEFAULT_VALUE_POWER_ASSIST_CONTROL_MODE,
DEFAULT_VALUE_CONTROLLER_MAX_CURRENT

And on LCD3 I am using much more the EEPROM:

DEFAULT_VALUE_ASSIST_LEVEL,
DEFAULT_VALUE_WHEEL_PERIMETER_0,
DEFAULT_VALUE_WHEEL_PERIMETER_1,
DEFAULT_VALUE_MAX_SPEED,
DEFAULT_VALUE_UNITS_TYPE,
DEFAULT_VALUE_WH_OFFSET,
DEFAULT_VALUE_WH_OFFSET,
DEFAULT_VALUE_WH_OFFSET,
DEFAULT_VALUE_WH_OFFSET,
DEFAULT_VALUE_HW_X10_100_PERCENT,
DEFAULT_VALUE_HW_X10_100_PERCENT,
DEFAULT_VALUE_HW_X10_100_PERCENT,
DEFAULT_VALUE_HW_X10_100_PERCENT,
DEAFULT_VALUE_SHOW_NUMERIC_BATTERY_SOC,
DEFAULT_VALUE_ODOMETER_FIELD_STATE,
DEFAULT_VALUE_BATTERY_MAX_CURRENT,
DEFAULT_VALUE_TARGET_MAX_BATTERY_POWER
 
casainho said:
About modbus, thanks for the explanation. I did a quick look on the first github code but I am not sure I did understand everything. For what I can understand, the controller would need to send the full data/many bytes every time and I don't like it because we need processing time!! We even would like to run PWM at higher frequency and we need even more free processor time.

On TSDZ2, PWM interrupt runs the fast code for motor controller. On slow loop, I try to run at ever 4ms the FOC angle calculation and if UART sending of modbus is long, motor control will loose quality because of that delays...

The controller is the slave, it never sends anything unless requested by a master. And it only sends the specific data items requested, not the full data. For example: if you want to update the power on the display every 200ms, and the speed every 500ms then the display would every 200ms ask for one variable and every 500ms another. Since it is a binary format the data bytes can be shipped directly without transformation so the overhead is small.

For tuning or software development, you might connect a different master that could ask for more information on different schedule. Which could become a burden if you ask for too much, but in that case the slave (controller) is free to simply return an
error response and skip over it.

The other thing is that I plan to drive the UART via interrupts, so the actual time sending should never be in the way of the fast loop.
 
stancecoke said:
In my fork, we don't use the EEPROM, in casainhos, the EEPROM is used to save the latest LCD-Settings.

-dg said:
I noticed some people posting settings.ini type files that contain just raw data items.
This are the values that are defined in the GUI of the JavaTool that creates the config.h. For the order of the parameters you have to look at the sourcecode of the java-tool.
https://github.com/stancecoke/BMSBattery_S_controllers_firmware/blob/Master/tools/OSEC.java

My preference is a controller that can run "stand alone" without the need of any "master" device.... Driven "by wire" is the whole system already. There is no mechanical lever to the controller for the throttle e.g. :wink:
You should consider that the whole environment of the ebike is massively contaminated with electrosmog, due to the PWM in the motor-wires. Therefore, increased attention must be paid to the electromagnetic compatibility for a stable data transmission.

Thanks for the info about the settings, I'll look at it this week.

I agree the controller should run stand alone. That is why it should have defaults loaded when it is first set up.

I suspect in industrial applications the Modbus slaves running a pump or a heater or whatever are expected to run even with the master offline for some reason. The master just enhances the basic function. This is also how I see this working for us, the controller works on its own, but it is possible to have more functionality by connecting an external device. Different people want different things. By providing a standard way to open up the controller data and settings we enable people to enhance the system as they wish without having to do it all ourselves. The only real new requirement on the controller is that it expose its data and settings. The rest is up to the external device if any.

The noise environment is certainly a consideration. This applies to analog voltage throttles as well as to digital message based throttles, but analog does not have CRC so in case of a water induced short an analog throttle can command full output (I have had this happen) but a message based controller can detect that was no valid throttle message for 100ms and simply shut down if desired.

That said, what do we know about the noise environment? We have examples of working displays sending serial messages, so it appears possible to do so. I'd love to know what bit rate the current connection to the LCD can run without excessive errors. Does anyone know or have a way to test this?

Perhaps for a fully fly by wire system with a lot of display ordata logging we might need to upgrade to shielded cable and rs-485 if we need a higher data rate, but the basic functions we have now should not need much more than the existing controller to LCD link.

TBH, I'm more a digital and software sort, so analog issues like noise are something I will have to learn about.
 
casainho said:
On TSDZ2, PWM interrupt runs the fast code for motor controller. On slow loop, I try to run at ever 4ms the FOC angle calculation and if UART sending of modbus is long, motor control will loose quality because of that delays...

I see that you can optimize the code for size but seems we are using about half of the size and firmwares and almost complete, so, no need for sizing optimizations. I think what we need is optimizations for speed, because of motor control needs speed!!
Please point me at the functions that are a speed concern. I'm still feeling my way around this code base so don't want to just guess.

Thanks.
 
-dg said:
The controller is the slave, it never sends anything unless requested by a master. And it only sends the specific data items requested, not the full data. For example: if you want to update the power on the display every 200ms, and the speed every 500ms then the display would every 200ms ask for one variable and every 500ms another. Since it is a binary format the data bytes can be shipped directly without transformation so the overhead is small.

For tuning or software development, you might connect a different master that could ask for more information on different schedule. Which could become a burden if you ask for too much, but in that case the slave (controller) is free to simply return an
error response and skip over it.
Ok, that seems will work well for us.

-dg said:
The other thing is that I plan to drive the UART via interrupts, so the actual time sending should never be in the way of the fast loop.
1. Once I tried to run UART interrupts and I tried to put it in a way that PWM interrupt had higher priority so UART interrupt would be interrupted by PWM interrupt however I never got it working so I forgot about that idea.

2. PWM interrupt is top priority and the remain time is used for other things, there is no problem of UART transmission waits for PWM interrupt...
For TSDZ2, priority should be: 1. PWM (that's runs every 64us, just like on KT and we want to increase to 50us); 2. FOC code that should run at every 5ms or less; 3. any other code like UART transmission and data processing.

PWM interrupt code on motor.c:
void TIM1_CAP_COM_IRQHandler(void) __interrupt(TIM1_CAP_COM_IRQHANDLER)

Slow loop code on main.c loop:
while (1)
{
// because of continue; at the end of each if code block that will stop the while (1) loop there,
// the first if block code will have the higher priority over any others
ui16_TIM3_counter = TIM3_GetCounter ();
if ((ui16_TIM3_counter - ui16_motor_controller_counter) > 4) // every 4ms
{
ui16_motor_controller_counter = ui16_TIM3_counter;
motor_controller ();
continue;
}

ui16_TIM3_counter = TIM3_GetCounter ();
if ((ui16_TIM3_counter - ui16_ebike_app_controller_counter) > 100) // every 100ms
{
ui16_ebike_app_controller_counter = ui16_TIM3_counter;
ebike_app_controller ();
continue;
}
 
casainho said:
1. Once I tried to run UART interrupts and I tried to put it in a way that PWM interrupt had higher priority so UART interrupt would be interrupted by PWM interrupt however I never got it working so I forgot about that idea.

2. PWM interrupt is top priority and the remain time is used for other things, there is no problem of UART transmission waits for PWM interrupt...
For TSDZ2, priority should be: 1. PWM (that's runs every 64us, just like on KT and we want to increase to 50us); 2. FOC code that should run at every 5ms or less; 3. any other code like UART transmission and data processing.

Thanks for the info. I still have a lot to look at and learn. Why does the FOC code run at 5ms? Would it be better faster?
Why does the PWM want to decrease from 64us to 50us? Is that just because the TSDZ2 has higher erpm, or are there other reasons?

I think next steps are:

- Cobble up an example Modbus map and some fake code to use it in the display. I say fake code because it is just to better explain the concept, not intended to work.
- Finish my wheel build and install so I have a test bike.
- Mod a controller and flash. Should I try to use your branch or the stancecoke branch? This would be for a Q100.
- During this I'll keep looking at code and making notes
- Finally code a non-interrupt proof of concept demo implementation replacing some config with Modbus.

This is gonna take a bit of time as its not my day job. Plus I'm kinda slow. Once we have a proof of concept we can work out how to merge the rest of the configuration and data.
 
@stancecoke, just a small query, is the 'Speed sensor Internal' option implemented as yet? Had a long test ride using your fw last night and noticed that the speed indication is reading low (Wheel circumference setting ok) and also only operates when the motor is driving, when coasting it slowly decays to zero.

No big deal though, I can always add an external sensor if necessary - I can see there are much more interesting things being discussed :wink:
 
-dg said:
casainho said:
1. Once I tried to run UART interrupts and I tried to put it in a way that PWM interrupt had higher priority so UART interrupt would be interrupted by PWM interrupt however I never got it working so I forgot about that idea.

I'm using several interrupts in my fork
- PWM timer
- Slow loop timer
- UART
- external speedsensor
- PAS sensor

It works without problems, I never thougt about setting priorities of interrupts. The "kernel" of the motor commutation is identical to casainhos and owed to him.


geofft said:
the speed indication is reading low (Wheel circumference setting ok)

Please check / adust the value for gear ratio

geofft said:
only operates when the motor is driving, when coasting it slowly decays to zero.
That's normal for a motor with freewheel, as the speed is calculated from the erps in "internal speed sensor" mode. It's the same with stock firmware.

regards
stancecoke
 
stancecoke said:
geofft said:
only operates when the motor is driving, when coasting it slowly decays to zero.
That's normal for a motor with freewheel, as the speed is calculated from the erps in "internal speed sensor" mode. It's the same with stock firmware.

Ah....ok, I was misinterpreting the way the Internal speed sensor option works in your code.
The Q128H motor I'm using is actually fitted with a physical sensor internally in the hub, this outputs via an extra (white) wire in the hall sensor plug. The stock controller is set up to work with this.
No problem, like I said, an external sensor is an easy fix.
 
-dg said:
The noise environment is certainly a consideration. This applies to analog voltage throttles as well as to digital message based throttles, but analog does not have CRC so in case of a water induced short an analog throttle can command full output (I have had this happen) but a message based controller can detect that was no valid throttle message for 100ms and simply shut down if desired.

That said, what do we know about the noise environment? We have examples of working displays sending serial messages, so it appears possible to do so. I'd love to know what bit rate the current connection to the LCD can run without excessive errors. Does anyone know or have a way to test this?
That's also why I am interested in a more advanced solution, because current firmware for LCD3 sends now like 3x more the data of original firmware and I am getting corrupted data on LCD3, just sometimes and the result is very strange for the user. I am using checksum but I think I will quickly try to use the CRC16 from that implementation of modbus.
Current bit rate, as also on original firmware is 19200.
 
-dg said:
Thanks for the info. I still have a lot to look at and learn. Why does the FOC code run at 5ms? Would it be better faster?
I think faster would be better but with current hardware, the motor phase current value is measured from a "slow"circuit/low pass filter so I am not sure that faster would be better, probably could even be worst. But I think it should not be slower at least.

-dg said:
- Mod a controller and flash. Should I try to use your branch or the stancecoke branch? This would be for a Q100.
My branch is not maintained anymore, only Stancecoke maintains his branch. I am only actively developing TSDZ2 and LCD3 firmwares and TSDZ2 firmware is very similar to KT firmware (the only different parts like FOC are already done and well tested on both).
I think, IMO, my code has more tecnhical features like: simple/cleaner SVM/FOC code, faster/better current phase protection, protection for motor blocked, EEPROM, (LCD3: battery power limit, battery watts hour, etc). Also I am improving my code but for TSDZ2, but should be easy to reuse for KT, I just can't test because I have no more any ebike with the motor and controllers.
As I told before, I would be happy to explain and help develop my code if someone want to do it -- and I can do it because I am actively developing for TSDZ2 and the code is very similar.
 
casainho said:
Current bit rate, as also on original firmware is 19200.

Bitrate in stock firmware (and our KT open source firmware) of controller and LCD3 is 9600.

Code:
void uart_init (void)
{
  UART2_DeInit();
  UART2_Init((uint32_t)9600,
	     UART2_WORDLENGTH_8D,
	     UART2_STOPBITS_1,
	     UART2_PARITY_NO,
	     UART2_SYNCMODE_CLOCK_DISABLE,
	     UART2_MODE_TXRX_ENABLE);
  UART2_ITConfig(UART2_IT_RXNE_OR, ENABLE);
}

regards
stancecoke
 
geofft said:
The Q128H motor I'm using is actually fitted with a physical sensor internally in the hub, this outputs via an extra (white) wire in the hall sensor plug. The stock controller is set up to work with this.
You can choose between external (the in-hub sensor is "external" from controllers sight :wink: ) an internal sensor with the stock firmware also. (parameter P2)

If the wheel-integrated sensor gives one pulse per wheel revolution, you can use it directly with our firmware. If there are more pulses per revolution, you can do a workaround by the wheel circumference The white wire in the Hall-Sensor connector is on the same processor pin as the white wire at the extra speed connector...

regards
stancecoke
 
stancecoke said:
geofft said:
The Q128H motor I'm using is actually fitted with a physical sensor internally in the hub, this outputs via an extra (white) wire in the hall sensor plug. The stock controller is set up to work with this.
You can choose between external (the in-hub sensor is "external" from controllers sight :wink: ) an internal sensor with the stock firmware also. (parameter P2)

If the wheel-integrated sensor gives one pulse per wheel revolution, you can use it directly with our firmware. If there are more pulses per revolution, you can do a workaround by the wheel circumference The white wire in the Hall-Sensor connector is on the same processor pin as the white wire at the extra speed connector...

regards
stancecoke

Thanks for the explanation, that all makes complete sense now. I guess the word 'Internal' becomes a bit ambiguous in this context, it's easy to think it refers to the internally fitted sensor. Maybe we should call this speed option 'Firmware generated' or 'Calculated' or something similar.

On a slightly different topic, my entry to the world of torque sensors hasn't begun too well. I wired a controller for this purpose and loaded the fw but it was immediately obvious that things weren't right, with the motor operating in fits and starts only. I checked the various outputs form the sensor, all seemed ok except the actual torque sensor (white wire) output. This I believe should vary between 1.5 and 4.0v depending on load, but mine outputs a constant 3.02v at rest and doesn't vary with load. This is with the controller input disconnected, so it's not being pulled up externally.

I've messaged the seller about this this but I've actually had the unit for 3 months now so I'm not expecting much sympathy from them.
 
casainho said:
-dg said:
The noise environment is certainly a consideration. This applies to analog voltage throttles as well as to digital message based throttles, but analog does not have CRC so in case of a water induced short an analog throttle can command full output (I have had this happen) but a message based controller can detect that was no valid throttle message for 100ms and simply shut down if desired.

That said, what do we know about the noise environment? We have examples of working displays sending serial messages, so it appears possible to do so. I'd love to know what bit rate the current connection to the LCD can run without excessive errors. Does anyone know or have a way to test this?
That's also why I am interested in a more advanced solution, because current firmware for LCD3 sends now like 3x more the data of original firmware and I am getting corrupted data on LCD3, just sometimes and the result is very strange for the user. I am using checksum but I think I will quickly try to use the CRC16 from that implementation of modbus.
I added CRC16 and went to test with a few rides - now I don't get corrupted data on LCD3 (I mean, it should be ignored and LCD3 is working very well as expected).
 
geofft said:
On a slightly different topic, my entry to the world of torque sensors hasn't begun too well. ... all seemed ok except the actual torque sensor (white wire) output. ... outputs a constant 3.02v at rest and doesn't vary with load.

Looking at your photos, it seems to be a Sempu, 2. generation. I had problems with mine, too. There was a bad soldered wire, that I had to fix at a brand new device :shock:

Buying at aliexpress involves a certain risk, at least the seller gave me some discount on my next order.

regards
stancecoke

Sempu wire not soldered properly.jpg
 
stancecoke said:
geofft said:
On a slightly different topic, my entry to the world of torque sensors hasn't begun too well. ... all seemed ok except the actual torque sensor (white wire) output. ... outputs a constant 3.02v at rest and doesn't vary with load.

Looking at your photos, it seems to be a Sempu, 2. generation. I had problems with mine, too. There was a bad soldered wire, that I had to fix at a brand new device :shock:

Buying at aliexpress involves a certain risk, at least the seller gave me some discount on my next order.

I've been pretty lucky with Aliexpress stuff in the past, this is the first time I've had a real problem. Unsurprisingly, no reply from seller as yet, will probably end up having to pull it apart, maybe I'll get lucky too..
 
To let you guys know that I went further on LCD3 (now I used CRC16 for LCD communication and it seems I have no more issues of corrupted data!!):
casainho said:
I implemented a new configuration menu where now user can:
1. define on LCD the battery numbers of cells (used only to calculate battery state of charge to indicate on LCD battery bars)
2. define on LCD the battery low cut-off voltage

Configuration menu:
1: battery
__0: battery cells number: this value is used only to calculate battery state of charge to indicate on LCD battery bars symbols. For 48V battery, use value of 13.
__1: battery max current: in amps. Motor controller will use no more than this value. Motor controller firmware limits this value to a safe one, like 18 amps (but this can be configured on motor controller firmware, like for use 24 amps).
__2: battery low cut-off voltage: in volts. The motor controller firmware will limit battery discharge when the battery discharge down to this value. For a 48V battery, if each cells low cut-off voltage is 3.0V, you can use the value of 39.0 (3.0 * 13 = 39.0).

Full documentation here: https://github.com/OpenSource-EBike-firmware/TSDZ2_wiki/wiki/TSDZ2-and-KT-LCD3-advanced-features-with-Flexible-OpenSource-firmwares

See the video for exemplification:
[youtube]9AfBNpng6c4[/youtube]
 
@stancecoke, I thought I had this speedometer stuff all worked out............but it seems not.

I am now using the internally fitted sensor with 'External' selected in the configurator. This sensor outputs 1 pulse per revolution. Whilst coasting with no motor drive this now works ok and gives an accurate, steady reading.

The problem arises when the motor is energised (pas or throttle) when the speedo readout immediately races up to the maximum displayable. No alternative setting for 'Wheel circumference', 'Gear ratio' or P2 seems to have any effect on this. I'm probably doing something dumb but I've run out of things to try, any ideas?
 
Back
Top