RS232C 付 DMM(デジタルマルチメータ) MS8226 を読んでみました (2017/05/06)

MS8226 は MASTECH(中国)のデジタルマルチメータで、標準で RS232C ポートと専用ケーブルが付いています。
アマゾンで、¥4,950. で購入しました。中国から届きます。
TsDMMViewer の KAISE KU-2068 モード で接続すると、PC での計測値の表示、ロギングが可能になります。

通信は、1 秒に 1 回程度の間隔で、LCD 表示の 14 バイトのデータが送られてきます。
計測値は数値ではなく、7 セグメント x 4桁 のデータなので、解析が必要になります。
他にも、PCリンク(RS232C、Bluetooth、BLE ...)の DMM がありますが、通信データの内容は、LCD 表示なのではないかと思います。

■スクリーンショット



これを元に、RS-232C - WiFi 変換器を付けて、スマホ(iPhone、Android)に飛ばしています。
MS8226 は、DTR を ON にしないと、データを送信しません。(DTR をフォトカプラの電源として使用していると思われます。)
使用した RS-232C - WiFi 変換器(ラトックシステム社 REX-WF60) は、DTR には対応していないため、DC5V を MS8226 の 4 番ピンに接続する必要があります。



■Delphi 10.1 + ComPort LIB ソースコード

unit MS8226Unit;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, CPort, CPortCtl;

type
  TForm2 = class(TForm)
    ComPort1: TComPort;
    Button1: TButton;
    Button2: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    Edit13: TEdit;
    ComComboBox1: TComComboBox;
    Edit4: TEdit;
    Edit5: TEdit;
    Edit6: TEdit;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure ComPort1RxChar(Sender: TObject; Count: Integer);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Button2Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
    GTicks : Cardinal;
    GStrHex :string;
    GStrBin :string;
    procedure DispStrBin;
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

// ComPort オープン
procedure TForm2.Button1Click(Sender: TObject);
begin
  ComPort1.BaudRate := TBaudRate.br2400;
  ComPort1.DataBits := TDataBits.dbEight;
  ComPort1.StopBits := TStopBits.sbOneStopBit;
  ComPort1.FlowControl.FlowControl := TFlowControl.fcNone;
  ComPort1.FlowControl.ControlDTR := TDTRFlowControl.dtrEnable;
  ComPort1.Open;

  GTicks := GetTickCount;
end;

// ComPort クローズ
procedure TForm2.Button2Click(Sender: TObject);
begin
  if Comport1.Connected then begin
    try
      Comport1.Close;
      Label1.Caption := '';
    except
      ;
    end;
  end;
end;

// 1バイト整数を2進文字列に
function ByteToBin(x: Byte) : string;
var
  i : integer;
begin
  result := '';
  for i := 1 to 8 do begin
    if ((x and 1) = 1) then
      result := '1' + result
    else
      result := '0' + result;
    x := x shr 1;
  end;
end;

// 1バイト16進文字列を2進文字列に
function HexToBin(const hex : string) : string;
var
  x : integer;
begin
  result := '';
  x := StrToIntDef('$' + hex, -1);
  if x >= 0 then
    result := ByteToBin(x);
end;

// 7セグメントデータを数値に
function SevenSegToStr(const efadcgb : string): string;
var
  s : string;
begin
  result := '';
  if efadcgb.Length = 7 then begin
    s := efadcgb;
    if      s = '1111101' then result := '0'
    else if s = '0000101' then result := '1'
    else if s = '1011011' then result := '2'
    else if s = '0011111' then result := '3'
    else if s = '0100111' then result := '4'
    else if s = '0111110' then result := '5'
    else if s = '1111110' then result := '6'
    else if s = '0010101' then result := '7'
    else if s = '1111111' then result := '8'
    else if s = '0111111' then result := '9'
    else if s = '1101000' then result := 'L';
  end;
end;

// 2進文字列をDMMデータとして表示
procedure TForm2.DispStrBin;
const
  offset = 4;
var
  s : string;
  AcDc, Range, Tani : string;
begin
  if GStrBin.Length = 14 * 8 then begin
    // AC / DC
    if GStrBin.Substring(offset + 0, 1) = '1' then AcDc := 'AC'
    else if GStrBin.Substring(offset + 1, 1) = '1' then AcDc := 'DC'
    else AcDc := '';
    Edit1.Text := AcDc;

    // Rnage
    if GStrBin.Substring(offset + 2, 1) = '1' then Range := 'AUTO'
    else Range := 'MANUAL';
    Edit2.Text := Range;

    // 単位(Unit)
    if GStrBin.Substring(offset + 82, 1) = '1' then Tani := 'M'
    else if GStrBin.Substring(offset + 81, 1) = '1' then Tani := '%'
    else if GStrBin.Substring(offset + 80, 1) = '1' then Tani := 'm'
    else if GStrBin.Substring(offset + 74, 1) = '1' then Tani := 'K'
    else if GStrBin.Substring(offset + 73, 1) = '1' then Tani := 'n'
    else if GStrBin.Substring(offset + 72, 1) = '1' then Tani := 'u'
    else Tani := '';

    if GStrBin.Substring(offset + 98, 1) = '1' then Tani := Tani + 'Hz'
    else if GStrBin.Substring(offset + 97, 1) = '1' then Tani := Tani + 'V'
    else if GStrBin.Substring(offset + 96, 1) = '1' then Tani := Tani + 'A'
    else if GStrBin.Substring(offset + 89, 1) = '1' then Tani := Tani + 'Ω'
    else if GStrBin.Substring(offset + 88, 1) = '1' then Tani := Tani + 'F'
    else if GStrBin.Substring(offset + 105, 1) = '1' then Tani := Tani + '℃';
    Edit3.Text := Tani;

    if GStrBin.Substring(offset + 83, 1) = '1' then Edit4.Text := 'Beep'
    else if GStrBin.Substring(offset + 75, 1) = '1' then Edit4.Text := 'Diode'
    else Edit4.Text := '';

    if GStrBin.Substring(offset + 91, 1) = '1' then Edit5.Text := 'HOLD'
    else Edit5.Text := '';
    if GStrBin.Substring(offset + 90, 1) = '1' then Edit6.Text := 'REL'
    else Edit6.Text := '';
    {
    if GStrBin.Substring(offset + 3, 1) = '1' then Edit7.Text := 'RS232C'
    else Edit7.Text := '';
    }

    // 測定値
    s := '';
    if GStrBin.Substring(offset + 8, 1) = '1' then s := s + '-' else s := s + ' ';
    s := s + SevenSegToStr(GStrBin.Substring(offset + 9, 3) + GStrBin.Substring(offset + 9 + 7, 4));
    if GStrBin.Substring(offset + 24, 1) = '1' then s := s + '.';
    s := s + SevenSegToStr(GStrBin.Substring(offset + 25, 3) + GStrBin.Substring(offset + 25 + 7, 4));
    if GStrBin.Substring(offset + 40, 1) = '1' then s := s + '.';
    s := s + SevenSegToStr(GStrBin.Substring(offset + 41, 3) + GStrBin.Substring(offset + 41 + 7, 4));
    if GStrBin.Substring(offset + 56, 1) = '1' then s := s + '.';
    s := s + SevenSegToStr(GStrBin.Substring(offset + 57, 3) + GStrBin.Substring(offset + 57 + 7, 4));
    Edit13.Text := s;

  end;
end;

// ComPort から受信
procedure TForm2.ComPort1RxChar(Sender: TObject; Count: Integer);
var
  s : string;
  i : integer;
  Ticks : Cardinal;
begin
  if Count > 0 then begin
    Ticks := GetTickCount;
    ComPort1.ReadStr(s, Count);
    if s.Length > 0 then begin
      if Ticks - GTicks > 200 then  begin
        if GStrHex.Length = 28 then begin
          GStrBin := '';
          // 2進文字列に
          for i := 0 to 28 div 2 -1 do
            GStrBin := GStrBin + HexToBin(GStrHex.Substring(i * 2, 2));
          if Label1.Caption <> '■' then Label1.Caption := '■'
          else Label1.Caption := '';
          //Memo1.Lines.Insert(0, GStrBin);

          // 2進文字列をDMMデータとして表示
          DispStrBin;
        end;
        GTicks := Ticks;
        GStrHex := '';
      end;
      // 一時的に16進文字列に
      for i := 0 to s.Length -1 do
        GStrHex := GstrHex + IntToHex(Ord(s.Chars[i]), 2);
    end;
  end;
end;

// フォームクローズ
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if Comport1.Connected then begin
    try
      Comport1.Close;
    except
      ;
    end;
  end;
end;

end.