Lazarus

Programming => LCL => Topic started by: Pe3s on March 21, 2023, 08:36:40 pm

Title: [SOLVED] Timer
Post by: Pe3s on March 21, 2023, 08:36:40 pm
Hello, I wanted to try to write a timer and it's easy with seconds. What do I need to do to separate hours, minutes, seconds

Code: Pascal  [Select][+][-]
  1. var
  2.   Form1: TForm1;
  3.   TimeOut: TDateTime;
  4.  
  5. implementation
  6.  
  7. {$R *.lfm}
  8.  
  9. function CTimer(ASecs: Integer): String;
  10. begin
  11.   Result := Format('%2d:%2.2d:%2.2d', [ASecs div 3600, ASecs mod 3600 div 60, ASecs mod 3600 mod 60]);
  12. end;
  13.  
  14. { TForm1 }
  15.  
  16. procedure TForm1.Timer1Timer(Sender: TObject);
  17. begin
  18.   Label1.Caption := CTimer(SecondsBetween(Now, TimeOut));
  19.   if Now > Timeout then
  20.   Timer1.Enabled := False;
  21. end;
  22.  
  23. procedure TForm1.Button1Click(Sender: TObject);
  24. var
  25.   Seconds: integer;
  26. begin
  27.   if TryStrToInt(Edit1.Text, Seconds) then
  28.   begin
  29.     TimeOut := IncSecond(Now, Seconds);
  30.     Timer1.Enabled := True;
  31.     Label1.Caption := CTimer(SecondsBetween(Now, TimeOut));
  32.   end
  33.   else
  34.     ShowMessage('Error in number of seconds');
  35. end;
  36.  
Title: Re: Timer
Post by: KodeZwerg on March 21, 2023, 09:11:14 pm
To generate from seconds a HH:MM:SS string, you can do:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   Secs: QWord;
  4. begin
  5.   if TryStrToQWord(Edit1.Text, Secs) then
  6.     begin
  7.       Label1.Caption := FormatDateTime('hh:nn:ss', Secs / SecsPerDay);
  8.     end;
  9. end;
Title: Re: Timer
Post by: Pe3s on March 21, 2023, 09:42:30 pm
@KodeZwerg, I mean how to separate setting the timer timer separately hours, minutes, seconds?

Title: Re: Timer
Post by: KodeZwerg on March 21, 2023, 09:57:24 pm
EncodeTime(Hour, Minute, Second, MilliSecond) ?

I still have no idea what you actual want.
Title: Re: Timer
Post by: KodeZwerg on March 21, 2023, 09:59:55 pm
Or the opposite...
DecodeTime(TDateTime, Hour, Minute, Second, MilliSecond) ?
Title: Re: Timer
Post by: cdbc on March 21, 2023, 10:41:08 pm
Hi
Given the granularity of ttimer is 1 millisecond...
Maybe these two methods can be of use to you:
Code: Pascal  [Select][+][-]
  1. { first from milliseconds to datetime }
  2. procedure TIsoTime.set_AsInteger(const aValue: ptrint); //bm
  3. var
  4.   H,M,S,MSec: word;
  5.   L: cardinal; // leftover can be a pretty high number :-)
  6. begin
  7.   // 14.08.2022 new implementation, stored as milliseconds per day
  8.   // formula: fIntTime = ((H*3600000) + (M*60000) + (S*1000) + MSec
  9.   //          H = fIntTime div 3600000; L = fIntTime mod 3600000
  10.   //          M = L div 60000; L = L mod 60000
  11.   //          S = L div 1000
  12.   //          MSec = L mod 1000
  13.   if aValue <> fIntTime then begin
  14.     fIntTime:= aValue;
  15.     H:= fIntTime div 3600000; L:= fIntTime mod 3600000;
  16.     M:= L div 60000; L:= L mod 60000;
  17.     S:= L div 1000;
  18.     MSec:= L mod 1000;
  19.     fTime:= EncodeTime(H,M,S,MSec);
  20.   end;
  21. end;
  22.  
And from datetime to milliseconds:
Code: Pascal  [Select][+][-]
  1. procedure TIsoTime.set_AsTime(const aValue: TDateTime);
  2. var
  3.   H,M,S,MSec: word;
  4. begin
  5.   if aValue <> fTime then begin
  6.     H:= 0; M:= 0; S:= 0; MSec:= 0;
  7.     DecodeTime(aValue,H,M,S,MSec);
  8.     fIntTime:= ((H*3600000)+(M*60000)+(S*1000)+MSec); { changed to include msecs //bm }
  9.     fTime:= EncodeTime(H,M,S,MSec);
  10.   end;
  11. end;
  12.  
So, get the hours, minutes, seconds & milliseconds from your user and calculate the "fIntTime" above and use that in your timer value...
The procedures should be turned into functions for ease of use in your case.
Hth - Regards Benny
Title: Re: Timer
Post by: Pe3s on March 22, 2023, 04:26:38 pm
@KodeZwerg, I'm talking about setting the countdown time, I want to set hours, minutes and seconds separately.

1.spinedit - hour
2.spinedit - minutes
3.spinedit - seconds
Title: Re: Timer
Post by: KodeZwerg on March 22, 2023, 04:51:05 pm
There is no possibility to set up the timer like you want it (with seperated values) but you can of course count them up and tell timer that value.
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   H, M, S: Integer;
  4.   Secs: UInt64;
  5. begin
  6.   if (TryStrToInt(Edit1.Text, H) and TryStrToInt(Edit2.Text, M) and TryStrToInt(Edit3.Text, S)) then
  7.     begin
  8.       Secs := S;
  9.       Secs := (M * SecsPerMin) + Secs;
  10.       Secs := (H * SecsPerHour) + Secs;
  11.       Label1.Caption := IntToStr(Secs);
  12.       Timer1.Interval := Secs * 1000;
  13.     end;
  14. end;
Title: Re: Timer
Post by: Pe3s on March 22, 2023, 06:30:34 pm
Thank you for your help :)

Title: Re: Timer
Post by: Pe3s on March 23, 2023, 10:54:59 am
I noticed that TTimer when setting the interval: 1000, distorts the time, is there any advice for this?
Title: Re: Timer
Post by: KodeZwerg on March 23, 2023, 11:08:21 am
I noticed that TTimer when setting the interval: 1000, distorts the time, is there any advice for this?
If you explain what you mean with "distorts time" we can help ;D
TTimer is based on milliseconds (1000 ms = 1 s)
But in general, TTimer is not that precise like a multimedia timer (on Windows) is.
Title: Re: Timer
Post by: Pe3s on March 23, 2023, 11:17:27 am
I set 20 seconds, the timer counts down from 18, which means it loses 1 second
Title: Re: Timer
Post by: KodeZwerg on March 23, 2023, 11:45:16 am
Since you do not show how you are doing, use my example and document the place where you think it does fail.
Title: Re: Timer
Post by: alpine on March 23, 2023, 11:48:27 am
I set 20 seconds, the timer counts down from 18, which means it loses 1 second

In order to sample something (in your case - time in seconds) without distortion, you must sample it with a higher rate than the Nyquist rate (https://en.wikipedia.org/wiki/Nyquist_rate). If the highest frequency of the signal is (1/1s=1Hz) then <500ms. Your timer interval must be less than 500.
Title: Re: Timer
Post by: Pe3s on March 23, 2023, 12:36:33 pm
Great, both solutions work. Thank you :)
Have a nice day
Title: Re: Timer
Post by: alpine on March 24, 2023, 09:03:52 am
Great, both solutions work. Thank you :)
Have a nice day
If the accuracy is important, I wouldn't count on a solution which decrements the seconds by itself rather than calculating a delta from the saved timestamp at the beginning. TTimer works with WM_TIMER messages and the docs says they can be coalesced when not processed quickly enough. Also any delay in processing may sum up into a cumulative error.
Title: Re: Timer
Post by: KodeZwerg on March 24, 2023, 04:47:40 pm
Great, both solutions work. Thank you :)
Have a nice day
If the accuracy is important, I wouldn't count on a solution which decrements the seconds by itself rather than calculating a delta from the saved timestamp at the beginning. TTimer works with WM_TIMER messages and the docs says they can be coalesced when not processed quickly enough. Also any delay in processing may sum up into a cumulative error.
If you mean my example, I decrement in one timer each second a value to display but other timer (the real) is not harmed by it ...
TinyPortal © 2005-2018