示例#1
0
        /// <summary>
        /// Convert from abc to dq
        /// Theta is radian
        /// </summary>
        /// <param name="a">fa</param>
        /// <param name="b">fb</param>
        /// <param name="c">fc</param>
        /// <param name="theta">Angle (radian) from 0a to 0d (counter clockwise)</param>
        /// <returns></returns>
        public static Fdq abc_dq(double a, double b, double c, double theta)
        {
            Fdq fdq = new Fdq();

            fdq.d = 2.0 / 3 * (Math.Cos(theta) * a + Math.Cos(theta - 2 * Math.PI / 3) * b + Math.Cos(theta + 2 * Math.PI / 3) * c);
            fdq.q = -2.0 / 3 * (Math.Sin(theta) * a + Math.Sin(theta - 2 * Math.PI / 3) * b + Math.Sin(theta + 2 * Math.PI / 3) * c);
            return(fdq);
        }
示例#2
0
 public static Fabc dq_abc(Fdq fdq, double theta)
 {
     return(dq_abc(fdq.d, fdq.q, theta));
 }
示例#3
0
        private VoltageLimitEllipse buildVoltageLimitEllipse(double speed, int count = 50, double Imax = 55, double Umax = 140)
        {
            var vle = new VoltageLimitEllipse
            {
                speed   = speed,
                Imax    = Imax,
                Umax    = Umax,
                curve   = new List <Fdq>(),
                torques = new List <double>(),
            };

            double maxt     = 0;
            bool   minfound = false;

            int index = 0;

            for (int j = 0; j < count + 1; j++)
            {
                double id = -Imax * j / count;
                double iq;
                double t  = 0;
                bool   bb = Brent.TryFindRoot(iq_ =>
                {
                    var d    = calculatePointdata(id, iq_, speed);
                    double u = Math.Sqrt(d.ud * d.ud + d.uq * d.uq);
                    t        = d.torque;
                    return(u - Umax);
                }, 0, Imax, 1e-5, 100, out iq);

                if (bb)
                {
                    var idq = new Fdq {
                        d = id, q = iq
                    };
                    if (maxt < t)
                    {
                        maxt = t;
                        vle.maxtorque_point = index;
                    }
                    if (!minfound)
                    {
                        vle.minid_point = index;
                        minfound        = true;
                    }

                    vle.curve.Add(idq);
                    vle.torques.Add(t);
                    index++;
                }
            }

            if (vle.curve[0].d < 0)
            {
                Fdq idq1 = vle.curve[0];
                Fdq idq2 = vle.curve[1];
                Fdq idq0 = new Fdq
                {
                    d = idq1.d + (Imax / count) * (idq1.q / idq2.q) / (1 - idq1.q / idq2.q),
                    q = 0,
                };
                vle.curve.Insert(0, idq0);
                vle.torques.Insert(0, 0);
                vle.maxtorque_point++;
            }

            return(vle);
        }
示例#4
0
        private EfficiencyMap buildEfficiencyMap(int torque_count, int speed_count, double Imax, double Umax, double max_speed)
        {
            MaxtorqueCapabilityCurve mtcc = buildMaxtorqueCapabilityCurve(speed_count, Imax, Umax, max_speed);
            VoltageLimitCurve        vlc  = buildVoltageLimitCurve(speed_count, Imax, Umax, max_speed);

            var em = new EfficiencyMap()
            {
                // input
                Imax     = Imax,
                Umax     = Umax,
                MaxSpeed = max_speed,

                // axis
                speed_points  = new double[speed_count + 1],
                torque_points = new double[torque_count + 1],

                // value
                power           = new double[speed_count + 1, torque_count + 1],
                windingloss     = new double[speed_count + 1, torque_count + 1],
                rotor_coreloss  = new double[speed_count + 1, torque_count + 1],
                stator_coreloss = new double[speed_count + 1, torque_count + 1],
                coreloss        = new double[speed_count + 1, torque_count + 1],
                totalloss       = new double[speed_count + 1, torque_count + 1],
                efficiency      = new double[speed_count + 1, torque_count + 1],

                voltage = new double[speed_count + 1, torque_count + 1],
                current = new double[speed_count + 1, torque_count + 1],
                beta    = new double[speed_count + 1, torque_count + 1],
                Ld      = new double[speed_count + 1, torque_count + 1],
                Lq      = new double[speed_count + 1, torque_count + 1],
            };

            em.power.Fill2D(double.NaN);
            em.windingloss.Fill2D(double.NaN);
            em.rotor_coreloss.Fill2D(double.NaN);
            em.stator_coreloss.Fill2D(double.NaN);
            em.coreloss.Fill2D(double.NaN);
            em.totalloss.Fill2D(double.NaN);
            em.efficiency.Fill2D(double.NaN);

            em.voltage.Fill2D(double.NaN);
            em.current.Fill2D(double.NaN);
            em.beta.Fill2D(double.NaN);
            em.Ld.Fill2D(double.NaN);
            em.Lq.Fill2D(double.NaN);

            var    mtpa  = buildTableMaxtorquePerAmple();
            double max_t = mtpa.GetMaxTorqueWithCurrentMagnitude(Imax);

            LinearSpline torqueCapabilityLimit = LinearSpline.Interpolate(mtcc.speeds, mtcc.maxtorques);

            for (int i = 0; i < speed_count + 1; i++)
            {
                for (int j = 0; j < torque_count + 1; j++)
                {
                    // speed
                    double speed = max_speed * i / speed_count;
                    em.speed_points[i] = speed;

                    // torque
                    double t = max_t * j / torque_count;
                    em.torque_points[j] = t;
                    double max_possible_torque = torqueCapabilityLimit.Interpolate(speed);
                    if (t > max_possible_torque)
                    {
                        continue;
                    }

                    // speed limit 1
                    double speed1 = vlc.GetMaxSpeedForTorque(t);

                    APointData data = null;

                    if (t == 0)
                    {
                        data = calculatePointdata(0, 0, speed);
                    }
                    // zone 1
                    else if (speed <= speed1)
                    {
                        Fdq idq = mtpa.GetCurrentForTorque(t);
                        if (double.IsNaN(idq.d) || double.IsNaN(idq.q))
                        {
                            data = null;
                        }
                        else
                        {
                            data = calculatePointdata(idq.d, idq.q, speed);
                        }
                    }
                    else
                    {
                        Fdq idq = getCurrentForZone2(t, speed, Imax, Umax);
                        if (double.IsNaN(idq.d) || double.IsNaN(idq.q))
                        {
                            data = null;
                        }
                        else
                        {
                            data = calculatePointdata(idq.d, idq.q, speed);
                        }
                    }

                    if (data != null)
                    {
                        em.rotor_coreloss[i, j]  = data.rotorloss;
                        em.stator_coreloss[i, j] = data.statorloss;
                        em.coreloss[i, j]        = data.rotorloss + data.statorloss;
                        em.windingloss[i, j]     = data.copperloss;
                        em.totalloss[i, j]       = data.copperloss + data.rotorloss + data.statorloss;
                        em.power[i, j]           = data.power;
                        em.efficiency[i, j]      = 100 * data.power / (data.power + em.totalloss[i, j]);

                        em.voltage[i, j] = data.voltage;
                        em.current[i, j] = data.current;
                        em.beta[i, j]    = data.beta;
                        em.Ld[i, j]      = double.IsNaN(data.Ld) || data.Ld < 0 ? -0.0001 : data.Ld * 1000; //to mH
                        em.Lq[i, j]      = double.IsNaN(data.Ld) || data.Ld < 0 ? -0.0001 : data.Lq * 1000; //to mH
                    }
                }
            }

            return(em);
        }
示例#5
0
        private MaxtorqueCapabilityCurve buildMaxtorqueCapabilityCurve(int count = 50, double Imax = 55, double Umax = 140, double max_speed = 6000)
        {
            var mtpa = buildTableMaxtorquePerAmple();

            MaxtorqueCapabilityCurve mtcc = new MaxtorqueCapabilityCurve()
            {
                Imax     = Imax,
                Umax     = Umax,
                MaxSpeed = max_speed,
            };

            // Look for beta to get max torque

            double max_t = mtpa.GetMaxTorqueWithCurrentMagnitude(Imax);
            Fdq    idq   = mtpa.GetCurrentForTorque(max_t);

            // Create PointPairList
            // look for speed1
            var speed1 = Brent.FindRoot(s =>
            {
                var data_ = calculatePointdata(idq.d, idq.q, s);
                var u_    = Math.Sqrt(data_.ud * data_.ud + data_.uq * data_.uq);
                return(u_ - Umax);
            }, 100, max_speed, 1e-3);

            // speed by speed
            int count1 = (int)(speed1 / max_speed * count) + 1;
            int count2 = count - count1;

            for (int i = 1; i < count1 + 1; i++)
            {
                double speed = speed1 * i / count1;

                var data = calculatePointdata(idq.d, idq.q, speed);

                mtcc.speeds.Add(speed);
                mtcc.maxtorques.Add(data.torque);
                mtcc.currents.Add(idq);
                mtcc.voltages.Add(new Fdq()
                {
                    d = data.ud, q = data.uq
                });
                mtcc.power.Add(data.power);
                mtcc.effs.Add(data.efficiency);
            }

            double t = max_t;

            for (int i = 1; i < count2 + 1; i++)
            {
                double speed = speed1 + (max_speed - speed1) * i / count2;

                // find beta which make U=Umax
                //double beta = 0;
                //bool success = Brent.TryFindRoot(b =>
                //{
                //    var data_ = calculatePointdata(Imax * Math.Cos(b * Math.PI / 180), Imax * Math.Sin(b * Math.PI / 180), speed);
                //    var u_ = Math.Sqrt(data_.ud * data_.ud + data_.uq * data_.uq);
                //    return u_ - Umax;
                //}, 100, 180, 1e-5, 100, out beta);

                // Here:
                // Find Id,Iq that bring max torque at speed
                // it is intersect of circle Imax and ellipse Umax/w if Imax < ellipse center (-psiM/Ld)
                // or ellipse center itself if Imax > ellipse center

                Fdq  idq2  = default(Fdq);
                bool found = false;

                var vle = buildVoltageLimitEllipse(speed, 1000, Imax, Umax);

                var maxtorque_point = vle.curve[vle.maxtorque_point];
                var minid_point     = vle.curve[vle.minid_point];

                if (maxtorque_point.Magnitude <= Imax)
                {
                    idq2 = new Fdq {
                        d = maxtorque_point.d, q = maxtorque_point.q
                    };
                    found = true;
                }
                else if (minid_point.Magnitude > Imax) //Imax out of ellipse
                {
                    found = false;
                }
                else
                {
                    var range = Enumerable.Range(0, vle.maxtorque_point);

                    LinearSpline spline = LinearSpline.Interpolate(range.Select(k => vle.curve[k].Magnitude), range.Select(k => vle.curve[k].d));
                    double       id     = spline.Interpolate(Imax);
                    double       iq     = Math.Sqrt(Imax * Imax - id * id);
                    idq2 = new Fdq {
                        d = id, q = iq
                    };
                    found = true;
                }

                if (found)
                {
                    //double id = idq2.d;//Imax * Math.Cos(beta * Math.PI / 180);
                    //double iq = idq2.q;//Imax * Math.Sin(beta * Math.PI / 180);
                    var data = calculatePointdata(idq2.d, idq2.q, speed);

                    mtcc.speeds.Add(speed);
                    mtcc.maxtorques.Add(data.torque);
                    mtcc.currents.Add(idq2);
                    mtcc.voltages.Add(new Fdq()
                    {
                        d = data.ud, q = data.uq
                    });
                    mtcc.power.Add(data.power);
                    mtcc.effs.Add(data.efficiency);
                }
            }

            return(mtcc);
        }