1 /*
2  * CRRCsim - the Charles River Radio Control Club Flight Simulator Project
3  *   Copyright (C) 2005, 2006, 2008, 2009 - Jens Wilhelm Wulf (original author)
4  *   Copyright (C) 2006, 2007, 2010 - Jan Reucker
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  */
21 #ifndef ENGINE_DCM_H
22 # define ENGINE_DCM_H
23 
24 # include "gearing.h"
25 # include "values_step.h"
26 # include "../../mod_math/ratelim.h"
27 
28 namespace Power
29 {
30 
31   /**
32    * This class is part of the power system. To simply use the system, you should not
33    * access or call any of its members. Please take a look at Power instead.
34    *
35    * This class models a direct current motor. The model is quite realistic. However, modeling
36    * the emc brake proved to be not strong enough to stop a Propeller in flight. But this is a
37    * problem of the Propeller I think. The brake is modelled by Shaft now.
38    *
39    * The xml configuration of an engine looks like this (without gearbox to shaft):
40    \verbatim
41    <engine k_M="4.3e-03" R_I="0.185" J_M="1.79e-05" I_0="1.01" />
42    \endverbatim
43    *
44    *
45    * Example for an xml description, connection to shaft via a gearbox:
46    *
47    \verbatim
48    <engine k_M="4.3e-03" R_I="0.185" J_M="1.79e-05" I_0="1.01" >
49      <gearing i="1.13" J="0" />
50    </engine>
51    \endverbatim
52    * The inertia \c J of the engine is translated to the shaft automatically. The inertia \c J of the gearing is
53    * the value seen by the shaft.
54    *
55    * See Power::Gearing for a description of a gearbox.
56    *
57    * It is possible to read the parameters of a engine from a separate file. In this case use
58    * something like
59    \verbatim
60    <engine filename="astro_cobalt"/>
61    \endverbatim
62    \verbatim
63    <engine filename="astro_cobalt">
64      <gearing i="1.13" J="0" />
65    </engine>
66    \endverbatim
67    * instead of writing down the parameters directly. The system will try to load a file
68    * <tt>./models/engine/astro_cobalt.xml</tt> which might look like this:
69    \verbatim
70    <?xml version="1.0"?>
71    <!--
72     Astro Cobalt 05 at 10 V
73 
74     Data taken from
75     Retzbach, Ludwig: Ratgeber Elektroflug, Neckar Verlag, 1991.
76 
77     M_r = 1.15E-2; // Nm
78     I_0 = M_r/k_M = 2.74A
79 
80     J_M is just guessed.
81 
82     -->
83 
84    <engine R_I="0.08" k_M="0.42E-2" I_0="2.74" J_M="1.6E-6" >
85    </engine>
86    \endverbatim
87    *
88    * Given \c U_K is the voltage applied to the engine and omega is its speed,
89    * it will draw a current of
90    * <tt>I_M = (U_K - omega * k_M) / R_I</tt>
91    * and will apply a torque to the gearing which is
92    * <tt>M_M = k_M * (I_M - I_0)</tt>.
93    *
94    *
95    * Finding a complete parameter set for a specific engine can be impossible,
96    * but luckily the parameters can be calculated from measured data.
97    * Given the current draw for the idle engine and
98    * voltage, current draw and speed
99    * values for at least two different load points (one of them may be the
100    * idle point as well), all electric parameters can be calculated.
101 
102 
103    * A worked example: Speed 400 with flux ring
104    *
105    * For one model I wanted to simulate a Speed 400 (aka Mabuchi RS-380 PH)
106    * with an additional flux ring.
107    * I found an Excel sheet on the Internet that contained motor data for
108    * exactly this engine:
109    *
110    \verbatim
111     U_K [V]  I_M [A]   n [rpm]  n [1/s]   remark
112     -----------------------------------------------------------------------------------
113      7.96     0.94     22290    371.5     idle, n = n_0, U_K = U_0 and I_M = I_0
114      7.37     7.47     13740    229       near max. load
115    \endverbatim
116    * J_M, the engine's rotor's inertia, can be found in the manufacturer's
117    * data sheet, or it has to be guessed. I assumed 1.0E-6 for the
118    * Speed 400. You can estimate it by regarding the rotor as a
119    * solid iron cylinder of mass m (in kg) and diameter d (in m)
120    * using the formula
121    *
122    \verbatim
123    J_M = 0.5 * m * d^2 / 4
124    \endverbatim
125    *
126    * All this resulted in the following engine file:
127    *
128    \verbatim
129    <?xml version="1.0"?>
130    <!--
131      Mabuchi 380 (aka Speed 400) with additional flux ring
132 
133      J_M is just guessed.
134    -->
135 
136     <engine_dcm  J_M="1.0E-6" calc="1">
137       <data>
138         <data U_K="7.96" I_M="0.94" n="371.5" />
139         <data U_K="7.37" I_M="7.47" n="229.0" />
140       </data>
141       <data_idle>
142         <data I_M="0.94" />
143       </data_idle>
144     </engine_dcm>
145    \endverbatim
146    *
147    * There must be at least two entries with different load points, but
148    * if you have more, just supply all of them.
149    *
150    * If you only have one set of idle data, the voltage
151    * does not matter.
152    * But if you can provide several values for idle current at a certain voltage, do so. Replace
153    \verbatim
154       <data_idle>
155         <data I_M="0.94" />
156       </data_idle>
157    \endverbatim
158    * by something like
159    \verbatim
160       <data_idle>
161         <data U_K="7.96" I_M="0.94" />
162         <data U_K="6.13" I_M="0.87" />
163         <data U_K="5.07" I_M="0.82" />
164       </data_idle>
165    \endverbatim
166    *
167    * @author Jens Wilhelm Wulf
168    */
169   class Engine_DCM : public Gearing
170   {
171     public:
172 
173      /**
174       *
175       */
176      Engine_DCM();
177 
178      /**
179       * virtual base class should have a virtual dtor
180       */
~Engine_DCM()181      virtual ~Engine_DCM() {};
182 
183      /**
184       * Load or reload parameters
185       */
186      void ReloadParams(SimpleXMLTransfer* xml);
187 
188      /**
189       * Load or reload parameters in case of automagic settings
190       */
191      void ReloadParams_automagic(SimpleXMLTransfer* xml);
192 
193      /**
194       * Go ahead values->dt seconds in the simulation.
195       */
196      virtual void step(PowerValuesStep* values);
197 
198      virtual void InitStates(CRRCMath::Vector3 vInitialVelocity, double& dOmega);
199 
200     private:
201 
202      /**
203       * resistance [Ohm]
204       */
205      double R_I;
206 
207      /**
208       * Friction [Nm]. This part does not depend on rotational speed.
209       * The most significant frictional losses are proportional to
210       * speed and M_r can/should be very small if k_r is known. In order
211       * to calculate k_r, data of more than one idle setpoint is needed.
212       * In case this data is not available, k_r=0 and M_r!=0.
213       */
214      double M_r;
215 
216      /**
217       * This coefficient describes friction losses which are proportional
218       * to rotational speed. See M_r.
219       */
220      double k_r;
221 
222      /**
223       * Motorkonstante [Nm/A]
224       */
225      double k_M;
226 
227 
228      /**
229       * throttle input, rate limited
230       */
231      CRRCMath::RateLimiter<double> throttle;
232 
233      /**
234       * rate limit for throttle
235       */
236      double throttle_rate_max;
237 
238      /**
239       * Do logging?
240       */
241      int nLog;
242   };
243 };
244 #endif
245