Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MM32 pin autodetect firmware :-) #66

Open
RoboDurden opened this issue Feb 19, 2024 · 321 comments
Open

MM32 pin autodetect firmware :-) #66

RoboDurden opened this issue Feb 19, 2024 · 321 comments

Comments

@RoboDurden
Copy link
Owner

@AILIFE4798 has written a complete new autodetect for his MM32 firmware that saves the found pins to EEPROM that his hoverboard firmware reads on startup. So only one hoverboard firmware needed :-)

The autodetect firmware currently is the pin-finder branch of his MM32 firmware: https://github.com/AILIFE4798/Hoverboard-Firmware-Hack-Gen2.x-MM32/tree/pin-finder

This autodetect firmware offeres a uart serial user interface in which you can also set the UartBus id for controlling multiple boards on one uartBus !

Would be great if people with a MM32 board start testing it :-)

@RoboDurden
Copy link
Owner Author

two friendly suggestions to make your autodetect.c code more readable:

i do not like

extern uint32_t pins[33][3];
extern uint32_t adcs[10][3];

this suggests that the two arrays share the same type of information.
furthermore, pins do not contain a uint32 at all:

const uint32_t pins[33][3] = {   // port,pin,pinsrc,ADC,ADC2,HALL AF,HALL TIM,UART AF
{IOA,GPIO_Pin_0,GPIO_PinSource0},

...

#define IOA 1
#define GPIO_Pin_0                  (0x0001U)                                   ///< Pin 0 selected
#define GPIO_PinSource0             (0x00U)

using structs will save memory and improves readability:

typedef struct {
   uint8_t port;
   uint16_t pin;
   uint8_t pinBit;
} PinMM32;

const PinMM32 pins[33] = {   // port,pin,pinsrc,ADC,ADC2,HALL AF,HALL TIM,UART AF
{IOA,GPIO_Pin_0,GPIO_PinSource0},
...

pinMode(pins[i][0],pins[i][1],GPIO_Mode_FLOATING);
could be rewritten to pinMode(pins[i],GPIO_Mode_FLOATING);

with something like

void pinMode(PinMM32& p,uint8_t state){
	switch (p.port){
		case IOA:
			GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
			GPIO_InitStruct.GPIO_Mode = state;
			GPIO_InitStruct.GPIO_Pin = p.pin;
			GPIO_Init(GPIOA, &GPIO_InitStruct);
		break;
  ...

And better use enum or defines instead of plain integers. I used bits insead of 1,2,3 to easily test for multiple cases:

	#define AUTODETECT_Stage_Startup 	1
	#define AUTODETECT_Stage_VBatt 		2
	#define AUTODETECT_Stage_Hold 		4
	#define AUTODETECT_Stage_Button 	8
	#define AUTODETECT_Stage_Led 			16
	#define AUTODETECT_Stage_Hall 		32
	#define AUTODETECT_Stage_HallOrder 64
	#define AUTODETECT_Stage_CurrentDC 128
	#define AUTODETECT_Stage_Results 	256
	#define AUTODETECT_Stage_Finished	512
	if (!(wStage & (AUTODETECT_Stage_CurrentDC|AUTODETECT_Stage_Hold|AUTODETECT_Stage_Button))	)
		msTicksTest = msTicks + 50;	// never 

peace :-)

@RoboDurden
Copy link
Owner Author

RoboDurden commented Feb 19, 2024

p.s. i only see 20kB Code size for your pin-finder firmware. 32kB limit for the free Keil IDE.

Program Size: Code=20028 RO-data=4192 RW-data=748 ZI-data=2388

Activating the MicroLIB (memory optimized libraries)
grafik
yield two errors:

.\Objects\HoverboardOutput.axf: Error: L6218E: Undefined symbol __use_two_region_memory (referred from startup_mm32spin06xx_s_keil.o).
.\Objects\HoverboardOutput.axf: Error: L6218E: Undefined symbol __initial_sp (referred from entry2.o).

My autodetect without this MicroLIB:
Program Size: Code=30096 RO-data=1408 RW-data=472 ZI-data=2984
with MicroLIB (but code did not work when i tested it):
Program Size: Code=25980 RO-data=1232 RW-data=472 ZI-data=1864

@AILIFE4798
Copy link

i will replace the switch case magic number with enum or define
multiple state at same time is not possible in my firmware so it is not needed
for the pins ill look into it not sure if i should change it
i forgot to remove pa13 pa14 and only realizes after everything else is coded and i did not use num_pin define so i cannot remove those
i may also change that

i thought the storage is calculated by program+ro+rw data i have searched for it last time
i have also tried the microlib before and got same error
those are in startup which is in assembly so i cannot do anything about it
but anyways i think its very unlikely i will run out if only 20k is used
i can use max 31k for my firmware cuz the last 1k is left for eeprom to prevent it being erased when programming other firmware

@AILIFE4798
Copy link

this is my first time writing code for other people to use insted of for my self so its not very readable but itll get better

@RoboDurden
Copy link
Owner Author

Yes you are right, for the difference between spin05 and spin06 the 32kb inlcudes program+ro+rw data I think.

But for the Keil free 32 kB I think I got the error message when only program data exceed 32 kB.

But I should test my autodetect binary with a new gd32f130c6 target to very that.

@novval
Copy link

novval commented Feb 19, 2024

use gcc or platformio+gcc to unlimited

@RoboDurden
Copy link
Owner Author

Oh yes, please build me a makefile, then I could add these firmwares to my free online compiler: https://pionierland.de/hoverhack

I strongly dislike Linux :-/

@AILIFE4798
Copy link

i have unlimited compile size and compiler v5 in keil dont need to worry about that
and my goal is to not require other people to compile so it is not an issue
only hardware limit is relevent

linux is great

@AILIFE4798
Copy link

@RoboDurden i have edited the code a bit and hopefully its more understandable now
i have added allot of comments also
incase you want to reverse engineer my firmware to make your better
i have written everything my self didnt copy too much from yours
i will now work on the normal firmware side

@novval
Copy link

novval commented Feb 19, 2024

Oh yes, please build me a makefile, then I could add these firmwares to my free online compiler: https://pionierland.de/hoverhack

Why not, I'll try to do it when I have free time... so far, there are problems with this ((

I strongly dislike Linux :-/

gcc is also available for Windows

ps. A good option is Visual Studio Code + Platformio plugin, it can download and install gcc itself.
An example can be found at the EFeru known to us

@AILIFE4798
Copy link

i think @GRROWL911 is using the platformio plugin

@AILIFE4798
Copy link

but can it support mm32 because eferu is gd32

@RoboDurden
Copy link
Owner Author

As many hoverboards only have 32kB anyway, the 32kB free Keil limit is no problem for us.

@AILIFE4798
Copy link

yeah the mm32spin06 is really quite rare and not needed in most case anyways 32k is enough

@AILIFE4798
Copy link

i may have forgot to git push but its done now

@GRROWL911
Copy link

GRROWL911 commented Feb 19, 2024 via email

@AILIFE4798
Copy link

hows your progress now
have you got adcs and uart at least

@GRROWL911
Copy link

GRROWL911 commented Feb 19, 2024 via email

@AILIFE4798
Copy link

same as mine uart2 rx not working
i think bug in the library
with debug it can work i see data in RDR register but interrupt and dma not work
but my firmware do not need 2 uart anyways 1 is enough

nice to see you making progress with lks just as fast as i did with mm
i think it will not be hard as all example and hal library is available

@GRROWL911
Copy link

GRROWL911 commented Feb 19, 2024 via email

@AILIFE4798
Copy link

it should be but its not idk why either
because one of my board annoyingly used uart2 for masterslave and im still unable to get it to work and i also bricked it with the clock fix
but to control master and slave just physically connect 2 board tx and rx together then command will be sent to both board
and you have successfully used slave board??
why everyone can do that i cant

@GRROWL911
Copy link

GRROWL911 commented Feb 19, 2024 via email

@GRROWL911
Copy link

GRROWL911 commented Feb 19, 2024 via email

@AILIFE4798
Copy link

because my firmware is made for just 1 uart i never designed for 2 to be enabled at same time so i reuse UARTEN
i just want to allow board like layout2.21 that use uart2 as masterslave to use uart2
i did not know uart2 is dma channel 4/5 thats why it doesnt work
i can easily fix it now but because to support autodetect i will choose to ignore uart2 anyways as uart2 have too many pin
uart1 only have 6 and 2 of them is used by motor so only 4 wire and 4 combinations
automaticly matching pinmodeAF is very very hard so i choose not support uart2

@AILIFE4798
Copy link

and if i support uart2 i will need to compile tens of hundreds of binary every time which is def not possible
4 firmware every time is ok
only the outdated board from gd32 era use uart2 anyways ,and those board always use uart1 pin for i2c so you can reuse it for serial

@AILIFE4798
Copy link

i think i will get some 7815 regulators to try out the slave board to see if it work

@GRROWL911
Copy link

GRROWL911 commented Feb 20, 2024 via email

@AILIFE4798
Copy link

ok if you have any new layout you can help try out the autodetect firmware
it can trace every pin other then the serial in 30 seconds if you are fast

@GRROWL911
Copy link

GRROWL911 commented Feb 20, 2024 via email

@AILIFE4798
Copy link

no,there is 2 pins going to the current sens resistor,one going to adc and other one go to a comparator
the one going to adc have a hardware rc filter to average the pwm noise, to get good current reading
the one going to comparator is directly connected because it is used to stop the motor in case a short circuit occured it need to be very fast before the mosfet burn out

@RoboDurden
Copy link
Owner Author

That is what i wrote i did :-)
And yes, now the main firmware is running and button push will turn off the board.
Great work @AILIFE4798

@AILIFE4798
Copy link

you can now try the sine wave mode

@RoboDurden
Copy link
Owner Author

https://youtu.be/0jwVfbfLZfA :-/

The aweful stuttering at high speed sometimes does not seem to be because of the cc power supply.
It happens at 1.5A max and 3A max.

Maybe the 32.0 Volt low battery.
Do not know how to decrease this. Have not read the manual :-)

@AILIFE4798
Copy link

if you fancy using the autodetect again then use w batempty 24000
if not you can also adjust it in pinout.h

@RoboDurden
Copy link
Owner Author

for testing, i prefer to overwrite the main.c:
grafik

@RoboDurden
Copy link
Owner Author

Yes that helped.
I will set the next video public so my followers can see your great firmware in action.

at one point there was still that stuttering. Right at the beginning the sine firmware did boot up and the esp32 was directly sending pwm 1000. I guess at very high torques the voltage even went below the new 24000 = 24 V limit and your software tries to stop the motor.
You should only stop the motor when speed is zero, not in full driving.
EFeru is also only beeping low battery and will shut down the board when speed is zero for the first time.

@AILIFE4798
Copy link

set it to 0 will disable low battery protection
see if that helps
i will implement only stop motor if speed is 0

@RoboDurden
Copy link
Owner Author

public video: https://youtu.be/ZMJMT-ILVzc

I really want to do other stuff on this sunny day.

@RoboDurden
Copy link
Owner Author

RoboDurden commented Apr 7, 2024

So here my working pin definition for 2.4.1 (ex2.8):

uint16_t pinstorage[64]={26, 27, 28, 8, 32, 31, 23, 65535, 65535, 22, 15, 65535, 14, 65535, 19, 17, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 56491, 31, 250, 0, 19200, 8192, 1, 30, 0, 10, 300, 1, 1, 42000, 32000, 1000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
some more feedback from a Windows user:
I already said i do not like 65535 as it is not intuitive. And with int16_t this value woud cast to -1 anyway, which is more intuitive.
But then max value would be 32768. But 42000 and 32000 are not intuitive anyway. Why set the max votage to 42.001 Volt ?
420 = 42.0 would be good enough. Yet also not intuitive.
And when i see 19200 i already fear a coming (Linux beliver type) bug comming when BDC want to set the baud rate to the standard 115200, which makes uint16_t overflow too.

So of course good programming would not mean to use a uint16_t or int16_t anyway but a nice struct with uint8_t for pin definitions, float for battery voltages and uint32_t for baud rate.
That woud make your code way more readable too.

And for storing in "eeprom" you can aways cast the struct to (u8*)
This compiles successfully:

#pragma pack(1)	// needed to get correct sizeof()

#define EEPROM_VERSION 1
typedef struct {	
    uint32_t iVersion;
    int8_t  iPinHallA; 
    float fBattFull;
  } ConfigType;
ConfigType pinstorage2 = {EEPROM_VERSION,-1,42.0};

	
uint8_t restorecfg2(){
	ConfigType oConfigTemp;
	EEPROM_Read((u8*)&oConfigTemp, sizeof(ConfigType));
	if(oConfigTemp.iVersion==EEPROM_VERSION){    //verify config is valid
		memcpy(&pinstorage2,&oConfigTemp,sizeof(ConfigType));
		return 1;
	}
	return 0;
}

The pinFinder dump would become intuitive as well: ConfigType pinstorage2 = {1,26,42.0};

And now we have the Linux vs OOP dispute again :-(
The Linux believer always is only focused on new features in order to become the most clever one of the world.
Therefore he does not see enough value in reworking his code so that it becomes more beautiful (=more intuitive = more safe).
The OOP guy instead prefers to love the inner beauty.

@RoboDurden
Copy link
Owner Author

You can get rid of this warning

Src/main.c(108): warning: 4 enumeration values not handled in switch: 'MODE_MENU', 'MODE_ITOTAL', 'MODE_CLI'... [-Wswitch]
                switch (mode){
                        ^~~~

by adding a default: to the end of the switch clause:

			default:	break;
		}

Linux believes don't care about warnings ;-)

@RoboDurden
Copy link
Owner Author

and this brings the warnings to zero:

#ifdef TARGET_MM32SPIN25
	char PXX[PINCOUNT][5]={"PA0\0","PA1\0","PA2\0","PA3\0","PA4\0","PA5\0","PA6\0","PA7\0","PA11\0","PA12\0","PA13\0","PA14\0","PA15\0","PB0\0","PB1\0","PB2\0","PB3\0","PB4\0","PB5\0","PB6\0","PB7\0","PB8\0","PB9\0","PB10\0","PB11\0","PB12\0","PC13\0","PC14\0","PC15\0","PD0\0","PD1\0","PD2\0","PD3\0","PD7\0"};
#else
	char PXX[PINCOUNT][5]={"PA0\0","PA1\0","PA2\0","PA3\0","PA4\0","PA5\0","PA6\0","PA7\0","PA11\0","PA12\0","PA13\0","PA14\0","PA15\0","PB0\0","PB1\0","PB2\0","PB3\0","PB4\0","PB5\0","PB6\0","PB7\0","PB8\0","PB9\0","PB10\0","PB11\0","PB12\0","PC13\0","PC14\0","PC15\0","PD0\0","PD1\0","PD2\0","PD3\0"};
#endif

@RoboDurden
Copy link
Owner Author

I also added 's' for 'short list' to the CLI

							case 's':    //list pin values
								for(uint8_t i=0;i<16;i++)	printstorage(i);
							break;

'l' listing all values did always flood the putty console and i needed to scroll upwards to see the pin definitons :-/

@RoboDurden
Copy link
Owner Author

RoboDurden commented Apr 7, 2024

Yes, the CLI will have problems to access values from a config struct.
But a CLI is the most typical thing of these Linux believers that still live in the 1990s.
As well as this "total control" read and write acceess to every data. The typical Linux mind set :-(

When you really want to read and overwrite a special value, you of course need to read a manual :-((

To access a value of a struct you would need something like that (compiles successfuly):

void configSet(ConfigType* pC, uint8_t i,double fSet)
{
	switch (i)
	{
		case 0: pC->iVersion = (uint32_t) fSet; break;
		case 1: pC->iPinHallA = (int8_t) fSet; break;
		case 2: pC->fBattFull = (float) fSet; break;
	}
}

double configGet(ConfigType* pC, uint8_t i)
{
	switch (i)
	{
		case 0: return pC->iVersion;
		case 1: return pC->iPinHallA;
		case 2: return pC->fBattFull;
	}
	return 0;
}

char* configGetName(ConfigType* pC, uint8_t i)
{
	switch (i)
	{
		case 0: return "iVersion";
		case 1: return "iPinHallA";
		case 2: return "fBattFull";
	}
	return "";
}

or continue your


	char addrdescription[64][14]={
{"halla\0"},
{"hallb\0"},

to link the index to the configType

@AILIFE4798
Copy link

the struct will be better on saving eeprom storage, but there is no need to save storge
you need to at least allocate 1 page to eeprom which is 1kb, it can do allot already
the real problem with uint16t is the baud rate
yes i have already saw that comming,but lets be real we can just cancel the trailng two zero
but that would require a maual so i didnt do it
plus the uartbus protocol just calls for 19200 so why would you change it
same reason for using 42000,the firmwre only measure to 42.00 anyways, but i do not want to need a manual
you can def make a more intelegent command line to use struct, but not in 30kb (last 1k cant be used,and 1k for eeprom)
so this array is here to stay for now,take it or leave it
all other par ive tried to make it best readable

the switch case i really dont need to handle those condition so it is ok
the pin to string array the additional initialize will be automaticly ignored, but it is also ok to use seperate one,if i want to support completely different mcu i will need a new one for sure

@RoboDurden
Copy link
Owner Author

UartBus does not require 19200, it is only the defaut to support softwareSerial.
Yes, better only store baud/100 and give a warning to user if (input%100 != 0)

@AILIFE4798
Copy link

the best solution is to let user type 115200 and store 1152,type 42000 and store 4200,type SIN_VOLT and store 2,but again not in 32k

@RoboDurden
Copy link
Owner Author

Yes, BAT_EMPTY = 0; seems to prevent the stuttering when board is started while esp32 is sending pwm 1000 :-)
Yes, slave board is also detecting and running nicey :-)

I could make a youtube tutorial on your nice pinFinder and main firmware.

How do i test SINE_SPEED ? When i send 300, will that be 300 rpm ?

@AILIFE4798
Copy link

yes,open the serial feedback from esp,command sped will equal to real feedback speed
and you can put some load on the motor it will not slow down

@RoboDurden
Copy link
Owner Author

Yes, speed mode works great :-)

Maybe you want to add a SINE_POS (SINE_ODOM) mode.
Would be cool to see the motor rotate forward and backward when testspeed is going from -180 to +180
I think that 90 steps is one rotation.
Might open up your firmware for robotics..

@AILIFE4798
Copy link

yes indeed,position mode will be useful,with sine wave position holding is possible by increasing the positive d axis (opposite of field weakening),it will require complicated algrorithm to acheive but it might be doable
if you want to build a 3d printer this will be needed
one rotation is 60 step(motor have 30 poles,theres 6 step in each electrical rotation,so 60 step in each mechanical rotation)
i have seen someone requested this on gen1,so if this is acheived this will be the day the gen2 finally surpassed the gen1

btw now field weakening is disabled,if you have need of spinning very fast it can do at least 2x the current speed with just 24v(by drawing more current)

@AILIFE4798
Copy link

I think that 90 steps is one rotation.

maybe you are right,because i actually go rotate the motor by hand 1 revolution and it is 90
idk the logic behind it but anyways im not familiar with how bldc works to begin with

@RoboDurden
Copy link
Owner Author

You should sleep now :-)

@AILIFE4798
Copy link

i have not fixed the low battery problem, have to work on other things during the day

@I-hate-2FA
Copy link

for testing, i prefer to overwrite the main.c: grafik

this literly backfired because i forgot to remove it in the release

@I-hate-2FA
Copy link

someone said the low battery mode is active when it is disabled, and i tried it it actually didnt get disabled, and i end up have to use keil to debug to find it, cuz it is 1 month ago i already forgot

@RoboDurden
Copy link
Owner Author

Yes, my autodetect code is even older ;-)

@I-hate-2FA
Copy link

must be very hard to work with a gd32, cuz its not possible to debug ive tried that

@I-hate-2FA
Copy link

and now f103 series(gd/stm/mm) support is on the list too
cuz now ive used gen1 once i completely gave up on that, it is easier to port my firmware to mm32f103
and your code does not work with f103 either, the target is not configured correctly, the code is still for f130

@RoboDurden
Copy link
Owner Author

when you have ported to f103, i dream that then f130 will not be a big step.

@I-hate-2FA
Copy link

there is no mm32f130 unfortunately
so it would not be possible
next would be f031 series, or maybe the lks if its possible

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants