private void bt_show_maxtorque_capa_curve_Click(object sender, EventArgs e) { try { double Imax = double.Parse(tb_Imax.Text); double Umax = double.Parse(tb_Umax.Text); double max_speed = double.Parse(tb_maxSpeed.Text); MaxtorqueCapabilityCurve mtcc = buildMaxtorqueCapabilityCurve(50, Imax, Umax, max_speed); VoltageLimitCurve vlc = buildVoltageLimitCurve(50, Imax, Umax, max_speed); GraphWindow tc = new GraphWindow(); tc.addData("Torque-speed", new PointPairList(mtcc.speeds.ToArray(), mtcc.maxtorques.ToArray())); tc.addData("Current-speed", new PointPairList(mtcc.speeds.ToArray(), mtcc.currents.Select(f => f.Magnitude).ToArray())); tc.addData("CurrentPhase-speed", new PointPairList(mtcc.speeds.ToArray(), mtcc.currents.Select(f => f.Phase).ToArray())); tc.addData("Voltage-speed", new PointPairList(mtcc.speeds.ToArray(), mtcc.voltages.Select(f => f.Magnitude).ToArray())); tc.addData("Power-speed", new PointPairList(mtcc.speeds.ToArray(), mtcc.power.ToArray())); tc.addData("Efficiency", new PointPairList(mtcc.speeds.ToArray(), mtcc.effs.ToArray())); tc.addData("Boundary-Torque-speed1", new PointPairList(vlc.speeds.ToArray(), vlc.torques.ToArray())); tc.addData("(iq,id)", new PointPairList(mtcc.currents.Select(f => f.d).ToArray(), mtcc.currents.Select(f => f.q).ToArray())); tc.addData("id-speed", new PointPairList(mtcc.speeds.ToArray(), mtcc.currents.Select(f => f.d).ToArray())); tc.addData("iq-speed", new PointPairList(mtcc.speeds.ToArray(), mtcc.currents.Select(f => f.q).ToArray())); tc.Show(); } catch (Exception ex) { MessageBox.Show("Error: " + ex.Message); } }
private void bt_showmap_Click(object sender, EventArgs e) { bool success = true; double Imax = 0; success = success && double.TryParse(tb_Imax.Text, out Imax); double Umax = 0; success = success && double.TryParse(tb_Umax.Text, out Umax); double max_speed = 0; success = success && double.TryParse(tb_maxSpeed.Text, out max_speed); string config = string.Format("{0},{1},{2}", Imax, Umax, max_speed); MapType maptype = MapType.power; Enum.TryParse <MapType>(comboBox_maptype.Text, true, out maptype); if (!success) { MessageBox.Show("Error parse text to double"); return; } var mtpa = buildTableMaxtorquePerAmple(); int n = 100; double x0 = 0; double x1 = max_speed; double y0 = 0; double y1 = mtpa.GetMaxTorqueWithCurrentMagnitude(Imax); if (last_config != config) { effMap = buildEfficiencyMap(50, 100, Imax, Umax, max_speed); last_config = config; } var data = effMap.power; string title = "Power (W)"; switch (maptype) { case MapType.power: data = effMap.power; title = "Power (W)"; break; case MapType.efficiency: data = effMap.efficiency; title = "Efficiency (%)"; break; case MapType.windingloss: data = effMap.windingloss; title = "Winding loss (W)"; break; case MapType.rotor_coreloss: data = effMap.rotor_coreloss; title = "Rotor core loss (W)"; break; case MapType.stator_coreloss: data = effMap.stator_coreloss; title = "Stator loss (W)"; break; case MapType.coreloss: data = effMap.coreloss; title = "Core loss (W)"; break; case MapType.total_loss: data = effMap.totalloss; title = "Total loss (W)"; break; case MapType.voltage: data = effMap.voltage; title = "Voltage (V)"; break; case MapType.current: data = effMap.current; title = "Current (A)"; break; case MapType.beta: data = effMap.beta; title = "Beta (degree)"; break; case MapType.Ld: data = effMap.Ld; title = "Ld (mH)"; break; case MapType.Lq: data = effMap.Lq; title = "Ld (mH)"; break; default: break; } double fmin = double.MaxValue; for (int i = 0; i < data.GetLength(0); i++) { for (int j = 0; j < data.GetLength(1); j++) { if (data[i, j] >= 0 && fmin > data[i, j]) { fmin = data[i, j]; } } } var model = new PlotModel { Title = title, }; model.Axes.Add(new LinearColorAxis { Position = AxisPosition.Right, Palette = OxyPalettes.Jet(500), HighColor = OxyColors.Gray, LowColor = OxyColors.White, Minimum = fmin, //Maximum = 100, Title = title }); model.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, Title = "Speed", //MajorGridlineStyle = LineStyle.Solid, //MinorGridlineStyle = LineStyle.Solid, //MajorGridlineColor = OxyColor.FromAColor(40, c), //MinorGridlineColor = OxyColor.FromAColor(20, c) }); model.Axes.Add(new LinearAxis { Position = AxisPosition.Left, Title = "Torque", //AbsoluteMinimum = 0, //Minimum = 0, //MajorGridlineStyle = LineStyle.Solid, //MinorGridlineStyle = LineStyle.Solid, //MajorGridlineColor = OxyColor.FromAColor(40, c), //MinorGridlineColor = OxyColor.FromAColor(20, c) }); var hms = new HeatMapSeries { X0 = x0, X1 = x1, Y0 = y0, Y1 = y1, Data = data, Interpolate = true, }; model.Series.Add(hms); // contour var cs = new ContourSeries { //Color = OxyColors.Gray, //FontSize = 12, //ContourLevelStep = double.NaN, //LabelBackground = OxyColors.White, ColumnCoordinates = effMap.speed_points, RowCoordinates = effMap.torque_points, Data = data, }; if (cs.Data == effMap.efficiency) { cs.ContourLevels = new double[] { 0, 20, 40, 60, 80, 90, 91, 92, 93, 94, 95, 95.2, 95.4, 95.6, 95.8, 96, 96.2, 97, 98, 99 }; model.Series.Add(cs); } // max-torque capability curve MaxtorqueCapabilityCurve mtcc = buildMaxtorqueCapabilityCurve(100, Imax, Umax, max_speed); var mtcc_series = new LineSeries() { LineStyle = LineStyle.Solid, Color = OxyColor.FromArgb(255, 0, 0, 0), StrokeThickness = 3, }; for (int i = 0; i < mtcc.speeds.Count; i++) { mtcc_series.Points.Add(new OxyPlot.DataPoint(mtcc.speeds[i], mtcc.maxtorques[i])); } model.Series.Add(mtcc_series); // voltage limit curve 1 VoltageLimitCurve vlc = buildVoltageLimitCurve(100, Imax, Umax, max_speed); var vlc_series = new LineSeries() { LineStyle = LineStyle.Dash, StrokeThickness = 1, }; for (int i = 0; i < vlc.speeds.Count; i++) { vlc_series.Points.Add(new OxyPlot.DataPoint(vlc.speeds[i], vlc.torques[i])); } model.Series.Add(vlc_series); plot.Model = model; }
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); }
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); }