C#modbus通讯

nebuung 2020-10-19 10:31:43
将信捷PLC中的数据存入MySQL(RTU&TCP)
Q:巴妖妖武妻妻久灵灵
...全文
7552 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
Antony_WU_SZ 2020-10-30
  • 打赏
  • 举报
回复
引用 3 楼 nebuung 的回复:
[quote=引用 2 楼 jameswjw 的回复:]信捷PLC有数据接口吗?能取出数据吗?如果能,哪不是就对数据库的新增操作吗?
有,而且我也取出来了存到了数据库,但是数据有缺失。知识有限无奈只能找人帮忙写一个。 链接是我写的 https://download.csdn.net/download/nebuung/12928267[/quote] 你这个下载还收积分???
ziqi0716 2020-10-26
  • 打赏
  • 举报
回复
引用 12 楼 nebuung 的回复:
[quote=引用 11 楼 阿达King 的回复:]把PLC的串口线接到PC,然后用.net写程序,调用NModbus,里面有例程,直接用窗口的Timer组件不停地扫描从PLC串口传过来的数据
我面临的是这个问题: 数据丢失的原因在于数据接收与数据处理同在一个线程中,如果数据处理时间较长,来不及接收的数据只能暂存于缓存中。一旦缓存满了,新到的数据就会冲刷掉未来的及接收的数据,从而造成数据的丢失。 查到的解决方法: 数据接收与数据处理分别在两个线程中进行,数据接收线程负责数据接收并将接收的数据存入数据池中;数据处理线程负责从数据池中读取数据和处理数据。 问题是我不知道怎么改。[/quote] 真的,你还是看NModbus等现成库吧,即使你把所有问题都解决了,也只不过是写了一个类似NModbus库的轮子,而且很可能是菱形或者三角形的(学习原理及实现技巧啥的虽然也有必要的,但是从面相对象的角度来讲,你当下应该关心的是业务数据的处理,而不是如何保证数据传输的过程的安全可靠等问题).
jameswjw 2020-10-26
  • 打赏
  • 举报
回复
我大致看了一下你的代码,我可以给你一个思路,你把信捷PLC中的数据先存放到一个.txt文本文件中,首先得对比一下日志数据与数据库中的数据丢了多少?是不是循环写错了,先对比数据,我感觉不应该丢失,理论上是代码有漏洞,把哪些数据给丢了
  • 打赏
  • 举报
回复
固然,后续数据处理本来就可以跟数据 I/O 线程分开来,异步并发执行。但是异步并发时就又有新的技术、新的问题(新的bug)需要注意处理。那么前提是,最低级地开发的时候,为什么用一些技术的属于把主管直接打发掉了?为什么没有给出具体的调试结果数据,而仅仅是一个定性的说词儿?如果不会5%的技术来保证先逻辑正确地处理,你让这样的人去运用15%层级的技术,这不现实。
  • 打赏
  • 举报
回复
引用 12 楼 nebuung 的回复:
我面临的是这个问题:
数据丢失的原因在于数据接收与数据处理同在一个线程中,如果数据处理时间较长,来不及接收的数据只能暂存于缓存中。一旦缓存满了,新到的数据就会冲刷掉未来的及接收的数据,从而造成数据的丢失。。

你确定你看到“缓存满了”的代码和调试过它吗?是底下的人给你的解释吧?有些话听上去“完全正确”,但是其实根本不能当作“声东击西”的借口,而是应该找准解决方向。
nebuung 2020-10-22
  • 打赏
  • 举报
回复
引用 11 楼 阿达King 的回复:
把PLC的串口线接到PC,然后用.net写程序,调用NModbus,里面有例程,直接用窗口的Timer组件不停地扫描从PLC串口传过来的数据

我面临的是这个问题:
数据丢失的原因在于数据接收与数据处理同在一个线程中,如果数据处理时间较长,来不及接收的数据只能暂存于缓存中。一旦缓存满了,新到的数据就会冲刷掉未来的及接收的数据,从而造成数据的丢失。
查到的解决方法:
数据接收与数据处理分别在两个线程中进行,数据接收线程负责数据接收并将接收的数据存入数据池中;数据处理线程负责从数据池中读取数据和处理数据。
问题是我不知道怎么改。
阿达King哥 2020-10-22
  • 打赏
  • 举报
回复
引用 12 楼 nebuung 的回复:
[quote=引用 11 楼 阿达King 的回复:]把PLC的串口线接到PC,然后用.net写程序,调用NModbus,里面有例程,直接用窗口的Timer组件不停地扫描从PLC串口传过来的数据
我面临的是这个问题: 数据丢失的原因在于数据接收与数据处理同在一个线程中,如果数据处理时间较长,来不及接收的数据只能暂存于缓存中。一旦缓存满了,新到的数据就会冲刷掉未来的及接收的数据,从而造成数据的丢失。 查到的解决方法: 数据接收与数据处理分别在两个线程中进行,数据接收线程负责数据接收并将接收的数据存入数据池中;数据处理线程负责从数据池中读取数据和处理数据。 问题是我不知道怎么改。[/quote] 我的经验是PLC传过来的速度是非常慢的,计算机的速度是非常快的,你如果需要保存数据,可以把保存数据的操作放在另一个线程中
蜗牛慢慢趴 2020-10-21
  • 打赏
  • 举报
回复
NModbus
owennol 2020-10-21
  • 打赏
  • 举报
回复
modbus只是一种协议格式,通信还是串口或者网络,参考SerialPort和Socket
阿达King哥 2020-10-21
  • 打赏
  • 举报
回复
把PLC的串口线接到PC,然后用.net写程序,调用NModbus,里面有例程,直接用窗口的Timer组件不停地扫描从PLC串口传过来的数据
Antony_WU_SZ 2020-10-20
  • 打赏
  • 举报
回复
在西门子,三菱和台达的PLC上均可实现,经过批量生产验证.
Antony_WU_SZ 2020-10-20
  • 打赏
  • 举报
回复
libmodbus库 小菜一碟 几年前的老技术了 https://blog.csdn.net/ericwuhk/article/details/79992080
nebuung 2020-10-19
  • 打赏
  • 举报
回复
我是不知道怎么改自己的代码,求大神帮忙写个可用的,Q在一楼,马尼好说
nebuung 2020-10-19
  • 打赏
  • 举报
回复
引用 2 楼 jameswjw 的回复:
信捷PLC有数据接口吗?能取出数据吗?如果能,哪不是就对数据库的新增操作吗?

看到设置的免费下载还收C币,代码全部贴了
using System;
using System.Windows.Forms;
using Modbus.Device;
using System.IO.Ports;
using MySql.Data.MySqlClient;

namespace Modbus72
{
public partial class MainForm : Form
{
private static IModbusMaster master;
private static SerialPort port;
//写线圈或写寄存器数组
private bool[] coilsBuffer;
private ushort[] registerBuffer;
//参数(分别为站号,起始地址,长度)
private byte slaveAddress;
private ushort startAddress;
private ushort startAddress1;
private ushort numberOfPoints;
private ushort numberOfPoints1;
//串口参数 串口名 波特率 校验 数据位 停止位
private string portName;
private int baudRate;
private Parity parity;
private int dataBits;
private StopBits stopBits;
public MainForm()
{
InitializeComponent();
}

private void MainForm_Load(object sender, EventArgs e)
{
timer1.Interval = 3000;
btnstart.Enabled = true;
btnstop.Enabled = false;
}
private SerialPort InitSerialPortParameter()
{
if (cbxcom.SelectedIndex < 0)
{
MessageBox.Show("请选择串口号");
return null;
}
else
{
portName = cbxcom.SelectedItem.ToString();
baudRate = 19200;
parity = Parity.Even;
dataBits = 8;
stopBits = StopBits.One;
port = new SerialPort(portName, baudRate, parity, dataBits, stopBits);
return port;
}
}

private void btnread_Click(object sender, EventArgs e)
{
try
{
//初始化串口参数
InitSerialPortParameter();
master = ModbusSerialMaster.CreateRtu(port);
ExecuteFunction();
}
catch (Exception)
{
MessageBox.Show("初始化异常");
}
}
private void ExecuteFunction()
{
slaveAddress = byte.Parse("1");
string today = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
String connetStr = "server=10.10.20.5;port=3309;user=root;password=rootqsr; database=db_qualitymanager;";
MySqlConnection conn = new MySqlConnection(connetStr);
try
{
//每次操作是要开启串口 操作完成后需要关闭串口
//目的是为了slave更换连接是不报错
if (port.IsOpen == false)
{
port.Open();
}
startAddress = ushort.Parse("0");
numberOfPoints = ushort.Parse("20");
//读取线圈
coilsBuffer = master.ReadCoils(slaveAddress, startAddress, numberOfPoints);
for (int i = 0; i < coilsBuffer.Length; i++)
{
bool m = coilsBuffer[i];//线圈状态
if (m == true)
{
//读取寄存器
int j = i * 4 + 6;
startAddress1 = ushort.Parse(j + "");
numberOfPoints1 = ushort.Parse("3");
registerBuffer = master.ReadHoldingRegisters(slaveAddress, startAddress1, numberOfPoints1);
string x = registerBuffer[0] + "";
string y = registerBuffer[2] + "";
if (x == "0")
{
continue;
}
else
{
if (i < 10)
{
#region
string dpr = "z_0" + i;
conn.Open();
string sql = string.Format("insert into " + dpr + "(vultime,opetime,prdate) values ('{0}','{1}','{2}')", x, y, today);
MySqlCommand cmd = new MySqlCommand(sql, conn);
cmd.ExecuteNonQuery();
conn.Close();

//修改寄存器
string s = j + "";
startAddress = ushort.Parse(s);
string[] strarr = { "0" };
registerBuffer[0] = ushort.Parse(strarr[0]);
master.WriteSingleRegisterAsync(slaveAddress, startAddress, registerBuffer[0]);
#endregion
}
else
{
#region
string dpr = "z_" + i;
conn.Open();
string sql = string.Format("insert into " + dpr + " (vultime,opetime,prdate) values ('{0}','{1}','{2}')", x, y, today);
MySqlCommand cmd = new MySqlCommand(sql, conn);
cmd.ExecuteNonQuery();
conn.Close();

//修改寄存器
string s = j + "";
startAddress = ushort.Parse(s);
string[] strarr = { "0" };
registerBuffer[0] = ushort.Parse(strarr[0]);
master.WriteSingleRegisterAsync(slaveAddress, startAddress, registerBuffer[0]);
#endregion
}
}
}
//SetMsg(coilsBuffer[i] + " ");
}
//SetMsg("\r\n");
port.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

public void SetMsg(string msg)
{
showdetail.Invoke(new Action(() => { showdetail.AppendText(msg); }));
}

private void btnclear_Click(object sender, EventArgs e)
{
showdetail.Clear();
}

private void btnstart_Click(object sender, EventArgs e)
{
timer1.Start();
btnstart.Enabled = false;
btnstop.Enabled = true;
}

private void btnstop_Click(object sender, EventArgs e)
{
timer1.Stop();
btnstart.Enabled = true;
btnstop.Enabled = false;
}

private void timer1_Tick(object sender, EventArgs e)
{
btnread.PerformClick();
}
}
}
nebuung 2020-10-19
  • 打赏
  • 举报
回复
引用 2 楼 jameswjw 的回复:
信捷PLC有数据接口吗?能取出数据吗?如果能,哪不是就对数据库的新增操作吗?

有,而且我也取出来了存到了数据库,但是数据有缺失。知识有限无奈只能找人帮忙写一个。
链接是我写的 https://download.csdn.net/download/nebuung/12928267
jameswjw 2020-10-19
  • 打赏
  • 举报
回复
信捷PLC有数据接口吗?能取出数据吗?如果能,哪不是就对数据库的新增操作吗?
nebuung 2020-10-19
  • 打赏
  • 举报
回复
没人接的么,不费时间的项目啊
ziqi0716 2020-10-19
  • 打赏
  • 举报
回复
可以看看NModBus这个库.

110,567

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧