first commit

This commit is contained in:
Dana Markova
2025-07-28 13:21:36 +03:00
commit 0de214c9a1
547 changed files with 287132 additions and 0 deletions

View File

@ -0,0 +1,604 @@
using System;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.IO;
using System.Diagnostics;
using System.Windows.Forms.DataVisualization.Charting;
using System.Runtime.InteropServices;
using System.Net;
namespace WindowsFormsApp1
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
foreach (var s in chart_Graph.Series) s.XValueType = ChartValueType.DateTime;
chart_Graph.ChartAreas[0].AxisX.LabelStyle.Format = "mm:ss";
chart_Graph.ChartAreas[0].AxisX.Minimum = DateTime.Now.ToOADate();
chart_Graph.ChartAreas[0].AxisX.Maximum = DateTime.Now.AddSeconds(trackBar_GraphX_Down.Value).ToOADate();
chart_Graph.ChartAreas[0].AxisX.IntervalAutoMode = IntervalAutoMode.FixedCount;
chart_Graph.ChartAreas[0].AxisX.Interval = (new DateTime(1, 1, 1, 0, 0, 1)).ToOADate();
for (int a = 0; a < checkedListBox_Series.Items.Count; a++) checkedListBox_Series.SetItemChecked(a, true);
PIDs[0] = numericUpDown_PID_Min; PIDs[1] = numericUpDown_PID_Max;
PIDs[2] = numericUpDown_PID_P_Min; PIDs[3] = numericUpDown_PID_P_Max; PIDs[4] = numericUpDown_PID_P_Value;
PIDs[5] = numericUpDown_PID_I_Min; PIDs[6] = numericUpDown_PID_I_Max; PIDs[7] = numericUpDown_PID_I_Value;
PIDs[8] = numericUpDown_PID_D_Min; PIDs[9] = numericUpDown_PID_D_Max; PIDs[10] = numericUpDown_PID_D_Value;
PIDs[11] = numericUpDown_Yaw_P_Min; PIDs[12] = numericUpDown_Yaw_P_Max; PIDs[13] = numericUpDown_Yaw_P_Value;
PIDs[14] = numericUpDown_Yaw_I_Min; PIDs[15] = numericUpDown_Yaw_I_Max; PIDs[16] = numericUpDown_Yaw_I_Value;
PIDs[17] = numericUpDown_Yaw_D_Min; PIDs[18] = numericUpDown_Yaw_D_Max; PIDs[19] = numericUpDown_Yaw_D_Value;
}
private byte[] getStructBytes(RecvHead str)
{
int size = Marshal.SizeOf(str);
byte[] arr = new byte[size];
IntPtr ptr = IntPtr.Zero;
try
{
ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(str, ptr, true);
Marshal.Copy(ptr, arr, 0, size);
}
finally
{
Marshal.FreeHGlobal(ptr);
}
return arr;
}
private object fromBytestoStruct(byte[] arr)
{
RecvHead str = new RecvHead();
int size = Marshal.SizeOf(str);
IntPtr ptr = IntPtr.Zero;
try
{
ptr = Marshal.AllocHGlobal(size);
Marshal.Copy(arr, 0, ptr, size);
str = (RecvHead)Marshal.PtrToStructure(ptr, str.GetType());
}
finally
{
Marshal.FreeHGlobal(ptr);
}
return str;
}
private bool CheckCRC8(byte crc1, byte crc2)
{
bool ret = crc1 == crc2;
if (ret)
{
RecvCounts++;
textBox_Count.Text = RecvCounts.ToString();
}
else
{
RecvErrors++;
textBox_Error.Text = RecvErrors.ToString();
}
RecvMain.Mode = RecvModeEnum.Begin;
return ret;
}
void OperationResult(bool res)
{
if (res)
{
RecvCounts++;
textBox_Count.Text = RecvCounts.ToString();
}
else
{
RecvErrors++;
textBox_Error.Text = RecvErrors.ToString();
}
RecvMain.Mode = RecvModeEnum.Begin;
}
private byte GetCRC8(byte[] arr, int size)
{
byte crc = 0;
for (int a = 0; a < Math.Min(arr.Length, size); a++) crc ^= arr[a];
return crc;
}
private bool CheckCRC8(byte[] arr, int size, byte crc2)
{
byte crc1 = GetCRC8(arr, size);
return CheckCRC8(crc1, crc2);
}
private void SendData(RecvModeEnum mode, byte[] data)
{
if (data == null) data = new byte[0];
RecvHead head = new RecvHead(mode, data.Length, GetCRC8(data, data.Length));
byte[] h = getStructBytes(head);
byte[] send = new byte[1 + h.Length + data.Length];
send[0] = 0xAA;
Buffer.BlockCopy(h, 0, send, 1, h.Length);
Buffer.BlockCopy(data, 0, send, 1 + h.Length, data.Length);
serialPort_COM.Write(send, 0, send.Length);
}
string RecordsFolder = "";
BinaryWriter RecordWriter = null;
private object[] PIDs = new object[20];
private const int RecvCount = 512;
private byte[] RecvData = new byte[RecvCount];
private int RecvSize = 0;
private enum RecvModeEnum : byte { Begin, Head, Titles, Data, Auto, SetPID, GetPID, Done };
private int TimerStop = 0;
private int RecvErrors = 0;
private int RecvCounts = 0;
private DateTime GraphLast = DateTime.Now;
private struct RecvHead
{
public RecvHead(RecvModeEnum mode, int size, byte crc8)
{
Mode = mode;
DataSize = (byte)size;
DataCRC8 = crc8;
CRC8 = (byte)(((byte)Mode) ^ DataSize ^ DataCRC8);
}
public RecvModeEnum Mode;
public byte DataSize;
public byte DataCRC8;
public byte CRC8;
public bool Check()
{
return CRC8 == (byte)(((byte)Mode) ^ DataSize ^ DataCRC8);
}
}
private RecvHead RecvMain;
private void DrawGraph(byte[] data, int from, int size)
{
if (checkBox_Track.Checked)
{
chart_Graph.ChartAreas[0].AxisX.Minimum = DateTime.Now.AddSeconds(-trackBar_GraphX_Down.Value).ToOADate();
chart_Graph.ChartAreas[0].AxisX.Maximum = DateTime.Now.ToOADate();
}
else
{
TimeSpan shift = DateTime.Now.Subtract(GraphLast);
if (shift.TotalSeconds > trackBar_GraphX_Down.Value)
{
GraphLast = DateTime.Now;
for (int a = 0; a < chart_Graph.Series.Count; a++) chart_Graph.Series[a].Points.Clear();
chart_Graph.ChartAreas[0].AxisX.Minimum = DateTime.Now.ToOADate();
chart_Graph.ChartAreas[0].AxisX.Maximum = DateTime.Now.AddSeconds(trackBar_GraphX_Down.Value).ToOADate();
}
}
RecordWriter?.Write(Encoding.UTF8.GetBytes(DateTime.Now.ToOADate().ToString()));
short[] lines = new short[size / 2];
Buffer.BlockCopy(data, from, lines, 0, size);
for (int a = 0; a < Math.Min(lines.Length, chart_Graph.Series.Count); a++)
{
chart_Graph.Series[a].Points.AddXY(DateTime.Now, lines[a]);
if (checkBox_Track.Checked)
{
while (true)
{
if ((DateTime.Now - DateTime.FromOADate(chart_Graph.Series[a].Points[0].XValue)).TotalSeconds > trackBar_GraphX_Down.Value + 1)
chart_Graph.Series[a].Points.RemoveAt(0);
else break;
}
}
RecordWriter?.Write(Encoding.UTF8.GetBytes("|" + lines[a].ToString()));
}
RecordWriter?.Write(Encoding.UTF8.GetBytes("\r\n"));
RecordWriter?.Flush();
}
private void RecvPID(byte[] data)
{
for (int a = 0; a < 20; a++)
{
((NumericUpDown)PIDs[a]).Value = (decimal)BitConverter.ToSingle(data, a * 4);
}
}
private byte[] SendPID()
{
byte[] send = new byte[20 * 4];
float[] data = new float[20];
for (int a = 0; a < 20; a++)
{
float v = (float)((NumericUpDown)PIDs[a]).Value;
data[a] = v;
}
Buffer.BlockCopy(data, 0, send, 0, send.Length);
return send;
}
private void button_Connect_Click(object sender, EventArgs e)
{
if (button_Connect.Text == "Connect")
{
try { serialPort_COM.PortName = comboBox_Port.Text; } catch { MessageBox.Show("Error to set port", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; }
try
{
serialPort_COM.Open();
serialPort_COM.DiscardInBuffer();
SendData(RecvModeEnum.Titles, null);
}
catch { MessageBox.Show("Error to connect", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; }
RecvErrors = 0;
RecvCounts = 0;
textBox_Error.Text = "0";
textBox_Count.Text = "0";
timer_Tick.Enabled = true;
button_Connect.Text = "Disonnect";
checkBox_Save_CheckedChanged(null, null);
}
else
{
serialPort_COM.Close();
timer_Tick.Enabled = false;
button_Connect.Text = "Connect";
panel_PID.Enabled = false;
RecordWriter?.Close();
RecordWriter = null;
}
}
private void timer_Tick_Tick(object sender, EventArgs e)
{
switch (RecvMain.Mode)
{
case RecvModeEnum.Begin:
{
TimerStop = 20;
byte[] recv = new byte[1];
int len;
try { len = serialPort_COM.Read(recv, 0, 1); } catch { break; }
if (recv[0] == 0xAA) RecvMain.Mode = RecvModeEnum.Head;
break;
}
case RecvModeEnum.Head:
{
int size = Marshal.SizeOf(RecvMain);
int len;
try { len = serialPort_COM.Read(RecvData, RecvSize, size - RecvSize); } catch { break; }
RecvSize += len;
if (RecvSize < size) break;
RecvSize = 0;
RecvHead head = (RecvHead)fromBytestoStruct(RecvData);
if (!head.Check()) { OperationResult(false); break; }
RecvMain = head;
break;
}
case RecvModeEnum.Titles:
{
int len;
try { len = serialPort_COM.Read(RecvData, RecvSize, RecvMain.DataSize - RecvSize); } catch { break; }
RecvSize += len;
if (RecvSize < RecvMain.DataSize) break;
RecvSize = 0;
if (!CheckCRC8(RecvData, RecvMain.DataSize, RecvMain.DataCRC8)) break;
string titles = Encoding.UTF8.GetString(RecvData, 0, len);
string[] tit = titles.Split('|');
chart_Graph.Series.Clear();
checkedListBox_Series.Items.Clear();
foreach (var t in tit)
{
var s = chart_Graph.Series.Add(t);
s.ChartType = SeriesChartType.FastLine;
s.XValueType = ChartValueType.DateTime;
int i = checkedListBox_Series.Items.Add(t);
checkedListBox_Series.SetItemChecked(i, true);
}
break;
}
case RecvModeEnum.Data:
{
int len;
try { len = serialPort_COM.Read(RecvData, RecvSize, RecvMain.DataSize - RecvSize); } catch { break; }
RecvSize += len;
if (RecvSize < RecvMain.DataSize) break;
RecvSize = 0;
if (!CheckCRC8(RecvData, len, RecvMain.DataCRC8)) break;
if (chart_Graph.Series.Count == 0) break;
DrawGraph(RecvData, 0, RecvMain.DataSize);
break;
}
case RecvModeEnum.GetPID:
{
int len;
try { len = serialPort_COM.Read(RecvData, RecvSize, RecvMain.DataSize - RecvSize); } catch { break; }
RecvSize += len;
if (RecvSize < RecvMain.DataSize) break;
RecvSize = 0;
if (!CheckCRC8(RecvData, len, RecvMain.DataCRC8)) break;
RecvPID(RecvData);
label_PID_State.Text = "Done";
for (int a = 0; a < 20; a++) ((NumericUpDown)PIDs[a]).BackColor = Color.White;
panel_PID.Enabled = true;
break;
}
case RecvModeEnum.Done:
{
for (int a = 0; a < 20; a++) ((NumericUpDown)PIDs[a]).BackColor = Color.White;
label_PID_State.Text = "Done";
RecvMain.Mode = RecvModeEnum.Begin;
break;
}
default:
{
RecvMain.Mode = RecvModeEnum.Begin;
break;
}
}
TimerStop--;
if (TimerStop <= 0)
{
RecvErrors++;
textBox_Error.Text = RecvErrors.ToString();
RecvMain.Mode = RecvModeEnum.Begin;
}
}
private void comboBox_Port_DropDown(object sender, EventArgs e)
{
comboBox_Port.Items.Clear();
foreach (string p in SerialPort.GetPortNames()) comboBox_Port.Items.Add(p);
}
private void numericUpDown_Min_ValueChanged(object sender, EventArgs e)
{
trackBar_GraphX_Down.Maximum = (int)numericUpDown_Min.Value;
if (sender == numericUpDown_Min) trackBar_GraphX_Down.Value = trackBar_GraphX_Down.Maximum;
else foreach (var s in chart_Graph.Series) s.Points.Clear();
GraphLast = DateTime.Now;
chart_Graph.ChartAreas[0].AxisX.Minimum = DateTime.Now.ToOADate();
chart_Graph.ChartAreas[0].AxisX.Maximum = DateTime.Now.AddSeconds(trackBar_GraphX_Down.Value).ToOADate();
chart_Graph.ChartAreas[0].AxisX.Interval = (new DateTime(1, 1, 1, 0, 0, 0).AddSeconds(((double)trackBar_GraphX_Down.Value) / 10)).ToOADate();
if (trackBar_GraphX_Down.Value < 10) chart_Graph.ChartAreas[0].AxisX.LabelStyle.Format = "mm:ss.f";
else chart_Graph.ChartAreas[0].AxisX.LabelStyle.Format = "mm:ss";
}
private void button_PID_Read_Click(object sender, EventArgs e)
{
label_PID_State.Text = "Read";
SendData(RecvModeEnum.GetPID, null);
}
private void button_PID_Write_Click(object sender, EventArgs e)
{
if (!panel_PID.Enabled) return;
label_PID_State.Text = "Write";
byte[] data = SendPID();
SendData(RecvModeEnum.SetPID, data);
}
private void button_Color_Click(object sender, EventArgs e)
{
if (colorDialog_Color.ShowDialog() == DialogResult.Cancel) return;
if (checkedListBox_Series.SelectedIndex == -1) return;
//---
int index = checkedListBox_Series.SelectedIndex;
chart_Graph.Series[index].Color = colorDialog_Color.Color;
button_Color.BackColor = colorDialog_Color.Color;
}
private void label_PID_State_TextChanged(object sender, EventArgs e)
{
if (label_PID_State.Text != "Done") label_PID_State.BackColor = Color.Tomato;
else label_PID_State.BackColor = Color.LightGreen;
}
private void numericUpDown_PID_Min_ValueChanged(object sender, EventArgs e)
{
((NumericUpDown)sender).BackColor = Color.Tomato;
}
private void checkBox_Save_CheckedChanged(object sender, EventArgs e)
{
if (!checkBox_Save.Checked)
{
RecordWriter?.Close();
RecordWriter = null;
return;
}
DateTime dt = DateTime.Now;
string file = Path.Combine(RecordsFolder, "record=" + dt.ToString("yyyy-MM-dd+HH_mm_ss") + ".tel");
try
{
RecordWriter = new BinaryWriter(File.OpenWrite(file));
string head = "Telem v1\r\nTime";
foreach (var s in chart_Graph.Series) head += "|" + s.Name;
head += "\r\n";
RecordWriter.Write(Encoding.UTF8.GetBytes(head));
RecordWriter.Flush();
}
catch
{
MessageBox.Show("Incorrect save file!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
checkBox_Save.Checked = false;
}
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
string folder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
string specificFolder = Path.Combine(folder, "Telem");
//---
RecordsFolder = Path.Combine(specificFolder, "Records");
Directory.CreateDirectory(RecordsFolder);
openFileDialog_Open.InitialDirectory = RecordsFolder;
}
catch { }
string[] input = Environment.GetCommandLineArgs();
if (input.Length > 1)
{
string file = input[1];
byte[] record = File.ReadAllBytes(file);
short[] data = new short[record.Length / 2];
Buffer.BlockCopy(record, 0, data, 0, record.Length);
for (int a = 0; a < data.Length; a++)
{
chart_Graph.Series[a % 9].Points.AddXY(a / 9, data[a]);
}
chart_Graph.ChartAreas[0].AxisX.Maximum = double.NaN;
groupBox_Connect.Enabled = false;
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
RecordWriter?.Close();
RecordWriter = null;
}
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
if (openFileDialog_Open.ShowDialog() != DialogResult.OK) return;
Record w = new Record();
w.RecordFile = openFileDialog_Open.FileName;
w.Show();
}
private void folderToolStripMenuItem_Click(object sender, EventArgs e)
{
try { Process.Start(RecordsFolder); }
catch { MessageBox.Show("No records!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); }
}
private void numericUpDown_Graph_MaxY_ValueChanged(object sender, EventArgs e)
{
chart_Graph.ChartAreas[0].AxisY.Minimum = (double)numericUpDown_Graph_MinY.Value;
chart_Graph.ChartAreas[0].AxisY.Maximum = (double)numericUpDown_Graph_MaxY.Value;
trackBar_GraphY_Left.Maximum = (int)numericUpDown_Graph_MaxY.Value;
trackBar_GraphY_Left.Minimum = (int)numericUpDown_Graph_MinY.Value;
trackBar_GraphY_Right.Maximum = (int)numericUpDown_Graph_MaxY.Value;
trackBar_GraphY_Right.Minimum = (int)numericUpDown_Graph_MinY.Value;
}
private void checkBox_AutoY_CheckedChanged(object sender, EventArgs e)
{
if (checkBox_AutoY.Checked)
{
chart_Graph.ChartAreas[0].AxisY.Minimum = double.NaN;
chart_Graph.ChartAreas[0].AxisY.Maximum = double.NaN;
numericUpDown_Graph_MinY.Enabled = false;
numericUpDown_Graph_MaxY.Enabled = false;
panel_GraphY.Enabled = false;
}
else
{
numericUpDown_Graph_MaxY_ValueChanged(null, null);
numericUpDown_Graph_MinY.Enabled = true;
numericUpDown_Graph_MaxY.Enabled = true;
panel_GraphY.Enabled = true;
trackBar_GraphY_Left.Value = trackBar_GraphY_Left.Minimum;
trackBar_GraphY_Right.Value = trackBar_GraphY_Right.Maximum;
}
}
private void trackBar_GraphY_Left_Scroll(object sender, EventArgs e)
{
int min = trackBar_GraphY_Left.Value;
int max = trackBar_GraphY_Right.Value;
if (min > max)
{
int sub = min;
min = max;
max = sub;
}
if (max == min) max += 1;
chart_Graph.ChartAreas[0].AxisY.Minimum = min;
chart_Graph.ChartAreas[0].AxisY.Maximum = max;
}
private void checkedListBox_Series_SelectedIndexChanged(object sender, EventArgs e)
{
if (checkedListBox_Series.SelectedIndex == -1) return;
int index = checkedListBox_Series.SelectedIndex;
button_Color.BackColor = chart_Graph.Series[index].Color;
//---
for (int a = 0; a < checkedListBox_Series.Items.Count; a++)
{
chart_Graph.Series[a].Enabled = checkedListBox_Series.GetItemChecked(a);
}
}
}
}