-
Notifications
You must be signed in to change notification settings - Fork 5
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
adding LowsideCurrentSense ... #6
Comments
Hi @Candas1 , maybe you are back from holidays and fully refreshed start doing/porting the current sensing in the next days.. I really think we need some 16 kHz timer to get the And if simpleFOC does not yet offer such a interrupt, why not doing it the Gen2 way and call Should be no problem to allow an optional callback to our current sensor that gets initialized with motor.loopFOC .. But feel free to do your "inserted adc" :-) |
There is still a lot for work to be done on the 6PWM driver before starting to work on current sensing. |
You mean that the init code of the 6 pwm drivers need to be improved ? That of course would impact my speed tests :-)
finding available/optimal timers might be good for supporting multiple bldc motors like with Gen1 boards. |
I think that @Candas1 meant that the GD32 implementation of 6PWM is not complete. For example, we don't correctly process the various flags for the signal polarity. It's an item on my todo list. But we won't improve performance by doing so. After all, the 6PWM is simply setting up a timer for the complementary PWM signals of the 3 phases. Once the timer is properly set, there're no further gains to have: a timer is a timer, and PWM is PWM. It's the rest of the code that can be improved. Gen1 boards do not use the GD32F130, as far as I know, so there's no value in doing the other PWMs. The Gen 2 boards only support 6PWM. I mean, it might be good to have a truly generic GD32 implementation, but before we spend the time, we might as well ensure that the Gen2 boards work properly. Once that works, if there is interest from the community, we could consider adding the remaining PWM types. STM32 implements all those types because there are widely used STM32 boards (e.g. BluePill, Nucleo, etc) that can be connected to any type of drivers. There are no GD32F130 boards available, and very few GD32F103 ones as well |
So i have begun to port the Gen2 adc code and maybe @robcazzaro would like to help me with my low-level code problems. I now think that adc sampling is not triggered by a new timer but by the bldc pwm timer0 !
Yes i began with a new sub class The Gen2 init code for adc compiles nicely and if the TIMER_BLDC triggered TIMER0_BRK_UP_TRG_COM_IRQHandler this handler function then calls
I monitor the two
Now i do not see crucial changes in the pwm port from Candas to GD32F130C8\Simple FOC\src\drivers\hardware_specific\gd32\gd32_mcu.cpp Only thing that was missing (droped by Candas) was
But When i place that function in two different files i get a linker error of mulitple definitions. So my one function does get compiled and linked into the binary. Now TIMER0_BRK_UP_TRG_COM_IRQHandler might be a Keil specific naming convention defined in Gen2 startup_gd32f1x0.s
and PlatformIO might have a different handler definition ? The Gen2 and Gen2.1 github repos also do not have a platformio.ini file.. I found a code example TIMER0_6-steps that also utilizes such a handler function: https://github.com/EFeru/hoverboard-sideboard-hack-GD/blob/main/docs/GD32F1x0_Firmware_Library_v3.1.0/Examples/TIMER/TIMER0_6-steps/main.c#L78C9-L78C9 . EFeru/hoverboard-sideboard-hack-GD has a platformio.ini but i am not sure if these exmaples were made for PlatformIO. // configure the nested vectored interrupt controller The handler function is found in https://github.com/EFeru/hoverboard-sideboard-hack-GD/blob/main/docs/GD32F1x0_Firmware_Library_v3.1.0/Examples/TIMER/TIMER0_6-steps/gd32f1x0_it.c#L125
This is a Timer2 handler function example from the GD-Arduino community that i will try to compile: https://github.com/CommunityGD32Cores/gd32-pio-projects/blob/main/gd32-spl-timer/src/main.c#L82
and
But these changes do also not work for me. Only changes between the Candas port and Gen2.x seems to be
But i tried all 4 combinations and no interrupt handler gets called. Candas added close to the end what is not in the Gen2.x code but in that TIMER0_6-steps example:
This is the init code from Candas that i am working on at the moment:
And my latest handler function:
Ideas welcome :-) |
@RoboDurden yes, happy to help. Please let me know exactly what you'd like me to look into. But, please, keep in mind that the right way to handle low side current sampling is by using the inserted ADC functionality (injected for STM32), not using a very slow software interrupt timer. That's what the STM32 driver does. We are working with a 48MHz processor, and should avoid doing in software what can be done in hardware |
The Timer2 example from the GD32-Arduino community works. And i guess it is better anyway to keep driver code seperated from current_sensor code.
Don't understand why you two keep on repeating this.
is correct then
should also succeed with 2 adc (battery voltage and overall current) at a 16 kHz rate. And when adc is complete it is also the best time to call Calling this function from the main loop only achieved about 5kHz with exceptions of below 1 kHz :-( Will continue tomorrow. |
Could no longer flash my board so i had to solder a little wire from the NRST mcu pin to the RST header pin. inside one of my ST-Link dongles: https://modwiggler.com/forum/viewtopic.php?p=1999431#p1999431 When i copy the working TIMER2 code (see previous post) into my Split_Hoverboard_SimpleFOC project, it does no longer work.
Is there some other ini file in our Split_Hoverboard_SimpleFOC project that sets some compiler directives ?
Ideas welcome. |
Okay :-( But the Timer example no longer works when compiled as c++ (rename to main.cpp):
Then the main.cpp code compiles but the led is not blinking. And F5 debug confirms that the interrupt handler never gets called. @robcazzaro , you might have an idea how to port this c-code example to c++ :-) My platformio.ini for both, the main.c and main.cpp project:
|
For sure i strongly dislike this low-level c-style code :-( there is already a nice
Of course now i fear that simply adding
to that
because that probably is also stupid c-style code :-( |
I'm confused, @RoboDurden... Why are you using the DMA IRQ handler, given that there is no DMA interrupt generated in your code? Gen2 code used an ADC conversion with DMA transfer, so the DMA IRQ was called at the end of the conversion. But if you are using a timer, there's no DMA IRQ... |
Yes, i will port that Gen2 code https://github.com/RoboDurden/Hoverboard-Firmware-Hack-Gen2.x/blob/main/HoverBoardGigaDevice/Src/setup.c#L336 I will now use a seperate TIMER2 with that nice GD32-Arduino. Does not really matter from where the adc conversion is triggered. But i fear that the DMA IRQ will not get call in c++ just like the TIMER0 handler did not get called. |
of course the DMA IRQ handler gets not called:
ideas welcome :-/ P.S. there is an GD32-Arduino example that one by one triggers adc conversion and then stupidly wait for the conversion to end. Maybe it would be sufficient to trigger all wanted adc conversion and simply check with the TIMER2-callback when all conversions have finished: |
@RoboDurden if I understand what you are doing, you are mixing Arduino code and low level SPL code from the old project. That might result in either the ADC or the DMA not being properly initialized, so either the ADC conversion doesn't happen or the DMA IRQ is not properly set to happen. You will need to single step thru the code to see if the ADC, DMA and IRQ registers are set the right way. Or at least start by manually calling the ADC conversion and see if it works and transfers the data into the DMA structures. My guess is that you will see that the ADC conversion is not happening, hence no DMA IRQ is generated. If the ADC/DMA works when called from your code, check if the timer is firing as expected |
Ah thanks @robcazzaro that's nice, i can already monitor the
But i guess i will see when i monitor |
Yes, that's one of the concerns with a slow processor and all the Arduino framework overhead. Don't forget that Gen2 on the GD32 was overclocked to 72MHz, and we are running at 48MHz. So you need to make sure that the timer initialization code takes that into account. If the ADC transfers values via DMA to adc_buffer, your code will always find valid values in that variable. Worst case, the battery ADC and current adc will be from different read cycles, but it makes no real difference since those are not related at all. As a matter of fact, the code is wasting a lot of time converting the battery voltage so frequently, I would suggest checking the battery no more than a few times per second, if that. Given your last message (no valid ADC values), it looks as if the initialization didn't work as expected |
Enjoy your trip @RoboDurden 🌞 |
@robcazzaro , if you thinks my Gen2 style adc approach with loopFOC called by a TIMER callback might be a way to go, i can upload my code to a new github repo. That is something you could also work on with your blue pills :-) |
@RoboDurden I can't promise I can do it in the next couple of days, but if you upload your code somewhere I'll have a look as soon as I have time. |
Will then do so when i really take the break :-) I also read
So i might be able to "attach" the adc conversion begin to TIMER2 and only use the TIMER2 callback to run But yes, if the 4 adc conversion will only take a few microseconds, the values will mostly be "quite old" when the 100 μs TIMER2 callback runs loopFOC. Don't know if this will affect the bldc closed loop much. |
The conversion time depends on the ADC settings, and can be much higher. From the manual, section 10.4.8 If the ADC is actually using DMA, the conversion time is not taking away processor time, but can result in the current ADC being sampled at the wrong time, depending on the code sampling the current or the battery first |
Okay, it is ugly but extern " I have kept all code in one main.cpp and uploaded the repo to https://github.com/RoboDurden/GD32_SimpleFOC/blob/main/src/main.cpp With the conversion defines of Gen2 i get this output when cutting off the the voltage:
here the uint16 values:
There is also So of course it now would be nice to measure the microseconds for And of course doing it the c++ style without that ugly But i have to force myself now to stop and enjoy the rest of this day with packing all i need into my little camper. So @robcazzaro maybe you want to take a look at my low level code. |
Added the microseconds evaluation: https://github.com/RoboDurden/GD32_SimpleFOC/blob/main/src/main.cpp#L48 |
Already spent whole sunday to port the working "bulk adc" to a new class So directly porting the working https://github.com/RoboDurden/GD32_SimpleFOC/blob/main/src/main.cpp into a c++ class was a too big step :-/ Will first have to simply copy the With LowsideCurrentSenseTimer we wil be able to have multiple motors and the option to add additional adc pins:
code is online here ideas welcome :-/ |
You have limited time to sample the phase currents, and you have to do it at the right time. That's why I said I can tackle the current sensing myself later. |
Ah now i understand why you always onsist on 'inserted' = 'synced' ! like:
However, over the 50% of the low-side C being on, the current might also differ, because the three hi-side mosfets have different ON-times ! So what kind of low-side currents does the foc alghorithm needs anyway ? An average over the complete cycle ? Using TIMER2 will not work my way. |
Yes check that document I shared in the past, I can share the link again if needed. |
ha ha yes please post the link again. our threads here are so long that i have diffucultis to find something again. |
With 3volts |
You mean 30 volt ? When i force
the 2.09 and CCW get confirmed. I compile+upload with strg+shift+U. When i F5 compile the debug firmware, the poor current consumptions increases to over 1.5A and the 1.5A CC power supply shuts down. Will now start overwriting library files with my 29.7.2023 version :-/ |
Okay after step by step overwriting the entire code files i at the very end found the solution in defines_2-0.h
Now you @Candas1 might have an idea why disableing these two lines reduce the current consumption back to the nice 0.3 A. Will now activate
to
Update: No, the |
When VBAT is defined it uses voltage sense driver to read the battery voltage. |
Yes swaping the phase currents seems to be correct. At least the motor is stuttering with that defines :-) With my old defines, it does not spin at all. But as VBAT also effects TorqueControlType::voltage i first would like to resolve that issue. |
I am wondering if this is slowing down the loop too much together with UART DEBUG. |
I am using DEBUG_STLINK.
is linked at all to the motor / driver stuff at all :-/ Update:
however is still producing the ugly 0.7A (at lower speed than the 0.3A without VBAT) Update:
|
Okay, this line increase the loop time from 400 micro seconds to 1000 microseconds (= 1 kHz) and is the reason for this ugly poor 0.7A current consumption: If remove that line but add I still do not understand how that VBAT does effect the loop at all, because i have deactivated
at the end of the loop function. @Candas1 is still do not understand why you keep insisting to let |
Because if you put it in the interrupt you will have to deal with overlaps. |
Do not understand what you mean with overlaps. A simple boolean Okay, with The target "foc_current" somehow matches the current i see on my power supply. So t0.2 leads to 0.26 amps. Now i do not really need torque control. I would be happy with a pwm/voltage target but current_sense FOC.
|
Yes 10a is too much |
Okay @Candas1 then your current_sense seems to work great :-) I still do not like a voltage as a target instead of a pwm ratio but the simpleFOC community will never change that. But when i will encapsulate all of your init code into a new class like CHoverMotor, i might want to tranlsate a +-1000 pwm ratio into these (to me) stupid voltages. @robcazzaro , velocity control also works nicely:
The slowest smooth rotation for me is A |
To be honest I spend more time learning simplefoc than working on the drivers. I have another list of possible contributions to simplefoc but it will take a lot of time. Still some EFeru features missing. |
Nice that you want dig deeper in the SimpleFOC code. With a working pwm control and rpm control i think i can begin with an i2c hoverboard firmware that is better then my gen2.x Can you confirm that your VBAT has no interaction with with simpleFOC and you only added it as a test for StmViewer ? |
Vbat was added to test the use of analogread in parallel with the current sensing |
Yes, analogRead(PA4) does not affect the 235-283 microseconds of one loop and the motor spins nicely:
With VBAT however:
And these 512 - 612 microseconds per loop cause that naughty stuttering (i guess).
But these loop times stay at 500-600 us even if do not call the battery funcitons in the loop:
So somehow that In the |
But this is running only once, how is it impacting the loop. |
Even if it is not running at all in the loop it is affecting the loop duration. I guess some simpleFOC function takes longer.
All i can say is that line 24 of GenericVoltageSense.cpp makes the difference. |
Maybe it happens at compiling |
Good that you picked this up, my last work was only about analogread so I wasn't making the wheel spin much. The use of pow even makes the flash usage increase 7%. Arduino-gd32 uses a 4 years old gcc. On Gen 1, I have not noticed the performance change but the flash usage is increased 2% although there is 4 times more flash. As this function is only used for powers of 2, I will propose to replace it with a helper function or macro that only shifts a bit. |
I have done some current testing. Now your current_sense.getDCCurrent(); outputs
With
@Candas1 , maybe your current_sense parameters are a bit wrong ? |
What do you mean by parameters ? I forgot gen2 also also has a dc current measurement, as there is not opamp for it. I am having the same discussion here. I am not totally sure about getDCCurrent. |
yes the gain and maybe something like
Please remember that i do not want to understand that low FOC level :-/ So you agree that If you also want to compare with shunt current, this is my code:
|
That's what I am telling you, I don't think it's the same thing. |
No no i thought those two values were the same but i gladly believe you that they are not and then of course will no longer compare them and discard |
I think battery DC current is calculated in a different, this must be motor DC current. |
We could try something like that: |
|
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:
The text was updated successfully, but these errors were encountered: