【问题标题】:Connect from C# to a digital scale从 C# 连接到数字秤
【发布时间】:2008-12-02 00:05:49
【问题描述】:

我正在尝试找出一种将 C# 代码连接到数字秤的方法。特殊的秤是带有 USB 连接的 Ohaus SP202 数字秤。我想以编程方式读取秤上测量的重量。我还没有规模,我只是在做手头的研究。

以前有人做过吗?我一直在互联网上做研究,还没有发现任何值得一提的东西。

【问题讨论】:

    标签: c# usb


    【解决方案1】:

    USB 硬件通信通常采用以下三种方式之一。

    1. 专有软件通过专有驱动程序与硬件通信。

    2. 设备有一个串行仿真芯片(例如FTDI)当您插入电子秤时,您只需安装虚拟通信端口驱动程序,设备就会在您的系统上显示为一个通信端口。然后就像使用 System.IO.Ports.SerialPort 与设备对话一样简单。

    3. 设备实施 HID 配置文件,可通过操作系统的 HID 系统使用。我在 Windows 上使用this .NET HID 库成功地与实现 HID 的条码扫描器通信。 HID 库将根据您正在与之交谈的硬件以块的形式从硬件向您发送数据。

    使用方法 2 和 3,您只需要找到您正在与之交谈的秤的数据格式。我使用的秤每秒左右发送一次更新,其中包含硬件 UI 上显示的重量和其他信息,例如负载是否稳定。

    查看他们的论坛,看起来他们的体重秤使用方法 2 (http://ohaus.com/support/forum_messages.asp?topicid=584),您需要通过发送“P\r\n”来轮询体重秤,然后它会回复以下字符显示在显示屏上 (http://ohaus.com/support/forum_messages.asp?topicid=802)。

    【讨论】:

      【解决方案2】:

      我没有使用过那个特定的秤,但我以前连接过其他数字秤。基本上它通常只是通过 USB 到 Com 转换器进行串行通信。

      如果秤有一个 API 就更好了,但如果没有,那么您将只使用 System.IO.Ports.SerialPort,这是非常标准的串行编程。 A starter article here

      【讨论】:

      • 第二个。我还针对工业秤进行了此操作,所需要的只是一些串行通信并阅读秤的手册以获取正确的消息。
      【解决方案3】:

      我不知道这个规模的任何细节,但我做过一些 USB 的东西。

      它最有可能使用 USB 中断来传输数据。所有的usb鼠标也都使用中断,所以如果你能弄清楚如何读取鼠标信号(使用HID api),那么它应该与scale完全一样,只是返回的数据格式会完全不同。

      在ftw上运行

      【讨论】:

      • 这种USB设备通常会添加一个模拟的com端口,所以它就像连接到ra232端口的秤一样简单。
      • 实际上数据更有可能通过大容量管道发送。不包括隐藏用于通知而不是数据传输的中断管道。如果设计得当,数据采集设备会使用散装管道。
      【解决方案4】:

      Scales 是我必须从中读取数据的第一批设备之一。那时只是一个串口,我猜你还是可以用SerialPort.Net从串口读取数据。

      这是在 Windows 上进行串口传输的代码

      Reference

      using Device.Net;
      using Device.Net.Windows;
      using Microsoft.Extensions.Logging;
      using Microsoft.Extensions.Logging.Abstractions;
      using Microsoft.Win32.SafeHandles;
      using System;
      using System.IO;
      using System.Threading;
      using System.Threading.Tasks;
      
      namespace SerialPort.Net.Windows
      {
          public class WindowsSerialPortDevice : DeviceBase, IDevice
          {
              #region Fields
              private readonly int _BaudRate;
              private readonly byte _ByteSize;
              private bool disposed;
              private readonly Parity _Parity;
              private SafeFileHandle _ReadSafeFileHandle;
              private readonly StopBits _StopBits;
              private ushort ReadBufferSize { get; }
              #endregion
      
              #region Public Properties
              public bool IsInitialized => _ReadSafeFileHandle != null && !_ReadSafeFileHandle.IsInvalid;
              /// <summary>
              /// TODO: No need to implement this. The property probably shouldn't exist at the base level
              /// </summary>
              public IApiService ApiService { get; }
              public ConnectedDeviceDefinition ConnectedDeviceDefinition { get; private set; }
              #endregion
      
              #region Constructor
              public WindowsSerialPortDevice(
                  string deviceId,
                  int baudRate = 9600,
                  StopBits stopBits = StopBits.One,
                  Parity parity = Parity.None,
                  byte byteSize = 8,
                  ushort readBufferSize = 1024,
                  ILoggerFactory loggerFactory = null,
                  IApiService apiService = null) : base(
                      deviceId,
                      loggerFactory,
                      (loggerFactory ?? NullLoggerFactory.Instance).CreateLogger<WindowsSerialPortDevice>())
              {
                  ApiService = apiService ?? new ApiService(null);
      
                  ConnectedDeviceDefinition = new ConnectedDeviceDefinition(DeviceId, DeviceType.SerialPort);
      
                  if ((byteSize == 5 && stopBits == StopBits.Two) || (stopBits == StopBits.OnePointFive && byteSize > 5))
                      throw new ArgumentException(Messages.ErrorInvalidByteSizeAndStopBitsCombo);
      
                  if (byteSize is < 5 or > 8)
                      throw new ArgumentOutOfRangeException(nameof(byteSize), Messages.ErrorByteSizeMustBeFiveToEight);
      
                  if (baudRate is < 110 or > 256000)
                      throw new ArgumentOutOfRangeException(nameof(baudRate), Messages.ErrorBaudRateInvalid);
      
                  if (stopBits == StopBits.None)
                      throw new ArgumentException(Messages.ErrorMessageStopBitsMustBeSpecified, nameof(stopBits));
      
                  ReadBufferSize = readBufferSize;
                  _BaudRate = baudRate;
                  _ByteSize = byteSize;
                  _StopBits = stopBits;
                  _Parity = parity;
              }
              #endregion
      
              #region Public Methods
              public Task InitializeAsync(CancellationToken cancellationToken = default) => Task.Run(Initialize, cancellationToken);
      
              private uint Write(byte[] data) => data == null ? 0 : ApiService.AWriteFile(_ReadSafeFileHandle, data, data.Length, out var bytesWritten, 0) ? (uint)bytesWritten : 0;
      
              public override Task<uint> WriteAsync(byte[] data, CancellationToken cancellationToken = default)
              {
                  ValidateConnection();
                  return Task.Run(() =>
                  {
                      var bytesWritten = Write(data);
                      Logger.LogDataTransfer(new Trace(false, data));
                      return bytesWritten;
                  }, cancellationToken);
              }
      
              public override Task<TransferResult> ReadAsync(CancellationToken cancellationToken = default)
              {
                  ValidateConnection();
      
                  return Task.Run(() =>
                  {
                      var buffer = new byte[ReadBufferSize];
                      var bytesRead = Read(buffer);
                      var transferResult = new TransferResult(buffer, bytesRead);
                      Logger.LogDataTransfer(new Trace(false, transferResult));
                      return transferResult;
                  }, cancellationToken);
              }
      
              public override Task Flush(CancellationToken cancellationToken = default)
              {
                  ValidateConnection();
      
                  return Task.Run(() => ApiService.APurgeComm(_ReadSafeFileHandle, APICalls.PURGE_RXCLEAR | APICalls.PURGE_TXCLEAR),
                      cancellationToken);
              }
      
              public override void Dispose()
              {
                  if (disposed)
                  {
                      Logger.LogWarning(Messages.WarningMessageAlreadyDisposed, DeviceId);
                      return;
                  }
      
                  disposed = true;
      
                  Logger.LogInformation(Messages.InformationMessageDisposingDevice, DeviceId);
      
                  if (_ReadSafeFileHandle != null)
                  {
                      _ReadSafeFileHandle.Dispose();
                      _ReadSafeFileHandle = new SafeFileHandle((IntPtr)0, true);
                  }
      
                  base.Dispose();
              }
      
              public void Close() => Dispose();
              #endregion
      
              #region Private Methods
              private void Initialize()
              {
                  _ReadSafeFileHandle = ApiService.CreateReadConnection(DeviceId, FileAccessRights.GenericRead | FileAccessRights.GenericWrite);
      
                  if (_ReadSafeFileHandle.IsInvalid) return;
      
                  var dcb = new Dcb();
      
                  var isSuccess = ApiService.AGetCommState(_ReadSafeFileHandle, ref dcb);
      
                  _ = WindowsHelpers.HandleError(isSuccess, Messages.ErrorCouldNotGetCommState, Logger);
      
                  dcb.ByteSize = _ByteSize;
                  dcb.fDtrControl = 1;
                  dcb.BaudRate = (uint)_BaudRate;
                  dcb.fBinary = 1;
                  dcb.fTXContinueOnXoff = 0;
                  dcb.fAbortOnError = 0;
      
                  dcb.fParity = 1;
      #pragma warning disable IDE0010 // Add missing cases
                  dcb.Parity = _Parity switch
                  {
                      Parity.Even => 2,
                      Parity.Mark => 3,
                      Parity.Odd => 1,
                      Parity.Space => 4,
                      Parity.None => 0,
                      _ => 0
                  };
      
                  dcb.StopBits = _StopBits switch
                  {
                      StopBits.One => 0,
                      StopBits.OnePointFive => 1,
                      StopBits.Two => 2,
                      StopBits.None => throw new ArgumentException(Messages.ErrorMessageStopBitsMustBeSpecified),
                      _ => throw new ArgumentException(Messages.ErrorMessageStopBitsMustBeSpecified),
                  };
      #pragma warning restore IDE0010 // Add missing cases
      
                  isSuccess = ApiService.ASetCommState(_ReadSafeFileHandle, ref dcb);
                  _ = WindowsHelpers.HandleError(isSuccess, Messages.ErrorCouldNotSetCommState, Logger);
      
                  var timeouts = new CommTimeouts
                  {
                      WriteTotalTimeoutConstant = 0,
                      ReadIntervalTimeout = 1,
                      WriteTotalTimeoutMultiplier = 0,
                      ReadTotalTimeoutMultiplier = 0,
                      ReadTotalTimeoutConstant = 0
                  };
      
                  isSuccess = ApiService.ASetCommTimeouts(_ReadSafeFileHandle, ref timeouts);
                  _ = WindowsHelpers.HandleError(isSuccess, Messages.ErrorCouldNotSetCommTimeout, Logger);
      
                  Logger.LogInformation("Serial Port device initialized successfully. Port: {port}", DeviceId);
              }
      
              private uint Read(byte[] data)
              =>
                   ApiService.AReadFile(_ReadSafeFileHandle, data, data.Length, out var bytesRead, 0)
                      ? bytesRead
                      : throw new IOException(Messages.ErrorMessageRead);
      
      
              private void ValidateConnection()
              {
                  if (!IsInitialized)
                  {
                      throw new InvalidOperationException(Messages.ErrorMessageNotInitialized);
                  }
              }
              #endregion
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2012-07-15
        • 1970-01-01
        • 1970-01-01
        • 2022-01-23
        • 1970-01-01
        • 2016-01-04
        • 2016-03-20
        • 2013-10-20
        • 2013-12-13
        相关资源
        最近更新 更多