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

stancecoke said:
I get minimum current for correction value of~138. At higher duty cycle this "best" value increases....
You can look at my code/changes were I tried to get automatic/dynamic correction value, based on phase current sinusoid zero cross timings...
 
I just added a video to Youtube:
[youtube]pujSqUnBa7k[/youtube]

casainho said:
Do you have an oscilloscope??
The other signal is the hall sensor, which is great as a trigger for the oscilloscope.

Yes, I have a very old fashioned one, see my other youtube-videos :)

casainho said:
What is or motor RPM and eRPM? Can you please tell what is the RPM -- max wheel speed x perimeter...
eRPM we need to know RPM and the number of magnets your motor have...

I just don't now the specs of the motor. Perhaps you can get some information analyzing the audio of my video with something like this.

casainho said:
You can look at my code/changes were I tried to get automatic/dynamic correction value, based on phase current sinusoid zero cross timings...

In which branch you did the changes?

In principle I'm satisfied with the current status, now I can begin to test my software for the bottom bracket sensor ;)

regards
stancecoke
 
Ok I think I got the eRPM of your motor: I saw value of 40 of ui16_speed_inverse and that means 40 * 64us = 2.560ms per eRPM at 36V power supply -- I guess you want run motor at 36v. The firmware will draw the "sine wave" voltage using 40 points.

My Q85 at 30V (and I think it is a 24v motor), have a 1.808ms eRPM as seen on the next picture -- so firmware will draw the "sine wave" voltage using 28 points... I think this is an issue!! (we can verify/count the 28 number of PWM pulses on the next image)
42-9.png


Can you please use the oscilloscope to verify if the phase B current is a sinewave when you run the motor at low and at high speeds, with the optimum value of ui8_position_correction_value?? Because if so, that means this controller should be able to run well your motor... and the firmware just need to dynamically adjust ui8_position_correction_value and we will need to find a strategy to do it :)


stancecoke said:
casainho said:
You can look at my code/changes were I tried to get automatic/dynamic correction value, based on phase current sinusoid zero cross timings...
In which branch you did the changes?

To the master as also in your branch as you can see here (gitg software):


You can for instance, copy your sources folder to another with other name and:
- git reset --hard (to delete all the files/code you changed)
- git checkout 30fa9915170fa255f531479c2dc3bd2d1ce273ab (you will be on the commit I did with that code

Anyway, if you prefer to focus on your feature, no problem, I will continue as I want to finish the motor control code. Please just test and tell me if you could get the sine wave on phase B at max speed and what was the ui16_speed_inverse.
 
casainho said:
Please just test and tell me if you could get the sine wave on phase B at max speed and what was the ui16_speed_inverse.
can you post a picture where I can find the via for the current?

I tested my code in hardware now. Just connected the sensor, not the motor to the controller yet. After fixing some bugs I get proper values now, I think, tomorrow I can test with the motor connected :)

In your selftuning code, the correction value is zero initially. Do i have to add the 127 to MOTOR_ROTOR_DELTA_PHASE_ANGLE_RIGHT that i found with the "static" code?

regards
stancecoke
 
stancecoke said:
casainho said:
Please just test and tell me if you could get the sine wave on phase B at max speed and what was the ui16_speed_inverse.
can you post a picture where I can find the via for the current?

I tested my code in hardware now. Just connected the sensor, not the motor to the controller yet. After fixing some bugs I get proper values now, I think, tomorrow I can test with the motor connected :)

In your selftuning code, the correction value is zero initially. Do i have to add the 127 to MOTOR_ROTOR_DELTA_PHASE_ANGLE_RIGHT that i found with the "static" code?
Sorry I am not on PC so can't take a picture. But is pin 17 and you can see on the S06S schematic all the pins/circuit: https://opensourceebikefirmware.bitbucket.io/Controllers--BMSBattery_S06x--S06S.html

The idea is simple: increment/decrement 1 unit as you did manually. So stick with your working values for the angle and that variable can start at zero (255 is equal to -1, etc).
 
stancecoke said:
I've just updated the feature_torque_sensor branch. I added a tutorial for setting up the toolchain with windows to reduce pain for other potential users, that are not experienced with linux 8)
I must say I almost didn't look at your code yet, as I want to focus on correct motor control. And trying to drive by electric unicycle motor (direct drive), the code fails... this motor is very low eRPM and the uint16_t variables couldn't hold the multiplication of PWM cycle counter * 256. But still I have some issue on the code because it still fails...

That is very nice and I just put the file on the HTML notes file: https://opensourceebikefirmware.bitbucket.io/Development_tools--Windows.html

I am using note taking software for the documentation, maybe next time you can use it and put the file on git and I can simple import your file as a node, like a specific node for the windows documentation -- we can import/export just a specific part of the notes files.
But using this software is not user friendly for collaboration... I think the ideal would be a wiki but it is very slow to copy paste data to the wiki... unlike this note take software.
The documentation notes files are on bitbucket because it does provide more space, and the documentation is HUGE -- the notes files have 253 MBytes (not counting with the HTML files).
 
I received my Lishui LSW-675 from BMSBattery. I bought without the LCD and it didn't work, seams dead although I short circuited the pin for "ignition" and there is a LED on the board that is flashing -- connected the throttle and the motor but nothing.

After, I tried to connect the STLinkV2 and after some tries and verifications, I can't connect with OpenOCD... so I am not sure the STM32FEBKC6T6 is the same as STM32F103 other way I was expecting it could connect using OpenOCD.

About the S06S controller, I still have some bug on the firmware to run my electric unicycle motor, but I found some more information. Need to work more on this.
 
casainho said:
I tried to connect the STLinkV2 and after some tries and verifications,

Do you have the correct wiring? I had no problems with flashing the STM32 Lishuis so far...

Regards
stancecoke
 
stancecoke said:
casainho said:
I tried to connect the STLinkV2 and after some tries and verifications,

Do you have the correct wiring? I had no problems with flashing the STM32 Lishuis so far...
After following that information, worked!!! :)



The C6T6 (STM32FEBKC6T6) means it should have only 32kbytes :-( --- but I will try to flash different files size and try understand if for some magic reason it can hold more than 32kbytes...
 
Using OpenOCD I was able to erase the 32kbytes flash (0x8000) but failed to erase 64kbytes flash (0x10000). So I think this STM32 have only 32bytes of flash memory :-(

> flash erase_address unlock 0x08000000 0x8000
target state: halted
target halted due to breakpoint, current mode: Handler HardFault
xPSR: 0x61000003 pc: 0x2000003a msp: 0xffffffdc
erased address 0x08000000 (length 32768) in 0.831294s (38.494 KiB/s)
>

> flash erase_address unlock 0x08000000 0x10000
target state: halted
target halted due to breakpoint, current mode: Handler HardFault
xPSR: 0x61000003 pc: 0x2000003a msp: 0xffffffdc
stm32x device protected
failed erasing sectors 0 to 63
>
 
SxxP versus SxxS versus LSW-675

SxxP
The SxxP version is a sensorless, square wave/6 steps motor controller and has a secondary board that includes another microcontroller (STM8S003F3) as seen on the next picture. The main microcontroller is the 16 MHz, 8 bits, 32kbytes flash program memory, STM8S105C6T6 and don't have processing power to do FOC.

To be sensorless, it may look at BEMF zero crossing and for that 1 phase must not be energized during 1 step - because of this, the motor phases can't be driven with a sinewave/SVM.
I think the secondary board implements the sensorless algorithm.



SxxS
The SxxS version is sensored, sinewave/SVM motor controller and unlike SxxP, doesn't have a secondary board. The main microcontroller is the 16 MHz, 8 bits, 32kbytes flash program memory, STM8S105C6T6 and don't have processing power to do FOC.

Because it is sensored, it can drive the motor phases with sinewave/SVM.

LSW-675
The LSW-675 is a sensorless, FOC/sinewave/SVM motor controller. The main microcontroller is the 48 MHz, 32 bits, 32kbytes flash program memory, STM32FEBKC6T6 (similar to STM32F103?) and have processing power to implement FOC.

The 32kbytes flash program memory seems to little to implement FOC however, I found that ST have a FOC library that uses only ~16kbytes of flash memory:

Performances of FOC with STM32F103
Configuration: 1 shunt/sensorless at 10 kHz FOC sampling time
• Motor control code size is 16.2 Kbytes
• Motor control RAM usage is <2.5 Kbytes
• FOC total execution time is 26.1 μs (ADC ISR + TIM1 update ISR)
• FOC introduced CPU load is 30%
 
STM32FEBKC6T6:Ebike-Solution-Replace-With-STM32F103C6T6
 

Attachments

  • STM32FEBKC6T6-32-bit-ARM-Ebike-Solution-Replace-With-STM32F103C6T6.pdf
    1.4 MB · Views: 190
KingQueenWong said:
STM32FEBKC6T6:Ebike-Solution-Replace-With-STM32F103C6T6
Oh men, just you!! I searched all over the web and not datasheet for the STM32FEBKC6T6. I will put it on the notes files :)

I want to keep my focus on the S06S controller. Yesterday I also received a S12S and is very nice to see that is just the same hardware as S06S, but more mosfets and the phase B current sensor is bigger to handle the more current (25 max current = 1200W @ 48V).
 
casainho said:
Ok I think I got the eRPM of your motor: I saw value of 40 of ui16_speed_inverse and that means 40 * 64us = 2.560ms per eRPM at 36V power supply -- I guess you want run motor at 36v. The firmware will draw the "sine wave" voltage using 40 points.

My Q85 at 30V (and I think it is a 24v motor), have a 1.808ms eRPM as seen on the next picture -- so firmware will draw the "sine wave" voltage using 28 points... I think this is an issue!! (we can verify/count the 28 number of PWM pulses on the next image)
42-9.png
And I was having problems with my EUC2 motor and found that although I can run it well with sinewave as I did with my Q85 and you with your motor, my EUC2 motor can't start well, most time fails...

At 30V, this motor have an eRPM of 15ms!! 6x lower than my Q85 motor!! So the firmware will draw the "sine wave" voltage using 234 points VS the only 28 on my Q85.

After I went back to my commit with 6 steps and found that this motor starts very well with 6 steps... so next I want to implement for startup 6 steps and after startup phase, transition to the sine wave/SVM (in fact, that is what original firmware does, I just didn't felt the need yet). I am pretty sure this will work with this slow eRPM motor as also with your and my Q85 faster motors!!

I remember to try drive my Q85 with my MicroWorks 30B4 board (STM32F103), using FOC/sine wave/SVM and it worked well just up to medium speed and after that it was going craze!! I could see the value of position_correction_value start going backwards (crazy!!)... that firmware have the PWM running at 20MHz / 50us and with S06S it runs even lower at 16kHz / 64us... I am that afraid S06S can't run well this fast eRPM motors like Q85 and Q75, due to low PWM frequency / motor high eRPM.
One think I couldn't test was the LSW-675 PWM frequency (I will need to buy another unit with LCD to test again)... as there are reports it is the only controller that BMSBattery sells that runs well Q75 (unlike S06S).
 
Just updated the feature_torque_sensor branch. Motor is driven by the sensor now :)
The interrupts of PAS and SPEED don't disturb the motor in any way, you can't hear a change in sound or anything...

regards
stancecoke
 
stancecoke said:
Just updated the feature_torque_sensor branch. Motor is driven by the sensor now :)
The interrupts of PAS and SPEED don't disturb the motor in any way, you can't hear a change in sound or anything...
THAT'S GREAT!!! Congratulations.

But I think the feature is just finished when you record a video showing it working :) Please put on the title and description the main keywords like BMSBattery torque sensor S06S, etc. So others will be able to find your work.

I will not merge to master yet, unless you want to dot it by yourself as I want to focus on the missing motor control.
Are you planning to use it?? Because the code misses the motor control but I think we could take a shortcut: profile each mortor angle correction value for different speeds and apply it. Then I think we can read the phase current as you do, averaging all the positive values of the sinewave and then control the current.

Anyway, you have now a Makefile for Windows, mabe you could call it Makefile_windows and I will do the same for Linux and users can call make -f Makefile_windows on windows. This I would put right now on master.
 
casainho said:
.
But I think the feature is just finished when you record a video showing it working :) Please put on the title and description the main keywords like BMSBattery torque sensor S06S, etc. So others will be able to find your work.
That video would me making PR right now -- I would write to hackaday to see if they coud feature (again) the project on their news site.
 
So, someone that wanted to help me, sent me the firmware bin file for the Lishui LSW-675 to work without LCD. I flashed and found that it still didn't work... but the red LED was still flashing 2 times... and then I verified that my power supply was regulated to 30V and when increased to 36V, it started to work (red led started to flash only 1 time) :)

Lishui LSW-675 PWM frequency is 16kHz (62us).
The controller seems to have a startup sequence first and then jumps to another control mode. Looking at oscilloscope, seems there is no difference, the PWM signal is not Unipolar 4-Quadrant PWM Technique.

The startup sequence seems a bit instable and sometimes I see the wheel rotating a bit first to contrary direction. Sometimes the motor shakes a bit and the transition is not soft -- however I tested with my EUC2 motor that is a slow one, unlike Q85 for instance.

So, to resume: the way LSW-675 drives the motor seems equal to S06S but with the advantage that it is sensorless and almost for sure use an angle estimator that makes a robust system (although needs correct parameterization for motor windings resistance and inductance, but the firmware someone sent me just worked on my motor). LSW-675 have only 32 kbytes flash memory and half of that should be used for the motor control. S06S on the other side, needs a motor with hall sensors because it simple can't do the processing for an angle estimator. S06S also have only 32 kbytes flash memory and I would also say it uses also half of that to the motor control. I hope that with S06S we can achieve also a good angle control, just like LSW-675 does with the angle estimator -- this need to be done on current OpenSOurce firmware.
I am not seeing any big advantage on LSW-675 over S06S. LSW-675 seems to be available only for 250W motor while S series controllers are available for 250, 500 and 1000 or more watts. They are also cheaper and more available. LSW-675 have one advantage: it is sensorless and seems to be a robust algorithm unlike S06P that is also sensorless but seems that fails with fast motors as Q75.
 
I just tested LSW-675 with my Q85 motor. It starts ok (but not perfect) and makes the transition to the next phase where it starts to run a bit quieter up to medium speed where suddenly the motor starts to ask more current and the controller stops the motor -- this always happen with my Q85. I would say that the firmware I have have wrong values of motor coils inductance and resistance and so the rotor angle estimator fails -- I don't have a way to configure the firmware to work without LCD.

66-2.png
 
casainho said:
I will not merge to master yet
I think this would not make sense, as less people own such a bottom bracket sensor.
Perhaps we should place all customer relevant parameters into a config.h, and activate/disable the features with ifdefs...

casainho said:
I want to focus on the missing motor control.
Are you planning to use it??
Yes of course, i just didn't test the autotune feature. I have no possibility to put load on the shengyi middrive motor. I think I will switch to a very old panamotor, I can easily brake at the rim then.

casainho said:
I would say that the firmware I have have wrong values of motor coils inductance and resistance and so the rotor angle estimator fails -- I don't have a way to configure the firmware to work without LCD.
??? you can use exactly that tool, you are showing in the sceenshot?! You just have to use a FTDI USBtoUART converter and connect it to the display port of the controller. The old version of the toolworked with the PL2303 too.
file.php


regards
stancecoke
 

Attachments

  • USBtoUART.JPG
    USBtoUART.JPG
    50.2 KB · Views: 3,505
stancecoke said:
casainho said:
I will not merge to master yet
I think this would not make sense, as less people own such a bottom bracket sensor.
Perhaps we should place all customer relevant parameters into a config.h, and activate/disable the features with ifdefs...
Yes, ifdefs even because I am almost sure we should almost run out of programming memory. Also, for instance, I am planning to use the BMSBattery torque sensor and so I will need to disable the code for the torque sensor you just did.

Also, I suggest for you to keep the files including the name of torque sensor, maybe like: "torque_sensor-brand-model.c", "torque_sensor-brand-model-update_setpoint.c", etc. Will be easy to manage the files/code/features.

stancecoke said:
casainho said:
I want to focus on the missing motor control.
Are you planning to use it??
Yes of course, i just didn't test the autotune feature. I have no possibility to put load on the shengyi middrive motor. I think I will switch to a very old panamotor, I can easily brake at the rim then.
From my experience, the angle don't change to much with the load current, maybe it is not expressive. I think we just need to profile the motor speed VS angle and apply the adjustment value to ui8_position_correction_value.

I am pretty sure the autotune feature will take some months to be finished, if possible at all. Because I need to improve the PWM resolution (right now is only at 8bits) and also increase the angle resolution.

stancecoke said:
casainho said:
I would say that the firmware I have have wrong values of motor coils inductance and resistance and so the rotor angle estimator fails -- I don't have a way to configure the firmware to work without LCD.
??? you can use exactly that tool, you are showing in the sceenshot?! You just have to use a FTDI USBtoUART converter and connect it to the display port of the controller. The old version of the toolworked with the PL2303 too.
file.php
Thanks. I just put that controller on the drawer for now. I want to explore the S06S first and try make a good firmware for it.
 
OK, I think a very important thing to do is to implement a motor phase current limitation. You read in the maximium current already, but this value "ui16_adc_current_phase_B_filtered" is not used for any further actions yet? Is there any possibility that Phase A or C take too much current, while Phase B is OK? Then we should limit the battery current, too.

regards
stancecoke
 
stancecoke said:
OK, I think a very important thing to do is to implement a motor phase current limitation. You read in the maximium current already, but this value "ui16_adc_current_phase_B_filtered" is not used for any further actions yet?
My code was expecting a perfect sinewave but that happens only when the angle is correct. For now, at top speeds, it is not a sinewave... so that code will fail. What I propose is:

http://www.electronics-tutorials.ws/accircuits/average-voltage.html

The issue with that code is the division, that takes like about 5us (I measured before this value using oscilloscope).

---

This is the way I implemented on electric unicycle: https://github.com/EGG-electric-unicycle/firmware-gen2_boards/blob/modifiedFOC-motorMicroWorks30kmh/motor_foc.c

Max current to control torque
Input: Value measured on the phase B current sensor

- On the slow loop, something like at every 10ms
- iq is the measured current value
- motor_max_current_factor is the output value that is used later on the PWM controller
Code:
  // Max current controller
  //------------------------------------------------------------------------
  if (abs_f(iq) > MOTOR_MAX_CURRENT) // start limitting the current
  {
    if (motor_max_current_factor > 0)
    {
      motor_max_current_factor -= MOTOR_MAX_CURRENT_STEP;
    }
  }
  else
  {
    if (motor_max_current_factor < 1000)
    {
      motor_max_current_factor += MOTOR_MAX_CURRENT_STEP;
    }
  }
// ------------------------------------------------------------------------

And on the PWM controller, that runs every PWM cycle:
Code:
  // apply over current limit factor
  _duty_cycle *=  motor_max_current_factor;
_duty_cycle /= 1000;

Over current
Input: Value measured on the shunt

On the EUC I had 2 phase current sensors and so I could have all the 3 phase values. On S06S, we need to use the shunt that should give the motor total current. The issue is were during the PWM cycle read the current... but for first try, we can measure at the middle or something like that... just put the readings after the motor_fast_loop().

Done every PWM cycle:

Code:
  // measure raw currents A and C and filter
  int _adc_phase_a_current = (int) adc_get_phase_a_current_value ();
  int _adc_phase_c_current = (int) adc_get_phase_c_current_value ();
  adc_phase_a_current1 += _adc_phase_a_current;
  adc_phase_c_current1 += _adc_phase_c_current;
  adc_phase_current1_cycles++;

  // verify motor over current
  //------------------------------------------------------------------------
  _adc_phase_a_current -= adc_phase_a_current_offset;
  int _adc_phase_b_current;
  _adc_phase_c_current -= adc_phase_c_current_offset;

  /* Calc phase B current assuming balanced currents
   * considering: a + b + c = 0 ; a + c = -b ; b = -(a + c) ; b = -a -c */
#if MOTOR_TYPE == MOTOR_TYPE_EUC1
  _adc_phase_b_current = -_adc_phase_a_current - _adc_phase_c_current;
#elif MOTOR_TYPE == MOTOR_TYPE_EUC2
  // change currents as for this motor, the phases are: BAC and not ABC
  _adc_phase_b_current = _adc_phase_a_current;
  _adc_phase_a_current = -_adc_phase_b_current - _adc_phase_c_current;
#elif MOTOR_TYPE == MOTOR_TYPE_MICROWORKS_500W_30KMH
  _adc_phase_b_current = _adc_phase_c_current;
  _adc_phase_c_current = _adc_phase_a_current;
  _adc_phase_a_current = -_adc_phase_b_current -_adc_phase_c_current;
#endif

  if (
      (abs(_adc_phase_a_current) > ADC_MOTOR_OVER_CURRENT_LIMIT) ||
      (abs(_adc_phase_b_current) > ADC_MOTOR_OVER_CURRENT_LIMIT) ||
      (abs(_adc_phase_c_current) > ADC_MOTOR_OVER_CURRENT_LIMIT))
  {
    over_current_fault_counter += 10;

    if (over_current_fault_counter > 1000) { motor_over_current_action(); }
  }
  else
  {
    if (over_current_fault_counter > 0) { over_current_fault_counter -= 1; }
  }
  //------------------------------------------------------------------------

Code:
void motor_over_current_action (void)
{
  // disable PWM / motor!!
  disable_phase_a ();
  disable_phase_b ();
  disable_phase_c ();

  buzzer_on ();

  // infinite loop: block here, user will need to reset the system
  while (1) ;
}
 
casainho said:
But I think the feature is just finished when you record a video showing it working :)

here you are... :D

[youtube]TYOgayUF5E8[/youtube]

I had to set the wheel circumference to 4 meter to have measured speed in the range the motor can turn, to proof the speed limitation function.

Regards
stancecoke
 
Back
Top