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

Hmm

Stancecoke wrote somewhere that the KTs sometimes have resonance issues with cheap DD motor, though i'm unsure what that means.
How hot is hot? Can you hold the case?

I wouldn't expect that it gets hot with your modest current levels, so I'm a bit unsure what to think.
How do you verify current?
 
It gets pretty hot, I cant hold the case for more than 5 seconds
I verify current with a an external digital ammeter hooked up inline with the battery
Im still pretty puzzled by this

I doubt its the hall sensors cause the motor came with the controller and it runs normally with the stock fw
 
I've reduced the battery amps to 10A and phase amps to 20A
and the controller is still getting worryingly hot :(
Im at my wits end right now
 
snips said:
I've reduced the battery amps to 10A and phase amps to 20A
and the controller is still getting worryingly hot :(
Im at my wits end right now
It is a known fact that the OSF seems to produce more heat in the controller than the stock firmware. I think this is down to the way that the pwm is operated in the OSF, but I don't have developer knowledge on this.

I'm using the 6 fet, if I run the motor with the controller inside the saddlebag it gets pretty hot after a ride, almost too hot to hold. My solution to this was to mount it under the rear saddlebag rack, here it's in the airflow and remains much cooler, maybe a little warm after a longish ride but quite acceptable. This is running with a battery current max of around 18-19 amps on a geared hub motor (i.e. no regen).

Are you running with the controller enclosed? If so it is well worth placing it in the open air if possible.
 
I'm pretty relieved to hear that
So I guess i have to live with it right, especially when I'm using a pretty aggressive regen (15A)
My current configuration right now is the controller is placed inside a saddlebag on the downtube, so placing it outside the bag would give it a significant amount of airflow. The only problem is cable management but I'll figure that out somehow

Ordered a bluetooth module and a stepdown converter so I can get blueosec and monitor whats going on
I also saw the magic smoke come out of the controller, turns out the new firmware burns the light switcher module :shock:
 
snips said:
My current configuration right now is the controller is placed inside a saddlebag on the downtube, so placing it outside the bag would give it a significant amount of airflow. The only problem is cable management but I'll figure that out somehow..

My solution here was to make a largish hole in the bottom of the saddlebag near the cable end of the controller and pull the cables through this hole into the bag. This means I can keep all the connections in base of the saddlebag out of the way, but get some air around the controller. Also being hidden away under the bag the controller is out of sight and gets some protection from the weather... :)
 
I thought of making a hole on the bag and then making a kind of a scoop to force air into the mosfet side of the controller
and then a hole on the bottom for the exhaust

Another option would be just exposing the whole controller and hiding the cables in a box beneath the bottom bracket
but the KT controller isnt particularly well sealed so I probably have to beefen up the weather sealing with some hot glue or silicone
 
geofft said:
It is a known fact that the OSF seems to produce more heat in the controller than the stock firmware
Hm, has anyone tried to increase the deadtime?
https://github.com/stancecoke/BMSBattery_S_controllers_firmware/blob/18fdd5ce9479425b2fba97a2997f7b2d5f4d27f5/pwm.c#L102

reagards
stancecoke
 
Hm, has anyone tried to increase the deadtime?

Yes, under Casainho's instruction I played around with increasing the deadtime many moons ago when he was investigating this issue. We also played around with the motor angle to no avail. I have also tried running with 'pwm off at coast' selected but was surprised to find this doesn't seem to help either.

The extra heat definitely seems to be produced at the mosfets but obviously the 'normal' heat produced by the LM317/resistor doesn't help. It would be a real bonus to find a fix for this, there are obvious efficiency gains to be had here.

Unfortunately my current installation makes it difficult to revisit these tests as the controller position in the airflow keeps it cool and effectively masks the issue. Maybe @snips could help if you wanted some new tests done?
 
Yeah I've tried running the controller with the top open, the heat definitely comes from the mosfets

Unfortunately my current installation makes it difficult to revisit these tests as the controller position in the airflow keeps it cool and effectively masks the issue. Maybe @snips could help if you wanted some new tests done?

I'm up for that since I have a pigtail connector for programming that is always accessible
Although my use case is throttle only since I dont have PAS sensor or torque sensor installed
 
I have set the overvoltage as high as it can go but the regen still acts strangely. If I apply full regen with my left hand throttle, the stopping power is greater but I actually get less current back into the battery than when I apply only a small amount of regen throttle. How is the regen implemented in this firmware? Is it done by pulsing the bottom 3 fets of the h bridge or is it more complex synchronous regen?
 
sdobbie said:
How is the regen implemented in this firmware
The duty cycle is simply modulated by a PI control in the normal center aligned pwm scheme. If the wanted regen current can't be generated and the duty cycle runs to zero, the control loop is disabled and the duty cycle is set to a speed depending value, calculated from a motorspecific constant. If this constant does not fit to your motor, you'll get poor results...

regards
stancecoke
 
Hi everyone,

As someone recently also tried, I would like to upgrade my 18 mosfet 48VZWS controller with a current sensor (ACS 758 right?) to run the open source firmware, because with the stock KT firmware, the motor gets quite hot and it makes a lot of noise and maybe I will get a bit more speed out of it. I also have a 1500w CSC ebike wheel.
I have my controller mounted on the seatstay, with a box on it for the wires, so I think I dont have to worry about high temps right?

I also have a couple of questions about the display I use, it is an LCD8. Does it have the same communication protocol as the LCD3? And would all the functions still work, apart from changing settings? (So the lights+icon, brake icon, max speed, avg speed, live speed readout, battery meter, watt meter and temperature) If not how do I add this in the code? By probing the signal wire of the screen first?
 
As someone recently also tried, I would like to upgrade my 18 mosfet 48VZWS controller with a current sensor (ACS 758 right?)

Yeah you need to install an ACS758 current sensor (I have the 150A version installed) and remove the solder bridge between the two pads. It should work right away when you flash the open firmware

the motor gets quite hot and it makes a lot of noise

From my experience the motor runs way cooler than with the stock kunteng fw and its absolutely silent. But note that using aggressive regen tends to heat up the motor fast.

I don't know about the LCD8 but since its a kunteng product you can try it. But I recommend just installing a bluetooth module and use BluOSEC since its way more feature packed and you can tune the bike right in the app
 
Thanks for the answer snips.

Yeah you need to install an ACS758 current sensor (I have the 150A version installed)
I will go for the 100A version

I don't know about the LCD8 but since its a kunteng product you can try it. But I recommend just installing a bluetooth module and use BluOSEC since its way more feature packed and you can tune the bike right in the app

Somebody else knows if the LCD8 is supported? I like the LCD8. Maybe someone can explain how the communication between screen and controller works, so I can program it to have the same features. Somebody mentioned his light switcher module burned, I use it all the time, so I want to avoid that.
 
My 2wd project has been running nicely the whole summer. I modded my s06s controllers so they transfer the heat of the big resistor and the lm317 and I have been riding with the factory firmware on both of them at 58.8V max without any problems. Without display I wasn't able to use PAS so I used only throttle instead. Last week I flashed my rear motor controller with OSEC and got my PAS working.

There seems to be one single problem though. When I ride a certain speed(~34km/h) the motor seems to start braking, hangs a few seconds and then reverts back to operating and running smooth. This did not happen with the original firmware at all. The controller does not boot because I can continue with activated offroad mode after the controller becomes responsive a few seconds later. Either way, when I accelerate to this same speed with PAS, throttle or just by freerolling a steep hill the same happens repeatedly again and again. I can see that the correction angle at the paragraph view of the BluOSEC seems to do an odd curve but nothing else. I cannot drive faster than this(~34km/h). What parameter changes could I try to fix this?
 

Attachments

  • IMG_20210614_224247.jpg
    IMG_20210614_224247.jpg
    361.6 KB · Views: 576
Valopallo said:
What parameter changes could I try to fix this?
This has nothing to do with parameter settings. It's just a processor overload. As written several times before, you need to replace all the float- and division operations in Xnyles code with integers and right shifts. We have done this for the branch "Torque from X4" for the Torquesensor mode:

https://github.com/stancecoke/BMSBattery_S_controllers_firmware/blob/a370abc9e0f2c1ab7552eafefeacfe8db04c547d/ACAsetPoint.c#L237

You would have to do it in a similar way in the master branch for PAS/Throttle mode.
https://github.com/stancecoke/BMSBattery_S_controllers_firmware/blob/18fdd5ce9479425b2fba97a2997f7b2d5f4d27f5/ACAsetPoint.c#L211

reagards
stancecoke
 
stancecoke said:
Valopallo said:
What parameter changes could I try to fix this?
This has nothing to do with parameter settings. It's just a processor overload. As written several times before, you need to replace all the float- and division operations in Xnyles code with integers and right shifts. We have done this for the branch "Torque from X4" for the Torquesensor mode:

https://github.com/stancecoke/BMSBattery_S_controllers_firmware/blob/a370abc9e0f2c1ab7552eafefeacfe8db04c547d/ACAsetPoint.c#L237

You would have to do it in a similar way in the master branch for PAS/Throttle mode.
https://github.com/stancecoke/BMSBattery_S_controllers_firmware/blob/18fdd5ce9479425b2fba97a2997f7b2d5f4d27f5/ACAsetPoint.c#L211

reagards
stancecoke

So I basically just copy/ paste /replace everything starting from line 211 of ACAsetpoint.c from the "Torque from X4" -branch to the master branch and flash with my normal parameters? Correct?

Code:
if (((ui16_aca_flags & TQ_SENSOR_MODE) != TQ_SENSOR_MODE)) {

			// add dynamic assist level based on past throttle input
			ui8_temp = ui8_assist_percent_actual;

			if ((ui16_aca_flags & DYNAMIC_ASSIST_LEVEL) == DYNAMIC_ASSIST_LEVEL) {
				ui8_temp += ui8_assist_dynamic_percent_addon;
			}

			if (ui16_time_ticks_between_pas_interrupt_smoothed > ui16_s_ramp_end) {
				//if you are pedaling slower than defined ramp end
				//or not pedalling at all
				//current is proportional to cadence
				uint32_current_target = (ui8_temp * (ui16_battery_current_max_value) / 100);
				float_temp = 1.0 - (((float) (ui16_time_ticks_between_pas_interrupt_smoothed - ui16_s_ramp_end)) / ((float) (ui16_s_ramp_start - ui16_s_ramp_end)));
				uint32_current_target = ((uint16_t) (uint32_current_target)*(uint16_t) (float_temp * 100.0)) / 100 + ui16_current_cal_b;
				controll_state_temp += 1;

				//in you are pedaling faster than in ramp end defined, desired battery current level is set,
			} else {
				uint32_current_target = (ui8_temp * (ui16_battery_current_max_value) / 100 + ui16_current_cal_b);
				controll_state_temp += 2;
			}
		} else { // torque sensor mode


		             //erst mal alles aufmultiplizieren, damit beim Teilen was über 1 übrig bleibt. Bitte mal überschlagen, ob die int32 da nicht überlaufen kann...
		             uint32_temp = ui16_sum_torque;
		             uint32_temp *= ui8_assist_percent_actual;
		             uint32_temp *= ui16_battery_current_max_value;
		             uint32_temp *= uint32_torquesensorCalibration;

		             uint32_temp /= ui16_time_ticks_between_pas_interrupt_smoothed; // hier lässt sich die geteilt-Operation nicht vermeiden :-(

		             if(PAS_is_active)
		             uint32_current_target = (uint32_temp >>8) +  (uint32_t) ui16_current_cal_b; //right shift 15 fasst die Operationen /100 (annähernd >>7) aus der assist_percent und /255 ( >>8) aus dem battery_current max zusammen, ist nicht ganz korrekt, ggf. nur >>14 nehmen -->/(256*128) vs. /(256*64)
		             else uint32_current_target =(uint32_t) ui16_current_cal_b;


			controll_state_temp += 4;

		}


		float_temp = 0.0;
		// throttle / torquesensor override following
		if (((ui16_aca_flags & TQ_SENSOR_MODE) != TQ_SENSOR_MODE)) {
			if (ui8_speedlimit_kph > 1){
				// do not apply throttle at very low speed limits (technical restriction, speelimit can and should never be lover than 1)
				float_temp = (float) ui16_sum_throttle;
			}
		} else {
			float_temp = (float) ui16_momentary_throttle; // or ui16_sum_throttle
			//float_temp *= (1 - (float) ui16_virtual_erps_speed / 2 / (float) (ui16_speed_kph_to_erps_ratio * ((float) ui8_speedlimit_kph))); //ramp down linear with speed. Risk: Value is getting negative if speed>2*speedlimit

		}

		// map curret target to assist level, not to maximum value
		if ((ui16_aca_flags & ASSIST_LVL_AFFECTS_THROTTLE) == ASSIST_LVL_AFFECTS_THROTTLE) {
			float_temp *= ((float) ui8_assist_percent_actual / 100.0);
			controll_state_temp += 8;
		}

		float_temp = float_temp * (float) (ui16_battery_current_max_value) / 255.0 + (float) ui16_current_cal_b; //calculate current target


		if ((uint32_t) float_temp > uint32_current_target) {

				//override current target with throttle
				uint32_current_target = (uint32_t) float_temp; 

			controll_state_temp += 16;
		}

		// check for overspeed
		uint32_temp = uint32_current_target;
		uint32_current_target = CheckSpeed((uint16_t) uint32_current_target, (uint16_t) ui16_virtual_erps_speed, (ui16_speed_kph_to_erps_ratio * ((uint16_t) ui8_speedlimit_actual_kph)) / 100, (ui16_speed_kph_to_erps_ratio * ((uint16_t) (ui8_speedlimit_actual_kph + 2))) / 100); //limit speed
		if (uint32_temp != uint32_current_target) {
			controll_state_temp += 32;
		}

		if (uint32_current_target > ui16_battery_current_max_value + ui16_current_cal_b) {
			uint32_current_target = ui16_battery_current_max_value + ui16_current_cal_b;
			controll_state_temp += 64;
		}
		//phase current limiting
		if (setpoint_old > 0 && (uint32_current_target - ui16_current_cal_b)*255 / setpoint_old > PHASE_CURRENT_MAX_VALUE) { // limit phase current according to Phase Current = battery current/duty cycle
			uint32_current_target = (PHASE_CURRENT_MAX_VALUE) * setpoint_old / 255 + ui16_current_cal_b;
			controll_state_temp += 128;
		}
		
		// control power instead of current
		if ((ui16_aca_flags & POWER_BASED_CONTROL) == POWER_BASED_CONTROL) {
			// nominal voltage based on limits
			ui8_temp = ((ui8_s_battery_voltage_max - ui8_s_battery_voltage_min)>>1)+ui8_s_battery_voltage_min;
			uint32_current_target*=ui8_temp/ui8_BatteryVoltage;
		}
		
		if ((ui16_aca_experimental_flags & DC_STATIC_ZERO) == DC_STATIC_ZERO) {
			ui32_dutycycle = 0;
			controll_state_temp += 256;
		}else if (!checkUnderVoltageOverride() && !checkMaxErpsOverride()){

			if (ui8_walk_assist) uint32_current_target = 10 + ui16_current_cal_b;
			//send current target to PI-controller
			ui32_dutycycle = PI_control(ui16_BatteryCurrent, uint32_current_target,uint_PWM_Enable);
		}
		
		if ((ui16_aca_experimental_flags & PWM_AUTO_OFF) == PWM_AUTO_OFF) {
			controll_state_temp += 512;
			//disable PWM if enabled and no power is wanted
			if (uint_PWM_Enable && ui32_erps_filtered == 0 && uint32_current_target == ui16_current_cal_b) {
				TIM1_CtrlPWMOutputs(DISABLE);
				uint_PWM_Enable = 0;
			}
			//enable PWM if disabled and voltage is 6.25% higher than min, some hysteresis and power is wanted
			if (!uint_PWM_Enable && ui8_BatteryVoltage > (ui8_s_battery_voltage_min +  (ui8_s_battery_voltage_min >>4)) && (uint32_current_target != ui16_current_cal_b)){
				TIM1_CtrlPWMOutputs(ENABLE);
				uint_PWM_Enable = 1;
			}
		}else{

			//enable PWM if disabled and voltage is 6.25% higher than min, some hysteresis
			if (!uint_PWM_Enable && ui8_BatteryVoltage > (ui8_s_battery_voltage_min + (ui8_s_battery_voltage_min >>4))) { 
				TIM1_CtrlPWMOutputs(ENABLE);
				uint_PWM_Enable = 1;
			}
		}
	}
	ui16_control_state = controll_state_temp;
	return cutoffSetpoint(ui32_dutycycle);

}
 
Valopallo said:
So I basically just copy/ paste /replace everything starting from line 211 of ACAsetpoint.c from the "Torque from X4" -branch to the master branch and flash with my normal parameters? Correct?

I'm wondering if you couldn't simply use the 'Torque from X4' branch and just de-select the 'Torquesensor' option? (leaving X4 unconnected)
Seems too easy, maybe I'm missing something here... :?
 
Valopallo said:
So I basically just copy/ paste /replace everything starting from line 211 of ACAsetpoint.c
No, not if you want to use PAS / Throttle. I have only optimized the part for the torquesensor data processing.

There is the basic PAS calculation in lines 220-232 that has to be changed and then later, depending on the options you have set, the lines 257-290.
ASSIST_LVL_AFFECTS_THROTTLE causes extra float calculations, I don't know, if geofft has activated this option.

It would be smarter to replace all the floats and divisions in the lines 257-290, but it works with them in the "Torque on X4" branch for geofft obviously.

regards
stancecoke
 
ASSIST_LVL_AFFECTS_THROTTLE causes extra float calculations, I don't know, if geofft has activated this option.

No, I don't use this option, I prefer to have full throttle available in all assist levels.

Would just add that since switching to the 'Torque from X4' branch (from Xnyle's torquesensor branch) I have had no processor 'hangs' whatsoever, previously I was getting a few every ride. This is using the 'Torquesensor' option of course, I have never tried this branch in PAS/throttle mode.
 
stancecoke said:
Valopallo said:
So I basically just copy/ paste /replace everything starting from line 211 of ACAsetpoint.c
No, not if you want to use PAS / Throttle. I have only optimized the part for the torquesensor data processing.

There is the basic PAS calculation in lines 220-232 that has to be changed and then later, depending on the options you have set, the lines 257-290.
ASSIST_LVL_AFFECTS_THROTTLE causes extra float calculations, I don't know, if geofft has activated this option.

It would be smarter to replace all the floats and divisions in the lines 257-290, but it works with them in the "Torque on X4" branch for geofft obviously.

regards
stancecoke

So basically I'm stuck now. I don't understand the code even if I try to see the variables and rationalize the logic behind them to the best of my abilities. I don't know how to proceed with the "need to replace all the float- and division operations in Xnyles code with integers and right shifts". If this processor overload is a common problem, are there any chance, some of you devs had the time to do this? For me, it would take months to even get a crasp of the code and some of you might be able to do it in a fraction of that time, is my humble estimation. I do understand that this is a hobby project and I'm not allowed to mimimimi but help would be highly appreciated.

These are the parameters I use:
 

Attachments

  • param_.jpg
    param_.jpg
    147.2 KB · Views: 932
you could try to replace all the lines 206-324 by just this two lines:

Code:
uint32_current_target =ui16_sum_throttle + ui16_current_cal_b; 
ui32_dutycycle = PI_control(ui16_BatteryCurrent, uint32_current_target,uint_PWM_Enable);

This just takes the throttle signal for controlling the current. You can do a test ride with throttle and check if the problem is gone.
If yes, it's worth to do the optimizations. If not, there is another cause for your problems...

I do not have a Kunteng controller any longer, so I can't do tests for this project any more. The Lishui controllers are much more interesting ;)
So of course be aware, that this suggested code modification is not tested at all and there is a risk to burn your system...


regards
stancecoke
 
stancecoke said:
you could try to replace all the lines 206-324 by just this two lines:
---
So of course be aware, that this suggested code modification is not tested at all and there is a risk to burn your system...


regards
stancecoke

Well that's quite risky. I might try other branches before that operation. I did some test drives with different parameters. The speed limit is exactly 37km/h and persists. When the processor overloads I can see that the motor generates 5-7A back to the battery. So coasting generates power when the motor does not respond to input.
 
Vallopallo, have you ever thought of just getting a vesc controller? They don't do torque sensor I don't think but they are miles ahead of the kt controllers running this firmware. I am in the process of designing one in a waterproof aluminium case specifically for electric bikes and it will sell for around £80 if it passes all my tests. Genuine vesc controllers from trampa boards are very expensive sadly.
 
Back
Top