4

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

有没有人这样做过?我一直在互联网上进行研究,并没有发现任何值得一提的东西。

4

4 回答 4

6

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

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

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

  3. 该设备实施 HID 配置文件,可通过您操作系统的 HID 系统使用。我在 Windows 上使用了这个 .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)。

于 2008-12-02T01:40:29.803 回答
1

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

如果秤有一个 API 就更好了,但如果没有,那么您将只使用 System.IO.Ports.SerialPort 这是非常标准的串行编程。这里有一篇入门文章

于 2008-12-02T00:19:13.227 回答
0

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

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

在ftw上运行

于 2008-12-02T01:35:52.823 回答
0

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

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

参考

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
    }
}
于 2021-02-16T09:58:14.637 回答