SetTimer event issue

General FreeBASIC programming questions.
Post Reply
Tonigau
Posts: 36
Joined: Feb 25, 2021 20:19

SetTimer event issue

Post by Tonigau »

I am making a simple RS485 Data-logger for an AC power meter. Using Win7px64, FreeBASIC-1.07.2-win32
Just using dummy data for now until I get real hardware.
It is working ok except I am having trouble getting a consistent log period time (typically 1000ms)

First: I had a loop in a sub to test timer + log-period but the loop was getting killed by the winapi? & period was randomly short. (I didn't like waiting in the loop.)

Second try: I set 'Start1 = Timer' in Sub Get_Data & tested in the main loop 'If Timer > Start1+Log-interval' Then Get_Data
This worked but needed mouse to move over Window_Main to get correct period time.

Fourth try: I used 'SetTimer(Window_Main, 0, 1000, 0 )'' & timer event in 'Select Case msg.hwnd' of main loop, this didn't work but if I changed the 'Select Case msg.hwnd' to 'Select Case msg.message' the timer works (with the DEBUG line un-commented as the mouseup events stop working), but still some period time anomaly.


So If someone can have a look it will be most helpful.


sorry about the indenting(Tabs), it displays ok in my IDE (FbEdit)

Main Code: Also need WinGUI.bi to compile

Code: Select all

'-------------------------------------------------
' AC301L_GUI_Logger.bas V0.10 - FreeBasic code
' App To Get Data from AC301L PWR monitor & save To CSV file
' Created on 2023-10-09  ToniG
' Last Update 2023-10-17
' V0.10 - In Dev... 
' 
' KWS-AC301L_logcollect.py used for reference  - Thanks kutasg'  
'-------------------------------------------------


' This program is WIP....

'TooDoo:
'		Startup init File
'		Error Handling 
'     Log time period issue
'     Display end of log    (API does not have AppendText, only SetText)
'		
'		

#Include "WinGUI.bi"
#Include "AC301L_Logger.bi"

Dim Shared As HWND Window_Main, LogWindow, Editor2, FnameTextBox, FnameEditBox, COMnTextBox, Btn_StrtLog, Btn_StopLog, Btn_Copy, Btn_TstCom, Btn_ClrLog, Btn_Fname, Btn_Exit, Group1
Dim Shared As HWND Edit_Font, Check1, Button_State, Radio1, Radio2, Group2
Dim Shared As HFONT hFont
Dim Shared As HWND Label_txt2

Dim As MSG msg												' Shared vars in dev...
Dim As Long x0, y0, W1, H1, Rpos, Vpos1, Vpos2
Dim As Integer Chk1State, Chk2State, BtnX, pos1, pos2  
Dim As String Text1, Text2, HelpTxt1, FnameText
Dim Shared As String  CR_LF, CSV_Line, LogWindowText, CsvHdr, FileHdr, Time_, Date_
Dim Shared As Double Start1
Dim Shared As Integer LineNo 'LogStart 'StopLog
Dim Shared As Byte LogState ' 4 states of logging (start, stopped, running, paused) 
Const Strt_ = 10
Const Stop_ = 20
Const Run_  = 30
Const Paus_ = 40

'#define ID_TIMER    1

Declare Sub LogError (InMessage As String, Origin As String = "")
Declare Sub MsgBox (Window_Main As HWND, InMessage As String, Origin As String)
Declare Sub Get_Data
Declare Sub ChkEvent


'  Change to Constants...
  W1 = 1050	   ' Window Width
  H1 = 720     ' Window Height
  Vpos1 = 40   ' Editor 1
  Vpos2 = 410  ' Editor 2
  Rpos = 210   ' Right ref
  BtnX = 30    ' Button x ref
  CR_LF = Chr(13, 10)
  Text1 = "Input:   DataLog Window.   "
  'Text2 = "Output:   Data Table.           "
 											' Note: --* Position & size are set in resize event *--
'  Create a window with text editor, buttons, etc...
	Window_Main = Window_New	(500, 100, W1, H1, "AC301L PWR Mon Logger V0.10   2023.10.23")
'                               X    Y   W   H
	LogWindow = Editor_New		   (20, 40, 800, 500, "",, Window_Main)
'	FnameTextBox = EditBox_New	(W1-200, 210, 175, 20, "DataLog_01.csv", WS_TABSTOP Or ES_READONLY, Window_Main)
	FnameTextBox = EditBox_New	(W1-200, 210, 175, 20, "DataLog_01.csv",, Window_Main)
	COMnTextBox = EditBox_New	(W1-200, 235, 50, 20, "COM3",, Window_Main)
	
	Var Label_txt1 = Label_New	(30, Vpos1 -20, 400, 20, Text1,, Window_Main)
	Label_txt2 = Label_New	(700, Vpos1 -20, 350, 20, "Logger Stopped ",, Window_Main) '< not "Var xxx" on this line to enable change text
	'Var Label_txt2 = Label_New	(30, Vpos2 - 20, 800, 20, Text2,, Window_Main)

	Btn_TstCom = Button_New		(W1-180, 100, 100, 40, "Test Comm",, Window_Main)
	Btn_ClrLog = Button_New		(W1-180, 100, 100, 40, "Clear Log",, Window_Main)
	Btn_Fname = Button_New		(W1-195, 160, 100, 40, "File Name",, Window_Main)
	Btn_StrtLog = Button_New		(W1-180, 100, 100, 40, "Start Log",, Window_Main)
	Btn_StopLog = Button_New		(W1-180, 100, 100, 40, "Stop Log",, Window_Main)
	Btn_Copy = Button_New		(W1-180, 100, 100, 40, "Copy All",, Window_Main)
	Btn_Exit = Button_New		(W1-180, 100, 100, 40, "EXIT",, Window_Main)
	Check1 = CheckBox_New		(W1-180, 100, 150, 20, "Remember settings",, Window_Main)
'	Check2 = CheckBox_New		(W1-180, 100, 150, 20, "Include String Len",, Window_Main)
	CheckBox_SetCheck				(Check1, 0)
'	CheckBox_SetCheck				(Check2, 0)
	Group2 = GroupBox_New	(W1-180, 100, 100, 70, "Index Pointers", Window_Main)	
	Radio1 = RadioButton_New	(W1-180, 100, 100, 20, "Start   Values", WS_GROUP, Window_Main)	'new group of radio buttons
	Radio2 = RadioButton_New	(W1-180, 100, 100, 20, "Start - End Values",, Window_Main)
	Group1 = GroupBox_New		(W1-180, 100, W1-10, H1-10, "", Window_Main) ' Main window border
'	X, Y, W, H, are set in Window resize event (& form open)
   RadioButton_SetCheck(Radio1, 1)


' Fonts
'-----------------------------------
hFont = Control_Createfont("Courier New",,, FW_BOLD)
Control_SetFont(LogWindow), hFont
Control_SetFont(Editor2), hFont

	' Quick Help splash
'-------------------------------	
	HelpTxt1 = CR_LF +  "Info:"  
	HelpTxt1 &= CR_LF +  "       Simple  DataLogger for AC301-L Power Display, NOT tested yet on real hardware" + CR_LF 
	HelpTxt1 &= CR_LF + "  Comms is RS485 (2 wire Bidirectional 5V differential signal) "
	HelpTxt1 &= CR_LF + "          * There is no error checking yet (program may hang on error) "
	HelpTxt1 &= CR_LF + "          * ."
	HelpTxt1 &= CR_LF + "  "
	HelpTxt1 &= CR_LF +  "          ComTest gets 1 record from AC301-L "
	HelpTxt1 &= CR_LF +  "          While each log is retrieved buttons are un-responsive "
	HelpTxt1 &= CR_LF + "  "
	HelpTxt1 &= CR_LF +  "          It is advised to put 10V TVS protection devices on each 485 line to Mains EARTH !"
	HelpTxt1 &= CR_LF +  "          The AC301 display is a Mains voltage device, leakage or fault may damage connected equipment"
	HelpTxt1 &= CR_LF +  "          or electric shock hazard. Could also fit a trusted RS485 Isolator"
	HelpTxt1 &= CR_LF +  "          AC301-L has isolated comms but do you trust these cheap products !!!"
   HelpTxt1 &= CR_LF +  "                                              [Circuit not assesed yet]"
	HelpTxt1 &= CR_LF + CR_LF + " Edit the filename text  "
	HelpTxt1 &= CR_LF + CR_LF + "     --- This App is WIP, expect some issues ---  "  
	EditBox_SetText(LogWindow, HelpTxt1)

	
'	
FileHdr = "Data Log from AC301L AVPower Meter display"
CsvHdr = "Record"+", " + Fieldname(1) + ", " + Fieldname(2) + ", " + Fieldname(3) + ", " + Fieldname(4) _ 
+ ", " + Fieldname(5) + ", " + Fieldname(6) + ", " + Fieldname(7) + ", " + Fieldname(8) + ", " + Fieldname(9) + ", " + "TimeStamp" + ", " + "Log Date"
	

	LogState = Stop_  'initial state	

' Datalogging
'---------------------------------------------------
Sub StartLog 'Open files & write headers
	    Date_ = Date
'	    Date_ = Format(Date_, yyyy-mm-dd)Date     ' < Not Working...
	    LogLineNum = 0
	    FnumCOM = FreeFile
'	    Open Com COMn & ":9600,n,8,1,CD,CS,DS,RS,BIN" For Binary As FnumCOM' #2 ' (control lines disable)
	    FnumCSV = FreeFile
       Open LogFileName For Binary As FnumCSV
       EditBox_SetText(LogWindow, (FileHdr + "  " +Date_ + CR_LF + CR_LF))
       LogWindowText = EditBox_GetText(LogWindow)
       'LogWindowText &= CsvHdr + CR_LF
       EditBox_SetText(LogWindow, (LogWindowText + CsvHdr + CR_LF))
       'EditBox_SetText(LogWindow, LogWindowText) 
       Print #FnumCSV, CsvHdr 
End Sub  
 
Sub Get_Data	 
	 	Read_AC301 (FnumCOM, SendReq())
	 	Write_LogFile (FnumCSV,SendReq())	' get data & save each record
      LogLineNum += 1
''		Start1 = Timer			' reset log period counter
End Sub

Sub Read_AC301 (FnumCOM As Byte, SendReq() As LongInt)
	  Dim LP1 As Integer
	  Time_ = Time
	  Date_ = Date
	For LP1 = 1 To 9
	  Put #FnumCOM,, SendReq(LP1)		' request data from AC301
	 '' Print Err  <DEBUG
	  		 
	  Sleep 25	' wait ms... for TX done before read value from buffer array
	  'Value(LP1) = Val(Input(LOC(1), 2))   '<- Just for now until know input...
'	  Get #COMn,, ReadValue(LP)
	  'ReadValue(LP1) = Val(ReadValue(LP1)) 	
'	  ReadValue(LP1) = ReadValue(LP1) * Multiplier(LP1)
	Next
End Sub

Sub Write_LogFile (FnumCSV As Byte,SendReq() As LongInt)
	Dim LP1 As Integer
	' Build CSV line
	CSV_Line = Str(LogLineNum)+ ", "
	For LP1 = 1 To 9
'		Put #FnumCSV,, Str(SendReq(LP1))
	CSV_Line &=  Str(LogValue(LP1)) '+ "  "
	If LP1 < 9 Then CSV_Line &= ", " 'Else CSV_Line &= CR_LF
'		Print #FnumCSV, Str(SendReq(LP1));", ";  	 
	Next
	  
	  CSV_Line &= ", " + Time_ + ",  " +Date_
	  LogWindowText = EditBox_GetText(LogWindow) ' Windows.bi does not have 'AppendText'
'	  LogWindowText &= CSV_Line + CR_LF
	  EditBox_SetText(LogWindow, (LogWindowText + CSV_Line + CR_LF))
'	  EditBox_SetText(LogWindow, LogWindowText)
	  Print #FnumCSV, CSV_Line
'	  Print #FnumCSV,
End Sub
'---------------------------------------------------



SetTimer(Window_Main, 0, 1000, 0 )			'<4th>


 Do     'Main loop to check WinAPI event states: 
	
	WaitEvent(Window_Main, msg)
	Select Case msg.hwnd
'	Select Case msg.message	  '<4th>   '< Timer works but with inconsistent period [but no buttons events]
			
		Case WM_TIMER									'<4th>
			If LogState = Run_ Then Get_Data
'			Get_Data  '<<<-- DEBUG ONLY to test timer

		Case Btn_TstCom
			If msg.message = WM_LBUTTONUP Then
			  EditBox_Paste(LogWindow)
			End If

		Case Btn_ClrLog
			If msg.message = WM_LBUTTONUP Then
'			  EditBox_Clear(LogWindow) '< This clears selected text
			  EditBox_SetText(LogWindow,"")
			  LogWindowText = ""
			End If  		
           
		Case Btn_Fname
			If msg.message = WM_LBUTTONDOWN Then
'				FnameText = InputBox(1000, 100, 300, "LogFile", "Enter FileName:", "DataLog_01.csv")
'				EditBox_SetText(FnameTextBox, FnameText)
			End If

		Case Btn_StrtLog
			If msg.message = WM_LBUTTONUP Then
				'EditBox_GetText(Edit_Text)
				If LogState = Stop_ Then   
					LogFileName = EditBox_GetText(FnameTextBox)
					SetWindowText(Btn_StrtLog, "Pause Log")  ' windows.bi command
					StartLog
				   LogState = Run_ 
				Else 			
					If LogState = Run_ Then	
						LogState = Paus_
						SetWindowText(Btn_StrtLog, "Continue")  
					Else
						If LogState = Paus_ Then	LogState = Run_
						SetWindowText(Btn_StrtLog, "Pause Log")  
					End If
				EndIf
	'	     		Start1 = Timer
			End If

		Case Btn_StopLog
			If msg.message = WM_LBUTTONUP Then
		      LogState = Stop_
		     	Close FnumCSV
	  	     	Close FnumCOM
	  	     	SetWindowText(Btn_StrtLog, "Start Log")
			End If	

		Case Btn_Exit
			If msg.message = WM_LBUTTONUP Then
'			SendMessage(Window_Main, WM_CLOSE,0,0)' this just removed KBD focus
'			DestroyWindow(Window_Main) '< Close window but exe still run as task
'			PostQuitMessage(0)			'< Seems to do nothing
			  Exit Do						'< Exit Application ok                
			End If			

		Case Btn_Copy		
         If msg.message = WM_LBUTTONUP Then
            SetFocus(LogWindow)   							'< This SelectALL!
            SendMessage(LogWindow, EM_SETSEL, 0, -1) '< SelectAll(Does not work)
            pos1 = LoWord(SendMessage(LogWindow, EM_GETSEL, 0, 0))
            pos2 = HiWord(SendMessage(LogWindow, EM_GETSEL, 0, 0))
            EditBox_Copy(LogWindow)
            'Print "pos1="; pos1; "pos2="; pos2 		  ' <DEBUG
         End If


	  Case Else	
		 'Resize/Repos Controls x if window size change
       Window_GetSize(Window_Main, x0, y0, W1, H1)

       Control_Resize(LogWindow, 20, Vpos1, W1-Rpos-10, 630)
       'Control_Resize(Editor2, 20, Vpos2, W1-Rpos, 250)
       Control_Resize(FnameTextBox, W1-185, 210, 175, 20)
       Control_Resize(COMnTextBox, W1-185, 235, 50, 20)
       
       ''COMnTextBox = EditBox_New	(W1-200, 235, 50, 20, "COM3",, Window_Main)
'       Control_Resize(InputBox, W1-(Rpos-300), Vpos1 + 170, 300)       'InputBox doesnt have height value so cant 'Control_Resize' 
       'Control_Resize(InputBox, 100, 100, 300, "LogFile", "Enter FileName:", "DataLog_01.csv")
       
       Control_Resize(Btn_TstCom, W1-(Rpos-BtnX), Vpos1, 100, 40)
       Control_Resize(Btn_ClrLog, W1-(Rpos-BtnX), Vpos1 + 60, 100, 40)
       Control_Resize(Btn_Fname, W1-(Rpos-BtnX), Vpos1 + 120, 100, 40)
       Control_Resize(Btn_StrtLog, W1-(Rpos-BtnX), Vpos1 + 220, 100, 40)
       Control_Resize(Btn_StopLog, W1-(Rpos-BtnX), Vpos1 + 280, 100, 40)
       Control_Resize(Btn_Copy, W1-(Rpos-BtnX), Vpos2 + 150, 100, 40)  
       Control_Resize(Btn_Exit, W1-(Rpos-BtnX), H1- 60, 100, 40)       
       Control_Resize(Check1,	W1-(Rpos-BtnX), Vpos1 + 350, 160, 20)
'       Control_Resize(Check2,	W1-(Rpos-BtnX), Vpos1 + 315, 160, 20)
       Control_Resize(Group2, W1-(Rpos-(BtnX)+4), Vpos1 + 40 + 365, 165, 70)	
		 Control_Resize(Radio1, W1-(Rpos-BtnX),     Vpos1 + 40 + 385, 150, 20)	'new group of radio buttons
		 Control_Resize(Radio2, W1-(Rpos-BtnX),     Vpos1 + 40 + 410, 150, 20)
 
       Control_Resize(Group1,x0+7, y0+5, W1-13, H1-11) '< Main window border

'		 W1 = 1050, H1 = 720, Vpos1 = 40, Vpos2 = 410, Rpos = 210, BtnX = 30  
                 			
	End Select
					' this might not need here if shared As
	Chk1State = CheckBox_GetCheck(Check1)  ' Capture state of checkbox

'-------------------------------------------------
''   This works with 'Start1 = Timer' set in GetData Sub, but only correct period if mous moved over window. 	
'	If LogState = Run_  Then 
'		If Timer > Start1+LogInterval  Then Get_Data   ' 1 line at a time
'	EndIf
'-------------------------------------------------

	If LogState = Stop_ Then LogLineNum = 0                 
	If LogState = Stop_ Then Label_SetText(Label_txt2, "Logger Stopped " )
	If LogState = Paus_ Then Label_SetText(Label_txt2, "Logger Paused " )
	If LogState = Strt_ Then Label_SetText(Label_txt2, "Logger Starting " )
	If LogState =  Run_ Then Label_SetText(Label_txt2, "Logger Running " ) 
	  
 Loop Until Window_Event_Close(Window_Main, msg)



	Control_DeleteFont(hFont) ' < If exit pressed
End

'Wait until window is closed:
Do
	WaitEvent(Window_Main, msg) ' How to test this code(file write?)
Loop Until Window_Event_Close(Window_Main, msg)

'Delete font:
''	Control_DeleteFont(hFont)
End





AC301L_Logger.bi

Code: Select all


' Freebasic code - ToniG 2023.10.13 V0.1
'Arrays & inits inc for AC301L Logger 'AC301L_GUI_Logger.bas' 
' Original python code used for reference & snippets. - Thanks kutasg

' This program is WIP....


Dim Shared SendReq(1 To 9) As LongInt
Dim Shared ReadValue(1 To 9) As Double => {0, 0, 0, 0, 0, 0, 0, 0, 0}	' Value from AC301
Dim Shared LogValue(1 To 9) As Double => {0, 0, 0, 0, 0, 0, 0, 0, 0}	' Value save to logfile
Dim Shared Fieldname (1 To 9) As String
Dim Shared Multiplier(1 To 9) As Double
Dim Shared LogFileName As String
Dim Shared As Integer StopLog, FnumCOM, FnumCSV, LogLineNum 

'Dim As LongInt LogInterval 			's
Dim Shared As Double  LogInterval
'Dim As Long Start1, LogInterval
'Dim As Integer LP1
Dim Shared As String COMn

'Dim Shared

'Declare Sub OpenIO()
'Declare Sub CloseIO()
Declare Sub Process_Data()
Declare Sub Write_LogFile(FnumCSV As Byte,SendReq() As LongInt)
Declare Sub Read_AC301(As Byte, () As LongInt) ' (COMn, Array)
Declare Sub PrintLog (LogWindow As HWND, CSV_Line As String)

' Defaults & init values
'-------------------------
' CSV list Header
Fieldname(1) = "Volt"
Fieldname(2) = "Amp"
Fieldname(3) = "Watt"
Fieldname(4) = "Time"
Fieldname(5) = "kWh"
Fieldname(6) = "PF"
Fieldname(7) = "??"
Fieldname(8) = "Hz"
Fieldname(9) = "degC"

'Default multipliers
Multiplier(1) = 10.0
Multiplier(2) = 1000.0
Multiplier(3) = 10.0
Multiplier(4) = 1
Multiplier(5) = 1000.0
Multiplier(6) = 100.0
Multiplier(7) = 1
Multiplier(8) = 10.0
Multiplier(9) = 1

'Value(1) = 0

' Send requests to AC301L
SendReq(1) = &h0203000E0001E5FA
SendReq(2) = &h0203000F0002F43B
SendReq(3) = &h020300110002943D
SendReq(4) = &h02030019000155FE
SendReq(5) = &h020300170002743C
SendReq(6) = &h0203001D0001143F
SendReq(7) = &h0203001F0001B5FF
SendReq(8) = &h0203001E0001E43F
SendReq(9) = &h0203001A0001A5FE
 
' Temp for tsting values
LogValue(1) = 235
LogValue(2) = 5.3
LogValue(3) = 1245.5
LogValue(4) = 46
LogValue(5) = 1057.6
LogValue(6) = 0.90
LogValue(7) = 235
LogValue(8) = 50.0
LogValue(9) = 29.4


' LogInterval = 0.75 ' seconds 
' COMn = "COM1"


'-------------------------


Last edited by Tonigau on Oct 17, 2023 22:40, edited 2 times in total.
Lothar Schirm
Posts: 441
Joined: Sep 28, 2013 15:08
Location: Germany

Re: SetTimer event issue

Post by Lothar Schirm »

I think the timer identifier should be nonzero. And the first part of the message loop looks a bit strange. Should it be like this?

Code: Select all

SetTimer(Window_Main, 1, 1000, 0 )			'<4th>

 Do     'Main loop to check WinAPI event states: 
	
	WaitEvent(Window_Main, msg)

	Select Case msg.message	  '<4th>   '< Timer works but with inconsistent period [but no buttons events]
			
		Case WM_TIMER									'<4th>
			If LogState = Run_ Then Get_Data
'			Get_Data  '<<<-- DEBUG ONLY to test timer

	End Select

	Select Case msg.hwnd

		Case Btn_TstCom
			If msg.message = WM_LBUTTONUP Then
			  EditBox_Paste(LogWindow)
			End If
			
		.........
Tonigau
Posts: 36
Joined: Feb 25, 2021 20:19

Re: SetTimer event issue

Post by Tonigau »

Thank you Lothar, that works.
I did try a separate Select Case at one point but my references? were wrong.

But I have an issue of the Case WM_TIMER being true when the mouse is moved, specifically when moved between WindowMain & LogWindow right or bottom edge. making a new log record additional to the timer log.
Can see this behavior best if comment out line 194 SetTimer(Window_Main, 1, 1000, 0 )

It looks like the timer timeout state is interfered by the WM_MOUSMOVE ?


Main Code:

Code: Select all

'-------------------------------------------------
' AC301L_GUI_Logger.bas V0.10 - FreeBasic code
' App To Get Data from AC301L PWR monitor & save To CSV file
' Created on 2023-10-09  ToniG
' Last Update 2023-10-17
' V0.10 - In Dev...
'
' KWS-AC301L_logcollect.py used for reference  - Thanks kutasg'
'-------------------------------------------------


' This program is WIP....

'TooDoo:
'     Startup init File
'     Error Handling
'     Log time period issue
'     Display end of log    (API does not have AppendText, only SetText)
'
'

#Include "WinGUI.bi"
#Include "AC301L_Logger.bi"

Dim Shared As HWND Window_Main, LogWindow, Editor2, FnameTextBox, FnameEditBox
Dim Shared As HWND COMnTextBox, Btn_StrtLog, Btn_StopLog, Btn_Copy, Btn_TstCom
Dim Shared As HWND Btn_ClrLog, Btn_Fname, Btn_Exit, Group1, Label_txt2
Dim Shared As HWND Edit_Font, Check1, Button_State, Radio1, Radio2, Group2
Dim Shared As HFONT hFont


Dim As MSG msg                                  ' Shared vars in dev...
Dim As Long x0, y0, W1, H1, Rpos, Vpos1, Vpos2
Dim As Integer Chk1State, Chk2State, BtnX, pos1, pos2
Dim As String Text1, Text2, HelpTxt1, FnameText
Dim Shared As String  CR_LF, CSV_Line, LogWindowText, CsvHdr, FileHdr, Time_, Date_
Dim Shared As Double Start1
Dim Shared As Integer LineNo 'LogStart 'StopLog
Dim Shared As Byte LogState ' 4 states of logging (start, stopped, running, paused)
Const Strt_ = 10
Const Stop_ = 20
Const Run_  = 30
Const Paus_ = 40

'#define ID_TIMER    1

Declare Sub LogError (InMessage As String, Origin As String = "")
Declare Sub MsgBox (Window_Main As HWND, InMessage As String, Origin As String)
Declare Sub Get_Data
Declare Sub ChkEvent


'  Change to Constants...
  W1 = 1050    ' Window Width
  H1 = 720     ' Window Height
  Vpos1 = 40   ' Editor 1
  Vpos2 = 410  ' Editor 2
  Rpos = 210   ' Right ref
  BtnX = 30    ' Button x ref
  CR_LF = Chr(13, 10)
  Text1 = "Input:   DataLog Window.   "
  'Text2 = "Output:   Data Table.           "
                                 ' Note: --* Position & size are set in resize event *--
'  Create a window with text editor, buttons, etc...
   Window_Main = Window_New   (500, 100, W1, H1, "AC301L PWR Mon Logger V0.10   2023.10.23")
'                               X    Y   W   H
   LogWindow = Editor_New     (20, 40, 800, 500, "",, Window_Main)
'  FnameTextBox = EditBox_New (W1-200, 210, 175, 20, "DataLog_01.csv", WS_TABSTOP Or ES_READONLY, Window_Main)
   FnameTextBox = EditBox_New (W1-200, 210, 175, 20, "DataLog_01.csv",, Window_Main)
   COMnTextBox = EditBox_New  (W1-200, 235, 50, 20, "COM1",, Window_Main)

   Var Label_txt1 = Label_New (30, Vpos1 -20, 400, 20, Text1,, Window_Main)
   Label_txt2 = Label_New  (700, Vpos1 -20, 350, 20, "Logger Stopped ",, Window_Main) '< not "Var xxx" on this line to enable change text
   'Var Label_txt2 = Label_New   (30, Vpos2 - 20, 800, 20, Text2,, Window_Main)

   Btn_TstCom = Button_New    (W1-180, 100, 100, 40, "Test Comm",, Window_Main)
   Btn_ClrLog = Button_New    (W1-180, 100, 100, 40, "Clear Log",, Window_Main)
   Btn_Fname = Button_New     (W1-195, 160, 100, 40, "File Name",, Window_Main)
   Btn_StrtLog = Button_New      (W1-180, 100, 100, 40, "Start Log",, Window_Main)
   Btn_StopLog = Button_New      (W1-180, 100, 100, 40, "Stop Log",, Window_Main)
   Btn_Copy = Button_New      (W1-180, 100, 100, 40, "Copy All",, Window_Main)
   Btn_Exit = Button_New      (W1-180, 100, 100, 40, "EXIT",, Window_Main)
   Check1 = CheckBox_New      (W1-180, 100, 150, 20, "Remember settings",, Window_Main)
'  Check2 = CheckBox_New      (W1-180, 100, 150, 20, "Include String Len",, Window_Main)
   CheckBox_SetCheck          (Check1, 0)
'  CheckBox_SetCheck          (Check2, 0)
   Group2 = GroupBox_New   (W1-180, 100, 100, 70, "Index Pointers", Window_Main)
   Radio1 = RadioButton_New   (W1-180, 100, 100, 20, "Start   Values", WS_GROUP, Window_Main)   'new group of radio buttons
   Radio2 = RadioButton_New   (W1-180, 100, 100, 20, "Start - End Values",, Window_Main)
   Group1 = GroupBox_New      (W1-180, 100, W1-10, H1-10, "", Window_Main) ' Main window border
'  X, Y, W, H, are set in Window resize event (& form open)
   RadioButton_SetCheck(Radio1, 1)


' Fonts
'-----------------------------------
hFont = Control_Createfont("Courier New",,, FW_BOLD)
Control_SetFont(LogWindow), hFont
Control_SetFont(Editor2), hFont

   ' Quick Help splash
'-------------------------------
   HelpTxt1 = CR_LF +  "Info:"
   HelpTxt1 &= CR_LF +  "       Simple  DataLogger for AC301-L Power Display, NOT tested yet on real hardware" + CR_LF
   HelpTxt1 &= CR_LF + "  Comms is RS485 (2 wire Bidirectional 5V differential signal) "
   HelpTxt1 &= CR_LF + "          * There is no error checking yet (program may hang on error) "
   HelpTxt1 &= CR_LF + "          * ."
   HelpTxt1 &= CR_LF + "  "
   HelpTxt1 &= CR_LF +  "          ComTest gets 1 record from AC301-L "
   HelpTxt1 &= CR_LF +  "          While each log is retrieved buttons are un-responsive "
   HelpTxt1 &= CR_LF + "  "
   HelpTxt1 &= CR_LF +  "          It is advised to put 10V TVS protection devices on each 485 line to Mains EARTH !"
   HelpTxt1 &= CR_LF +  "          The AC301 display is a Mains voltage device, leakage or fault may damage connected equipment"
   HelpTxt1 &= CR_LF +  "          or electric shock hazard. Could also fit a trusted RS485 Isolator"
   HelpTxt1 &= CR_LF +  "          AC301-L has isolated comms but do you trust these cheap products !!!"
   HelpTxt1 &= CR_LF +  "                                              [Circuit not assesed yet]"
   HelpTxt1 &= CR_LF + CR_LF + " Edit the filename text  "
   HelpTxt1 &= CR_LF + CR_LF + "     --- This App is WIP, expect some issues ---  "
   EditBox_SetText(LogWindow, HelpTxt1)


FileHdr = "Data Log from AC301L AVPower Meter display"
CsvHdr = "Record"+", " + Fieldname(1) + ", " + Fieldname(2) + ", " + Fieldname(3) + ", " + Fieldname(4) _
+ ", " + Fieldname(5) + ", " + Fieldname(6) + ", " + Fieldname(7) + ", " + Fieldname(8) + ", " + Fieldname(9) + ", " + "TimeStamp" + ", " + "Log Date"

   LogState = Stop_  'initial state
   LogInterval = 0.75 ' seconds
'   COMn = "COM1"

' Datalogging
'---------------------------------------------------
Sub StartLog 'Open files & write headers
       Date_ = Date
'      Date_ = Format(Date_, yyyy-mm-dd)Date     ' < Not Working...
       LogFileName = RTrim(EditBox_GetText(FnameTextBox))
              COMn = RTrim(EditBox_GetText(COMnTextBox))
       LogLineNum = 0
       FnumCOM = FreeFile
''       Open Com COMn & ":9600,n,8,1,CD,CS,DS,RS,BIN" For Binary As FnumCOM' #2 ' (control lines disable)
       FnumCSV = FreeFile
       Open LogFileName For Binary As FnumCSV
       EditBox_SetText(LogWindow, (FileHdr + "  " +Date_ + CR_LF + CR_LF))
       LogWindowText = EditBox_GetText(LogWindow)
       'LogWindowText &= CsvHdr + CR_LF
       EditBox_SetText(LogWindow, (LogWindowText + CsvHdr + CR_LF))
       'EditBox_SetText(LogWindow, LogWindowText)
       Print #FnumCSV, CsvHdr
End Sub

Sub Get_Data
      Read_AC301 (FnumCOM, SendReq())
      Write_LogFile (FnumCSV,SendReq())   ' get data & save each record
      LogLineNum += 1
''    Start1 = Timer       ' reset log period counter
End Sub

Sub Read_AC301 (FnumCOM As Byte, SendReq() As LongInt)
     Dim LP1 As Integer
     Time_ = Time
     Date_ = Date
   For LP1 = 1 To 9
     Put #FnumCOM,, SendReq(LP1)    ' request data from AC301
    '' Print Err  <DEBUG

     Sleep 25  ' wait ms... for TX done before read value from buffer array
     'Value(LP1) = Val(Input(LOC(1), 2))   '<- Just for now until know input...
'    Get #COMn,, ReadValue(LP)
     'ReadValue(LP1) = Val(ReadValue(LP1))
'    ReadValue(LP1) = ReadValue(LP1) * Multiplier(LP1)
   Next
End Sub

Sub Write_LogFile (FnumCSV As Byte,SendReq() As LongInt)
    Dim LP1 As Integer
    ' Build CSV line
      CSV_Line = Str(LogLineNum)+ ", "
    For LP1 = 1 To 9
'     Put #FnumCSV,, Str(SendReq(LP1))
      CSV_Line &=  Str(LogValue(LP1)) '+ "  "
      If LP1 < 9 Then CSV_Line &= ", " 'Else CSV_Line &= CR_LF
'     Print #FnumCSV, Str(SendReq(LP1));", ";
    Next

      CSV_Line &= ", " + Time_ + ",  " +Date_
      LogWindowText = EditBox_GetText(LogWindow) ' Windows.bi does not have 'AppendText'
'     LogWindowText &= CSV_Line + CR_LF
      EditBox_SetText(LogWindow, (LogWindowText + CSV_Line + CR_LF))
'     EditBox_SetText(LogWindow, LogWindowText)
      Print #FnumCSV, CSV_Line
'     Print #FnumCSV,
End Sub
'---------------------------------------------------

 SetTimer(Window_Main, 1, 1000, 0 )  ' <- with disabled, Case WM_TIMER is true when
                                      ' mousemove(WM_MOUSEMOVE) Between Window_main & LogWindow
                                      '                              (Right & bottom edge only)

 Do     'Main loop to check WinAPI event states:

   WaitEvent(Window_Main, msg)
   
   Select Case msg.message
      Case WM_TIMER                          '<4th>
         If LogState = Run_ Then Get_Data
'        Get_Data  '<<<-- DEBUG ONLY to test timer

   End Select

   Select Case msg.hwnd
      Case Btn_TstCom
         If msg.message = WM_LBUTTONUP Then
            EditBox_Paste(LogWindow)
         End If

      Case Btn_ClrLog
         If msg.message = WM_LBUTTONUP Then
'           EditBox_Clear(LogWindow) '< This clears selected text
            EditBox_SetText(LogWindow,"")
            LogWindowText = ""
         End If

      Case Btn_Fname
         If msg.message = WM_LBUTTONDOWN Then
'           FnameText = InputBox(1000, 100, 300, "LogFile", "Enter FileName:", "DataLog_01.csv")
'           EditBox_SetText(FnameTextBox, FnameText)
         End If

      Case Btn_StrtLog
         If msg.message = WM_LBUTTONUP Then
            If LogState = Stop_ Then
               SetWindowText(Btn_StrtLog, "Pause Log")  ' windows.bi command
               StartLog
               LogState = Run_
            Else
               If LogState = Run_ Then
                  LogState = Paus_
                  SetWindowText(Btn_StrtLog, "Continue")
               Else
                  If LogState = Paus_ Then   LogState = Run_
                  SetWindowText(Btn_StrtLog, "Pause Log")
               End If
            EndIf
   '           Start1 = Timer
         End If

      Case Btn_StopLog
         If msg.message = WM_LBUTTONUP Then
            LogState = Stop_
            Close FnumCSV
            Close FnumCOM
            SetWindowText(Btn_StrtLog, "Start Log")
         End If

      Case Btn_Exit
         If msg.message = WM_LBUTTONUP Then
'        SendMessage(Window_Main, WM_CLOSE,0,0)' this just removed KBD focus
'        DestroyWindow(Window_Main) '< Close window but exe still run as task
'        PostQuitMessage(0)         '< Seems to do nothing
         If LogState <> Stop_ Then
            Close FnumCSV
            Close FnumCOM
         EndIf
           'Open  FnumSET
           '  Save Settings...
           'Close FnumSET
           Exit Do                  '< Exit Application ok
         End If

      Case Btn_Copy
         If msg.message = WM_LBUTTONUP Then
            SetFocus(LogWindow)                       '< This SelectALL!
            SendMessage(LogWindow, EM_SETSEL, 0, -1) '< SelectAll(Does not work)
            pos1 = LoWord(SendMessage(LogWindow, EM_GETSEL, 0, 0))
            pos2 = HiWord(SendMessage(LogWindow, EM_GETSEL, 0, 0))
            EditBox_Copy(LogWindow)
            'Print "pos1="; pos1; "pos2="; pos2         ' <DEBUG
         End If

     Case Else
       'Resize/Repos Controls x if window size change
       Window_GetSize(Window_Main, x0, y0, W1, H1)
       Control_Resize(LogWindow, 20, Vpos1, W1-Rpos-10, 630)
       Control_Resize(FnameTextBox, W1-185, 210, 175, 20)
       Control_Resize(COMnTextBox, W1-185, 235, 50, 20)

'       Control_Resize(InputBox, W1-(Rpos-300), Vpos1 + 170, 300)       'InputBox doesnt have height value so cant 'Control_Resize'
       'Control_Resize(InputBox, 100, 100, 300, "LogFile", "Enter FileName:", "DataLog_01.csv")

       Control_Resize(Btn_TstCom, W1-(Rpos-BtnX), Vpos1, 100, 40)
       Control_Resize(Btn_ClrLog, W1-(Rpos-BtnX), Vpos1 + 60, 100, 40)
       Control_Resize(Btn_Fname, W1-(Rpos-BtnX), Vpos1 + 120, 100, 40)
       Control_Resize(Btn_StrtLog, W1-(Rpos-BtnX), Vpos1 + 220, 100, 40)
       Control_Resize(Btn_StopLog, W1-(Rpos-BtnX), Vpos1 + 280, 100, 40)
       Control_Resize(Btn_Copy, W1-(Rpos-BtnX), Vpos2 + 150, 100, 40)
       Control_Resize(Btn_Exit, W1-(Rpos-BtnX), H1- 60, 100, 40)
       Control_Resize(Check1, W1-(Rpos-BtnX), Vpos1 + 350, 160, 20)
'       Control_Resize(Check2,   W1-(Rpos-BtnX), Vpos1 + 315, 160, 20)
       Control_Resize(Group2, W1-(Rpos-(BtnX)+4), Vpos1 + 40 + 365, 165, 70)
       Control_Resize(Radio1, W1-(Rpos-BtnX),     Vpos1 + 40 + 385, 150, 20)  'new group of radio buttons
       Control_Resize(Radio2, W1-(Rpos-BtnX),     Vpos1 + 40 + 410, 150, 20)  ' to be deleted...

       Control_Resize(Group1,x0+7, y0+5, W1-13, H1-11) '< Main window border
'      W1 = 1050, H1 = 720, Vpos1 = 40, Vpos2 = 410, Rpos = 210, BtnX = 30    < just for ref.

   End Select
               ' this might not need here if shared As
   Chk1State = CheckBox_GetCheck(Check1)  ' Capture state of checkbox

'-------------------------------------------------
''   This works with 'Start1 = Timer' set in GetData Sub, but only correct period if mouse moved over window.
'  If LogState = Run_  Then       ' (Need to test what is stealing time from main loop)
'     If Timer > Start1+LogInterval  Then Get_Data   ' 1 line at a time
'  EndIf
'-------------------------------------------------

   If LogState = Stop_ Then LogLineNum = 0
   If LogState = Stop_ Then Label_SetText(Label_txt2, "Logger Stopped " )
   If LogState = Paus_ Then Label_SetText(Label_txt2, "Logger Paused " )
   If LogState = Strt_ Then Label_SetText(Label_txt2, "Logger Starting " )
   If LogState =  Run_ Then Label_SetText(Label_txt2, "Logger Running " )

 Loop Until Window_Event_Close(Window_Main, msg)



   Control_DeleteFont(hFont) ' < If exit pressed
End

'Wait until window is closed:
Do
   WaitEvent(Window_Main, msg) ' How to test this code(file write?)
Loop Until Window_Event_Close(Window_Main, msg)

'Delete font:
'' Control_DeleteFont(hFont)
End



Can see extra log records (same stime stamp)
Image
Lothar Schirm
Posts: 441
Joined: Sep 28, 2013 15:08
Location: Germany

Re: SetTimer event issue

Post by Lothar Schirm »

Tonigau wrote: Oct 17, 2023 22:38 It looks like the timer timeout state is interfered by the WM_MOUSMOVE ?
Maybe. I found this in Win32_fb.chm in the description of WM_TIMER:

Remarks
The DispatchMessage function forwards this message when no other messages are in the thread's message queue.
Tonigau
Posts: 36
Joined: Feb 25, 2021 20:19

Re: SetTimer event issue

Post by Tonigau »

ok,
I will try to find how to filter the rogue win32api message to the timer case.
It seems maybe related to scroll bars (or where they would be)
Tonigau
Posts: 36
Joined: Feb 25, 2021 20:19

Re: SetTimer event issue

Post by Tonigau »

Ok, I didn't get anywhere with trying to isolate the Timer ID '1' (second param in SetTimer) in the WM message so I will only respond to the specific timer message event.

I did a hack that works well enough for now until maybe I get a better handle on the W32 message events.
The unwanted event message i am sure is when mouse-over the scroll bars of the edit window.

Here is the mitigating code in Sub Get_Data (but it does not address the root cause of my issue)

Code: Select all

If Timer < TimerPrev + (LogInterval * 1.25) Then Exit Sub
TimerPrev = Timer 
There is a small jitter in the log period but it is not an issue.
Tonigau
Posts: 36
Joined: Feb 25, 2021 20:19

Re: SetTimer event issue

Post by Tonigau »

After some discussion & research, it appears there is a timer associated with the EditBox scroll bars, when the mouseover's the scroll bar the 'Case WM_TIMER' is capturing all Timer messages so this gives additional logs.

I have tried but so far without success to filter the WM_TIMER message to capture only the Timer ID "1" specified in SetTimer(Window_Main, 1, 1000, 0 ).

I will start a new thread in Windows section
Post Reply