Comments (14)
Yes take your time :-) It is just that when my repo is ready for a youtube tutorial, users should download lib_deps from your main branch so you can continue to experiment with your dev branches !
I now already successfully moved the entire simpleFOC code as well as all io code to a new class Hoverboard
and the main.cpp
is nicley empty and ready for users to add their code:
https://github.com/RoboDurden/Split_Hoverboard_SimpleFOC/blob/main/include/Hoverboard.h
https://github.com/RoboDurden/Split_Hoverboard_SimpleFOC/blob/main/src/Hoverboard.cpp
#include "Hoverboard.h"
#ifdef DEBUG_STLINK
#include <RTTStream.h>
RTTStream rtt;
#endif
Hoverboard oHoverboard;
float target = 0;
LowPassFilter LPF_target(0.5); // the higher the longer new values need to take effect
Commander command = Commander(SERIALDEBUG);
void doTarget(char* cmd) { command.scalar(&target, cmd); }
#ifdef IRQMOTOR
void doUsLoopFoc(char* cmd) { float f; command.scalar(&f, cmd); oHoverboard.motor.iUsLoopFOC = f;}
#endif
unsigned long iTimeSetupFinished = 0;
void setup()
{
#ifdef DEBUG_UART
DEBUG_UART.begin(DEBUG_UART_BAUD);
SimpleFOCDebug::enable(&DEBUG_UART);
motor.useMonitoring(DEBUG_UART);
#endif
//Serial2.begin(DEBUG_UART_BAUD); // when using Serial1 as DEBUG_UART
#ifdef DEBUG_STLINK
SimpleFOCDebug::enable(&rtt);
oHoverboard.motor.useMonitoring(rtt);
#endif
OUTN("Split Hoverboards with C++ SimpleFOC :-)")
if (!oHoverboard.Init())
{
OUTN("oHoverboard.Init() failed :-(")
return;
}
// add target command T
command.add('t', doTarget, "target voltage");
#ifdef IRQMOTOR
command.add('f', doUsLoopFoc, "set us of loopFoc");
#endif
oHoverboard.Blink(3,oHoverboard.oLedGreen);
iTimeSetupFinished = millis();
}
unsigned long iTimeLast = 0;
unsigned long iTimeSend = 0;
void loop()
{
unsigned long iNowMs = _micros();
unsigned long iLoopMS = iNowMs - iTimeLast;
iTimeLast = iNowMs;
unsigned long iNow = millis();
if ( oHoverboard.Move(LPF_target(target)) ) // return only once TRUE when current calibrating is done
{
target = 10;
}
command.run(); // user communication
#ifdef IRQMOTOR
delayMicroseconds(500);
#endif
if (iTimeSend > iNow) return;
iTimeSend = iNow + 100; // TIME_SEND
OUT2T("A",oHoverboard.GetDcCurrent())
OUT2T("hall",oHoverboard.sensor.pulse_diff);
#ifdef IRQMOTOR
OUT2T("adc us",oHoverboard.motor.iAdcMicros)
OUT2T("adc Hz",1000000 / oHoverboard.motor.iAdcMicros)
OUT2T("iAdcMicrosLoop",oHoverboard.motor.iAdcMicrosLoop)
#endif
OUT2T(target,oHoverboard.motor.target)
OUT2T("v",oHoverboard.GetRpmPerVolt() )
OUT2N("loop us",iLoopMS)
}
Next step could already be to add my https://github.com/RoboDurden/GD32_I2C_Slave :-)
from split_hoverboard_simplefoc.
Okay i added a nice IrqMotor class extending BLDCMotor:
https://github.com/RoboDurden/Arduino-FOC/blob/master/src/IrqMotor.h
class IrqMotor: public BLDCMotor
{
public:
IrqMotor(int pp, float R = NOT_SET, float KV = NOT_SET, float L = NOT_SET);
// overriding
int initFOC() override;
void loopFOC() {};
void move(float target = NOT_SET) override;
void IrqHandler();
unsigned long iAdcMicros = 0;
unsigned long iAdcMicrosLoop = 0;
int iUsLoopFOC = 300;
protected:
unsigned long iAdcLast = 0;
unsigned long iAdcMicrosLoopLast = 0;
};
https://github.com/RoboDurden/Arduino-FOC/blob/master/src/IrqMotor.cpp
IrqMotor* pIrqMotor = NULL;
boolean bIrqMotorThreadNotRunning = true; // thread safety
IrqMotor::IrqMotor(int pp, float _R, float _KV, float _inductance)
: BLDCMotor(pp, _R, _KV, _inductance)
{
pIrqMotor = this;
}
int IrqMotor::initFOC()
{
int iRet = BLDCMotor::initFOC();
adc_interrupt_flag_clear(ADC_INT_EOIC);
adc_interrupt_enable(ADC_INT_EOIC);
nvic_irq_enable(ADC_CMP_IRQn, 3, 3);
return iRet;
}
void IrqMotor::move(float new_target)
{
if(_isset(new_target)) target = new_target;
}
void IrqMotor::IrqHandler()
{
unsigned long iNow = _micros();
iAdcMicros = iNow - iAdcLast;
iAdcLast = iNow;
if (enabled)
{
if (bIrqMotorThreadNotRunning && (iNow - iAdcMicrosLoopLast > iUsLoopFOC) ) // 250 us = 4 kHz
{
bIrqMotorThreadNotRunning = false;
BLDCMotor::loopFOC();
BLDCMotor::move(target);
iAdcMicrosLoop = iNow - iAdcMicrosLoopLast;
iAdcMicrosLoopLast = iNow;
bIrqMotorThreadNotRunning = true;
}
}
}
extern "C"
{
void ADC_CMP_IRQHandler(void)
{
if ( adc_interrupt_flag_get(ADC_INT_EOIC) != RESET)
{
adc_interrupt_flag_clear(ADC_INT_EOIC);
if (pIrqMotor) pIrqMotor->IrqHandler();
}
}
}
And i only have about 1% less performance with no more time restrictions in the loop():
22 Volt
T5 T10 T20 T50
KV [rpm/V] current [A]
IrqMotor
4.49 0.15
9.17 0.27
9.64 0.28
12.6 1.0
BLDCMotor
4.48 0.15
9,23 0.27
9,75 0.28
13,03 1.2
BLDCMotor + loop()::delayMicroseconds(500);
4.49 0.15
8.89 0.3 :-(
9.28 0.3 :-(
11.33 0.6
It only needs
#define IRQMOTOR
#ifdef IRQMOTOR
IrqMotor motor = IrqMotor(BLDC_POLE_PAIRS, NOT_SET, NOT_SET, 0.00036858);
#else
BLDCMotor motor = BLDCMotor(BLDC_POLE_PAIRS, NOT_SET, NOT_SET, 0.00036858);
#endif
All the other init and loop code can stay in place: https://github.com/RoboDurden/Split_Hoverboard_SimpleFOC/blob/main/src/main.cpp
@Candas1 where is your _powtwo
defined ? I needed to add #define _powtwo(n)(1 << n)
to SimpleFOCDrivers\src\voltageGenericVoltageSense.cpp
:-/
Ideas welcome !
from split_hoverboard_simplefoc.
Maybe @robcazzaro will like to check my
ADC_CMP_IRQHandler
for thread safty.
Is 3,3 the lowest possible interrupt priority ?
From a very quick look at the docs, a priority of 0, 0 should work and be the highest priority for the processor. But I haven't checked if the Arduino library uses priority 0 (should not)
from split_hoverboard_simplefoc.
the Hall interrupts run at 3,0 priority!
If i let the ADC_INT_EOIC
= EndOfInsertedConversion run at 0,0 , the hall interrupts seem to get postponed to when the 300 us loopFOC+move have finished :-(
I only get the near loop()::loopFOC()
performence when i let it run at lower priority than 3,0. I think that is 3,3.
I guess that there are only two bits for
void nvic_irq_enable(uint8_t nvic_irq, uint8_t nvic_irq_pre_priority, uint8_t nvic_irq_sub_priority)
Then 3,3 would be the highest number possible and therefore the lowest priority that allows the hall interrupts (and whatever code users will add) to be nested = interrupt the ADC_CMP_IRQHandler(void)
-> IrqMotor::IrqHandler()
and be executed immediately :-)
from split_hoverboard_simplefoc.
I first tried the wrapping approach like SmoothedSensor
.
But the loop()
code reads element variables like motor.enabled
which i can not update when some FocMotor function changes the _wrapped.enabled
:-/
I do not think that the simpleFOC community will accept a pull request to add my IrqMotor the the Arduino-FOC.
Should i try for a SimpleFOCDrivers/motors/IrqMotor.cpp
?
I guess i better move my class to the Split_Hoverboard_simpleFOC
repo.
Hopefully Simple FOC\src\current_sense\hardware_specific\gd32\gd32f130\gd32f130_mcu.cpp
will make it into the Arduino-FOC
main branch :-)
from split_hoverboard_simplefoc.
Then 3,3 would be the highest number possible and therefore the lowest priority that allows the hall interrupts (and whatever code users will add) to be nested = interrupt the
ADC_CMP_IRQHandler(void)
->IrqMotor::IrqHandler()
and be executed immediately :-)
Well, you could change the Hall interrupt to be 0,0, and the ADC to be 0,1 or even 1,0. The system uses negative priority numbers for the non-maskable hardware interrupts, and you have full control over the others. But if there are no other interrupts, 3.0 and 3,3 are de facto equivalent to 0,0 and 0,3...
from split_hoverboard_simplefoc.
Hi,
I made the interrupt a parameter to keep it in case it's useful.
I synched arduino-foc-drivers thinking _powtwo will be released also in the main library, but it seems it's pending.
If this PR is accepted, loopFOC should be a bit faster.
They will not accept IRQMotor, it's very GD32 specific, and I am not even sure if they will accept my drivers.
There are still many changes pending, arduino-gd32 project is not really active.
I thought about making the gd32 drivers a submodule so it's separated from the library but it seems this can generate other problems.
from split_hoverboard_simplefoc.
you could change the Hall interrupt to be 0,0,
No, the Hall interrupts use the Arduino-Core attachInterrupt(digitalPinToInterrupt(pinA), doA, CHANGE);
which why the HallSensor instantly worked on the GD32. But the nvic priorities are hard coded into the Arduino-Core :-(
and you have full control over the others.
No, i have no control what other interrupt code/libraries end users might want to add. Therefore i need the lowest possible priority.
@Candas1 yes i also think they would never accept it. But they themselves are aware that running loopFOC in the main loop is not ideal.
I added an optional TIMER2 interrupt to my IrqMotor which would make it usuful for any platform:
int IrqMotor::initFOC(unsigned int iHz)
{
int iRet = BLDCMotor::initFOC();
if (iHz)
{
oTimer.setPeriodTime(iHz, FORMAT_HZ);
oTimer.attachInterrupt(&timer_cb);
nvic_irq_enable(TIMER2_IRQn, 3, 3);
oTimer.start();
}
else
{
adc_interrupt_flag_clear(ADC_INT_EOIC);
adc_interrupt_enable(ADC_INT_EOIC);
nvic_irq_enable(ADC_CMP_IRQn, 3, 3);
}
return iRet;
}
If there would be a SetPriority function in the Arduino-Core, this TimerX interrupt might run on any Arduino platform.
Perfomance with motor.initFOC(3000);
is not bad at all:
22 Volt
T5 T10 T20 T50
IrqMotor:Timer2 with loop()::delayMicroseconds(500);
4.45 0.15
9.05 0.3
9.52 0.28
12.33 1.8
IrqMotor:EOIC with loop()::delayMicroseconds(500);
4.45 0.15
9.08 0.26
9.52 0.28
12.33 1.0
BLDCMotor without loop()::delayMicroseconds(500);
4.46 0.15
9,01 0.27
9,43 0.27
11.70 1.3
from split_hoverboard_simplefoc.
That's a library so I think they let you run it from wherever you want.
from split_hoverboard_simplefoc.
Okay @Candas1 i have moved my class to #include "../include/IrqMotor.h" and now i am back to
lib_deps =
koendv/RTT Stream@^1.3.0
https://github.com/Candas1/Arduino-FOC.git#dev-gd32
https://github.com/Candas1/Arduino-FOC-drivers.git#dev
Would be nice if you temporarily add this to GenericVoltageSense.cpp
#ifndef _powtwo
#define _powtwo(n)(1 << n)
#endif
Would also be nice if you push your dev code to the main branches.
Because i am quite happy with your work already and now would continue with the I2C-Hoverboard code.
You then can happily continue with your dev branches and push to the main branch when the performance gets better :-)
from split_hoverboard_simplefoc.
I won't be able to work on it next few days. You just have to add it to your local copy
from split_hoverboard_simplefoc.
I will let you know when the main is updated.
Feel free to share this is you think it's good enough, but you will have to support those users, please don't send them to me.
I want to focus on Simplefoc improvements.
from split_hoverboard_simplefoc.
I am happy to help my users: RoboDurden/Hoverboard-Firmware-Hack-Gen2.x#16
well, happy to try to help..
from split_hoverboard_simplefoc.
That's a good user
I mean, the other users 😂
from split_hoverboard_simplefoc.
Related Issues (10)
- please join and help us :-) HOT 49
- I2C interfering with SimpleFOC ? HOT 10
- Improve memory footprint for C6 builds HOT 13
- Project dependency on https://github.com/Candas1/Arduino-FOC.git requires manual process to update HOT 13
- GD32 timer initialization is not working properly HOT 88
- motor does not reach max speed like old Gen2.x binary HOT 84
- adding LowsideCurrentSense ... HOT 160
- adding Gen1 enviroment (STM32F103RC) .. HOT 8
- HallSensor interpolation/smoothing/prediction HOT 27
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from split_hoverboard_simplefoc.