97 lines
3.8 KiB
C#
97 lines
3.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
|
|
namespace HC_APTBS.Models
|
|
{
|
|
/// <summary>
|
|
/// Maps a motor RPM setpoint to the corresponding analogue control voltage
|
|
/// required to drive the bench motor to that speed.
|
|
///
|
|
/// <para>
|
|
/// The lookup table is ordered by ascending RPM. <see cref="VoltageForRpm"/>
|
|
/// performs a linear scan and returns the voltage of the last entry whose
|
|
/// RPM is ≤ the requested value (step interpolation).
|
|
/// </para>
|
|
/// </summary>
|
|
public class RpmVoltageRelation
|
|
{
|
|
/// <summary>Analogue voltage to apply to the motor controller (V).</summary>
|
|
public double Voltage { get; set; }
|
|
|
|
/// <summary>Target motor speed (RPM).</summary>
|
|
public int Rpm { get; set; }
|
|
|
|
/// <param name="voltage">Motor control voltage (V).</param>
|
|
/// <param name="rpm">Corresponding motor speed (RPM).</param>
|
|
public RpmVoltageRelation(double voltage, int rpm)
|
|
{
|
|
Voltage = voltage;
|
|
Rpm = rpm;
|
|
}
|
|
|
|
// ── Lookup ────────────────────────────────────────────────────────────────
|
|
|
|
/// <summary>
|
|
/// Returns the control voltage for the given <paramref name="targetRpm"/>
|
|
/// by scanning the ordered <paramref name="table"/> for the closest lower entry.
|
|
/// Returns 0 if the table is empty or no lower entry is found.
|
|
/// </summary>
|
|
/// <param name="targetRpm">Requested motor speed in RPM.</param>
|
|
/// <param name="table">Ordered (ascending RPM) lookup table.</param>
|
|
public static double VoltageForRpm(int targetRpm, IReadOnlyList<RpmVoltageRelation> table)
|
|
{
|
|
double previousVoltage = -1;
|
|
foreach (var entry in table)
|
|
{
|
|
if (entry.Rpm == targetRpm)
|
|
return entry.Voltage;
|
|
|
|
if (targetRpm < entry.Rpm)
|
|
return previousVoltage < 0 ? 0 : previousVoltage;
|
|
|
|
previousVoltage = entry.Voltage;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// ── Serialisation ─────────────────────────────────────────────────────────
|
|
|
|
/// <summary>
|
|
/// Serialises a list of relations to the compact pipe-separated storage format
|
|
/// used in config.xml: <c>RPM|Voltage;RPM|Voltage;…</c>
|
|
/// </summary>
|
|
public static string Serialise(IReadOnlyList<RpmVoltageRelation> relations)
|
|
{
|
|
if (relations == null || relations.Count == 0) return string.Empty;
|
|
|
|
var parts = new List<string>(relations.Count);
|
|
foreach (var r in relations)
|
|
parts.Add($"{r.Rpm}|{r.Voltage.ToString(CultureInfo.InvariantCulture)}");
|
|
|
|
return string.Join(";", parts);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Deserialises a list of relations from the compact storage format.
|
|
/// </summary>
|
|
public static List<RpmVoltageRelation> Deserialise(string serialised)
|
|
{
|
|
var result = new List<RpmVoltageRelation>();
|
|
if (string.IsNullOrWhiteSpace(serialised)) return result;
|
|
|
|
foreach (var part in serialised.Split(';'))
|
|
{
|
|
var tokens = part.Split('|');
|
|
if (tokens.Length != 2) continue;
|
|
if (!int.TryParse(tokens[0], out int rpm)) continue;
|
|
if (!double.TryParse(tokens[1], NumberStyles.Float,
|
|
CultureInfo.InvariantCulture, out double voltage)) continue;
|
|
|
|
result.Add(new RpmVoltageRelation(voltage, rpm));
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
}
|