Candas1 / Split_Hoverboard_SimpleFOC

Split Hoverboards with C++ SimpleFOC (not yet)
MIT License
7 stars 5 forks source link

I2C interfering with SimpleFOC ? #11

Open RoboDurden opened 1 year ago

RoboDurden commented 1 year ago

Okay i added my I2C-Client code to my Split_Hoverboard_SimpleFOC and it runs :-) But the motor now heavily stutters :-(

I guess the SimpleFOC::I2CCommander has not yet been tested with the GD32-Arduino Core ?

Will investigate the next days. @Candas1 if this does not interest you this might be an Issue for my repo and @robcazzaro might like to also contribute to the final step of making a user friendly hoverboard firmware.

https://github.com/RoboDurden/Split_Hoverboard_SimpleFOC/blob/main/include/Pilot.h

https://github.com/RoboDurden/Split_Hoverboard_SimpleFOC/blob/main/src/PilotI2c.cpp

main.cpp

#include "Hoverboard.h"
#include "PilotI2c.h"

Hoverboard oHoverboard;
PilotI2c oPilot(oHoverboard);  // Pilot will call Hoverboard::Move(float fTarget)

setup()
{
  oHoverboard.Init();
  oPilot.init(8);   // iI2cAdress of hoverboard split board
}
RoboDurden commented 1 year ago

This function in twi.cpp::i2c_init(i2c_t *obj, PinName sda, PinName scl, uint8_t address) is causing the problem:

    /* I2C address configure */
    i2c_mode_addr_config(obj->i2c, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, address);
void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode, uint32_t addformat, uint32_t addr)
{
    /* SMBus/I2C mode selected */
    uint32_t ctl = 0U;

    ctl = I2C_CTL0(i2c_periph);
    ctl &= ~(I2C_CTL0_SMBEN); 
    ctl |= mode;
    I2C_CTL0(i2c_periph) = ctl;
    /* configure address */
    addr = addr & I2C_ADDRESS_MASK;
    I2C_SADDR0(i2c_periph) = (addformat | addr);
}

If i comment the last line I2C_SADDR0(i2c_periph) = (addformat | addr); , the motor is spinning nicely again. And that is nothing but

#define I2C_SADDR0(i2cx) REG32((i2cx) + 0x00000008U) /*!< I2C slave address register 0*/

Don't understand how the hardware i2c can block the SimpleFOC. No matter if i use my IrqMotor or the BLDCMotor.

As you @Candas1 like that SimpleFOC::I2CCommander, will you test this soon ? I do not like that stupid non-oo code which will again increase the overall binary..

Candas1 commented 1 year ago

More respect please. Some of the people that worked on this might end up reading this.

RoboDurden commented 1 year ago

More respect please. Some of the people that worked on this might end up reading this.

short answer: WWTDD (What would Tyler Durden do) the long answer would take at least ten pages and already by page 2 would it be clear that you do not want to understand anyway.

I fear the stuttering again is a interrupt priority issue. I might want to derive a HallSensor without GD32-Arduino Interrupts that simply checks the three hall states from the 16 kHz IrqMotor ADC_CMP_IRQHandler -> pIrqMotor->IrqHandler() I also do not like that general SmoothingSensor which makes use of the lowpass filter in BLDCMotor. With my own HallSensor i could add the smoothing with less code bytes i guess.

But decreasing the I2C interrupt priorities has only little effect:

  nvic_irq_enable(I2C0_EV_IRQn, 3, 3);
  nvic_irq_enable(I2C0_ER_IRQn, 3, 3);

So i am not sure that the stuttering comes from the HallSensor callbacks not getting called immediately. Increasing my IrqMotor from 3,3 to 2,1 also did not do much. But upping to nvic_irq_enable(ADC_CMP_IRQn, 1, 3) made the stuttering less evil. But i can only experiment at T4 (target 4.0 Volt) !

Here some log data:

stuttering at T4
ESP32 I2c communication + BLDCMotor:
A: -0.03        hall: 8011      4.00: 4.00      v: 3.75         loop us: 341
A: -0.03        hall: 1199      4.00: 4.00      v: 3.81         loop us: 313
A: -0.02        hall: 98        4.00: 4.00      v: 10.75        loop us: 9110
A: -0.02        hall: 90        4.00: 4.00      v: 18.43        loop us: 9184
A: -0.02        hall: 9183      4.00: 4.00      v: 17.02        loop us: 9095
A: -0.01        hall: 90        4.00: 4.00      v: 22.82        loop us: 9182
A: -0.01        hall: 5995      4.00: 4.00      v: 20.83        loop us: 321
A: -0.01        hall: 6263      4.00: 4.00      v: 18.19        loop us: 321
A: -0.01        hall: 6053      4.00: 4.00      v: 17.34        loop us: 325
A: -0.01        hall: 6265      4.00: 4.00      v: 17.00        loop us: 322

stuttering at T4
ESP32 + IrqMotor
A: -0.00        hall: 7889      adc us: 288     adc Hz: 26315   iAdcMicrosLoop: 347     4.00: 4.00      v: 3.60 loop us: 1687
A: -0.00        hall: 4515      adc us: 288     adc Hz: 26315   iAdcMicrosLoop: 375     4.00: 4.00      v: 3.64 loop us: 1687
A: -0.00        hall: 2378      adc us: 41      adc Hz: 3861    iAdcMicrosLoop: 326     4.00: 4.00      v: 3.68 loop us: 10437
A: -0.00        hall: 92        adc us: 279     adc Hz: 3584    iAdcMicrosLoop: 327     4.00: 4.00      v: 3.52 loop us: 10740
A: -0.00        hall: 11080     adc us: 288     adc Hz: 26315   iAdcMicrosLoop: 375     4.00: 4.00      v: 3.52 loop us: 10749
A: -0.00        hall: 11351     adc us: 38      adc Hz: 26315   iAdcMicrosLoop: 376     4.00: 4.00      v: 3.56 loop us: 2061
A: -0.00        hall: 6768      adc us: 286     adc Hz: 3875    iAdcMicrosLoop: 374     4.00: 4.00      v: 3.55 loop us: 1688
A: -0.00        hall: 6756      adc us: 39      adc Hz: 26315   iAdcMicrosLoop: 375     4.00: 4.00      v: 3.58 loop us: 1687

still slightly stuttering at T4
ESP32 + IrqMotor + 
nvic_irq_enable(ADC_CMP_IRQn, 1, 3);
nvic_irq_enable(I2C0_EV_IRQn, 3, 3);
nvic_irq_enable(I2C0_ER_IRQn, 3, 3);
A: -0.01        hall: 6765      adc us: 280     adc Hz: 25641   iAdcMicrosLoop: 368     4.00: 4.00      v: 3.94 loop us: 1625
A: -0.01        hall: 7136      adc us: 251     adc Hz: 3558    iAdcMicrosLoop: 364     4.00: 4.00      v: 3.93 loop us: 1626
A: -0.01        hall: 7169      adc us: 252     adc Hz: 3952    iAdcMicrosLoop: 359     4.00: 4.00      v: 3.91 loop us: 2251
A: -0.01        hall: 7167      adc us: 281     adc Hz: 23809   iAdcMicrosLoop: 372     4.00: 4.00      v: 3.89 loop us: 1626
A: -0.01        hall: 7172      adc us: 40      adc Hz: 25641   iAdcMicrosLoop: 369     4.00: 4.00      v: 3.89 loop us: 1624
A: -0.01        hall: 6819      adc us: 252     adc Hz: 3968    iAdcMicrosLoop: 360     4.00: 4.00      v: 3.90 loop us: 1321
A: -0.01        hall: 7186      adc us: 252     adc Hz: 3968    iAdcMicrosLoop: 360     4.00: 4.00      v: 3.91 loop us: 1934
A: -0.01        hall: 6820      adc us: 251     adc Hz: 3571    iAdcMicrosLoop: 358     4.00: 4.00      v: 3.89 loop us: 1624
A: -0.01        hall: 7790      adc us: 282     adc Hz: 3558    iAdcMicrosLoop: 359     4.00: 4.00      v: 3.89 loop us: 1624

no stuttering
ESP32 unplugged + IrqMotor + delayMicroseconds(500) in main():
A: -0.00        hall: 7161      adc us: 258     adc Hz: 3484    iAdcMicrosLoop: 367     4.00: 4.00      v: 3.74 loop us: 1688
A: -0.00        hall: 7422      adc us: 39      adc Hz: 26315   iAdcMicrosLoop: 376     4.00: 4.00      v: 3.73 loop us: 1688
A: -0.00        hall: 7406      adc us: 38      adc Hz: 25641   iAdcMicrosLoop: 376     4.00: 4.00      v: 3.73 loop us: 1688
A: -0.00        hall: 7506      adc us: 287     adc Hz: 500000  iAdcMicrosLoop: 365     4.00: 4.00      v: 3.73 loop us: 1688
A: -0.00        hall: 6723      adc us: 38      adc Hz: 25641   iAdcMicrosLoop: 376     4.00: 4.00      v: 3.74 loop us: 1686
A: -0.00        hall: 7389      adc us: 39      adc Hz: 3472    iAdcMicrosLoop: 368     4.00: 4.00      v: 3.74 loop us: 1687
A: -0.00        hall: 8135      adc us: 39      adc Hz: 3472    iAdcMicrosLoop: 331     4.00: 4.00      v: 3.73 loop us: 989

no stuttering
ESP32 unplugged + BLDCMotor:
A: -0.03        hall: 6667      4.00: 4.00      v: 3.73 loop us: 322
A: -0.03        hall: 7597      4.00: 4.00      v: 3.73 loop us: 322
A: -0.02        hall: 7600      4.00: 4.00      v: 3.73 loop us: 322
A: -0.02        hall: 6947      4.00: 4.00      v: 3.73 loop us: 321
A: -0.02        hall: 7184      4.00: 4.00      v: 3.73 loop us: 322
A: -0.01        hall: 7165      4.00: 4.00      v: 3.72 loop us: 321
A: -0.01        hall: 7372      4.00: 4.00      v: 3.72 loop us: 321
A: -0.01        hall: 6673      4.00: 4.00      v: 3.72 loop us: 322
A: -0.01        hall: 7451      4.00: 4.00      v: 3.72 loop us: 322
A: -0.01        hall: 6695      4.00: 4.00      v: 3.72 loop us: 321

With the new NVIC priorities, the hall sensor times get equal spaced again:

hall: 6765
hall: 7136
hall: 7169
hall: 7167

But with heavy stuttering, these distance would also become ugly. But when stuttering, the speed does not get so crazy with my IrqMotor than with BLDCMotor running in the loop():

BLDCMotor (the high loop times are also strange. I2C seems to take a long time..)
v: 3.81         loop us: 313
v: 10.75        loop us: 9110
v: 18.43        loop us: 9184
v: 17.02        loop us: 9095

IrqMotor:
v: 3.68 loop us: 10437
v: 3.52 loop us: 10740
v: 3.52 loop us: 10749
v: 3.56 loop us: 2061

So getting nice time delays again might only show that the higher priority of my IrqMotor at least made the motor running smoother (less stuttering) again.

But when i pull the usb cable from my notebook that powers the ESP32, the motor gets super smooth again :-/

Ideas welcome !

RoboDurden commented 1 year ago

Okay i had the oPilot.init(8); coming after oHoverboard.Init() :-( And of course the I2C priorities should be reset in PilotI2c:

void PilotI2c::init(byte iI2cAdress)
{
    pPilotI2c = this;
    Wire.begin(iI2cAdress);                // join i2c bus with address #8
    // ArduinoCore: nvic_irq_enable(I2C0_EV_IRQn, 1, 3);
    //              nvic_irq_enable(I2C0_ER_IRQn, 1, 2);

    nvic_irq_enable(I2C0_EV_IRQn, 3, 3);    // to not block IrqMotor nvic_irq_enable(XY_IRQn, 1, 2);
    nvic_irq_enable(I2C0_ER_IRQn, 3, 3);

    Wire.onReceive(ReceiveEventPilotI2c); // receiveEvent called when data from master received
    Wire.onRequest(RequestEventPilotI2c); // called when master requests data from this slave
}

Now my IrqMotor is again spinning nicely with I2c communication running :-) @Candas1 , The BLDCMotor however still heavily stutters !

Next step is finding a future-proof I2c protocol and publish a demo arduino .ino file to spin the motors forward and backwards.

RoboDurden commented 1 year ago

Now ESP32 is controlling via I2C:

https://github.com/RoboDurden/Split_Hoverboard_SimpleFOC/blob/main/arduino%20examples/ESP32_Mini_S2_I2c_Master/ESP32_Mini_S2_I2c_Master.ino

  if (iTimeHoverReady)
  {
    oMaster2Slave1.iCmd = CMD1_Speed;
    oMaster2Slave1.fValue = 0.10 * (ABS( (int)(((iNow-iTimeHoverReady)/20+100) % 400) - 200) - 100);   // repeats from +5.0 to -5.0 to +5.0 :-)
    OUT2T("\tiCmd",oMaster2Slave1.iCmd);
    byte iError = HoverSend(I2C_SLAVE_ADDR,oMaster2Slave1);
    if (iError != 0)
    {
      OUT2N("arduino: i2c transmission failed, timeout error code",iError)
    }
  }

  if (HoverRequest(I2C_SLAVE_ADDR,oSlave2Master))
  {
    if (!iTimeHoverReady && (oSlave2Master.iStatus & HOVERSTATUS_Ready)  )
      iTimeHoverReady = iNow;

    OUT2T("iCmdLast",oSlave2Master.iCmdLast);
    OUT2T("fRpm1",oSlave2Master.fRpm1);
    OUT2N("fCurrent1",oSlave2Master.fCurrent1);
  }
  else
  {
    OUTN("\narduino: CRC fail or too less received");
  }

https://github.com/RoboDurden/Split_Hoverboard_SimpleFOC/blob/main/src/PilotI2c.cpp#L81

I have defined 3 structs for communication:

#define CMD1_Speed 1
struct __attribute((__packed__)) Server2Hover1 
{
  uint16_t iCmd = 0;
  float fValue = 3.14;
} ;

struct __attribute((__packed__)) Server2Hover2
{
  uint16_t iCmdType = 0;
  float fValue1 = 3.14;
  float fValue2 = 42.0;
} ;

#define HOVERSTATUS_Ready 1
struct __attribute((__packed__)) Hover2Server 
{
  byte  iVersion = 0;
  uint16_t iCmdLast = 0;
  byte  iStatus = 0;
  float fCurrent1 = 0;
  float fRpm1 = 0;
} ;

So there can be future commands to set the battery voltage or 2-value commands to set speed+steer

Problem still is that when the ESP is restarted, Hoverboard must also restart otherwise the I2C communication hangs. Restarting the Hoverboard is okay, after 3 seconds calibration time, the incoming ESP comands get accepted again.

I am going to continue this issue on my https://github.com/RoboDurden/Split_Hoverboard_SimpleFOC/issues I think Candas does not want to do a general hoverboard firmware. Which is okay as he wants to focus on the SimpleFOC library for his robot projects :-) @Candas1 would be nice if you update your main branches in the next days.

Ideas welcome.

Candas1 commented 1 year ago

No it has nothing to do with the robotic project. Position control and encoder support is already available in Simplefoc. I want to focus on things where I add more value, improving the motor control.

Now any developer can use my work and build whatever firmware he wants.

I spent enough time supporting a firmware.

The next version of SimpleFOC is supposed to go out any time soon. I want to include all the latest fixes when I deploy to the main branch.

I haven't touched the GD32 branch in a while as it's only for the drivers, and I don't have feedback about the arduino-gd32 issues. If I add new features to Simplefoc, I will do it first on stm32, then only I will add it to the GD32 dev branch.

RoboDurden commented 1 year ago

Yes i am happy if you stay focused on the SimpleFOC libray ! And i am happy that you took the EFeruFOC firmware upon you !

Have you made some critical updates to the GD-Ardruino-Core that is not going to be merged ? Then my firmware can not access it with some added #xy to

platform = https://github.com/CommunityGD32Cores/platform-gd32.git
platform_packages = framework-arduinogd32@https://github.com/CommunityGD32Cores/ArduinoCore-GD32.git

??

Candas1 commented 1 year ago

The only work pending there on the drivers is depending on the fixes from the arduino-gd32 project. But of course I will have to synchronize any fixes from the simpleFOC project to the gd32 branch.

Candas1 commented 1 year ago

The latest SimpleFOC changes were just released to their Master branch. I synched all my branches, I only tried to compile, didn't do more tests. So you should be able to use my master branch for gd32 and their master branch for stm32. I will continue working on the dev branch, and push improvements to dev-gd32.

I haven't updating this repository yet, I don't think anybody is using it.

RoboDurden commented 1 year ago

Great, thank you. I will test your main arduino-foc.. branches today :-) Your repo here will be important for me to see your init parameters in main.cpp.