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

BLDC engine added #560

Merged
merged 27 commits into from
Jan 11, 2022
Merged

BLDC engine added #560

merged 27 commits into from
Jan 11, 2022

Conversation

pbecchi
Copy link
Contributor

@pbecchi pbecchi commented Jan 7, 2022

This pull request is relative to #333 and propose a new BrushLess DC motor to be incorporated as alternative to basic electric motor. BLDC motor code is based on basic "3 constant motor equations" and allow a good phisical model of motor performances.

It require 3 basic motor properties that are normally available from manufactures or easy to measure:

  • Kv speed motor constant
  • Rm internal coil resistance
  • I0 no load current

In addition a braking time constant has been added to allow change of braking torque:

 <torqueconstant> 6.1217 </torqueconstant>
 <coilresistance> 0.117 </coilresistance>
 <noloadcurrent> 0.45 </noloadcurrent>
 <maxvolts> 14.63 </maxvolts>
 <decelerationTime> 2.0 </decelerationTime>

Torque constant is just a unit conversion factor and maxvolts is battery voltage available. This voltage is nominal battery voltage that can be factored to consider internal and wires resistance. Next step could be to add a module that represent batteries (and wires) and that will output voltage as function of nominal battery data and SOC (state of charge).

This pull request include the source code files that have been modified as well as several examples.
Few examples have been tested and run OK. Some other are just an heritage from repositories from where have been taken @mvacanti and @rega0051 forks. May be they are unnecessary and it will be cleaner to remove it. I am not expert of PR procedures, so let me know what shoud be included.

@seanmcleod
Copy link
Member

I'd recommend only committing the core BLDC engine code in the initial pull request. Will make it easier for others to see/find the relevant code when looking at the commits without having to wade through tons of additional files related to aircraft specific examples etc.

Rather submit the aircraft example making use of the BLDC engine as a separate commit/pull request.

Also take a look at your CR-LF settings, I see a lot of the diffs are showing control-M characters.

Lastly also match the coding standards in terms of the number of spaces for indentation.

@rega0051
Copy link
Contributor

rega0051 commented Jan 7, 2022

I wouldn't want to push the F450 into the JSBSim repo. I still haven't validated it against flight data. And there are a bunch of commented out blocks, which I think is just more confusing. I also have Aero.xml, Gear.xml, ... as separate files because of how I auto generate config files and select amongst options. A clean version of a monolithic F450.xml would be appropriate in the future.

Also, this has a U of MN UAV Lab image, and I'm pretty sure the .ac file for FlightGear is actually an UltraStick25e...

@bcoconni
Copy link
Member

bcoconni commented Jan 7, 2022

Thanks for the PR @pbecchi 👍
As @seanmcleod and @rega0051 mentioned it needs to be split into several PRs to avoid reviewing a huge commit.

There is a bit of cleanup involved but you should start with a PR containing only the C++ code with the corresponding update to the build files (CMakeLists.txt and Visual Studio project files).

@pbecchi
Copy link
Contributor Author

pbecchi commented Jan 8, 2022

@seanmcleod
in the last 3 commit I have cleaned up as requested
and adjusted the c++ code indentation and line returns (I am not sure if it is what you expect...)
@bcoconni
It is OK to delete all examples , but without a user manual or input description , it is hard for future users to use BLDC motor.
@rega0051
dji f450 is a very good example that I have tested using PX4_sitl and , I think, perform very well.
As far as i know, it is the only multicopter PX4_sitl example that use jsbsim and represent motors as real electric motors.
If you agree , I can reformat the all thing and remove all references to your original files.
I think a good example is very usefull.

@bcoconni
Copy link
Member

bcoconni commented Jan 8, 2022

It is OK to delete all examples , but without a user manual or input description , it is hard for future users to use BLDC motor.

Sorry if I did not make myself clear but I meant that the example files should be merged in a separate PR for the only purpose of making this PR smaller and easier to review. I agree with you that including examples and documentation will be needed ...but in a separate PR.

Copy link
Member

@bcoconni bcoconni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks again for the PR @pbecchi

There is quite a lot of changes that are requested:

  1. Cosmetic changes
  • Do not use cryptic acronyms such as bldc for naming. That's OK for a proof of concept but not for production code. So please rename the files FGBlbc.* to FGBrushlessDCMotor.* and the class FGBldc to FGBrushlessDCMotor.
  • Please match JSBSim code formatting conventions:
    • No tabs.
    • 2 spaces indentations.
    • Camel case naming for class members.
    • No trailing spaces.
    • Opening brackets of methods shall be on a new line and on the leftmost column.
  • Remove outdated/useless comments.
  1. Legal changes
  • The C++ code shall be released under the LGPL2.0+ license. You will need Matt Vacanti's agreement for that.
  1. Implementation
  • I am concerned by the consistency of the units used in your code. The units of VelocityConstant are unclear and I am quite skeptical that RPM / (MaxVolts* VelocityConstant) is dimensionless (but I'd be glad to be proven wrong 😃).
    • Please check the units consistency.
    • Please specify the units using FindElementValueAsNumberConvertTo (note that you might need to update the container convert in src/input_output/FGXMLElement.cpp with new units).
  • Do real life brushless DC motor include an RPM controller ? I am surprised to find that the motor torque is computed from a target RPM commandedRPM...

src/models/FGPropulsion.cpp Outdated Show resolved Hide resolved
src/models/FGPropulsion.cpp Outdated Show resolved Hide resolved
src/models/FGPropulsion.cpp Outdated Show resolved Hide resolved
src/models/propulsion/CMakeLists.txt Outdated Show resolved Hide resolved
src/models/propulsion/CMakeLists.txt Outdated Show resolved Hide resolved
src/models/propulsion/FGBldc.h Outdated Show resolved Hide resolved
src/models/propulsion/FGBldc.h Outdated Show resolved Hide resolved
src/models/propulsion/FGBldc.h Outdated Show resolved Hide resolved
src/models/propulsion/FGBldc.h Outdated Show resolved Hide resolved
src/models/propulsion/FGBldc.h Outdated Show resolved Hide resolved
@bcoconni
Copy link
Member

bcoconni commented Jan 8, 2022

Actually, the units can be consistent provided that:

  • MaxVolts is supplied in Volts
  • VelocityConstant is supplied in A/W/min (Amperes per Watt per minute !?!)
  • TorqueConstant is dimensionless
  • NoLoadCurrent is supplied in Amperes
  • DecelerationTime is dimensionless

@pbecchi
Copy link
Contributor Author

pbecchi commented Jan 8, 2022

@bcoconni
All format changes will require a little time to be completed.

Regarding Units:
MaxVolts is in [Volts]
VelocityConstant is RPM/volts so units are [1/(min*volts)]
CoilResistance is in [Ohm]
TorqueConstant is dimensionless and is a fixed factor (may be should be taken out from input parameters)
NoLoadCurrent is in [Amperes]
DecelerationTime is dimensionless since is a factor (I should call it DecelerationFactor)

All those units are somehow "uniques", since there is no alternatives ....
Nevertheless I will try to find an example on how to code Unit conversions.

Regarding name of variables most are heritage from Vacanti code (commanded_rpm in reality is delta_rpm ) .
I will do a full renaming to make code more easy to understand.
At this point the new .cpp will be completely different from the M.Vacanti one.

another question : there is a standard copyright note I can copy from other files??

@bcoconni
Copy link
Member

bcoconni commented Jan 8, 2022

@bcoconni All format changes will require a little time to be completed.

No problem. There is no rush.

Regarding Units: MaxVolts is in [Volts] VelocityConstant is RPM/volts so units are [1/(min*volts)] CoilResistance is in [Ohm] TorqueConstant is dimensionless and is a fixed factor (may be should be taken out from input parameters) NoLoadCurrent is in [Amperes] DecelerationTime is dimensionless since is a factor (I should call it DecelerationFactor)

All those units are somehow "uniques", since there is no alternatives .... Nevertheless I will try to find an example on how to code Unit conversions.

You'll most likely need to add new lines to src/input_output/FGXMLElement.cpp:

// Power
convert["WATTS"]["HP"] = 0.001341022;
convert["HP"]["WATTS"] = 1.0/convert["WATTS"]["HP"];

New lines will be for instance:

  convert["VOLTS"]["VOLTS"] = 1.0
  convert["OHMS"]["OHMS"] = 1.0

You don't need to add unit conversion for a start, just add the units you need just as the example above.

Regarding name of variables most are heritage from Vacanti code (commanded_rpm in reality is delta_rpm ) . I will do a full renaming to make code more easy to understand.

Yes please.

At this point the new .cpp will be completely different from the M.Vacanti one.

No problem.

another question : there is a standard copyright note I can copy from other files??

Yes, see the example below:

/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Module: FGFDMExec.cpp
Author: Jon S. Berndt
Date started: 11/17/98
Purpose: Schedules and runs the model routines.
------------- Copyright (C) 1999 Jon S. Berndt ([email protected]) -------------
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option) any
later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc., 59
Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Further information about the GNU Lesser General Public License can also be
found on the world wide web at http://www.gnu.org.
FUNCTIONAL DESCRIPTION
--------------------------------------------------------------------------------

@pbecchi
Copy link
Contributor Author

pbecchi commented Jan 8, 2022

@bcoconni
I made all changes in a single commit working locally with visualstudio.
Only Makefile.txt and measurement units are missing.
Could you check if this commit is ok? Thanks.

@bcoconni
Copy link
Member

bcoconni commented Jan 8, 2022

@pbecchi The build fails because you've forgotten to update the file CMakeLists.txt.

Please take this opportunity to clean the tabs that you have inserted in CMakeLists.txt.
I'll review your code once the build will succeed.

Thanks.

@pbecchi
Copy link
Contributor Author

pbecchi commented Jan 8, 2022

Done...wait for your comments!

src/models/FGPropulsion.cpp Outdated Show resolved Hide resolved
src/models/FGPropulsion.cpp Outdated Show resolved Hide resolved
src/models/FGPropulsion.cpp Outdated Show resolved Hide resolved
src/input_output/FGXMLElement.cpp Outdated Show resolved Hide resolved
src/models/FGPropulsion.cpp Outdated Show resolved Hide resolved
src/models/propulsion/FGBrushLessDCMotor.cpp Outdated Show resolved Hide resolved
src/models/propulsion/FGBrushLessDCMotor.h Outdated Show resolved Hide resolved
src/models/propulsion/FGBrushLessDCMotor.cpp Outdated Show resolved Hide resolved
src/models/propulsion/FGBrushLessDCMotor.cpp Outdated Show resolved Hide resolved
src/models/propulsion/FGBrushLessDCMotor.cpp Show resolved Hide resolved
@pbecchi
Copy link
Contributor Author

pbecchi commented Jan 10, 2022

I made all corrections possible.....

TargetTorque = min(InertiaTorque, TorqueAvailable) + TorqueRequired;
} else {
// Deceleration is due to braking force given by the ESC and set by parameter deceleration_time
TargetTorque = TorqueRequired - min(abs(InertiaTorque)/(max(DecelerationFactor,0.01)*30),RPM*TorqueConstant/VelocityConstant/VelocityConstant/CoilResistance);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This wait the factor is approximately the time delay in seconds

Rather make this a constant with an appropriate name and comment so that anyone else looking at the code knows what it is.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RPM*TorqueConstant/VelocityConstant/VelocityConstant/CoilResistance) describes the energy dissipated by the Joule effect, doesn't it ?

src/models/propulsion/FGBrushLessDCMotor.h Outdated Show resolved Hide resolved
Copy link
Member

@bcoconni bcoconni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're almost getting there @pbecchi. A few additional comments (sorry !) mostly to polish the details.

src/models/propulsion/CMakeLists.txt Show resolved Hide resolved
src/models/propulsion/FGBrushLessDCMotor.cpp Outdated Show resolved Hide resolved
src/models/propulsion/FGBrushLessDCMotor.cpp Outdated Show resolved Hide resolved
src/input_output/FGXMLElement.cpp Outdated Show resolved Hide resolved
src/models/propulsion/FGBrushLessDCMotor.cpp Outdated Show resolved Hide resolved
src/models/propulsion/FGBrushLessDCMotor.h Outdated Show resolved Hide resolved
src/models/propulsion/FGBrushLessDCMotor.h Outdated Show resolved Hide resolved
src/models/propulsion/FGBrushLessDCMotor.cpp Show resolved Hide resolved
src/models/propulsion/FGBrushLessDCMotor.cpp Show resolved Hide resolved
src/models/propulsion/FGBrushLessDCMotor.cpp Outdated Show resolved Hide resolved
@pbecchi
Copy link
Contributor Author

pbecchi commented Jan 11, 2022

I have added units to motor speed constant Kv, i think it is necessary to avoid confusion.
Do you want me to add it also to FGXMLElement.cpp?
The last commits should close all remaining comments......at least i hope.....time is getting very short!

Copy link
Member

@bcoconni bcoconni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK now there has been a major improvement regarding units. The code looks much slicker and, with the exception of DecelerationFactor, it is no longer using magic factors.

And just for clarification: the formula RPM*TorqueConstant/VelocityConstant/VelocityConstant/CoilResistance) models the energy dissipated by the Joule effect, no ? But in that case, why isn't the Joule effect modeled during acceleration as well ? After all, the dissipation takes place as long as the current and the voltage are non-zero.

I'd suggest to keep these topics open for a later improvement.

V = MaxVolts * in.ThrottlePos[EngineNumber];

// Delta RPM = (input voltage - currentRequired * coil resistance) * velocity costant
DeltaRPM = round((V - CurrentRequired * CoilResistance) * VelocityConstant);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the purpose of this call to round() ? Why should DeltaRPM be rounded to the nearest integer ? I'd expect that to be destabilizing numerically the computations.

TargetTorque = TorqueRequired - min(abs(InertiaTorque)/(max(DecelerationFactor,0.01)*30),RPM*TorqueConstant/VelocityConstant/VelocityConstant/CoilResistance);
}

EnginePower = ((2 * M_PI) * max(RPM, 0.0001) * TargetTorque) / 60; //units [#*ft/s]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you using max(RPM, 0.0001) ? What's wrong with getting EnginePower null ? There again I'd expect this to destabilize the motionless state of the propeller.

TargetTorque = min(InertiaTorque, TorqueAvailable) + TorqueRequired;
} else {
// Deceleration is due to braking force given by the ESC and set by parameter deceleration_time
TargetTorque = TorqueRequired - min(abs(InertiaTorque)/(max(DecelerationFactor,0.01)*30),RPM*TorqueConstant/VelocityConstant/VelocityConstant/CoilResistance);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RPM*TorqueConstant/VelocityConstant/VelocityConstant/CoilResistance) describes the energy dissipated by the Joule effect, doesn't it ?

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

Successfully merging this pull request may close these issues.

4 participants