Candas1 / Split_Hoverboard_SimpleFOC

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

Improve memory footprint for C6 builds #2

Open robcazzaro opened 1 year ago

robcazzaro commented 1 year ago

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

robcazzaro commented 1 year ago

This check in https://github.com/simplefoc/Arduino-FOC/pull/285 should help reduce the memory size by ~270 bytes (haven't tested it, just base on the sin table size reduction

RoboDurden commented 1 year ago

Now with current_sense mostly working:

RAM:   [========  ]  75.2% (used 6160 bytes from 8192 bytes)
Flash: [======    ]  64.7% (used 42372 bytes from 65536 bytes)

Is there even a slightest chance to make this (dev) repo here running on a 32k GD32F130 ???

robcazzaro commented 1 year ago

@RoboDurden very unlikely we'll ever be able to reduce the code by more than 25% to squeeze from ~42k to 32k. When I looked at this, there was no obvious candidate for reduction. So it will be mostly a matter of small, surgical optimizations of few tens or hundreds bytes here or there. Which are unlikely to ever add up to >10k bytes

RoboDurden commented 1 year ago

Yes i also fear that this will be impossible. Yet @Candas1 just found out (https://github.com/Candas1/Split_Hoverboard_SimpleFOC/issues/6#issuecomment-1707671817 ) that only replacing the mathematical pow function will reduce the code size by 11%:

//#define VBAT PA4
RAM:   [========  ]  75.2% (used 6160 bytes from 8192 bytes)
Flash: [======    ]  64.8% (used 42484 bytes from 65536 bytes)

#define VBAT PA4
RAM:   [========  ]  75.7% (used 6204 bytes from 8192 bytes)
Flash: [=======   ]  72.6% (used 47572 bytes from 65536 bytes)

#define VBAT PA4 and maxValue = 1 << (resolution-1); instead of maxValue = pow(2, resolution);
RAM:   [========  ]  75.7% (used 6204 bytes from 8192 bytes)
Flash: [=======   ]  65.3% (used 42820 bytes from 65536 bytes)

And i would be willing to strip functionality like current_sensing andOr FOC for those boards only having the 32k MCU. Main motivation for me is remove this frustraion of gambling for an old gen1.0 board but finding a gen2 board inside a used hoverboard. But i think i already know of two Gen2 with a 32k MCU version. So the frustration would continue.

Candas1 commented 1 year ago

I already opened an issue to simplefoc about this, I see no reason they will not accept as it's also impacting stm32, at least it terms of flash usage. Another improvement I proposed will make SVPWM faster, but could also end up in size reduction.

It's going in the right direction. But something as simple as a new version of gcc could screw things up again.

I think your formula is wrong by the way, this should be good enough #define pwrtwo(x) (1 << (x))

RoboDurden commented 1 year ago

Yes my formula is wrong. But also because the usage of maxValue ( val = (val / (float)maxValue) * fullScaleVoltage; ) does need a maxValue = pow(2, resolution) -1 ; ? Then my formula should be maxValue = (1 << resolution) -1;

Candas1 commented 1 year ago

image

RoboDurden commented 1 year ago

Yes and with 12 bit, the max adc value is 2^12-1 = 4095 and with val = (val / (float)maxValue) * fullScaleVoltage; this 4095 should map to fullScaleVoltage. Therefore maxValue = (1 << resolution) -1;

Candas1 commented 1 year ago

That's not what is written on the screenshot.

But anyway that's a detail.

RoboDurden commented 1 year ago

I only mentioned the missing -1 in lines 24 and 27 of GenericVoltageSernse.cpp because simpleFoc might be even more happy to accept your #define pwrtwo(x) (1 << (x)) :-)

I think your screenshot is wrong :-) with 2 bit resolution adc can output 0 , 1 , 2 , 3 and the resolution for 3.3V is 3.3 / 3 = 1.1Volt. There are only 3 steps from 0 to 3.

For 12 bit i just stumbled over these lines in the Gen2 firmware confirming the 4095 = 2^n-1:

// ADC value conversion defines
#define MOTOR_AMP_CONV_DC_AMP 0.201465201465  // 3,3V * 1/3 - 0,004Ohm * IL(ampere) = (ADC-Data/4095) *3,3V
#define ADC_BATTERY_VOLT      0.024169921875    // V_Batt to V_BattMeasure = factor 30: ( (ADC-Data/4095) *3,3V *30 )
Candas1 commented 1 year ago

This discussion is all over the internet. At the end it doesn't matter much.

So this improvement will reduce impact of on the flash usage. This was committed recently also, I am not sure how much it impacted.

Because this library let's you use features on the fly like SinePWM or SVPWM, it uses memory even if finaly you are using only SVPWM. My proposal to improve SVPWM is just to use the SinePWM + few more lines of code on top to get SVPWM, I am not sure how the compiler deals with that but it should be an improvement. I think there is a lot of repetition in the code, some of it could be split in smaller functions.

RoboDurden commented 1 year ago

When i delete all unneccessary Simple_FOC and Simple_FOC_drivers libray files i get a bit less memory usage:

  before:
RAM:   [========  ]  76.4% (used 6256 bytes from 8192 bytes)
Flash: [=======   ]  66.4% (used 43496 bytes from 65536 bytes)
  after:
RAM:   [=======   ]  70.0% (used 5732 bytes from 8192 bytes)
Flash: [======    ]  62.6% (used 41048 bytes from 65536 bytes)

When i continue to delete the Simple FOC\src\drivers\hardware_specific\xy foldes with only GD32 remaining, i get the compiler errors:

Building in release mode
Compiling .pio\build\GD32F130C8\lib76c\Simple FOC\current_sense\hardware_specific\esp32\esp32_mcu.cpp.o
Compiling .pio\build\GD32F130C8\lib76c\Simple FOC\current_sense\hardware_specific\stm32\b_g431\b_g431_mcu.cpp.o
Compiling .pio\build\GD32F130C8\lib76c\Simple FOC\current_sense\hardware_specific\stm32\stm32f1\stm32f1_hal.cpp.o
Compiling .pio\build\GD32F130C8\lib76c\Simple FOC\current_sense\hardware_specific\stm32\stm32f1\stm32f1_mcu.cpp.o
.pio\libdeps\GD32F130C8\Simple FOC\src\current_sense\hardware_specific\esp32\esp32_mcu.cpp:3:10: fatal error: ../../../drivers/hardware_specific/esp32/esp32_driver_mcpwm.h: No such file or directory
    3 | #include "../../../drivers/hardware_specific/esp32/esp32_driver_mcpwm.h"
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
*** [.pio\build\GD32F130C8\lib76c\Simple FOC\current_sense\hardware_specific\esp32\esp32_mcu.cpp.o] Error 1

Any ideas which files is including stm32 and esp32 stuff ???

robcazzaro commented 1 year ago

@RoboDurden I'm not sure I understand the logic of deleting files... Even if the compiler has to compile a few unused extra files, the linker will only add the code actually used. There's no way to reduce the memory footprint by deleting files.

Your before and after might be different due to other code changes that you introduced while deleting the files. But unless there's something really weird in your configuration, deleting files should make no difference.