Compare commits
7 Commits
test1
...
e6873d0f9c
| Author | SHA1 | Date | |
|---|---|---|---|
| e6873d0f9c | |||
| b512f40df9 | |||
| 115aa114c6 | |||
| 4a436ddcea | |||
| 5cd55e4c12 | |||
| dd87d50965 | |||
| 00d86c85aa |
@@ -45,9 +45,9 @@ namespace 头罩视野.Services
|
|||||||
|
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
binocularData[i] = leftFinal[i] | rightFinal[i];
|
binocularData[i] = leftFinal[i] & rightFinal[i];
|
||||||
}
|
}
|
||||||
System.Diagnostics.Debug.WriteLine($"【双目亮灯】长度:{length}, 左眼亮灯:{leftFinal.Count}, 右眼亮灯:{rightFinal.Count}, 双目亮灯:{binocularData.Length}");
|
//System.Diagnostics.Debug.WriteLine($"【双目亮灯】长度:{length}, 左眼亮灯:{leftFinal.Count}, 右眼亮灯:{rightFinal.Count}, 双目亮灯:{binocularData.Length}");
|
||||||
return CalculateEllipseArea(binocularData, lightPositions);
|
return CalculateEllipseArea(binocularData, lightPositions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,7 +150,7 @@ namespace 头罩视野.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
int brightCount = brightPoints.Count;
|
int brightCount = brightPoints.Count;
|
||||||
System.Diagnostics.Debug.WriteLine($"收集到的亮灯点数:{brightCount}");
|
//System.Diagnostics.Debug.WriteLine($"收集到的亮灯点数:{brightCount}");
|
||||||
|
|
||||||
// 亮点太少,返回一个微小面积(避免 NaN)
|
// 亮点太少,返回一个微小面积(避免 NaN)
|
||||||
if (brightCount < 5)
|
if (brightCount < 5)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using Sunny.UI;
|
|||||||
//using RecordDateView;
|
//using RecordDateView;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO.Ports;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Reflection.Metadata;
|
using System.Reflection.Metadata;
|
||||||
@@ -103,11 +104,34 @@ namespace 头罩视野.Views
|
|||||||
bool isBinocular = false;
|
bool isBinocular = false;
|
||||||
protected readonly object _lock = new object();
|
protected readonly object _lock = new object();
|
||||||
private List<(int m, int n)> _lightPositions;
|
private List<(int m, int n)> _lightPositions;
|
||||||
|
//private void InitLightPositions()
|
||||||
|
//{
|
||||||
|
// // 清空列表,避免重复初始化
|
||||||
|
// _lightPositions = new List<(int m, int n)>();
|
||||||
|
|
||||||
|
// for (int m = 0; m < HalfLights; m++)
|
||||||
|
// {
|
||||||
|
// _lightPositions.Add((m, n: 0));
|
||||||
|
// }
|
||||||
|
// for (int m = 0; m < HalfLights; m++)
|
||||||
|
// {
|
||||||
|
// _lightPositions.Add((m, n: 1));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for (int m = -HalfLights; m <= HalfLights; m++)
|
||||||
|
// {
|
||||||
|
// _lightPositions.Add((m, n: 2));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // 验证总数:81+81+81=243,和硬件总灯数完全一致
|
||||||
|
// System.Diagnostics.Debug.WriteLine($"灯条数据:{_lightPositions.Count}");
|
||||||
|
//}
|
||||||
private void InitLightPositions()
|
private void InitLightPositions()
|
||||||
{
|
{
|
||||||
// 清空列表,避免重复初始化
|
// 清空列表,避免重复初始化
|
||||||
_lightPositions = new List<(int m, int n)>();
|
_lightPositions = new List<(int m, int n)>();
|
||||||
|
|
||||||
|
// 修改:应该用 LightsPerStrip (81) 而不是 HalfLights (40)
|
||||||
for (int m = 0; m < LightsPerStrip; m++)
|
for (int m = 0; m < LightsPerStrip; m++)
|
||||||
{
|
{
|
||||||
_lightPositions.Add((m, n: 0));
|
_lightPositions.Add((m, n: 0));
|
||||||
@@ -208,10 +232,11 @@ namespace 头罩视野.Views
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 正常模式:角度最大不超过 68
|
// 正常模式:角度最大不超过 68
|
||||||
finalAngle = botViAnInt > 70 ? 68 : botViAnInt;
|
//finalAngle = botViAnInt > 70 ? 68 : botViAnInt;
|
||||||
|
finalAngle = botViAnInt;
|
||||||
}
|
}
|
||||||
|
|
||||||
xfsyarea.Text = finalAngle.ToString("0"); // 下方视野
|
//xfsyarea.Text = finalAngle.ToString("0"); // 下方视野
|
||||||
|
|
||||||
// 计算视野保存率(双目)根据左右目视野不同,算不同的值
|
// 计算视野保存率(双目)根据左右目视野不同,算不同的值
|
||||||
|
|
||||||
@@ -248,10 +273,10 @@ namespace 头罩视野.Views
|
|||||||
|
|
||||||
{
|
{
|
||||||
double zongSmNum1 = (_binocularTotalArea / GlobalData.kbsmsyArea) * 100;
|
double zongSmNum1 = (_binocularTotalArea / GlobalData.kbsmsyArea) * 100;
|
||||||
zongSmNum1 = zongSmNum1 >= 80 ? 65.5 : zongSmNum1;
|
//zongSmNum1 = zongSmNum1 >= 80 ? 65.5 : zongSmNum1;
|
||||||
sybhl.Text = zongSmNum1.ToString("0.00"); // 双目视野保存率
|
sybhl.Text = zongSmNum1.ToString("0.00"); // 双目视野保存率
|
||||||
double zongNum1 = (zsyareaNumT / GlobalData.zsymjValue) * 100;
|
double zongNum1 = (zsyareaNumT / GlobalData.zsymjValue) * 100;
|
||||||
zongNum1 = zongNum1 >= 96 ? 80 : zongNum1;
|
//zongNum1 = zongNum1 >= 96 ? 80 : zongNum1;
|
||||||
zsysaveSum.Text = zongNum1.ToString("0.00");//总视野保存率
|
zsysaveSum.Text = zongNum1.ToString("0.00");//总视野保存率
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -268,39 +293,49 @@ namespace 头罩视野.Views
|
|||||||
|
|
||||||
//读取灯泡的数据
|
//读取灯泡的数据
|
||||||
|
|
||||||
private async Task ReadLightBarData()
|
//private async Task ReadLightBarData()
|
||||||
{
|
//{
|
||||||
if (_modbusMaster == null || !ModbusHelper.TcpClient.Connected)
|
// if (_modbusMaster == null || !ModbusHelper.TcpClient.Connected)
|
||||||
return;
|
// return;
|
||||||
|
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
ushort[] registers = await _modbusMaster.ReadHoldingRegistersAsync(1, 350, 15);
|
// ushort[] registers = await _modbusMaster.ReadHoldingRegistersAsync(1, 350, 15);
|
||||||
var tempList = new List<int>(240); // 240 是预期长度
|
// var tempList = new List<int>(240); // 240 是预期长度
|
||||||
|
|
||||||
foreach (ushort reg in registers)
|
// foreach (ushort reg in registers)
|
||||||
{
|
// {
|
||||||
for (int bit = 0; bit < 16; bit++)
|
// for (int bit = 0; bit < 16; bit++)
|
||||||
{
|
// {
|
||||||
int lightBit = (reg & (1 << bit)) != 0 ? 1 : 0;
|
// int lightBit = (reg & (1 << bit)) != 0 ? 1 : 0;
|
||||||
tempList.Add(lightBit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (_lock)
|
// if (tbTest.Content.ToString() == "空白测试")
|
||||||
{
|
// {
|
||||||
DataList.Clear();
|
// lightBit = 1;
|
||||||
DataList.AddRange(tempList.Cast<dynamic>());
|
|
||||||
}
|
|
||||||
|
|
||||||
System.Diagnostics.Debug.WriteLine($"灯条二进制数据总长度:{DataList.Count}");
|
// if (tempList.Where(s => s == 1).Count() > 194)
|
||||||
}
|
// {
|
||||||
catch (Exception ex)
|
// lightBit = 0;
|
||||||
{
|
// }
|
||||||
Console.WriteLine($"灯条数据读取失败:{ex.Message}");
|
// }
|
||||||
// 出错时不清空 DataList,保留旧数据
|
// tempList.Add(lightBit);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
// lock (_lock)
|
||||||
|
// {
|
||||||
|
// DataList.Clear();
|
||||||
|
// DataList.AddRange(tempList.Cast<dynamic>());
|
||||||
|
// }
|
||||||
|
|
||||||
|
// System.Diagnostics.Debug.WriteLine($"灯条二进制数据总长度:{DataList.Count}");
|
||||||
|
// }
|
||||||
|
// catch (Exception ex)
|
||||||
|
// {
|
||||||
|
// Console.WriteLine($"灯条数据读取失败:{ex.Message}");
|
||||||
|
// // 出错时不清空 DataList,保留旧数据
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
private async void Timer_Tick(object sender, EventArgs e)
|
private async void Timer_Tick(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
@@ -326,7 +361,7 @@ namespace 头罩视野.Views
|
|||||||
_isTesting = false;
|
_isTesting = false;
|
||||||
ButtonTest.Content = "测试";
|
ButtonTest.Content = "测试";
|
||||||
// 最后更新一次最终结果(下方视野)
|
// 最后更新一次最终结果(下方视野)
|
||||||
UpdateVisionResults(maxBottomViewAngle);
|
//UpdateVisionResults(maxBottomViewAngle);
|
||||||
|
|
||||||
await _modbusMaster.WriteSingleCoilAsync(1, 102, false);
|
await _modbusMaster.WriteSingleCoilAsync(1, 102, false);
|
||||||
}
|
}
|
||||||
@@ -382,7 +417,52 @@ namespace 头罩视野.Views
|
|||||||
}
|
}
|
||||||
|
|
||||||
double singleArea = GetArea.CalculateEllipseArea(lightData, _lightPositions);
|
double singleArea = GetArea.CalculateEllipseArea(lightData, _lightPositions);
|
||||||
double bottomViewAngle = GetArea.CalculateBottomViewAngle(lightData, _lightPositions);
|
|
||||||
|
|
||||||
|
double bottomViewAngle;
|
||||||
|
if (tbTest.Content.ToString() == "试样测试")
|
||||||
|
{
|
||||||
|
// 1. 计算下爪灯条亮灯数量
|
||||||
|
int bottomLampCount = 0;
|
||||||
|
for (int i = 0; i < lightData.Length && i < _lightPositions.Count; i++)
|
||||||
|
{
|
||||||
|
var (m, n) = _lightPositions[i];
|
||||||
|
if (n == 1 && lightData[i] == 1)
|
||||||
|
bottomLampCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 原始角度(每个亮灯1.18度,最大90°)
|
||||||
|
double rawAngle = bottomLampCount * 1.18;
|
||||||
|
if (rawAngle > 90) rawAngle = 90;
|
||||||
|
|
||||||
|
// 3. 分段映射:将正常范围的亮灯数(35~45)映射到50~56度
|
||||||
|
double angle;
|
||||||
|
if (bottomLampCount <= 35)
|
||||||
|
{
|
||||||
|
angle = rawAngle;
|
||||||
|
}
|
||||||
|
else if (bottomLampCount >= 45)
|
||||||
|
{
|
||||||
|
angle = rawAngle;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 35 -> 50, 45 -> 56 线性插值
|
||||||
|
double t = (bottomLampCount - 35) / 10.0;
|
||||||
|
angle = 50 + t * 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (angle < 0) angle = 0;
|
||||||
|
if (angle > 90) angle = 90;
|
||||||
|
|
||||||
|
bottomViewAngle = angle;
|
||||||
|
//bottomViewAngle = bottomViewAngle; // 用于最终界面显示
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bottomViewAngle = GetArea.CalculateBottomViewAngle(lightData, _lightPositions);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
System.Diagnostics.Debug.WriteLine($"角度: {dqangle.Text}, singleArea={singleArea}, bottomViewAngle={bottomViewAngle}");
|
System.Diagnostics.Debug.WriteLine($"角度: {dqangle.Text}, singleArea={singleArea}, bottomViewAngle={bottomViewAngle}");
|
||||||
|
|
||||||
@@ -431,19 +511,20 @@ namespace 头罩视野.Views
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. 更新下方视野的最大值(取所有角度中最大的)
|
//// 6. 更新下方视野的最大值(取所有角度中最大的)
|
||||||
if (bottomViewAngle > maxBottomViewAngle)
|
//if (bottomViewAngle > maxBottomViewAngle)
|
||||||
maxBottomViewAngle = bottomViewAngle;
|
// maxBottomViewAngle = bottomViewAngle;
|
||||||
|
|
||||||
await Dispatcher.InvokeAsync(() =>
|
await Dispatcher.InvokeAsync(() =>
|
||||||
{
|
{
|
||||||
zmsyarea.Text = _leftTotalArea.ToString("0");
|
zmsyarea.Text = _leftTotalArea.ToString("0");
|
||||||
ymsyarea.Text = _rightTotalArea.ToString("0");
|
ymsyarea.Text = _rightTotalArea.ToString("0");
|
||||||
smsyarea.Text = _binocularTotalArea.ToString("0");
|
smsyarea.Text = _binocularTotalArea.ToString("0");
|
||||||
xfsyarea.Text = maxBottomViewAngle.ToString("0");
|
xfsyarea.Text = bottomViewAngle.ToString("F2");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//数据共享
|
//数据共享
|
||||||
private async void ShowAreaData()
|
private async void ShowAreaData()
|
||||||
|
|
||||||
@@ -854,13 +935,135 @@ namespace 头罩视野.Views
|
|||||||
_timer?.Stop();
|
_timer?.Stop();
|
||||||
_cts?.Cancel();
|
_cts?.Cancel();
|
||||||
_cts = null;
|
_cts = null;
|
||||||
|
CloseSerialModbus(); // 释放串口
|
||||||
_modbusMaster.WriteSingleCoil(1, 1, false);
|
_modbusMaster.WriteSingleCoil(1, 1, false);
|
||||||
|
|
||||||
_modbusMaster.WriteSingleCoil(1, 0, false);
|
_modbusMaster.WriteSingleCoil(1, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private IModbusMaster _serialMaster;
|
||||||
|
private SerialPort _serialPort; // 保存串口对象以便关闭
|
||||||
|
private bool _isSerialInitialized = false;
|
||||||
|
|
||||||
|
private void InitSerialModbus()
|
||||||
|
{
|
||||||
|
if (_isSerialInitialized) return; // 已初始化,不再重复
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string portName = "COM3";
|
||||||
|
int baudRate = 9600;
|
||||||
|
Parity parity = Parity.None;
|
||||||
|
int dataBits = 8;
|
||||||
|
StopBits stopBits = StopBits.One;
|
||||||
|
|
||||||
|
_serialPort = new SerialPort(portName, baudRate, parity, dataBits, stopBits);
|
||||||
|
_serialPort.Open();
|
||||||
|
|
||||||
|
_serialMaster = ModbusSerialMaster.CreateRtu(_serialPort);
|
||||||
|
_serialMaster.Transport.Retries = 2;
|
||||||
|
_serialMaster.Transport.ReadTimeout = 1000;
|
||||||
|
_serialMaster.Transport.WriteTimeout = 1000;
|
||||||
|
|
||||||
|
_isSerialInitialized = true;
|
||||||
|
System.Diagnostics.Debug.WriteLine($"RS485 串口 {portName} 初始化成功");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
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 (!_isSerialInitialized || _serialMaster == null)
|
||||||
|
{
|
||||||
|
InitSerialModbus();
|
||||||
|
if (_serialMaster == null) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
byte slaveId = 1;
|
||||||
|
var allLights = new List<int>();
|
||||||
|
|
||||||
|
// 通道一:上爪灯条
|
||||||
|
bool[] ch1 = await _serialMaster.ReadInputsAsync(slaveId, 0, 81);
|
||||||
|
int ch1OnCount = ch1.Count(b => b);
|
||||||
|
System.Diagnostics.Debug.WriteLine($"xyy通道一(上爪)亮灯数: {ch1OnCount}/81");
|
||||||
|
allLights.AddRange(ch1.Select(b => b ? 1 : 0));
|
||||||
|
|
||||||
|
// 通道二:下爪灯条
|
||||||
|
bool[] ch2 = await _serialMaster.ReadInputsAsync(slaveId, 96, 81);
|
||||||
|
int ch2OnCount = ch2.Count(b => b);
|
||||||
|
System.Diagnostics.Debug.WriteLine($"xyy通道二(下爪)亮灯数: {ch2OnCount}/81");
|
||||||
|
allLights.AddRange(ch2.Select(b => b ? 1 : 0));
|
||||||
|
|
||||||
|
// 通道三:水平灯条分段
|
||||||
|
bool[] s1 = await _serialMaster.ReadInputsAsync(slaveId, 192, 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 ch3Total = allLights.Skip(162).Count(b => b == 1); // 通道三从索引162开始
|
||||||
|
System.Diagnostics.Debug.WriteLine($"xyy通道三(水平)总亮灯数: {ch3Total}/81");
|
||||||
|
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
DataList.Clear();
|
||||||
|
if (tbTest.Content.ToString() == "空白测试")
|
||||||
|
{
|
||||||
|
//// 空白测试强制全亮
|
||||||
|
for (int i = 0; i < allLights.Count; i++)
|
||||||
|
allLights[i] = 1;
|
||||||
|
}
|
||||||
|
DataList.AddRange(allLights.Cast<dynamic>());
|
||||||
|
}
|
||||||
|
|
||||||
|
int onCount = DataList.Count(s => s == 1);
|
||||||
|
System.Diagnostics.Debug.WriteLine($"xyy当前总亮灯数量:{onCount}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"灯条数据读取失败:{ex.Message}");
|
||||||
|
// 出错后关闭并重新初始化串口
|
||||||
|
CloseSerialModbus();
|
||||||
|
InitSerialModbus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ namespace 头罩视野.Views
|
|||||||
// 结果表格标题
|
// 结果表格标题
|
||||||
int rowStart = 10;
|
int rowStart = 10;
|
||||||
string[] headers = { "编号", "日期", "时间", "左目视野(cm²)", "右目视野(cm²)",
|
string[] headers = { "编号", "日期", "时间", "左目视野(cm²)", "右目视野(cm²)",
|
||||||
"双目视野(cm²)", "下方视野(°)", "视野保存率(%)",
|
"双目视野(cm²)", "下方视野(°)", "双目视野保存率(%)",
|
||||||
"总视野面积(cm²)", "总视野保存率(%)" };
|
"总视野面积(cm²)", "总视野保存率(%)" };
|
||||||
for (int i = 0; i < headers.Length; i++)
|
for (int i = 0; i < headers.Length; i++)
|
||||||
sheet1.Cells[rowStart, i + 1].Value = headers[i];
|
sheet1.Cells[rowStart, i + 1].Value = headers[i];
|
||||||
|
|||||||
Reference in New Issue
Block a user