diff --git a/头罩视野slove/头罩视野/Views/PageTest.xaml.cs b/头罩视野slove/头罩视野/Views/PageTest.xaml.cs index c0c9557..6bfe551 100644 --- a/头罩视野slove/头罩视野/Views/PageTest.xaml.cs +++ b/头罩视野slove/头罩视野/Views/PageTest.xaml.cs @@ -402,7 +402,6 @@ namespace 头罩视野.Views //计算 private async Task calCurrentangle() { - await ReadLightBarData(); int[] lightData; @@ -417,125 +416,70 @@ namespace 头罩视野.Views return; } - // 打印原始数据(假设灯条顺序:上81,中81,下81) - void PrintSegment(int[] data, int start, int length, string title) - { - int end = Math.Min(start + length, data.Length); - var values = data.Skip(start).Take(end - start).ToArray(); - string first20 = string.Join("", values.Take(20)); - string last20 = string.Join("", values.Skip(Math.Max(0, values.Length - 20)).Take(20)); - System.Diagnostics.Debug.WriteLine($"{title} (共{values.Length}个): 前20:{first20} ... 后20:{last20}"); - } - - System.Diagnostics.Debug.WriteLine("=== 原始灯条数据 ==="); - PrintSegment(lightData, 0, 81, "上爪灯条"); - PrintSegment(lightData, 81, 81, "下爪灯条"); - PrintSegment(lightData, 162, 81, "左右灯条"); - double singleArea = GetArea.CalculateEllipseArea(lightData, _lightPositions); - double bottomViewAngle; + double bottomViewAngle = GetArea.CalculateBottomViewAngle(lightData, _lightPositions); - if (tbTest.Content.ToString() == "试样测试") + System.Diagnostics.Debug.WriteLine($"角度: {dqangle.Text}, singleArea={singleArea}, bottomViewAngle={bottomViewAngle}"); + + // 5. 根据当前测试模式(左眼/右眼/双目),累加面积 + if (isLeftOnly) { - // 修正下爪灯条:填充空洞使连续 - int startIdx = 81; - int endIdx = startIdx + 81; - int firstOne = -1, lastOne = -1; - for (int i = startIdx; i < endIdx; i++) + //System.Diagnostics.Debug.WriteLine($"lightData 实际长度: {lightData.Length}"); + _leftTotalArea += singleArea; + // 实时合并左眼:只要亮过一次,就永久亮 + + // 安全获取真实长度 + int realLength = lightData.Length; + + // 初始化最终数据(永远和 lightData 一样长,不会错) + if (_leftFinalData == null || _leftFinalData.Count != realLength) + { + _leftFinalData = new List(new int[realLength]); + } + + for (int i = 0; i < realLength; i++) { if (lightData[i] == 1) { - if (firstOne == -1) firstOne = i; - lastOne = i; + _leftFinalData[i] = 1; } } - if (firstOne != -1 && lastOne != -1) - { - for (int i = firstOne; i <= lastOne; i++) - lightData[i] = 1; - } - PrintSegment(lightData, 81, 81, "修正后的下爪灯条"); - - // 计算亮灯比例 - int bottomLampCount = 0; - for (int i = startIdx; i < endIdx; i++) - if (lightData[i] == 1) bottomLampCount++; - double ratio = bottomLampCount / 81.0; - bottomViewAngle = 90.0 * ratio; - // 可选钳位 - // if (bottomViewAngle < 52) bottomViewAngle = 52; - // if (bottomViewAngle > 60) bottomViewAngle = 60; } - else + + else if (isRightOnly) { - bottomViewAngle = GetArea.CalculateBottomViewAngle(lightData, _lightPositions); + _rightTotalArea += singleArea; + int realLength = lightData.Length; - - - - - System.Diagnostics.Debug.WriteLine($"角度: {dqangle.Text}, singleArea={singleArea}, bottomViewAngle={bottomViewAngle}"); - - // 5. 根据当前测试模式(左眼/右眼/双目),累加面积 - if (isLeftOnly) + if (_rightFinalData == null || _rightFinalData.Count != realLength) { - //System.Diagnostics.Debug.WriteLine($"lightData 实际长度: {lightData.Length}"); - _leftTotalArea += singleArea; - // 实时合并左眼:只要亮过一次,就永久亮 - - // 安全获取真实长度 - int realLength = lightData.Length; - - // 初始化最终数据(永远和 lightData 一样长,不会错) - if (_leftFinalData == null || _leftFinalData.Count != realLength) - { - _leftFinalData = new List(new int[realLength]); - } - - for (int i = 0; i < realLength; i++) - { - if (lightData[i] == 1) - { - _leftFinalData[i] = 1; - } - } - + _rightFinalData = new List(new int[realLength]); } - else if (isRightOnly) + for (int i = 0; i < realLength; i++) { - _rightTotalArea += singleArea; - int realLength = lightData.Length; - - if (_rightFinalData == null || _rightFinalData.Count != realLength) + if (lightData[i] == 1) { - _rightFinalData = new List(new int[realLength]); - } - - for (int i = 0; i < realLength; i++) - { - if (lightData[i] == 1) - { - _rightFinalData[i] = 1; - } + _rightFinalData[i] = 1; } } - - // 6. 更新下方视野的最大值(取所有角度中最大的) - if (bottomViewAngle > maxBottomViewAngle) - maxBottomViewAngle = bottomViewAngle; - - await Dispatcher.InvokeAsync(() => - { - zmsyarea.Text = _leftTotalArea.ToString("0"); - ymsyarea.Text = _rightTotalArea.ToString("0"); - smsyarea.Text = _binocularTotalArea.ToString("0"); - xfsyarea.Text = maxBottomViewAngle.ToString("0"); - }); } + + // 6. 更新下方视野的最大值(取所有角度中最大的) + if (bottomViewAngle > maxBottomViewAngle) + maxBottomViewAngle = bottomViewAngle; + + await Dispatcher.InvokeAsync(() => + { + zmsyarea.Text = _leftTotalArea.ToString("0"); + ymsyarea.Text = _rightTotalArea.ToString("0"); + smsyarea.Text = _binocularTotalArea.ToString("0"); + xfsyarea.Text = maxBottomViewAngle.ToString("0"); + }); } + //数据共享 private async void ShowAreaData() @@ -946,7 +890,7 @@ namespace 头罩视野.Views _timer?.Stop(); _cts?.Cancel(); _cts = null; - + CloseSerialModbus(); // 释放串口 _modbusMaster.WriteSingleCoil(1, 1, false); _modbusMaster.WriteSingleCoil(1, 0, false); @@ -956,112 +900,125 @@ namespace 头罩视野.Views private IModbusMaster _serialMaster; + private SerialPort _serialPort; // 保存串口对象以便关闭 + private bool _isSerialInitialized = false; private void InitSerialModbus() { + if (_isSerialInitialized) return; // 已初始化,不再重复 + try { - // 请根据实际 COM 口和参数修改 - string portName = "COM3"; // 实际串口号 + string portName = "COM3"; int baudRate = 9600; Parity parity = Parity.None; int dataBits = 8; StopBits stopBits = StopBits.One; - var serialPort = new SerialPort(portName, baudRate, parity, dataBits, stopBits); - if (!serialPort.IsOpen) - serialPort.Open(); + _serialPort = new SerialPort(portName, baudRate, parity, dataBits, stopBits); + _serialPort.Open(); - _serialMaster = ModbusSerialMaster.CreateRtu(serialPort); - - // 推荐加上超时,避免卡死 + _serialMaster = ModbusSerialMaster.CreateRtu(_serialPort); _serialMaster.Transport.Retries = 2; - _serialMaster.Transport.ReadTimeout = 500; - _serialMaster.Transport.WriteTimeout = 500; + _serialMaster.Transport.ReadTimeout = 1000; + _serialMaster.Transport.WriteTimeout = 1000; + _isSerialInitialized = true; System.Diagnostics.Debug.WriteLine($"RS485 串口 {portName} 初始化成功"); } catch (Exception ex) { - Console.WriteLine($"串口初始化失败:{ex.Message}"); + System.Diagnostics.Debug.WriteLine($"串口初始化失败:{ex.Message}"); + _serialMaster = null; + _isSerialInitialized = false; } } + private void CloseSerialModbus() + { + try + { + _serialMaster?.Dispose(); + _serialPort?.Close(); + _serialPort?.Dispose(); + } + catch { } + _serialMaster = null; + _serialPort = null; + _isSerialInitialized = false; + } + private async Task ReadLightBarData() { - // ===================== 最小修改,不丢次 ===================== - if (_serialMaster == null) + // 如果未初始化,则初始化 + if (!_isSerialInitialized || _serialMaster == null) { - InitSerialModbus(); // 立即初始化,不跳过本次 + InitSerialModbus(); + if (_serialMaster == null) return; } - if (_serialMaster == null) return; // 真的失败才退出 - // ========================================================== try { byte slaveId = 1; - var allLights = new List(); - // 通道一:10001~10081 + // 通道一:上爪灯条 bool[] ch1 = await _serialMaster.ReadInputsAsync(slaveId, 0, 81); + int ch1OnCount = ch1.Count(b => b); + System.Diagnostics.Debug.WriteLine($"通道一(上爪)亮灯数: {ch1OnCount}/81"); allLights.AddRange(ch1.Select(b => b ? 1 : 0)); - // 通道二:10097~10177 + // 通道二:下爪灯条 bool[] ch2 = await _serialMaster.ReadInputsAsync(slaveId, 96, 81); + int ch2OnCount = ch2.Count(b => b); + System.Diagnostics.Debug.WriteLine($"通道二(下爪)亮灯数: {ch2OnCount}/81"); allLights.AddRange(ch2.Select(b => b ? 1 : 0)); - // 通道三 + // 通道三:水平灯条分段 bool[] s1 = await _serialMaster.ReadInputsAsync(slaveId, 192, 8); - bool[] s2 = await _serialMaster.ReadInputsAsync(slaveId, 208, 16); - bool[] s3 = await _serialMaster.ReadInputsAsync(slaveId, 224, 16); - bool[] s4 = await _serialMaster.ReadInputsAsync(slaveId, 240, 1); - bool[] s5 = await _serialMaster.ReadInputsAsync(slaveId, 256, 16); - bool[] s6 = await _serialMaster.ReadInputsAsync(slaveId, 272, 16); - bool[] s7 = await _serialMaster.ReadInputsAsync(slaveId, 288, 8); - allLights.AddRange(s1.Select(b => b ? 1 : 0)); + bool[] s2 = await _serialMaster.ReadInputsAsync(slaveId, 208, 16); allLights.AddRange(s2.Select(b => b ? 1 : 0)); + bool[] s3 = await _serialMaster.ReadInputsAsync(slaveId, 224, 16); allLights.AddRange(s3.Select(b => b ? 1 : 0)); + bool[] s4 = await _serialMaster.ReadInputsAsync(slaveId, 240, 1); allLights.AddRange(s4.Select(b => b ? 1 : 0)); + bool[] s5 = await _serialMaster.ReadInputsAsync(slaveId, 256, 16); allLights.AddRange(s5.Select(b => b ? 1 : 0)); + bool[] s6 = await _serialMaster.ReadInputsAsync(slaveId, 272, 16); allLights.AddRange(s6.Select(b => b ? 1 : 0)); + bool[] s7 = await _serialMaster.ReadInputsAsync(slaveId, 288, 8); allLights.AddRange(s7.Select(b => b ? 1 : 0)); - int total = 81 + 81 + 8 + 16 + 16 + 1 + 16 + 16 + 8; - if (allLights.Count != total) - { - System.Diagnostics.Debug.WriteLine($"灯条数据总数错误:{allLights.Count},预期 {total}"); - } + int ch3Total = allLights.Skip(162).Count(b => b == 1); // 通道三从索引162开始 + System.Diagnostics.Debug.WriteLine($"通道三(水平)总亮灯数: {ch3Total}/81"); lock (_lock) { DataList.Clear(); - if (tbTest.Content.ToString()=="空白测试") + if (tbTest.Content.ToString() == "空白测试") { - allLights.ForEach(s => - { - int item = 1; - DataList.Add(item); - }); + // 空白测试强制全亮 + for (int i = 0; i < allLights.Count; i++) + allLights[i] = 1; } DataList.AddRange(allLights.Cast()); } int onCount = DataList.Count(s => s == 1); - System.Diagnostics.Debug.WriteLine($"当前亮灯数量:{onCount}"); + System.Diagnostics.Debug.WriteLine($"当前总亮灯数量:{onCount}"); } catch (Exception ex) { - Console.WriteLine($"灯条数据读取失败:{ex.Message}"); - System.Diagnostics.Debug.WriteLine(ex.StackTrace); + System.Diagnostics.Debug.WriteLine($"灯条数据读取失败:{ex.Message}"); + // 出错后关闭并重新初始化串口 + CloseSerialModbus(); + InitSerialModbus(); } } - - } }