4

C# コードからデジタル スケールに接続する方法を見つけようとしています。特定のスケールは、USB 接続が付属している Ohaus SP202 デジタルスケールです。スケールで測定された重量をプログラムで読み取りたいと思います。私はまだスケールを持っていません。事前に調査を行っているだけです。

誰もこれを以前にやったことがありますか?私はインターネットで調査を行ってきましたが、言及する価値のあるものはまだ見つかりませんでした。

4

4 に答える 4

6

USBハードウェア通信は、一般的に3つの方法のいずれかで機能します。

  1. プロプライエタリソフトウェアは、プロプライエタリドライバを介してハードウェアと通信します。

  2. デバイスにはシリアルエミュレーションチップ(FTDIなど)が搭載されています。スケールを接続すると、仮想通信ポートドライバーをインストールするだけで、デバイスがシステムに通信ポートとして表示されます。次に、System.IO.Ports.SerialPortを使用してデバイスと通信するのと同じくらい簡単です。

  3. デバイスはHIDプロファイルを実装し、OSのHIDシステムから利用できるようになります。Windowsでこの.NETHIDライブラリを使用して、HIDを実装するバーコードスキャナーと正常に通信しました。HIDライブラリは、通信しているハードウェアに基づいて解読したチャンクでハードウェアからデータを送信します。

方法2と3では、話しているスケールのデータ形式を見つける必要があります。私が使用した体重計は、負荷が安定したかどうかなど、ハードウェアUIに表示される重量やその他の情報を使用して、1秒ごとに更新を送信します。

彼らのディスカッションフォーラムを見ると、彼らのスケールは方法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 to 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 は、私が初めてデータを読み取らなければならなかったデバイスの 1 つです。当時は単なるシリアル ポートでしたが、おそらく 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 に答える