Горизонтальное смещение, которое вы наблюдаете, относится к единице оси X. Ваши значения DateTime
не округляются, например, до секунд. Вы всегда берете полную метку времени, включая миллисекунды. При выделении секунд временные метки разных графиков совпадают. Но, глядя на миллисекунды, нет. Это совершенно очевидно при сравнении желтого ряда с синим: временные метки желтого ряда попадают прямо между голубыми рядами значений x, создавая «смещение», что абсолютно правильно, но не желательно. Замена единицы по оси x на DateTime
с фиксированным интервалом времени прохождения (например, 5, 10, 15) исправит это.
Текущая реализация не имитирует c, как работает осциллограф. Вы не показываете отметки времени на оси X или абсолютные значения на оси Y. Вы просто предоставляете постоянную сетку или шкалу для измерения сигнала. Вес интервала сетки (обе оси) настраивается пользователем. Например, каждый горизонтальный интервал составляет 5 мс, а вертикальный интервал - 1 Вольт. Таким образом, вам не нужна временная метка (DateTime
) для рисования сигнала, но время прохождения (TimeSpan
). Вы должны эмулировать триггер, чтобы выбрать правильный диапазон значений, чтобы обеспечить стабильный снимок сигнала. Таким образом, количество значений для построения экрана зависит от текущей временной базы. Число не является фиксированным, например, последние 150 значений. Вы можете использовать время прохождения или рассчитанную частоту, чтобы масштабировать сигнал, чтобы он соответствовал текущему выбранному временному интервалу сетки видового экрана. Допустим, ваш видовой экран имеет сетку 10 * 8, и пользователь устанавливает временную базу на 5 мс, затем вы должны построить 50 мс сигнала и обозначить ось х 5 мс, 10 мс, 15 мс, ....
Ваш стиль программирования не является объектно-ориентированным. Вы должны либо использовать наследование для инкапсуляции общего кода внутри базового класса. Таким образом, вместо двух классов Screen1
и Screen2
у вас должен быть один класс Screen
, который имеет все общие логики c, а затем извлекает Screen1
и Screen2
из него и добавляет некоторую спецификацию c функции. Или, если они не имеют определенных c функций, то есть один класс Screen
. Затем вы создаете два или n экземпляров этого класса
var screen1 = new Screen();
var screen2 = new Screen();
Всегда избегайте дублирования кода. То же относится и к Read1
и Read2
. Оба содержат одинаковый код. Вы должны объединить оба метода, а также читать каналы параллельно:
// Read each channel in a separate thread
private void ReadChannels()
{
Task.Run(() => ReadChannel(this.ChartValues1, this.ScreenA));
Task.Run(() => ReadChannel(this.ChartValues2, this.ScreenB));
Task.Run(() => ReadChannel(this.ChartValues3, this.ScreenC));
}
private void ReadChannel(ChartValues<MeasureModel> chartValues, Screen screen)
{
while (screen.IsReading1)
{
Thread.Sleep(100);
var now = DateTime.Now;
chartValues.Add(new MeasureModel
{
DateTime = now,
Value = screen.result1
});
screen.SetAxisLimits(now);
//lets only use the last 150 values
if (chartValues.Count > 150)
chartValues.RemoveAt(0);
}
}
Я рекомендую взглянуть на LiveCharts Geared , так как он может похвастаться высокой производительностью в сценарии живых графиков ios.
Также у живых графиков есть некоторые ограничения. Вы не можете изменить смещение сюжета. Это базовое требование c для осциллографа, чтобы свободно выровнять сигнал с сеткой, чтобы визуально интерпретировать сигнал. Вы должны были бы реализовать это самостоятельно. Вы можете нарисовать несколько рядов на одном графике, но не можете их сложить.