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

casainho said:
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.
If you want to try run your motor in 6 steps only, use my latest SVM branch and comment the following code on motor.c, inside the if where ui8_motor_state is set to MOTOR_STATE_RUNNING:

Code:
      // update MOTOR_STATE_RUNNING based on motor speed
      if ((ui8_motor_state != MOTOR_STATE_STARTUP) &&
	  (ui16_PWM_cycles_counter_total > SPEED_INVERSE_MOTOR_START_RUN))
      {
        ui8_motor_state = MOTOR_STATE_STARTUP;
        pwm_init_6_steps ();
      }
      if ((ui8_motor_state != MOTOR_STATE_RUNNING) &&
	  (ui16_PWM_cycles_counter_total <= SPEED_INVERSE_MOTOR_START_RUN))
      {
        ui8_motor_state = MOTOR_STATE_RUNNING;
        pwm_init_bipolar_4q ();
        ui16_PWM_cycles_counter_total = ui16_PWM_cycles_counter_total >> 2;
      }
 
casainho said:
So, what is the phase current sensor for??

It's just to avoid the need of manual fitting of the correction values according to your motor properties?! As far as I understand the phase current should be sinusoidal in my settings with SVM_TABLE == SINE_SVM_ORIGINAL. Perhaps the efficiency is not in optimum with manually set correction values, but it works in sinus mode.

I'm struggeling with one point of your code in hall_sensors_read_and_action:

In case 4, you reset interpolation_angle and set PWM_cycles_counter_total, says: one full rotation ended, next rotation begins.

If the motor runs, you ignore all 5 other cases to get the recent rotorposition out of the Hall Sensor Mask?!

You just calculate the interpolation angle from the number of timer tic for a whole rotation in motor_fast_loop.
Code:
ui8_interpolation_angle = (uint8_t) ((ui16_PWM_cycles_counter << 8) / ui16_PWM_cycles_counter_total);


regards
stancecoke
 
stancecoke said:
casainho said:
So, what is the phase current sensor for??

It's just to avoid the need of manual fitting of the correction values according to your motor properties?! As far as I understand the phase current should be sinusoidal in my settings with SVM_TABLE == SINE_SVM_ORIGINAL. Perhaps the efficiency is not in optimum with manually set correction values, but it works in sinus mode.
I am now pretty sure the phase current sensor is used for automatic angle adjustment.
http://minshine.cn/index.asp?lang=0&nid=2&aid=110&class=standard <--- point 4: "Automatically detect the motor phase angle".

So with phase current sensor to automatically adapt for different motors and have best efficiency. In your case, you can try:
- buy a new controller
- take out the current sensor from the broken controller to the one you have working
- use the function to adjust the angle using as input the motor speed and current

You should use: SVM_TABLE == SVM <--- that is what I am using with the best results, I think best than original firmware.

stancecoke said:
I'm struggeling with one point of your code in hall_sensors_read_and_action:

In case 4, you reset interpolation_angle and set PWM_cycles_counter_total, says: one full rotation ended, next rotation begins.

If the motor runs, you ignore all 5 other cases to get the recent rotorposition out of the Hall Sensor Mask?!

You just calculate the interpolation angle from the number of timer tic for a whole rotation in motor_fast_loop.
Code:
ui8_interpolation_angle = (uint8_t) ((ui16_PWM_cycles_counter << 8) / ui16_PWM_cycles_counter_total);
That is correct. And remember that I ignore the other 5 cases because on my motor, they have uneven timings.

Code:
(ui16_PWM_cycles_counter << 8) / ui16_PWM_cycles_counter_total
(ui16_PWM_cycles_counter * 256) / ui16_PWM_cycles_counter_total, where 256 is max number of points on the SVM table. Here is a clear example of advantage to use power of 2, so I avoided the multiply *256.

I am trying to make a startup using the 6 steps and then switch to sinewave -- motor don't start from sinewave on slow eRPM motors, like some direct drive motors.
 
casainho said:
So with phase current sensor to automatically adapt for different motors and have best efficiency. In your case, you can try:
- buy a new controller
- take out the current sensor from the broken controller to the one you have working
- use the function to adjust the angle using as input the motor speed and current

I just ordered one ACS712 for 4,50€ from ebay ;)

If I disable PWM TIM1_CtrlPWMOutputs(DISABLE), can I restart PWM at any time with TIM1_CtrlPWMOutputs(ENABLE), or do I have to take care of right timing, or have to run the Timer-init again?

Regards
stancecoke
 
stancecoke said:
If I disable PWM TIM1_CtrlPWMOutputs(DISABLE), can I restart PWM at any time with TIM1_CtrlPWMOutputs(ENABLE), or do I have to take care of right timing, or have to run the Timer-init again?
TIM1_CtrlPWMOutputs should be very fast and just enable/disable the signals on the output pins, as it keeps running internally as if signals output are enabled.

I think the timing will be running and you don't need to care about it, not timer-init again. BUT, I think you should need to adapt the duty_cycle to the new motor running speed (as I explained before: adapt duty_cycle to the running motor BEMF -- you know, I am now thinking that is my issue when transition from 6 steps to sinewave, because should be fast the transition but the duty_cycle value may not the same during transition.... I need to do some test to understand if is that and if so, try to implement that, which is not trivial. In your case, just go ahead because you have the lab power supply and you will find if there are current spikes or not.
 
I tried your SVM-Table from the current SVM branch. The MOTOR_ROTOR_DELTA_PHASE_ANGLE_RIGHT is nearly zero in this setting. But the start up is very poor. At higher speeds I calculate the correction value like shown in the diagramm.
Can the start up be improved somehow? (This is the thing, you are working on?!)

calculation correction value.JPG

regards
stancecoke
 
stancecoke said:
But the start up is very poor. At higher speeds I calculate the correction value like shown in the diagramm.
Can the start up be improved somehow? (This is the thing, you are working on?!)[/attachment]
Yes, I think I am trying since 1 week a ago :-(
I already saw code and application notes from others and the process is simple and linear but I must be doing something wrong.

The switch from SVM to 6 steps works well but the contrary fails and/or is jerky. On my code now, I have UART commands to do that both switchs and i can try at any speed but it always fails/jerky...
 
casainho said:
stancecoke said:
But the start up is very poor. At higher speeds I calculate the correction value like shown in the diagramm.
Can the start up be improved somehow? (This is the thing, you are working on?!)[/attachment]

The switch from SVM to 6 steps works well but the contrary fails and/or is jerky. On my code now, I have UART commands to do that both switchs and i can try at any speed but it always fails/jerky...
Can you please test the SVM branch?? it always starts with 6 steps, see if works well for your motor. Then, send the "1" to switch to SVM at a low speed and try go back sending "0". Let's see if at least the first part works well for your motor. Verify if switching works well from SVM -> 6 steps and vice-versa.
 
I have made the experience, that the original firmware of the S06ST does not switch at a certain speed from square to sine modulation. It needs a sufficient current to do the switch. With my direct drive i just had to put a little load on the wheel, then it switched very early and reliably. Starting the wheel with no load, the switching point was quite randomly. It took me a few days to learn that correlation :?

regards
stancecoke
 
stancecoke said:
I have made the experience, that the original firmware of the S06ST does not switch at a certain speed from square to sine modulation. It needs a sufficient current to do the switch. With my direct drive i just had to put a little load on the wheel, then it switched very early and reliably. Starting the wheel with no load, the switching point was quite randomly. I took me a few days to learn that correlation :?
Hmmmm, maybe because it needs a minimum current value to work on sinewave, but to be able to auto adjust the angle - not point to start sinewave before that minimum current. A S12S handles much more current and so should work well only with more powerfull motors.
 
Have you checked the erpm for a certain value of ui8_duty_cycle_target in both modes, square and sine? If there is a big difference between these both erpms, you should reduce ui8_duty_cycle_target to the relating erpm in sine mode with the jump from square to sine-wave and then ramp it up slowly to the Throttle value?!

regards
stancecoke
 
stancecoke said:
Have you checked the erpm for a certain value of ui8_duty_cycle_target in both modes, square and sine? If there is a big difference between these both erpms, you should reduce ui8_duty_cycle_target to the relating erpm in sine mode with the jump from square to sine-wave and then ramp it up slowly to the Throttle value?!
Yes I did some tests and found the speed is different for different PWM values on each 8 steps or sinewave -- but at low speed, is not that much difference.
I even multiply the duty_cycle in sinewave mode, to scale it/adapt and tried a different scale values, etc... still fails:
ui8__duty_cycle = (uint8_t) (((float) ui8__duty_cycle) * 1.5);
 
4.3.5 Motor start
Before the motor begins to run, the primary position of the motor can be known according to Hall sensors’
outputs. However, there is no speed to calculate flux angles. Besides, the speed value varies greatly in the
start stage of the motor. Therefore, it is difficult to start the motor by using sinusoidal control mode
directly.
In this application, the 6-step control technique is used to start the motor. Bipolar PWM with the duty
cycle of 20% controls the voltage applied to the phases, and then the speed of the motor. See Figure 11.
Table 2 shows the vectors for clockwise rotation.

After the motor starts successfully and the speed stabilizes, the sinusoidal control can be used. Here, the
time before sinusoidal control mode begins to work is set to one mechanical period. When sinusoidal
control mode is used, the duty cycle should be adjusted to keep speed and current smooth because of the
difference of flux generated in wye-connected windings in these two control modes. The modified duty
cycle should be 2 / 3 of the primary value.

In Freescale Semiconductor Document Number: AN4869
Sinusoidal Control of BLDCM with Hall Sensors Based on FRDM-KE04Z and Tower Board
 
casainho said:
In Freescale Semiconductor Document Number: AN4869

Funny, I just found the same document and wanted to post the link :), you were faster...

And, does it work?!

In this document, chapter 5.2, you can find a hint at which rotor position you should do the switch...

regards
stancecoke
 
:-(

Just one question to your old code.

motor fast loop:

Code:
  if (ui16_PWM_cycles_counter < PWM_CYCLES_COUNTER_MAX)
  {
    ui16_PWM_cycles_counter++;
  }
  else
  {
    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 ();
  }

hallsensor read and action:
Code:
	if (ui16_speed_inverse > SPEED_INVERSE_INTERPOLATION)
	{
	  motor_state = MOTOR_STATE_RUNNING_VERY_SLOW;
	}
	else
	{
	  motor_state = MOTOR_STATE_RUNNING; 	}

This means, that motor state is always == Running (or Running slow), except the one loop run when ui16_PWM_cycles_counter = PWM_CYCLES_COUNTER_MAX?! And except this one loop run, always the angle interpolation is done....

regards
stancecoke
 
stancecoke said:
:-(
Just one question to your old code.
That was development/unfinished testing code, forget about it :)
 
HAPPY!! -- I think I got it :)

So, this is the same motor but with the Electric Unicycle MicroWorks 30B4 board, using my FOC code (and using the same PWM scheme). It quick starts and also quick invert rotation, using only SVM/sine!!

[youtube]2nDZW4-uVys[/youtube]

But there is FOC and without FOC maybe it is not possible to start with SVM/sine and we must use 6 steps. AND I did remember that I start with SVM/sine but WITHOUT interpolation, after some speed I started the interpolation... So I did a quick test on current firmware and I now switches well and as expected from 6 steps <-> SVM/sine without interpolation. So now I will need to add interpolation after an even higher speed -- so the scheme will be:

6 step (very slow rotation) --> SVM/sine without interpolation (slow rotation) --> SVM/sine with interpolation (slow to max rotation)
 
Great, I hope it will run with this workaround!

I just tested your svm-branch. In square mode the motor runs backwards, so if i try to chance to sine, it just does a big bang :shock:
What do I have to change direction in square mode?!

in SVM mode, if PWM is enabled, the controller takes 110mA if the motor is not running. In SVM/sine mode it takes just 50mA....

Regards
stancecoke
 
stancecoke said:
I just tested your svm-branch. In square mode the motor runs backwards, so if i try to chance to sine, it just does a big bang :shock:
What do I have to change direction in square mode?!
See the hall sensors code, the rotation left or right: https://github.com/EGG-electric-unicycle/firmware-gen2_boards/blob/modifiedFOC-motorMicroWorks30kmh/motor_foc.c

stancecoke said:
in SVM mode, if PWM is enabled, the controller takes 110mA if the motor is not running. In SVM/sine mode it takes just 50mA....
Because at motor stop, the duty_cycle is 50% on each 3 phases and any unbalance should mean current running between them while it should be 0. We can simple disable PWM when duty_cycle = 50% (throttle = 0).

I tried manually:(1) 6 step (very slow rotation) --> (2) SVM/sine without interpolation (slow rotation) --> ( 3) SVM/sine with interpolation (slow to max rotation)
From 2 to 3, always fails as before!! So I would say there is something failing on the switch because I would expect not need 2, just 1 and 3.
From 2 to 3, PWM scheme is the same, the only difference is that I enable interpolation....
 
My opinion:
In low motor mechanical speed,the interpretation need to slow down;
In high motor mechanical speed,the interpretation need to speed up;
 
I think i got it!

I don't know exactly if you get an overflow at this point at low speed:
Code:
ui8_interpolation_angle = (uint8_t) ((((uint32_t) ui16_PWM_cycles_counter) << 8) / ui16_PWM_cycles_counter_total);

but with
Code:
ui8_interpolation_angle = (uint8_t) ((ui16_PWM_cycles_counter << 7) / (ui16_PWM_cycles_counter_total>>1));

it works smoothly and reliably (ok, just with 127 angle steps....)

Regards
stancecoke
 
stancecoke said:
I think i got it!

I don't know exactly if you get an overflow at this point at low speed:
Code:
ui8_interpolation_angle = (uint8_t) ((((uint32_t) ui16_PWM_cycles_counter) << 8) / ui16_PWM_cycles_counter_total);

but with
Code:
ui8_interpolation_angle = (uint8_t) ((ui16_PWM_cycles_counter << 7) / (ui16_PWM_cycles_counter_total>>1));

it works smoothly and reliably (ok, just with 127 angle steps....)
Don't work for m :-(

Maybe you can create a new branch an put there the code, so I can try it.
 
Back
Top