【问题标题】:Get scale weight over serial from Mettler Toledo Rice Lake scale从 Mettler Toledo Rice Lake 秤获取秤重
【发布时间】:2022-01-23 06:11:32
【问题描述】:

当通过 Mettler Toledo Rice Lake 秤的串行命令发出请求时,尝试接收重量。首先,如果我使用 putty 发送命令,它可以正常工作;它会正确返回当前显示在打印头上的重量,这实际上是我想要通过这些功能完成的全部内容。

这是我目前的代码,虽然我已经尝试了很多变体:

在表单加载时,它将修复与端口关联的变量,以遵循软件其他地方设置的设置。这似乎可以正常工作,并且在软件的许多其他部分中也可以正常工作。

设置: 12:COM1 13:9600 16:没有 17:8 18:一个 19: 印记

private void Get_Weight_Load(object sender, EventArgs e)
        {
            string path11 = File.ReadAllText(Application.StartupPath + @"\ConfigurationPathFile.txt") + @"\GeneralSettings.txt";
            path11 = path11.Replace("\r", "").Replace("\n", "");
            string[] settings = File.ReadAllText(path11).Split(',');

            LoadResources();
            #region Scale
            ScalePort.PortName = settings[12];
            ScalePort.BaudRate = Int32.Parse(settings[13]);
            ScalePort.Handshake = Handshake.RequestToSend; // This is one thing I have been changing in order to try and fix the problem.
            switch (settings[16])
            {
                case "None":
                    ScalePort.Parity = System.IO.Ports.Parity.None;
                    break;
                case "Odd":
                    ScalePort.Parity = System.IO.Ports.Parity.Odd;
                    break;
                case "Even":
                    ScalePort.Parity = System.IO.Ports.Parity.Even;
                    break;
                case "Mark":
                    ScalePort.Parity = System.IO.Ports.Parity.Mark;
                    break;
                case "Space":
                    ScalePort.Parity = System.IO.Ports.Parity.Space;
                    break;
            }
            ScalePort.DataBits = Int32.Parse(settings[17]);
            switch (settings[18])
            {
                case "None":
                    ScalePort.StopBits = System.IO.Ports.StopBits.None;
                    break;
                case "One":
                    ScalePort.StopBits = System.IO.Ports.StopBits.One;
                    break;
                case "Two":
                    ScalePort.StopBits = System.IO.Ports.StopBits.Two;
                    break;
                case "OnePointFive":
                    ScalePort.StopBits = System.IO.Ports.StopBits.OnePointFive;
                    break;
            }
            try
            {
                ScalePort.Open();
                ScalePort.WriteLine(settings[19]);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Contact your system admin if you are seeing this message" + System.Environment.NewLine + ex.ToString());
            }
            #endregion
        }

在表单关闭时:

private void Get_Weight_FormClosed(object sender, FormClosedEventArgs 
{
     if (ScalePort.IsOpen)
        { ScalePort.Close(); }
}

ScalePort 数据接收事件处理程序:

 private void ScalePort_DataReceived(object sender, SerialDataReceivedEventArgs e)
 {
      Thread.Sleep(30);
      SerialPort sp = (SerialPort)sender;
      string indata = sp.ReadExisting();
      textBox1.AppendText(indata + System.Environment.NewLine);
      //MessageBox.Show(indata);
 }

当它运行时,我在 textbox1 中收到的只是我发送的命令,在这种情况下是 kprint。

所以要弄清楚我的问题是什么;我做错了什么导致我无法接收重量,或者我是否发送了错误的命令,如果是,我该如何正确执行?

这是打印头的图像:

【问题讨论】:

  • 以下内容可能会有所帮助:stackoverflow.com/questions/65957066/…
  • 我尝试转换为 ascii 并按照上面提供的链接中的建议一次发送一个字节的写入命令,但这并没有解决问题。
  • 正确的串口设置很重要。我没有查找您的串口设备的文档,但是您是否尝试过帖子中使用的串口设置?
  • 体重秤有型号吗?
  • 以下内容可能会有所帮助:mt.com/us/en/home/applications/industrial_weighing/…

标签: c# serial-port


【解决方案1】:

根据documentation,终止字符有两种选择:CRLF(默认)或CR,因此您需要根据需要设置SerialPort.NewLine 值。将其他SerialPort 属性设置为与您正在使用的串行端口设备上相同的值也很重要。获取/设置值的过程可以在文档中找到。

以下代码已使用我拥有的串行端口设备(不是秤)进行了测试。但是,它对您的秤的用处可能会有所不同,并且取决于与为秤设置的属性匹配的串行端口属性。我还根据您的体重秤文档中的信息设置了一些串行端口属性值。

尝试以下方法:

添加以下 using 语句

using System.IO.Ports;
using System.Diagnostics;

枚举

public enum TerminationCharacterType
{
    CRLF,
    CR
};

public enum PortBaudRate : int
{
    Baud300 = 300,
    Baud600 = 600,
    Baud1200 = 1200,
    Baud2400 = 2400,
    Baud4800 = 4800,
    Baud9600 = 9600,
    Baud19200 = 19200,
    Baud38400 = 38400
};

注意:您说您使用过PuTTY,并且它似乎有效。安装 PuTTY 后,我注意到设置了以下值:

  • 波特率:9600
  • 数据位:8
  • 停止位:1
  • 奇偶校验:无
  • 流控制:XON/XOFF

在下面的代码中,我使用了以下设置:

  • ScalePort.Handshake = Handshake.XOnXOff;
  • ScalePort.DtrEnable = true;

如果设置不起作用,您可以尝试:

  • ScalePort.Handshake = Handshake.None;
  • ScalePort.DtrEnable = false;

连接

public System.IO.Ports.SerialPort ScalePort { get; private set; } = null;
private string _dataReceived = string.Empty;
private TerminationCharacterType _termin = TerminationCharacterType.CRLF;

public string Connect(string comPort, TerminationCharacterType termin = TerminationCharacterType.CRLF, PortBaudRate baudRate = PortBaudRate.Baud9600)
{
    //create new instance
    ScalePort = new SerialPort(comPort);

    //set properties
    ScalePort.BaudRate = (int)baudRate;
    ScalePort.Handshake = Handshake.XOnXOff; //Handshake.None or Handshake.XOnXOff 
    ScalePort.DtrEnable = true; //enable Data Terminal Ready - set true for Handshake.RequestToSend, Handshake.RequestToSendXOnXOff, or Handshake.XOnXOff
    ScalePort.RtsEnable = false; //enable Request to send - set true for Handshake.RequestToSend or Handshake.RequestToSendXOnXOff

    //if Parity.None is used, then use DataBits = 8
    //if Parity.Even or Parity.Odd is used, then use DataBits = 7
    ScalePort.Parity = Parity.None; //Even,None,Odd supported; default: Parity.None
    ScalePort.DataBits = 8; //default: 8

    //set value
    _termin = termin;

    if (termin == TerminationCharacterType.CR)
        ScalePort.NewLine = "\r"; //CR: \r
    else
        ScalePort.NewLine = "\r\n"; // CRLF: \r\n; this is the default

    ScalePort.StopBits = StopBits.One; //1 or 2 supported; default: 1
    ScalePort.ReadTimeout = 200; //num ms before a time-out occurs
    ScalePort.ReadBufferSize = 4096; //default is 4096; max value is 2147483647
    ScalePort.ReceivedBytesThreshold = 1; //default is 1; num bytes before DataReceived event occurs
    ScalePort.WriteBufferSize = 2048; //default is 2048
    ScalePort.WriteTimeout = 50; //num ms before a time-out occurs

    //subscribe to events
    ScalePort.DataReceived += ScalePort_DataReceived;
    ScalePort.ErrorReceived += ScalePort_ErrorReceived;

    //open port
    ScalePort.Open();
}

private void ScalePort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    SerialPort sp = (SerialPort)sender;

    //read data
    //string data = sp.ReadExisting();

    //System.Threading.Thread.Sleep(25);
    string data = sp.ReadLine();

    Debug.WriteLine("data: " + data);
}

private void ScalePort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
{
    Debug.WriteLine("Error - " + e.ToString());
}

注意SerialPort.ReadLine 也可能有效。如果你使用它,这个post 可能会有用。

发送数据

public void SerialCmdSend(string data, bool sendAsString = true)
{
    if (ScalePort.IsOpen && !String.IsNullOrEmpty(data))
    {
        if (sendAsString)
        {
            ScalePort.WriteLine(data);
        }
        else
        {
            if (_termin == TerminationCharacterType.CRLF)
                data = data.Trim() + "\r\n"; //append CRLF
            else if (_termin == TerminationCharacterType.CR)
                data = data.Trim() + "\r"; //append CR

            // Send the binary data out the port
            byte[] hexstring = Encoding.ASCII.GetBytes(data);

            foreach (byte hexval in hexstring)
            {
                byte[] _hexval = new byte[] { hexval }; // need to convert byte to byte[] to write
                ScalePort.Write(_hexval, 0, 1);
                System.Threading.Thread.Sleep(1);
            }
        }
    }
}

由于我没有您使用的秤,以下内容未经测试:

写入显示的重量

//write current displayed weight with units identifier
//SerialCmdSend("P", false);
SerialCmdSend("P", true);

列出所有参数值

//list all parameter values
SerialCmdSend("DUMPALL");

传输净重

//transmit net weight in displayed units
SerialCmdSend("XN");

根据documentation,“以较低的波特率连续传输可能需要 EOL,以确保在传输另一个字符串之前接收缓冲区是空的。”。

您可能还想查看“...选择用于连续传输的串行端口”的STREAM 设置选项。

资源

【讨论】:

  • 所有data == 比较都是错误的,换行符可以在单个ReadExisting 调用中与其他数据一起读取。此代码及其使用的SerialPort 方法还有许多其他问题,这可能会导致其行为异常。取消事件并使用await 和来自SerialPortBaseStream 成员的异步读取。
  • @BenVoigt:感谢您的反馈。我已经修改了一些代码,但我不确定你的意思是 Do away with the events and use await and async reads from the BaseStream member of SerialPort 或者如果我知道该怎么做那个。
猜你喜欢
  • 2012-03-29
  • 1970-01-01
  • 2018-09-21
  • 2019-03-17
  • 1970-01-01
  • 2016-05-30
  • 2021-09-20
  • 2017-05-27
  • 1970-01-01
相关资源
最近更新 更多