これは Delphi Advent Calendar 2016 4日目の記事です。
みなさん、おひさしぶりです。やましょうです。
ちょっと不思議というか本当にwindowsのタイマイベントって正しいのか?
と言う疑問にかられました。
理由はここ
Msさんの組込み用ラズパイのタイマがぼろぼろだったからです。
また、C#だと。。StopWatchが簡単に。。ですけどdelphiだとなかなか書いていないため
記載してみます。)
まずDelphiではStopWatchで時間計測です。
StopWatchを使用する為に、
System.Diagnosticsを追加
Createして、タイマイベントで計測&表示って感じです。
コード
unit TimerTestMain;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
System.Diagnostics,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo;
type
TForm36 = class(TForm)
Timer1: TTimer; //1000ms設定でenableにしておく
Memo1: TMemo;
procedure Timer1Timer(Sender: TObject);
procedure FormCreate(Sender: TObject);
private var
StopWatch : TStopwatch;
{ private 宣言 }
public
{ public 宣言 }
end;
var
Form36: TForm36;
implementation
{$R *.fmx}
procedure TForm36.FormCreate(Sender: TObject);
begin
StopWatch := TStopwatch.Create;
StopWatch.Start;
end;
procedure TForm36.Timer1Timer(Sender: TObject);
var
Tm : Int64;
begin
StopWatch.Stop;
Tm := StopWatch.ElapsedMilliseconds;
StopWatch.Reset;
StopWatch.Start;
if StopWatch.IsHighResolution then
form36.Caption := 'ハイレゾ'
else
form36.Caption := 'そんなでもない';
memo1.Lines.Add(IntTostr(Tm));
end;
結果、やっぱ正確じゃない。。。
単位[ms] です。
990
1002
996
1002
1000
1000
1000
994
1003
998
1002
1001
996
998
999
1000
999
1002
996
1001
1001
1000
1010
989
997
1001
998
i7のマシンでしかもハイレゾでも
これだけジッタというか、結構づれていそうです。
とは言っても平均すると1秒くらいに収束しそうです。
さすが、PC、だいたいでは問題ないですね。
ちなみに、念の為プロセスを最優先にしても正確ではありませんでした。 SetPriorityClass(GetCurrentProcess, REALTIME_PRIORITY_CLASS );
を追加
さて、ここから脱線して、
一つの疑問はタイマのイベントは他のイベント中に受け付けるのか?
と言うことですね。と言うことで確認です。
(タイマは割込処理なのか?違うのか?の検証です。)
keyを押すと3秒程度かかる処理を実装して、計測してみます。
procedure TForm36.Button1Click(Sender: TObject);
var
Tm : Int64;
i : DWORD;
begin
memo1.Lines.Add('ボタン1の処理開始');
for I := 0 to MAXINT do
begin
asm nop end;
asm nop end;
// if ( i mod 10000 ) = 0 then Application.ProcessMessages();
end;
Tm := StopWatch.ElapsedMilliseconds;
memo1.Lines.Add('ボタン1の処理終了:'+IntToStr(Tm));
end;
procedure TForm36.FormCreate(Sender: TObject);
begin
StopWatch := TStopwatch.Create;
StopWatch.Start;
end;
procedure TForm36.Timer1Timer(Sender: TObject);
begin
memo1.Lines.Add('1秒毎のタイマイベント発生');
end;
結果:
1秒毎のタイマイベント発生
1秒毎のタイマイベント発生
ボタン1の処理開始
ボタン1の処理終了:6368
1秒毎のタイマイベント発生
1秒毎のタイマイベント発生
ボタン1の処理開始
ボタン1の処理終了:10898
ボタン1の処理開始
ボタン1の処理終了:14581
1秒毎のタイマイベント発生
1秒毎のタイマイベント発生
1秒毎のタイマイベント発生
1秒毎のタイマイベント発生
keyを二度押ししても、ボタン1の終了までは、ボタン1の処理は開始せず、
タイマイベントも処理できていません。なので割込処理でもありませんね。
このことから重い処理を分散させるため Application.ProcessMessages();
の呪文を使います。
この場合多重にkeyの処理が走り出すので注意が必要です。
その時の結果は下記
1秒毎のタイマイベント発生
1秒毎のタイマイベント発生
ボタン1の処理終了:20532
1秒毎のタイマイベント発生
1秒毎のタイマイベント発生
1秒毎のタイマイベント発生
1秒毎のタイマイベント発生
1秒毎のタイマイベント発生
1秒毎のタイマイベント発生
1秒毎のタイマイベント発生
ボタン1の処理終了:27593
1秒毎のタイマイベント発生
1秒毎のタイマイベント発生
1秒毎のタイマイベント発生
ということで、タイマイベントは割込処理でなく単なるMsg処理になっています。
なので、特に難しい事は考えなくてもよさそうです。
以上
やましょうでした。
2016年12月4日日曜日
2016年11月12日土曜日
Delphi でApple Scriptを使用する。
こんにちは、おひさしぶりやましょうです。
とはいいつつも師匠から、Apple scriptの使い方をと言われたので
こんな感じです。
あくまでも例:コンパイルもしていない。スペルミスもあるかも。。
uses
Macapi.Foundation,
Macapi.Helpers,
const STRINGSCR = 'Apple script Desc'+slineBreak;
procedure TForm1.ApplescrClick(Sender: TObject);
var
Scr : NsAppleScript;
Err : Pointer;
begin
Err := nil;
Scr := TNSAppleScript.Wrap(TNSAppleScript.Alloc.initWithSource(StrToNSStr(STRINGSCR)));
Scr.executeAndReturnError(Err);
end;
こんな感じで動くと思います。
実際にはexecueAndReturnErrorはTryを使用した方が良いと思います。
とはいいつつも師匠から、Apple scriptの使い方をと言われたので
こんな感じです。
あくまでも例:コンパイルもしていない。スペルミスもあるかも。。
uses
Macapi.Foundation,
Macapi.Helpers,
const STRINGSCR = 'Apple script Desc'+slineBreak;
procedure TForm1.ApplescrClick(Sender: TObject);
var
Scr : NsAppleScript;
Err : Pointer;
begin
Err := nil;
Scr := TNSAppleScript.Wrap(TNSAppleScript.Alloc.initWithSource(StrToNSStr(STRINGSCR)));
Scr.executeAndReturnError(Err);
end;
こんな感じで動くと思います。
実際にはexecueAndReturnErrorはTryを使用した方が良いと思います。
Delphi でApple Scriptを使用する。
こんにちは、おひさしぶりやましょうです。
とはいいつつも師匠から、Apple scriptの使い方をと言われたので
こんな感じです。
あくまでも例:コンパイルもしていない。スペルミスもあるかも。。
uses
Macapi.Foundation,
Macapi.Helpers,
const STRINGSCR = 'Apple script Desc'+slineBreak;
procedure TForm1.ApplescrClick(Sender: TObject);
var
Scr : NsAppleScript;
Err : Pointer;
begin
Err := nil;
Scr := TNSAppleScript.Wrap(TNSAppleScript.Alloc.initWithSource(StrToNSStr(STRINGSCR)));
Scr.executeAndReturnError(Err);
end;
こんな感じで動くと思います。
実際にはexecueAndReturnErrorはTryを使用した方が良いと思います。
とはいいつつも師匠から、Apple scriptの使い方をと言われたので
こんな感じです。
あくまでも例:コンパイルもしていない。スペルミスもあるかも。。
uses
Macapi.Foundation,
Macapi.Helpers,
const STRINGSCR = 'Apple script Desc'+slineBreak;
procedure TForm1.ApplescrClick(Sender: TObject);
var
Scr : NsAppleScript;
Err : Pointer;
begin
Err := nil;
Scr := TNSAppleScript.Wrap(TNSAppleScript.Alloc.initWithSource(StrToNSStr(STRINGSCR)));
Scr.executeAndReturnError(Err);
end;
こんな感じで動くと思います。
実際にはexecueAndReturnErrorはTryを使用した方が良いと思います。
2016年11月2日水曜日
Delphi fmx タイトルバー無し フルスクリーン 表示方法
こんにちは、 やましょうです。
delphiで、fmx のフルスクリーン方法です。
form1.FullScreen := true;
以上です。
delphiで、fmx のフルスクリーン方法です。
form1.FullScreen := true;
以上です。
2016年2月29日月曜日
delphi 232c経由でi2cに送受信する。
こんにちは 。おひさしぶりのやましょうです。
ちょっとしたことからdelphiからi2cできれば楽ですね。。という
話になり。こんな感じで出来ました。
おきまりの青mbedのコードは下記です。
https://developer.mbed.org/users/yamasho/code/DelphiToI2c/
import して使用してください。
p9,p10にsda,sclとpull-up抵抗(5kくらいかな。。)をつければ動きます。
232cからのコマンドはこんな感じです。
1.PC=>I2C
0BYTE - 'O' ($4F)
1BYTE - 総送信バイト数
2BYTE - I2C ADDRESS (R/Wは含まず )
3BYTE - データ送信値
nBYTE - データ送信値[総送信バイト数-1]
戻り値 'T' 232C通信でエラー発生
戻り値 'S' I2C送信で送信成功
戻り値 'E' I2C送信でエラー発生
2.I2C=>PC
0BYTE - 'I' ($49)
1BYTE - 総受信バイト数
2BYTE - I2C ADDRESS (R/Wは含まず )
戻り値 'T' 232C通信でエラー発生
戻り値 'I' I2C送信で送信成功 +受信データ
戻り値 'E' I2C送信でエラー発生
3.I2C BUS速度決定
0BYTE - 'S' ($53)
1BYTE - 通信速度上位8BIT
2BYTE - 通信速度下位8BIT
戻り値 'T' 232C通信でエラー発生
戻り値 'S' I2C設定成功
動作中の画面はこれ、秋月さんの有機ELを使用しています。
(なんかアドレスの設定はできるのだが読み込み用に設定できない謎がある。)
Delphi側の送信はこんな感じでOK!
232Cのコンポーネントとかはご自由でどうぞ。。
procedure TMainForm.LcdCommnad(Dt1, Dt2 : Byte);
var
DataArray : array[0..15] of Byte;
begin
DataArray[0] := byte('O');
DataArray[1] := 3;
DataArray[2] := $03c shl 1; // write
DataArray[3] := dt1;
DataArray[4] := dt2;
Uni232C.Write( 5, @DataArray);
end;
procedure TMainForm.LcdDataOut();
var
DataArray : array[0..20] of Byte;
begin
DataArray[0] := byte('O');
DataArray[1] := 18;
DataArray[2] := $03c shl 1; // write //1
DataArray[3] := $40; //2
DataArray[4] := byte('A'); //3
DataArray[5] := byte('B'); //4
DataArray[6] := byte('C'); //5
DataArray[7] := byte('D'); //6
DataArray[8] := byte('E'); //7
DataArray[9] := byte('F'); //8
DataArray[10] := byte('G'); //9
DataArray[11] := byte('H'); //10
DataArray[12] := byte('I'); //11
DataArray[13] := byte('J'); //12
DataArray[14] := byte('K'); //13
DataArray[15] := byte('L'); //14
DataArray[16] := byte('M'); //15
DataArray[17] := byte('N'); //16
DataArray[18] := byte('O'); //17
DataArray[19] := byte('P'); //18
Uni232C.Write( 21 ,@DataArray);
end;
procedure TMainForm.Button2Click(Sender: TObject);
begin
LcdCommnad( $80,$01 );
sleep(10);
LcdCommnad( $80,$02 );
sleep(10);
LcdCommnad( $8b,$0c );
sleep(100);
LcdDataOut();
end;
procedure TMainForm.Button3Click(Sender: TObject);
var
str : String;
ret : integer;
i: byte;
Buffer: array [0 .. $3F] of byte;
DataArray : array[0..15] of Byte;
begin
FillChar(Buffer,Sizeof(Buffer),0);
ret := Uni232C.Read(64, @Buffer);
DataArray[0] := byte('O');
DataArray[1] := 2;
DataArray[2] := $03c shl 1; // write
DataArray[3] := $40;
// DataArray[4] := $40;
// DataArray[4] := byte('Z');
Uni232C.Write( 4, @DataArray);
sleep(5);
FillChar(Buffer,Sizeof(Buffer),0);
ret := Uni232C.Read(64, @Buffer);
if( Ret <= 0 ) then exit;
if Buffer[0] <> byte('S')then exit;
DataArray[0] := byte('I');
DataArray[1] := $16;
DataArray[2] := $03c shl 1; // write
Uni232C.Write( 5, @DataArray);
FillChar(Buffer,Sizeof(Buffer),0);
ret := Uni232C.Read(64, @Buffer);
str := '';
if( Ret >= 0) then
Label7.Text := 'Read Length:'+IntToHex(ret,8)
else
Label7.Text := 'Read Failed:ErrorCode'+IntTostr(ret) ;
if( Ret <= 0 ) then exit;
if Buffer[0] <> byte('I') then exit;
str := 'I:'+IntToHex(Buffer[1],2)+':';
for i := 2 to ret-1 do
str := str+ Char(Buffer[i]);
memo1.Lines.add(str);
end;
以上
やましょうでした。
ちょっとしたことからdelphiからi2cできれば楽ですね。。という
話になり。こんな感じで出来ました。
おきまりの青mbedのコードは下記です。
https://developer.mbed.org/users/yamasho/code/DelphiToI2c/
import して使用してください。
p9,p10にsda,sclとpull-up抵抗(5kくらいかな。。)をつければ動きます。
232cからのコマンドはこんな感じです。
1.PC=>I2C
0BYTE - 'O' ($4F)
1BYTE - 総送信バイト数
2BYTE - I2C ADDRESS (R/Wは含まず )
3BYTE - データ送信値
nBYTE - データ送信値[総送信バイト数-1]
戻り値 'T' 232C通信でエラー発生
戻り値 'S' I2C送信で送信成功
戻り値 'E' I2C送信でエラー発生
2.I2C=>PC
0BYTE - 'I' ($49)
1BYTE - 総受信バイト数
2BYTE - I2C ADDRESS (R/Wは含まず )
戻り値 'T' 232C通信でエラー発生
戻り値 'I' I2C送信で送信成功 +受信データ
戻り値 'E' I2C送信でエラー発生
3.I2C BUS速度決定
0BYTE - 'S' ($53)
1BYTE - 通信速度上位8BIT
2BYTE - 通信速度下位8BIT
戻り値 'T' 232C通信でエラー発生
戻り値 'S' I2C設定成功
動作中の画面はこれ、秋月さんの有機ELを使用しています。
(なんかアドレスの設定はできるのだが読み込み用に設定できない謎がある。)
Delphi側の送信はこんな感じでOK!
232Cのコンポーネントとかはご自由でどうぞ。。
procedure TMainForm.LcdCommnad(Dt1, Dt2 : Byte);
var
DataArray : array[0..15] of Byte;
begin
DataArray[0] := byte('O');
DataArray[1] := 3;
DataArray[2] := $03c shl 1; // write
DataArray[3] := dt1;
DataArray[4] := dt2;
Uni232C.Write( 5, @DataArray);
end;
procedure TMainForm.LcdDataOut();
var
DataArray : array[0..20] of Byte;
begin
DataArray[0] := byte('O');
DataArray[1] := 18;
DataArray[2] := $03c shl 1; // write //1
DataArray[3] := $40; //2
DataArray[4] := byte('A'); //3
DataArray[5] := byte('B'); //4
DataArray[6] := byte('C'); //5
DataArray[7] := byte('D'); //6
DataArray[8] := byte('E'); //7
DataArray[9] := byte('F'); //8
DataArray[10] := byte('G'); //9
DataArray[11] := byte('H'); //10
DataArray[12] := byte('I'); //11
DataArray[13] := byte('J'); //12
DataArray[14] := byte('K'); //13
DataArray[15] := byte('L'); //14
DataArray[16] := byte('M'); //15
DataArray[17] := byte('N'); //16
DataArray[18] := byte('O'); //17
DataArray[19] := byte('P'); //18
Uni232C.Write( 21 ,@DataArray);
end;
procedure TMainForm.Button2Click(Sender: TObject);
begin
LcdCommnad( $80,$01 );
sleep(10);
LcdCommnad( $80,$02 );
sleep(10);
LcdCommnad( $8b,$0c );
sleep(100);
LcdDataOut();
end;
procedure TMainForm.Button3Click(Sender: TObject);
var
str : String;
ret : integer;
i: byte;
Buffer: array [0 .. $3F] of byte;
DataArray : array[0..15] of Byte;
begin
FillChar(Buffer,Sizeof(Buffer),0);
ret := Uni232C.Read(64, @Buffer);
DataArray[0] := byte('O');
DataArray[1] := 2;
DataArray[2] := $03c shl 1; // write
DataArray[3] := $40;
// DataArray[4] := $40;
// DataArray[4] := byte('Z');
Uni232C.Write( 4, @DataArray);
sleep(5);
FillChar(Buffer,Sizeof(Buffer),0);
ret := Uni232C.Read(64, @Buffer);
if( Ret <= 0 ) then exit;
if Buffer[0] <> byte('S')then exit;
DataArray[0] := byte('I');
DataArray[1] := $16;
DataArray[2] := $03c shl 1; // write
Uni232C.Write( 5, @DataArray);
FillChar(Buffer,Sizeof(Buffer),0);
ret := Uni232C.Read(64, @Buffer);
str := '';
if( Ret >= 0) then
Label7.Text := 'Read Length:'+IntToHex(ret,8)
else
Label7.Text := 'Read Failed:ErrorCode'+IntTostr(ret) ;
if( Ret <= 0 ) then exit;
if Buffer[0] <> byte('I') then exit;
str := 'I:'+IntToHex(Buffer[1],2)+':';
for i := 2 to ret-1 do
str := str+ Char(Buffer[i]);
memo1.Lines.add(str);
end;
以上
やましょうでした。
登録:
投稿 (Atom)