RS232C 付 DMM(デジタルマルチメータ) MS8226 を読んでみました (2017/05/06~12/10)
・2017/12/10 iOS (iPhone) のコード (Delphi 10.1) を追加しました。
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.
■Delphi 10.1 + Wi-Fi (Indy) ソースコード
unit Unit2; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Controls.Presentation, FMX.StdCtrls, FMX.Layouts, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdUDPBase, IdUDPClient, IdUDPServer, FMX.Edit, IdGlobal, FMX.ScrollBox,{ FMX.Memo,} TTS.iOS,FMX.Platform, FMX.Objects, System.Math.Vectors,UIConsts; type TForm2 = class(TForm) ScaledLayout1: TScaledLayout; Button1: TButton; IdTCPClient1: TIdTCPClient; Timer1: TTimer; StyleBook1: TStyleBook; PaintBox1: TPaintBox; Label1: TLabel; Button3: TButton; Rectangle1: TRectangle; procedure Button1Click(Sender: TObject); procedure Timer1Timer(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure Button3Click(Sender: TObject); procedure PaintBox1Paint(Sender: TObject; Canvas: TCanvas); private { private 宣言 } function HandleAppEvent(AAppEvent: TApplicationEvent; AContext: TObject): Boolean; public { public 宣言 } cnt : Integer; TTS: TTextToSpeech; DMMValue : string; AcDcStr : string; UnitStr : string; end; var Form2: TForm2; implementation {$R *.fmx} {$R *.iPhone47in.fmx IOS} // ----------------------------------------------------------------------------- var SevenSegsData : array [0..43] of array [0..1] of Double = ( // a (-7.33526 , 13.9743) ,(-7.066240, 14.2) ,(-0.892448, 14.2), (-0.785713, 14.0728) ,(-2.89844 , 12.3) ,(-5.93038 , 12.3), // b (-0.477173, 13.7051) ,(-0.254734, 13.44) ,(-1.1403 , 8.4177), (-2.30772 , 7.43812) ,(-3.08004 , 8.35855),(-2.425590, 12.0702), // c (-2.36688 , 6.76188) ,(-1.59456 , 5.84146) ,(-2.49057 , 0.76), (-2.82852 , 0.476423),(-4.18485 , 2.09283) ,(-3.53430 , 5.7823), // d (-3.19622 , 0.167884),(-3.39629 , 0.0) ,(-9.57008 , 0.0), (-9.73467 , 0.19615) ,(-7.7041 , 1.9) ,(-4.64964 , 1.9), // e (-10.0432 , 0.56385) ,(-10.2078 , 0.76) ,(-9.32223 , 5.7823), (-8.15483 , 6.76188) ,(-7.3825 , 5.84146) ,(-8.01264 , 2.2677), // f (-8.09565 , 7.43813) ,(-8.86797 , 8.35854) ,(-7.97197 , 13.44), (-7.70297 , 13.6657) ,(-6.29808 , 11.9915) ,(-6.92823 , 8.4177), // g (-7.78711 , 7.07042) ,(-6.61969 , 8.05) ,(-3.44774 , 8.05), (-2.67543 , 7.12958) ,(-3.84285 , 6.15) ,(-7.01480 , 6.15), // dp (-0.85000 , 0.85000) ,(1.2, 0.0) ); function ToSevenSegsData(const src: string): string; var c: string; begin c := src.Substring(0, 1); if c = '0' then result := '1111110' else if c = '1' then result := '0110000' else if c = '2' then result := '1101101' else if c = '3' then result := '1111001' else if c = '4' then result := '0110011' else if c = '5' then result := '1011011' else if c = '6' then result := '1011111' else if c = '7' then result := '1110010' else if c = '8' then result := '1111111' else if c = '9' then result := '1111011' else if c = '-' then result := '0000001' else if c = '+' then result := '0110001' else if c = '=' then result := '0001001' else if c = '.' then result := '.' else if c = 'a' then result := '0011101'//='o' else if c = 'b' then result := '0011111' else if c = 'c' then result := '0001101' else if c = 'd' then result := '0111101' else if c = 'e' then result := '1001111'//='E' else if c = 'f' then result := '1000111'//='F' else if c = 'g' then result := '1111011' else if c = 'h' then result := '0010111' else if c = 'i' then result := '0010000' else if c = 'j' then result := '0111000' else if c = 'k' then result := '0010111'//='h' else if c = 'l' then result := '0110000'//='1' else if c = 'm' then result := '0010101'//='n' else if c = 'n' then result := '0010101'//='m' else if c = 'o' then result := '0011101'//='a' else if c = 'p' then result := '1100111'//='P' else if c = 'q' then result := '1110011' else if c = 'r' then result := '0000101' else if c = 's' then result := '1011011'//='5' else if c = 't' then result := '0001111' else if c = 'u' then result := '0011100' else if c = 'v' then result := '0011100'//='u' else if c = 'w' then result := '0011100'//='u' else if c = 'x' then result := '0011100'//='H' else if c = 'y' then result := '0100111'//='Y' else if c = 'z' then result := '1101101'//='2' else if c = 'A' then result := '1110111' //else if c = 'B' then result := '1111111'//='8' else if c = 'B' then result := '0011111' else if c = 'C' then result := '1001119' //else if c = 'D' then result := '1111110'//='0' else if c = 'D' then result := '0111101' else if c = 'E' then result := '1001111' else if c = 'F' then result := '1000111' else if c = 'G' then result := '1010111' else if c = 'H' then result := '0110111' else if c = 'I' then result := '0110000' else if c = 'J' then result := '0111100' else if c = 'K' then result := '0110110'//='H' else if c = 'L' then result := '0001110' else if c = 'M' then result := '1110110' else if c = 'N' then result := '1110110' else if c = 'O' then result := '1111110' else if c = 'P' then result := '1100111' else if c = 'Q' then result := '1111110'//='0' else if c = 'R' then result := '1110111'//='A' else if c = 'S' then result := '1011011'//='5' else if c = 'T' then result := '1000110' else if c = 'U' then result := '0111110' else if c = 'V' then result := '0111110' else if c = 'W' then result := '0111110' else if c = 'X' then result := '0110111'//='H' else if c = 'Y' then result := '0100111'//='y' else if c = 'Z' then result := '0101101'//='2' else result := ''; end; procedure DrawSevenSegsElement(const BitStr : string; dispX, dispY, scale: double; cv : TCanvas; co :TAlphaColor); var segdata : string; i, j : integer; pts : TPolygon ; // uses ,,, System.Math.Vectors; dpX, dpY, dpR : double; begin cv.BeginScene; try // 輪郭 cv.Stroke.Kind := TBrushKind.Solid ; cv.Stroke.Color := co; // 塗りつぶし cv.Fill.Kind := TBrushKind.Solid; cv.Fill.Color := co; if BitStr = '.' then begin dpR := SevenSegsData[43, 0] * scale * 1.5; dpX := SevenSegsData[42, 0] * scale + 10.2 * scale + dispX - dpR; dpY := SevenSegsData[42, 1] * scale + 14.1 * scale + dispY - dpR; cv.FillEllipse(RectF(dpX, dpY , dpX + dpR, dpY + dpR), 1.0); cv.DrawEllipse(RectF(dpX, dpY , dpX + dpR, dpY + dpR), 1.0); end else begin segdata := ToSevenSegsData(BitStr); if segdata.Length = 7 then begin SetLength(pts, 6); for i := 0 to 6 do begin if segdata.Substring(i, 1) = '1' then begin for j := 0 to 5 do begin pts[j] := PointF( SevenSegsData[i * 6 + j, 0] * scale +10.2 * scale + dispX, - SevenSegsData[i * 6 + j, 1] * scale +14.1 * scale + dispY ); end; cv.FillPolygon(pts, 1.0); cv.DrawPolygon(pts, 1.0); end; end; end; end; finally cv.EndScene; end; end; // 左上が基点 // 使用例: // src := '-12.34567890'; // DrawSevenSegsText(src, 0, 0, 5.0, PaintBox1.Canvas, claBlue); // uses ,,, UIConsts; for TAlphaColor; procedure DrawSevenSegsText(const src : string; stX, stY, scale: double; cv : TCanvas; co :TAlphaColor); var s : string; i : integer; dispX, dispY: double; begin dispY := stY; dispX := stX; for i := 0 to src.Length -1 do begin s := src.SubString(i, 1); if s = '.' then begin DrawSevenSegsElement(s, dispX- scale * 10, dispY, scale, cv, co); end else begin DrawSevenSegsElement(s, dispX, dispY, scale, cv, co); dispX := dispX + scale * 10.4; end; end; end; // ----------------------------------------------------------------------------- // FMX TApplicationEvents // uses ,, FMX.Platform; function TForm2.HandleAppEvent(AAppEvent: TApplicationEvent; AContext: TObject): Boolean; begin // ※ TimeChange,OpenURL は iOS のみサポート case AAppEvent of TApplicationEvent.FinishedLaunching: ; TApplicationEvent.BecameActive: ;// TApplicationEvent.WillBecomeInactive: begin ;// バックグラウンドになる直前に呼ばれる try if IdTCPClient1.Connected then begin IdTCPClient1.Disconnect; Button1.Text := '接続'; end; except ; end; end; TApplicationEvent.EnteredBackground: ;// バックグラウンドになった直後に呼ばれる TApplicationEvent.WillBecomeForeground: ;// フォアグラウンドになる直前に呼ばれる TApplicationEvent.WillTerminate : ; TApplicationEvent.LowMemory: ; TApplicationEvent.TimeChange: ; TApplicationEvent.OpenURL: ; end; Result := True; end ; procedure TForm2.PaintBox1Paint(Sender: TObject; Canvas: TCanvas); begin Canvas.Clear(claBlack); //DrawSevenSegsText(DMMValue, 0, 72, 7.5, Canvas, claAqua); DrawSevenSegsText(DMMValue, 0, 80, 12, Canvas, claYellow); Canvas.BeginScene; try // 輪郭 Canvas.Stroke.Kind := TBrushKind.Solid ; Canvas.Stroke.Color := claAqua; // 塗りつぶし Canvas.Fill.Kind := TBrushKind.Solid; Canvas.Fill.Color := claAqua; Canvas.Font.Size := 60; Canvas.FillText(RectF(15, 15, 660, 60), AcDcStr, False, 1.0, [], TTextAlign.Leading, TTextAlign.Center); Canvas.FillText(RectF( 0, 15, 640, 60), UnitStr, False, 1.0, [], TTextAlign.Trailing, TTextAlign.Center); finally Canvas.EndScene; 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; procedure TForm2.Button1Click(Sender: TObject); begin if Button1.Text = '接続' then begin IdTCPClient1.Host := '1.2.3.4'; IdTCPClient1.Port := 2000; IdTCPClient1.ReadTimeout := 500; IdTCPClient1.ConnectTimeout := 1000; try IdTCPClient1.Connect; if IdTCPClient1.Connected then begin Button1.Text := '切断'; end; except on E: Exception do begin ShowMessage( E.ClassName + sLineBreak + E.Message); end; end; end else begin Button1.Text := '接続'; if IdTCPClient1.Connected then begin try IdTCPClient1.Disconnect; //Button1.Text := '接続'; except on E: Exception do begin ShowMessage( E.ClassName + sLineBreak + E.Message); end; end; end; end; end; procedure TForm2.Button3Click(Sender: TObject); begin if Button3.Text = '音声OFF' then Button3.Text := '音声ON' else Button3.Text := '音声OFF'; end; procedure TForm2.FormCreate(Sender: TObject); var SvcEvents : IFMXApplicationEventService; //uses ... FMX.Platform; begin Label1.Text := ''; // 画面を縦に固定 //Application.FormFactor.Orientations := // [TFormOrientation.Portrait, TFormOrientation.InvertedPortrait]; // ApplicationEvent if TPlatformServices.Current.SupportsPlatformService (IFMXApplicationEventService, IInterface(SvcEvents)) then SvcEvents.SetApplicationEventHandler(HandleAppEvent); // テキストスピーチ TTS := TTextToSpeech.Create; TTS.Speed := TTS.SpeedMin; // インターバルタイマー Timer1.Interval := 250; Timer1.Enabled := True; end; procedure TForm2.FormDestroy(Sender: TObject); begin // テキストスピーチ解放 TTS.Free; end; // 小数点位置 function BinStrToDMMDecimalPoint(const BinStr: string): integer; const offset = 4; var i : integer; begin result := 0; for i := 0 to 2 do begin if BinStr.Substring(offset + 24 + i * 16, 1) = '1' then begin result := 3 - i; break; end; end; end; // 単位 function BinStrToDMMUnit(const BinStr: string): string; const offset = 4; begin // 単位(Unit) if BinStr.Substring(offset + 82, 1) = '1' then result := 'M' else if BinStr.Substring(offset + 81, 1) = '1' then result := '%' else if BinStr.Substring(offset + 80, 1) = '1' then result := 'm' else if BinStr.Substring(offset + 74, 1) = '1' then result := 'K' else if BinStr.Substring(offset + 73, 1) = '1' then result := 'n' else if BinStr.Substring(offset + 72, 1) = '1' then result := 'μ' else result := ''; if BinStr.Substring(offset + 98, 1) = '1' then result := result + 'Hz' else if BinStr.Substring(offset + 97, 1) = '1' then result := result + 'V' else if BinStr.Substring(offset + 96, 1) = '1' then result := result + 'A' else if BinStr.Substring(offset + 89, 1) = '1' then result := result + 'Ω' else if BinStr.Substring(offset + 88, 1) = '1' then result := result + 'F' else if BinStr.Substring(offset + 105, 1) = '1' then result := result + '℃'; end; // テキストスピーチ用単位 function BinStrToDMMUnitMessage(const BinStr: string): string; const offset = 4; begin // 単位(Unit) if BinStr.Substring(offset + 82, 1) = '1' then result := 'メガ' else if BinStr.Substring(offset + 81, 1) = '1' then result := 'パーセント' else if BinStr.Substring(offset + 80, 1) = '1' then result := 'ミリ' else if BinStr.Substring(offset + 74, 1) = '1' then result := 'キロ' else if BinStr.Substring(offset + 73, 1) = '1' then result := 'ナノ' else if BinStr.Substring(offset + 72, 1) = '1' then result := 'マイクロ' else result := ''; if BinStr.Substring(offset + 98, 1) = '1' then result := result + 'ヘルツ' else if BinStr.Substring(offset + 97, 1) = '1' then result := result + 'ボルト' else if BinStr.Substring(offset + 96, 1) = '1' then result := result + 'アンペア' else if BinStr.Substring(offset + 89, 1) = '1' then result := result + 'オーム' else if BinStr.Substring(offset + 88, 1) = '1' then result := result + 'ファラッド' else if BinStr.Substring(offset + 105, 1) = '1' then result := result + 'ド'; end; // AC / DC function BinStrToDMMAcDc(const BinStr: string): string; const offset = 4; begin result := ''; if BinStr.Substring(offset + 0, 1) = '1' then result := 'AC' else if BinStr.Substring(offset + 1, 1) = '1' then result := 'DC'; end; // 測定値 function BinStrToDMMValue(const BinStr: string; UnitFlag: boolean):string; const offset = 4; begin result := ''; if BinStr.Length = 14 * 8 then begin if BinStr.Substring(offset + 8, 1) = '1' then result := '-' else result := ' '; result := result + SevenSegToStr(BinStr.Substring(offset + 9, 3) + BinStr.Substring(offset + 9 + 7, 4)); if BinStr.Substring(offset + 24, 1) = '1' then result := result + '.'; result := result + SevenSegToStr(BinStr.Substring(offset + 25, 3) + BinStr.Substring(offset + 25 + 7, 4)); if BinStr.Substring(offset + 40, 1) = '1' then result := result + '.'; result := result + SevenSegToStr(BinStr.Substring(offset + 41, 3) + BinStr.Substring(offset + 41 + 7, 4)); if BinStr.Substring(offset + 56, 1) = '1' then result := result + '.'; result := result + SevenSegToStr(BinStr.Substring(offset + 57, 3) + BinStr.Substring(offset + 57 + 7, 4)); if UnitFlag then result := result + ' ' + BinStrToDMMUnit(BinStr); end; end; procedure TForm2.Timer1Timer(Sender: TObject); var res : string; binstr : string; svalue : string; vbuf : TIdBytes; i : integer; dvalue : double; dp : integer; ttstr : string; begin try if IdTCPClient1.Connected then begin IdTCPClient1.IOHandler.ReadTimeout := IdTCPClient1.ReadTimeout; try IdTCPClient1.IOHandler.ReadBytes(vbuf, 14); res := ''; binstr := ''; for i := 0 to Length(vbuf) -1 do begin res := res + IntToHex(vbuf[i], 2); binstr := binstr + ByteToBin(vbuf[i]); end; //for i := 0 to 28 div 2 -1 do // binstr := binstr + HexToBin(res.Substring(i * 2, 2)); // 16進表示 Label1.Text := res; // 測定値(表示そのまま) svalue := BinStrToDMMValue(binstr, False); DMMValue := svalue; // 測定値 dvalue := StrToFloatDef(svalue, 10000); dp := BinStrToDMMDecimalPoint(binstr); if dvalue < 10000 then ttstr := Format('%.' + dp.ToString + 'f', [dvalue]) else ttstr := 'Overflow Lebel';//svalue;//'O.L.'; //'OverflowLebel'; //ttstr := StringReplace(ttstr, '.', 'テン',[]); //DMMValue := ' ' + Label1.Text; //DMMValue := DMMValue.Substring(DMMValue.Length-6, 5); //PaintBox1.Repaint; // 単位 UnitStr := BinStrToDMMUnit(binstr); // AC / DC AcDcStr := BinStrToDMMAcDc(binstr); //AcDcStr := ttstr; PaintBox1.Repaint; // テキストスピーチ Inc(cnt); if (cnt >= 12) then begin if Button3.Text = '音声OFF' then TTS.Speak(ttstr + ' ' + BinStrToDMMUnitMessage(binstr)); cnt := 0; end; except on E: Exception do begin // Timeout Error Label1.Text := E.ClassName; end; end; end; except on E: Exception do begin Label1.Text := E.ClassName; end; end; end; end.