Git Product home page Git Product logo

split_hoverboard_simplefoc's Introduction

Candas's GitHub stats

split_hoverboard_simplefoc's People

Contributors

candas1 avatar robodurden avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

split_hoverboard_simplefoc's Issues

motor does not reach max speed like old Gen2.x binary

continued from #4 (comment)

In the past, I had problems with SimpleFOC due to the limited speed of the encoder readings. The Arduino interrupt handling code has a lot of overhead, made worse by the various processor layers. If the code handling the hall sensors is not fast enough, speed is limited by that. And we are using a 48MHz processor, pretty slow all considered.

I don't have time today, though. Over the weekend, I'll look at ways to speed up the interrupt handler and see if that improves anything.

I might be easier to slow down the hall sensor reading artifically and see if that has an effect on the motor max speed :-)

Improve memory footprint for C6 builds

This is a work item and a memory reminder.

Low hanging fruits are debug messages and the SIN/COS tables. The SimpleFOC team is also implementing a more efficient set of functions using smaller tables, so before optimizing the existing code we should wait for the new code (https://community.simplefoc.com/t/embedded-world-2023-stm32-cordic-co-processor/3107/81)

At the beginning, I think it would be more productive to use C8 processors which have more than enough FLASH for anything. Once the code is closer to being final, we can look for ways to optimize size. Optimizing heavily now will result in a lot of wasted time optimizing things that will change

HallSensor interpolation/smoothing/prediction

continuing from #6

@Candas1 applying https://github.com/dekutree64/Arduino-FOC-drivers/blob/dev/src/encoders/smoothing/SmoothingSensor.cpp#L11 wrote: The extrapolation seems to work at constant speed at least now.

Nice visualization tool you have: https://user-images.githubusercontent.com/20670049/256005760-0de8c63f-a36a-48b2-a815-bd4770bc186d.png

You may also want to check max speed with this new inline function HallSensor.h :

float getRpm(){return direction * (60000000.0f / pulse_diff) / (cpr); };

and in main.cpp

OUT2T("KV",sensor.getRpm() / driver.voltage_power_supply )

adding Gen1 enviroment (STM32F103RC) ..

Hi @Candas1 , thank you for accepting my pull request.
As i thought you would not want to do that, i pushed more changes to my fork that now found it's way into your repo.

I added the STM32F103RC enviroment that i found in the EFeruFOC platformio.ini and the code compiles.
But the code seems to hang in setup()

oKeepOn.Set(true); // now we can release the on button :-)
when i debug and step_over which does nothing but digitalWrite(m_iPin,bOn);

For that i also rearranged the defines_x-y.h in config.h and defines.h to allow for Gen1 and Gen2 boards.
You might like that.

#if defined(PLATFORMIO)
  #ifdef STM32F103RC
    #define HOVER_GEN   1
    #define HOVER_LAYOUT	0
  #else
    #define HOVER_GEN   2
    #define HOVER_LAYOUT	0
  #endif
#else
  // LAYOUT_x_y is used in defines.h
  #define HOVER_GEN   2
  #define HOVER_LAYOUT 0
  //  2_0	// https://github.com/flo199213/Hoverboard-Firmware-Hack-Gen2
  //  2_1	// https://github.com/krisstakos/Hoverboard-Firmware-Hack-Gen2.1
  //  2_2	// 2023/05/11 only MASTER and TEST_SPEED: motor is spinning but needs a push to startup :-/
  //  2_4	// NOT READY !!! https://github.com/RoboDurden/Hoverboard-Firmware-Hack-Gen2.x/issues/3
  //  2_5	// NOT READY !!! https://github.com/RoboDurden/Hoverboard-Firmware-Hack-Gen2.x/issues/11

  //  1_0	// old Gen 1 boards with two motors
#endif

In main.c there now is my test code to optimize zero_electric_angle

    OUT2T(fSpeedMin , fSpeedMax)
    OUT2T(fSpeedAvgMin , fSpeedAvgMax)
    OUT2T(abs(fSpeedMin+fSpeedMax), abs(fSpeedAvgMin+fSpeedAvgMax))
    //OUT2T("fLinAdd%",sensor.fLinAdd*100)
    OUT2T(fOptimize*1000, motor.zero_electric_angle*1000)
    OUT2T( iMicros , iMicrosMax )

You might want check your 2.09 again but feel free to delete all the fSpeedXY stuff :-)

the .gitignore now contains my failed attempt to push my HallSensor changes, you better remove that from your repo :-)

 # Ignore everything
*
# But descend into directories
!*/
# Recursively allow files under subtree
!.pio/libdeps/GD32F130C8/Simple FOC/src/**

When you test your Gen2 with a stm32 mcu, you might get stm32_env to work.
I did not have any idea what i was doing when simply copy and paste the env from the EFeru platformio.ini

please join and help us :-)

Hi @Candas1 , @robcazzaro i guess the candas fork should now be the place of activity and indeed the old RoboDurden/Hoverboard-Firmware-Hack-Gen2.x#11 needs seconds to load on my mobile data plan.

@RoboDurden Do you know if the emergency stop is really connected on this layout? If yes it will act as an overcurrent trigger and stop the pwm output. It would only be a matter of enabling This with the right polarity and would be safer.

[EDIT] And probably setting PB12 properly

I can probe PB12 with a dso to see if it offers analog or digital input. But according to your spreadsheet
https://docs.google.com/spreadsheets/d/15msbDAIMxC2rIkq8Au8vf82ub1qEaS67Lc1cFb86Jpc/edit#gid=0
"sed on some of the boards as overcurrent trigger when the dc current is high enough to turn a transistor ON. Should disable PW"
i need to find that transistor and see if i can verify an analog input there while putting a hand on the motor with my gen2.x firmware running.

But according to the 2.0 schemtaics, PB12 is functional:
current measure pb12 gen2 0

With the mosfet only driven by the shunt voltage, it should open slowely and indeed produce some analog value on PB12 when some strong current reaches the the gate threshold.

This sketch is already using 91% of the flash, the GD32F130C6T6 have really little memory. I wasn't able to add the serial commander for example, it was exceeding the size.

I checked the photos of the various layouts. Only 2.1 and 2.5 have a C6 mcu. The others have a C8 with doubled flash and ram = 64 kB flash and 8 kB ram. (2.2 has K8 which only has less pins)

So to get all features running i think for now it is okay to compile with the C8 enviroment :-)

I2C interfering with SimpleFOC ?

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
}

running simpleFOC from an interrupt and not the main loop()

Thanks @Candas1 for adding that ADC_USE_INTERRUPT code to Simple FOC\src\current_sense\hardware_specific\gd32\gd32f130/gd32f130_mcu.cpp.

//#define ADC_USE_INTERRUPT // If defined, will use the End of conversion interrupt of inserted ADC
I think this was only for testing and you are going to remove it ?

But i think i can use that code to call motor.loopFOC() ( and motor.move() ) right when the two low-side mofet currents have been sampled (which need to be in sync with the bldc pwm.)
I had to set a priority lower then the HallSensor interrupts which use

    nvic_irq_enable(gpio_exti_infor[pinNum].irqNum, EXTI_IRQ_PRIO, EXTI_IRQ_SUBPRIO);
=
    nvic_irq_enable(gpio_exti_infor[pinNum].irqNum, 3, 0);

Then i think, the hall interrupts can interrupt the 300 microseconds long loopFOC() (called nested interrupts = nvic = Nested vector interrupt control)

void* _configureADCLowSide(const void* driver_params, const int pinA, const int pinB, const int pinC)
{
...
  adc_interrupt_flag_clear(ADC_INT_EOIC);
  adc_interrupt_enable(ADC_INT_EOIC);
  nvic_irq_enable(ADC_CMP_IRQn, 3, 3);

At the moment i simply add many extern to the gd32f130_mcu.cpp to call motor.XY and allow OUT2T log output:

unsigned long iAdcMicros = 0;
unsigned long iAdcLast = 0;
unsigned long iAdcMicrosLoop = 0;
unsigned long iAdcMicrosLoopLast = 0;

#include <SimpleFOC.h>
extern BLDCMotor motor;
extern float target;
extern LowPassFilter LPF_target;  //  the higher the longer new values need to take effect

boolean bNoLoopFOC = false;
int iUsLoopFOC = 300;

Then this works nearly as nicely as having motor.loopFOC and motor.move in the main loop():

extern "C" {  
  void ADC_CMP_IRQHandler(void)
  {
    if ( adc_interrupt_flag_get(ADC_INT_EOIC) != RESET)
    {
      adc_interrupt_flag_clear(ADC_INT_EOIC);

      unsigned long iNow = _micros();
      iAdcMicros = iNow - iAdcLast;
      iAdcLast = iNow;

      if (motor.enabled)
      {
        if (bNoLoopFOC && (iNow - iAdcMicrosLoopLast > iUsLoopFOC) ) // 250 us = 4 kHz
        {
          bNoLoopFOC = false;
          motor.loopFOC();
          motor.move(LPF_target(target));
          iAdcMicrosLoop = iNow - iAdcMicrosLoopLast;
          iAdcMicrosLoopLast = iNow;
          bNoLoopFOC = true;
        }
      }
    }
  }
}

The sound of the motor has an additional frequency which i think links to iUsLoopFOC.

And now i can add delayMicroseconds(500); to the main loop() with no effect on motor performance :-)

Current consumption (for 22V and T10) is flucktuating from 0.27 A to 0.3 A for both methods. But with my interrupt driven method , the 0.3 A flickers on my lcd power supply a bit more often than the loop::motor.loopFOC() method does. So the old method is slightly more efficient. Do not know why !

The motor.loopFOC + motor.move takes about 300 micro seconds :-(
So a frequency of more then 3 kHz is not possible :-/
That is a bit frustrating considering that the very simple Gen2 block commutation runs at 16 kHz ?

It is okay Candas if you do not help here. I think your focus is on using SimpleFOC with a Gen2 board for a very specific robot task, whereas i want a replacement of the Gen2.x firmware where users can add whatever they want to the main loop().

Maybe @robcazzaro will like to check my ADC_CMP_IRQHandler for thread safty.
Is 3,3 the lowest possible interrupt priority ?

adding LowsideCurrentSense ...

In continuation of #5

I have added the needed code to my cloned fork but can not push because Github_Desktop hangs and therefore can not make a pull request.
But we might already talk about the best approach to add LowsideCurrentSense:

...
// BLDC motor & driver instance
BLDCMotor motor = BLDCMotor(BLDC_POLE_PAIRS);
BLDCDriver6PWM driver = BLDCDriver6PWM( BLDC_BH_PIN,BLDC_BL_PIN,  BLDC_GH_PIN,BLDC_GL_PIN,  BLDC_YH_PIN,BLDC_YL_PIN );

// shunt resistor value , gain value,  pins phase A,B,C
LowsideCurrentSense current_sense = LowsideCurrentSense(BLDC_CUR_Rds, BLDC_CUR_Gain, BLDC_CUR_G_PIN, BLDC_CUR_B_PIN, BLDC_CUR_Y_PIN);
setup()
{
...
/*  
  // succeeds but motor.initFOC(2.09,Direction::CCW)  hangs 
  // motor.initFOC() will turn motor forward and backward a bit and then also hangs
  // We probably need a SimpleFOC/src/current_sense/hardware_specific/gd32/gd32_mcu.cpp
  if (current_sense.init())
  {
    motor.linkCurrentSense(&current_sense);
    Blink(3,oLedOrange);
  }
  else
  {
    Blink(5);
    OUTN("current_sense.init() failed.")
    return;   // cancel simpleFOC setup
  }
*/

loop()
{
...
    if (current_sense.initialized)
    {
      PhaseCurrent_s currents = current_sense.getPhaseCurrents();
      float current_magnitude = current_sense.getDCCurrent();
      OUT2T("mA",current_magnitude*1000)  // milli Amps
      OUT2T("B mA",currents.b*1000)  // milli Amps
      OUT2T("C mA",currents.c*1000)  // milli Amps
    }

Project dependency on https://github.com/Candas1/Arduino-FOC.git requires manual process to update

I just realized that when there is a checkin in https://github.com/Candas1/Arduino-FOC.git, it doesn't get automatically processed just by updating (pull) this project.

To make sure all the most recent changes in https://github.com/Candas1/Arduino-FOC.git are picked up, the safest way is to remove the .pio directory and let Platformio re-download the most recent code from github.

Otherwise it's possible to copy the changed files into .pio\build\libdeps\GD32F130C8\SimpleFOC\ and .pio\build\libdeps\GD32F130C8\SimpleFOC\

This is simply a side effect of not having released versions of the GD32 SimpleFOC and the ability of updating them from the Platformio UI

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.