795 lines
31 KiB
C#
795 lines
31 KiB
C#
using Modbus.Device;
|
||
using Sunny.UI;
|
||
using System;
|
||
using System.ComponentModel;
|
||
using System.Configuration;
|
||
using System.Diagnostics;
|
||
using System.IO;
|
||
using System.Net.Sockets;
|
||
using System.Threading;
|
||
using System.Windows;
|
||
using System.Windows.Controls;
|
||
using System.Windows.Media;
|
||
using System.Windows.Threading;
|
||
using 滑动摩擦测试仪;
|
||
|
||
namespace PLCDataMonitor
|
||
{
|
||
public partial class MainWindow : Window, INotifyPropertyChanged
|
||
{
|
||
// 数据属性
|
||
private Brush _statusColor;
|
||
private string _connectionStatus;
|
||
string _plcIpAddress = string.Empty;
|
||
int _plcPort = 502;
|
||
private bool _isConnected;
|
||
private Thread _readThread;
|
||
private bool _keepReading;
|
||
private Function ma;
|
||
private DataChange c = new DataChange();
|
||
|
||
// 关键修改:创建一个共享的线程安全数据队列
|
||
private System.Collections.Concurrent.ConcurrentQueue<Tuple<DateTime, double, double>> _sharedCurveDataQueue = new System.Collections.Concurrent.ConcurrentQueue<Tuple<DateTime, double, double>>();
|
||
|
||
// 页面实例
|
||
private HomePage _homePage;
|
||
private ReportPage _reportPage;
|
||
private CurvePage _curvePage;
|
||
|
||
// 属性更改通知事件
|
||
public event PropertyChangedEventHandler PropertyChanged;
|
||
|
||
private TcpClient _tcpClient;
|
||
private IModbusMaster _modbusMaster;
|
||
|
||
|
||
// 暂停控制(HR500.04)
|
||
private const int PauseControlCoil = 41204; // 写入 true=暂停,false=继续
|
||
private const int PauseStatusCoil = 41204; // 读取当前暂停状态(同一地址)
|
||
|
||
|
||
// 记录暂停时间段(用于导出过滤)
|
||
private List<(DateTime start, DateTime end)> _pausePeriods = new List<(DateTime, DateTime)>();
|
||
private bool _lastPausedState = false; // 上一次读取的暂停状态
|
||
private DateTime _pauseStartTime; // 本次暂停开始时间
|
||
|
||
public List<(DateTime start, DateTime end)> PausePeriods => _pausePeriods;
|
||
|
||
|
||
|
||
|
||
// 【新增】用于记录净运行时间的秒表
|
||
private System.Diagnostics.Stopwatch _testStopwatch = new System.Diagnostics.Stopwatch();
|
||
// 【新增】用于检测新一轮测试开始
|
||
private int _lastActualCount = 0;
|
||
private int _lastSetCount = 0;
|
||
|
||
|
||
// 添加清空方法
|
||
public void ClearPausePeriods()
|
||
{
|
||
_pausePeriods.Clear();
|
||
_lastPausedState = false;
|
||
_pauseStartTime = default;
|
||
}
|
||
|
||
|
||
// 连接状态属性
|
||
public Brush StatusColor
|
||
{
|
||
get { return _statusColor; }
|
||
set { _statusColor = value; OnPropertyChanged(nameof(StatusColor)); }
|
||
}
|
||
|
||
public string ConnectionStatus
|
||
{
|
||
get { return _connectionStatus; }
|
||
set { _connectionStatus = value; OnPropertyChanged(nameof(ConnectionStatus)); }
|
||
}
|
||
|
||
// 报表相关:记录是否已插入当前批次报表(避免重复插入)
|
||
public bool _hasInsertedReport = false;
|
||
|
||
public MainWindow()
|
||
{
|
||
InitializeComponent();
|
||
DataContext = this;
|
||
|
||
// 初始化状态
|
||
StatusColor = Brushes.Red;
|
||
ConnectionStatus = "未连接";
|
||
|
||
_homePage = new HomePage();
|
||
|
||
|
||
// 订阅暂停/继续事件
|
||
_homePage.PauseRequested += (s, e) => SendPauseCommand();
|
||
_homePage.ResumeRequested += (s, e) => SendResumeCommand();
|
||
|
||
|
||
// 关键修改:创建报表页时传入共享队列
|
||
_reportPage = new ReportPage();
|
||
_reportPage.CurveDataQueue = _sharedCurveDataQueue;
|
||
|
||
// 关键修改:创建曲线页时传入同一个共享队列
|
||
_curvePage = new CurvePage(_sharedCurveDataQueue);
|
||
|
||
// 默认显示数据监控页
|
||
MainContentFrame.Navigate(_homePage);
|
||
|
||
SetupLogging();
|
||
|
||
_reportPage.OnExportCompleted += () =>
|
||
{
|
||
_hasInsertedReport = false; // 重置插入标记
|
||
};
|
||
|
||
|
||
|
||
// 设置IP和端口显示
|
||
string ip = ConfigurationManager.AppSettings["PLC_IP"];
|
||
string port = ConfigurationManager.AppSettings["PLC_PORT"];
|
||
TxtPLCIPValue.Text = string.IsNullOrEmpty(ip) ? "192.168.1.170" : ip;
|
||
TxtPLCPortValue.Text = string.IsNullOrEmpty(port) ? "502" : port;
|
||
|
||
|
||
|
||
|
||
|
||
|
||
}
|
||
|
||
public void SetupLogging()
|
||
{
|
||
var logFilePath = "log.txt";
|
||
var fileListener = new TextWriterTraceListener(File.CreateText(logFilePath));
|
||
Trace.Listeners.Add(fileListener);
|
||
Trace.AutoFlush = true;
|
||
}
|
||
|
||
private void InitializeModbusTcp()
|
||
{
|
||
try
|
||
{
|
||
_tcpClient = new TcpClient();
|
||
_plcIpAddress = ConfigurationManager.AppSettings["PLC_IP"];
|
||
_plcPort = ConfigurationManager.AppSettings["PLC_PORT"].ToString().ToInt16();
|
||
var connectResult = _tcpClient.BeginConnect(_plcIpAddress, _plcPort, null, null);
|
||
var success = connectResult.AsyncWaitHandle.WaitOne(3000);
|
||
|
||
if (!success || !_tcpClient.Connected)
|
||
throw new Exception("连接PLC超时,请检查IP和端口");
|
||
|
||
_modbusMaster = ModbusIpMaster.CreateIp(_tcpClient);
|
||
_modbusMaster.Transport.ReadTimeout = 1000;
|
||
_modbusMaster.Transport.WriteTimeout = 1000;
|
||
|
||
ma = new Function(_modbusMaster);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
throw new Exception($"Modbus初始化失败:{ex.Message}");
|
||
}
|
||
}
|
||
|
||
protected void OnPropertyChanged(string propertyName)
|
||
{
|
||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||
}
|
||
|
||
private void BtnHome_Click(object sender, RoutedEventArgs e)
|
||
{
|
||
UpdateNavButtonStyle(BtnHome, BtnReport, BtnCurve);
|
||
MainContentFrame.Navigate(_homePage);
|
||
}
|
||
|
||
private void BtnReport_Click(object sender, RoutedEventArgs e)
|
||
{
|
||
UpdateNavButtonStyle(BtnReport, BtnHome, BtnCurve);
|
||
MainContentFrame.Navigate(_reportPage);
|
||
}
|
||
|
||
private void BtnCurve_Click(object sender, RoutedEventArgs e)
|
||
{
|
||
UpdateNavButtonStyle(BtnCurve, BtnHome, BtnReport);
|
||
MainContentFrame.Navigate(_curvePage);
|
||
}
|
||
|
||
private void UpdateNavButtonStyle(FrameworkElement activeBtn,
|
||
params FrameworkElement[] inactiveBtns)
|
||
{
|
||
if (activeBtn is Button btnActive)
|
||
{
|
||
btnActive.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#3498DB"));
|
||
}
|
||
|
||
foreach (var btn in inactiveBtns)
|
||
{
|
||
if (btn is Button btnInactive)
|
||
{
|
||
btnInactive.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#2C3E50"));
|
||
}
|
||
}
|
||
}
|
||
|
||
private void ConnectToPLC()
|
||
{
|
||
try
|
||
{
|
||
Trace.WriteLine("Initializing Modbus TCP connection...");
|
||
InitializeModbusTcp();
|
||
|
||
_isConnected = true;
|
||
StatusColor = Brushes.Green;
|
||
ConnectionStatus = "已连接";
|
||
|
||
Trace.WriteLine("Connection established successfully.");
|
||
StartReadingData();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Trace.WriteLine($"Connection failed: {ex.Message}");
|
||
Trace.WriteLine($"Stack Trace: {ex.StackTrace}");
|
||
|
||
MessageBox.Show($"连接失败:{ex.Message}", "错误",
|
||
MessageBoxButton.OK, MessageBoxImage.Error);
|
||
StatusColor = Brushes.Orange;
|
||
ConnectionStatus = "连接失败";
|
||
}
|
||
}
|
||
|
||
private void DisconnectFromPLC()
|
||
{
|
||
try
|
||
{
|
||
_keepReading = false;
|
||
|
||
// 等待线程结束,最多 2 秒
|
||
if (_readThread != null && _readThread.IsAlive)
|
||
{
|
||
if (!_readThread.Join(2000))
|
||
{
|
||
// 如果线程未结束,强制终止(慎用)
|
||
// _readThread.Abort(); // 不推荐,此处仅为保底
|
||
}
|
||
}
|
||
|
||
_modbusMaster?.Dispose();
|
||
_modbusMaster = null;
|
||
|
||
if (_tcpClient != null)
|
||
{
|
||
if (_tcpClient.Connected)
|
||
_tcpClient.Close();
|
||
_tcpClient.Dispose();
|
||
_tcpClient = null;
|
||
}
|
||
|
||
_isConnected = false;
|
||
StatusColor = Brushes.Red;
|
||
ConnectionStatus = "已断开";
|
||
_homePage.UpdateData("0.0", "0.0", "0.0", "0.0", 0, 0, "0", "0", "0");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show($"断开失败:{ex.Message}", "错误",
|
||
MessageBoxButton.OK, MessageBoxImage.Error);
|
||
}
|
||
}
|
||
|
||
private void StartReadingData()
|
||
{
|
||
_keepReading = true;
|
||
_readThread = new Thread(ReadDataLoop) { IsBackground = true };
|
||
_readThread.Start();
|
||
}
|
||
|
||
private void ReadDataLoop()
|
||
{
|
||
//int i = 0;
|
||
//while (i < 100)
|
||
//{
|
||
// // 添加随机测试数据
|
||
// Random random = new Random();
|
||
|
||
// // 生成随机摩擦力值(包含负值)
|
||
// double friction1 = random.Next(-200, 200);
|
||
// double friction2 = random.Next(-200, 200);
|
||
|
||
// // 创建数据点(时间戳相同,确保数据一致性)
|
||
// var dataPoint = new Tuple<DateTime, double, double>(
|
||
// DateTime.Now,
|
||
// friction1,
|
||
// friction2
|
||
// );
|
||
|
||
// // 关键修改:同时添加到两个地方
|
||
// // 1. 添加到共享曲线数据队列(曲线页面和报表页面共享)
|
||
// _sharedCurveDataQueue.Enqueue(dataPoint);
|
||
|
||
// // 2. 添加到报表数据
|
||
// _reportPage.AddReportRecord(new ReportData
|
||
// {
|
||
// D = random.Next(1, 100),
|
||
// Friction1 = friction1.ToString("F1"), // 使用相同的摩擦力值
|
||
// Friction2 = friction2.ToString("F1"), // 使用相同的摩擦力值
|
||
// Id = (i + 11).ToString(),
|
||
// Pressure1 = random.Next(1, 10).ToString(),
|
||
// Pressure2 = random.Next(2, 12).ToString(),
|
||
// t1 = random.Next(20, 40),
|
||
// t2 = random.Next(25, 45),
|
||
// Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") // 使用相同的时间格式
|
||
// });
|
||
|
||
// // 3. 通知曲线页面更新(这个调用只是触发重绘,数据已经在队列中)
|
||
// _curvePage.AddFrictionData(friction1, friction2);
|
||
|
||
// // 为了让曲线更平滑,可以少量数据生成
|
||
// Thread.Sleep(100); // 每100ms一个数据点
|
||
|
||
// i++;
|
||
//}
|
||
|
||
|
||
|
||
|
||
while (_keepReading)
|
||
{
|
||
try
|
||
{
|
||
if (_isConnected && _tcpClient != null && _tcpClient.Connected)
|
||
{
|
||
// 读取所有数据(包含新增的次数、最大摩擦力)
|
||
var data = ReadModbusData();
|
||
|
||
// 读取暂停状态
|
||
bool isPaused = false;
|
||
try
|
||
{
|
||
bool[] pauseStatus = _modbusMaster?.ReadCoils(0x01, (ushort)PauseStatusCoil, 1);
|
||
isPaused = pauseStatus != null && pauseStatus.Length > 0 && pauseStatus[0];
|
||
}
|
||
catch
|
||
{
|
||
// 读取失败时默认 false
|
||
}
|
||
|
||
|
||
// --- 记录暂停时间段 ---
|
||
if (isPaused != _lastPausedState)
|
||
{
|
||
if (isPaused) // 进入暂停
|
||
{
|
||
_pauseStartTime = DateTime.Now;
|
||
}
|
||
else // 退出暂停
|
||
{
|
||
if (_pauseStartTime != default)
|
||
{
|
||
_pausePeriods.Add((_pauseStartTime, DateTime.Now));
|
||
}
|
||
}
|
||
_lastPausedState = isPaused;
|
||
|
||
// 【新增】同步更新 HomePage 上的按钮状态
|
||
Dispatcher.BeginInvoke(new Action(() =>
|
||
{
|
||
_homePage.SetButtonState(isPaused);
|
||
}), System.Windows.Threading.DispatcherPriority.Background);
|
||
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
// 【核心修改】1. 控制秒表逻辑 (处理暂停和重新开始)
|
||
// 判断是否是新的一轮测试开始 (实际次数归1,或者从上一轮结束状态变为1)
|
||
bool isNewTestStart = (data.actualCount == 1 && _lastActualCount == 0) ||
|
||
(data.actualCount == 1 && _lastActualCount == _lastSetCount && _lastSetCount > 0);
|
||
|
||
if (isNewTestStart)
|
||
{
|
||
// 新一轮测试,重置并启动秒表
|
||
_testStopwatch.Restart();
|
||
}
|
||
else
|
||
{
|
||
// 非新一轮,根据暂停状态控制秒表
|
||
if (!isPaused && data.setCount > 0 && data.actualCount > 0)
|
||
{
|
||
// 测试进行中且未暂停 -> 启动秒表 (如果之前是停的)
|
||
if (!_testStopwatch.IsRunning) _testStopwatch.Start();
|
||
}
|
||
else
|
||
{
|
||
// 暂停中 或 测试未开始 -> 停止秒表
|
||
if (_testStopwatch.IsRunning) _testStopwatch.Stop();
|
||
}
|
||
}
|
||
|
||
// 更新记录,供下一次循环判断
|
||
_lastActualCount = data.actualCount;
|
||
_lastSetCount = data.setCount;
|
||
|
||
// 【核心修改】2. 生成“净运行时间”戳
|
||
// 使用 DateTime.MinValue 作为基准,加上秒表时间。
|
||
// 这样计算 TotalSeconds 时,得到的就是纯粹的秒数,不包含暂停时间。
|
||
DateTime effectiveTime = DateTime.MinValue.AddMilliseconds(_testStopwatch.ElapsedMilliseconds);
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
// --- 结束记录暂停时间段 ---
|
||
|
||
var pressure1 = data.pressure1;
|
||
var pressure2 = data.pressure2;
|
||
var friction1 = data.friction1;
|
||
var friction2 = data.friction2;
|
||
var maxFriction1 = data.maxFriction1;
|
||
var maxFriction2 = data.maxFriction2;
|
||
|
||
|
||
|
||
// ----- 读取报警状态(HR504 / HR509)-----
|
||
bool[] alarmsHR504 = null;
|
||
bool[] alarmsHR509 = null;
|
||
try
|
||
{
|
||
// 连续读取 HR504.1 ~ HR504.5(5个线圈,起始 41265)
|
||
alarmsHR504 = _modbusMaster?.ReadCoils(0x01, 41265, 5);
|
||
// 连续读取 HR509.0 ~ HR509.3(4个线圈,起始 41345)
|
||
alarmsHR509 = _modbusMaster?.ReadCoils(0x01, 41344, 6);
|
||
}
|
||
catch
|
||
{
|
||
|
||
}
|
||
|
||
string alarmMessage = "";
|
||
if (alarmsHR504 != null && alarmsHR504.Length >= 5)
|
||
{
|
||
// 根据实测:索引0=41265=已达上限水位
|
||
if (alarmsHR504[0]) alarmMessage += "已达上限水位 ";
|
||
// 索引1=41266=急停被按下
|
||
if (alarmsHR504[1]) alarmMessage += "急停被按下 ";
|
||
// 索引2=41267=测试完成(待确认)
|
||
if (alarmsHR504[2]) alarmMessage += "测试完成 ";
|
||
// 索引3=41268=摩擦力过大(待确认)
|
||
//if (alarmsHR504[3]) alarmMessage += "摩擦力过大 ";
|
||
// 索引4=41269=超温95℃(待确认)
|
||
if (alarmsHR504[4]) alarmMessage += "超温95℃ ";
|
||
}
|
||
if (alarmsHR509 != null && alarmsHR509.Length >= 6)
|
||
{
|
||
if (alarmsHR509[0]) alarmMessage += "1工位低水位 ";
|
||
if (alarmsHR509[2]) alarmMessage += "水泵未运行 ";
|
||
// 索引3=41348=2工位低水位
|
||
if (alarmsHR509[3]) alarmMessage += "2工位低水位 ";
|
||
if (alarmsHR509[4]) alarmMessage += "摩擦力过大 ";
|
||
if (alarmsHR509[5]) alarmMessage += "伺服驱动器报警,请清除 ";
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
// 更新UI(数据监控页+曲线页)
|
||
// 使用 BeginInvoke 避免阻塞后台读取线程,减少 UI 卡死风险
|
||
Dispatcher.BeginInvoke(new Action(() =>
|
||
{
|
||
// 更新数据监控页数值
|
||
_homePage.UpdateData(
|
||
pressure1.ToString("F1"),
|
||
pressure2.ToString("F1"),
|
||
friction1.ToString("F1"),
|
||
friction2.ToString("F1"),
|
||
data.setCount,
|
||
data.actualCount,
|
||
data.t1.ToString("F1"),
|
||
data.t2.ToString("F1"),
|
||
data.D.ToString("F1")
|
||
);
|
||
|
||
// 新增:更新报警显示
|
||
_homePage.UpdateAlarms(alarmMessage);
|
||
|
||
|
||
if (!isPaused)
|
||
{
|
||
// 关键修改:确保曲线数据正确记录
|
||
if (data.setCount > 0 && data.actualCount > 0 &&
|
||
data.setCount > data.actualCount) // 点击了开始,且实际次数小于设定次数,才更新曲线
|
||
{
|
||
// 创建数据点
|
||
var dataPoint = new Tuple<DateTime, double, double>(
|
||
effectiveTime,
|
||
friction1,
|
||
friction2
|
||
);
|
||
|
||
// 添加到共享队列
|
||
_sharedCurveDataQueue.Enqueue(dataPoint);
|
||
|
||
// 通知曲线页面更新
|
||
_curvePage.AddFrictionData(friction1, friction2);
|
||
|
||
|
||
}
|
||
|
||
if (data.setCount > 0 && data.actualCount > 0 &&
|
||
data.setCount == data.actualCount && !_hasInsertedReport) // 一次测试执行完成,保存报表
|
||
{
|
||
//// 创建报表记录(时间+压力+最大摩擦力)
|
||
//var reportRecord = new ReportData(
|
||
// DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), // 当前时间
|
||
// pressure1.ToString("F1"), // 工位1压力
|
||
// pressure2.ToString("F1"), // 工位2压力
|
||
// maxFriction1.ToString("F1"), // 工位1最大摩擦力
|
||
// maxFriction2.ToString("F1"),
|
||
// data.t1,
|
||
// data.t2,
|
||
// data.D
|
||
//);
|
||
// 获取当前的净运行秒数
|
||
double currentElapsedSec = _testStopwatch.ElapsedMilliseconds / 1000.0;
|
||
|
||
var reportRecord = new ReportData(
|
||
currentElapsedSec.ToString(), // 绝对时间可以保留作为“发生时刻”,或者改为显示秒数
|
||
pressure1.ToString("F1"),
|
||
pressure2.ToString("F1"),
|
||
maxFriction1.ToString("F1"),
|
||
maxFriction2.ToString("F1"),
|
||
data.t1,
|
||
data.t2,
|
||
data.D
|
||
// 注意:如果你的 ReportData 构造函数没有 ElapsedSeconds 参数,需要重载构造函数或直接赋值
|
||
);
|
||
reportRecord.ElapsedSeconds = currentElapsedSec;
|
||
// 插入报表
|
||
_reportPage.AddReportRecord(reportRecord);
|
||
// 标记为已插入(避免同一批次重复插入)
|
||
_hasInsertedReport = true;
|
||
}
|
||
|
||
if (data.actualCount < data.setCount)
|
||
{
|
||
_hasInsertedReport = false;
|
||
}
|
||
}
|
||
|
||
}), System.Windows.Threading.DispatcherPriority.Background);
|
||
}
|
||
|
||
else
|
||
{
|
||
// 如果连接标志为 true 但实际未连接,主动断开
|
||
if (_isConnected)
|
||
{
|
||
Dispatcher.BeginInvoke(new Action(() => DisconnectFromPLC()));
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
// 捕获 Socket 异常
|
||
if (ex is SocketException || (ex.InnerException is SocketException) ||
|
||
ex.Message.Contains("non-connected") || ex.Message.Contains("socket"))
|
||
{
|
||
// 连接已丢失,触发断开
|
||
Dispatcher.BeginInvoke(new Action(() => DisconnectFromPLC()));
|
||
}
|
||
else
|
||
{
|
||
// 其他异常正常显示
|
||
Dispatcher.BeginInvoke(new Action(() =>
|
||
{
|
||
StatusColor = Brushes.Orange;
|
||
ConnectionStatus = $"读取错误:{ex.Message}";
|
||
}), System.Windows.Threading.DispatcherPriority.Background);
|
||
}
|
||
}
|
||
Thread.Sleep(200); // 100ms刷新一次
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
public void ResetTestTimer()
|
||
{
|
||
if (_testStopwatch != null)
|
||
{
|
||
_testStopwatch.Reset();
|
||
}
|
||
// 同时也重置一下计数记录,防止逻辑判断错误
|
||
_lastActualCount = 0;
|
||
_lastSetCount = 0;
|
||
}
|
||
|
||
|
||
|
||
private (float pressure1, float pressure2, float friction1, float friction2,
|
||
int setCount, int actualCount, float maxFriction1, float maxFriction2, float t1, float t2, float D, bool status) ReadModbusData()
|
||
{
|
||
try
|
||
{
|
||
// 修正地址:按手册公式计算后的Modbus地址
|
||
ushort[] p1 = _modbusMaster?.ReadHoldingRegisters(0x01, 18701, 2); // 原DM1700,17001+1700=18701
|
||
ushort[] p2 = _modbusMaster?.ReadHoldingRegisters(0x01, 18705, 2); // 原DM1704,17001+1704=18705
|
||
ushort[] f1 = _modbusMaster?.ReadHoldingRegisters(0x01, 17045, 2); // 原DM44,17001+44=17045
|
||
ushort[] f2 = _modbusMaster?.ReadHoldingRegisters(0x01, 17085, 2); // 原DM84,17001+84=17085
|
||
|
||
// 设定次数(H64)
|
||
ushort[] setCountArr = _modbusMaster?.ReadHoldingRegisters(0x01, 6734, 1);
|
||
ushort[] actualCountArr = _modbusMaster?.ReadHoldingRegisters(0x01, 19000, 1);
|
||
|
||
// 最大摩擦力1(DM1600):17001+1600=18601
|
||
ushort[] maxF1Arr = _modbusMaster?.ReadHoldingRegisters(0x01, 18601, 2);
|
||
// 最大摩擦力2(DM1604):17001+1604=18605
|
||
ushort[] maxF2Arr = _modbusMaster?.ReadHoldingRegisters(0x01, 18605, 2);
|
||
|
||
// 温度和其他数据
|
||
ushort[] p11 = _modbusMaster?.ReadHoldingRegisters(0x01, 18201, 2);
|
||
ushort[] p12 = _modbusMaster?.ReadHoldingRegisters(0x01, 18205, 2);
|
||
ushort[] p13 = _modbusMaster?.ReadHoldingRegisters(0x01, 19101, 2);
|
||
bool[] p14 = _modbusMaster?.ReadCoils(0x01, 7100, 100);
|
||
if (p14[0])
|
||
{
|
||
|
||
}
|
||
// 转换数据(压力、实时摩擦力:float类型)
|
||
float pressure1 = c.UshortToFloat(p1[0], p1[1]);
|
||
float pressure2 = c.UshortToFloat(p2[0], p2[1]);
|
||
float friction1 = c.UshortToFloat(f1[0], f1[1]);
|
||
float friction2 = c.UshortToFloat(f2[0], f2[1]);
|
||
|
||
float pressure11 = c.UshortToFloat(p11[0], p11[1]);
|
||
float pressure12 = c.UshortToFloat(p12[0], p12[1]);
|
||
float pressure13 = c.UshortToFloat(p13[0], p13[1]);
|
||
|
||
// 转换数据:设定次数、实际次数(int类型)
|
||
int setCount = setCountArr[0]; // 16位寄存器直接转int
|
||
int actualCount = actualCountArr[0];
|
||
|
||
// 转换数据:最大摩擦力(float类型)
|
||
float maxFriction1 = c.UshortToFloat(maxF1Arr[0], maxF1Arr[1]);
|
||
float maxFriction2 = c.UshortToFloat(maxF2Arr[0], maxF2Arr[1]);
|
||
|
||
bool stauts = p14[0];
|
||
// 保留4位小数返回
|
||
return (
|
||
(float)Math.Round(pressure1, 4),
|
||
(float)Math.Round(pressure2, 4),
|
||
(float)Math.Round(friction1, 4),
|
||
(float)Math.Round(friction2, 4),
|
||
setCount,
|
||
actualCount,
|
||
maxFriction1,
|
||
maxFriction2,
|
||
pressure11,
|
||
pressure12,
|
||
pressure13,
|
||
stauts
|
||
);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
//throw new Exception($"Modbus读取错误:{ex.Message}");
|
||
return (
|
||
0,
|
||
0,
|
||
0,
|
||
0,
|
||
0,
|
||
0,
|
||
0,
|
||
0,
|
||
0,
|
||
0,
|
||
0,
|
||
true
|
||
);
|
||
}
|
||
}
|
||
|
||
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
|
||
{
|
||
DisconnectFromPLC();
|
||
}
|
||
|
||
private void Window_Loaded(object sender, RoutedEventArgs e)
|
||
{
|
||
//if (!_isConnected)
|
||
//{
|
||
// ConnectToPLC();
|
||
// if (_isConnected)
|
||
// {
|
||
// BtnConnectPLC.Content = "断开PLC";
|
||
// BtnConnectPLC.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#E67E22"));
|
||
// }
|
||
//}
|
||
//else
|
||
//{
|
||
// DisconnectFromPLC();
|
||
// BtnConnectPLC.Content = "连接PLC";
|
||
// BtnConnectPLC.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#27AE60"));
|
||
//}
|
||
// 只做界面初始化,不自动连接
|
||
// 确保连接按钮状态正确
|
||
BtnConnectPLC.Content = "连接PLC";
|
||
BtnConnectPLC.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#27AE60"));
|
||
StatusColor = Brushes.Red;
|
||
ConnectionStatus = "未连接";
|
||
}
|
||
|
||
private void ConnectButton_Click(object sender, RoutedEventArgs e)
|
||
{
|
||
if (!_isConnected)
|
||
{
|
||
ConnectToPLC();
|
||
// 更新按钮文本
|
||
BtnConnectPLC.Content = "断开PLC";
|
||
BtnConnectPLC.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#E67E22"));
|
||
}
|
||
else
|
||
{
|
||
DisconnectFromPLC();
|
||
BtnConnectPLC.Content = "连接PLC";
|
||
BtnConnectPLC.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#27AE60"));
|
||
}
|
||
}
|
||
|
||
|
||
|
||
private void SendPauseCommand()
|
||
{
|
||
try
|
||
{
|
||
if (_isConnected && _modbusMaster != null)
|
||
{
|
||
_modbusMaster.WriteSingleCoil(0x01, (ushort)PauseControlCoil, true);
|
||
Thread.Sleep(100);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show($"发送暂停命令失败:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||
}
|
||
}
|
||
|
||
private void SendResumeCommand()
|
||
{
|
||
try
|
||
{
|
||
if (_isConnected && _modbusMaster != null)
|
||
{
|
||
_modbusMaster.WriteSingleCoil(0x01, (ushort)PauseControlCoil, false);
|
||
Thread.Sleep(100);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show($"发送继续命令失败:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||
}
|
||
}
|
||
}
|
||
} |