|
Post by Rod on Apr 20, 2023 10:49:16 GMT -5
If the simple clock program keeps going then it has to be program flow or com port issues. Only by logging your com port looping and activity will you get a handle on where it is getting hung up. A simple print will let you know it is still active. But far better to print the entry to each block of code till you pin down where it gets blocked.
|
|
|
Post by Rod on Apr 20, 2023 10:52:41 GMT -5
You might also consider a watch variable, a variable that counts up but gets reset on completion of a loop. So if the completion never gets done and it exceeds a value then report failure.
|
|
Nuno
Junior Member
Posts: 64
|
Post by Nuno on Apr 20, 2023 11:03:30 GMT -5
When this happens, have you gone into the Device Manager and checked that the port is still active or looked at a logic analyzer prior to bringing the window back into the foreground or otherwise activating it in any other way? {:0) Brandon Parker Good point! Will do just that. See what is going on. ************************************************* EDIT *********************************** Logic analyser shows that activity on the COM port follows exactly what the software does. Windows device manager is not altered in any way. The COM in question is always there ************************************************* EDIT *********************************** Tested COM port with some other Windows utility. No issues found.
Thanks
|
|
Nuno
Junior Member
Posts: 64
|
Post by Nuno on Apr 20, 2023 11:27:49 GMT -5
You might also consider a watch variable, a variable that counts up but gets reset on completion of a loop. So if the completion never gets done and it exceeds a value then report failure. Good debugging technique. Will try ****************************** EDIT 20/4 ******************************** Can see that the routine that handles communications, "sendpacket", gets halted when the problem happens. Once the L.B. is back in foreground, the racing, or fast forward, of software counter happens. Can also see that when this happens, the counter racing always starts at the point (or so it seems) where the L.B. window was sent to background Still investigating this further. Will keep updating the results
|
|
Nuno
Junior Member
Posts: 64
|
Post by Nuno on Apr 21, 2023 12:50:28 GMT -5
Update of the investigation described in previous posts: Was able to determine that problem is random in nature. It doesn't need a certain amount of time, or a set of circunstances, that I can see, to happen. When it does happen, the subroutine that handles the COM port is simply not called. However, my bigger outside loop "refreshes" all settings timer related. And when that happens, if L.B. is in the foreground, communications are resumed. It does not resume communications with the refresh loop if in background. Rod, I belive you were right. Code flow is the likely culprit. Haven't been able to determine the exact cause yet. Still under investigation. Getting mysterious as I get depper into it... Could you enligthen me on what diferences exist between a foreground, and a background L.B. window? Other than the already mentioned graphic segments memory
Thank you
|
|
|
Post by Rod on Apr 21, 2023 13:29:41 GMT -5
Well the program is probably “waiting” somewhere. The only way to know where is to print the location of the program flow. It might sound tedious but it will point you in the right direction.
Don’t know how well you know the debugger but you might also use animate, the triple arrow and watch the code run, but it may disappear into the background. Printing a log is the cast iron solution.
|
|
Nuno
Junior Member
Posts: 64
|
Post by Nuno on Apr 21, 2023 13:51:12 GMT -5
Well the program is probably “waiting” somewhere. The only way to know where is to print the location of the program flow. It might sound tedious but it will point you in the right direction. Don’t know how well you know the debugger but you might also use animate, the triple arrow and watch the code run, but it may disappear into the background. Printing a log is the cast iron solution. Been doing just that. Problem is: I've to wait for the problem to happen. Can be as quick as less then 5 min. Can take well over an hour. Have "prints" pretty much everywhere I can think of. I've started to suspect of the keyboard or mouse handlers. The main loop only ends when a timed variable is set, if either of 2 keys are pressed, or certain mouse locations clicked. Although no keys are pressed while L.B. is in the foreground, once in background, Windows is used for many other things that use keyboard and mouse aplenty.
|
|
|
Post by Walt Decker on Apr 21, 2023 18:51:41 GMT -5
I have had LB do strange things and give strange errors that I have had to work around. What I have done is create a window and instead of using a timer I use this functon:
' FUNCTION FN.Wait(Ms)
RetVal = 0 CALLDLL #kernel32, "Sleep", Ms AS LONG, RetVal AS VOID
RetVal = FN.YourComFunctionHere() SCAN END FUNCTION '
In your COM routine print the results to a file with a time stamp. That may give you a little better clue to what is happening.
Hide your window and minimize the IDE and see what happens.
|
|
|
Post by Rod on Apr 22, 2023 1:23:47 GMT -5
Windows keyboard and mouse input only reach Liberty while it is active. If you are expecting general mouse and keyboard activity to prompt Liberty thst just won’t happen. Drive the com port read with a timer event just like your clock update. And watch you don’t get caught with the crossing midnight issue where the time is suddenly never greater. There are no strange errors, Liberty must be twenty years old now, all strangeness is gone. Only newbie confusion persists. But if you have enthusiasm you can make Liberty do anything Windows is capable off.
|
|
Nuno
Junior Member
Posts: 64
|
Post by Nuno on Apr 22, 2023 2:58:00 GMT -5
Windows keyboard and mouse input only reach Liberty while it is active. If you are expecting general mouse and keyboard activity to prompt Liberty thst just won’t happen. Drive the com port read with a timer event just like your clock update. And watch you don’t get caught with the crossing midnight issue where the time is suddenly never greater. There are no strange errors, Liberty must be twenty years old now, all strangeness is gone. Only newbie confusion persists. But if you have enthusiasm you can make Liberty do anything Windows is capable off. Helpfull advice. No keyboard or mouse to worry about. Still scratching my head though...
|
|
Nuno
Junior Member
Posts: 64
|
Post by Nuno on Apr 22, 2023 3:08:27 GMT -5
I have had LB do strange things and give strange errors that I have had to work around. What I have done is create a window and instead of using a timer I use this functon: ' FUNCTION FN.Wait(Ms)
RetVal = 0 CALLDLL #kernel32, "Sleep", Ms AS LONG, RetVal AS VOID
RetVal = FN.YourComFunctionHere() SCAN END FUNCTION '
In your COM routine print the results to a file with a time stamp. That may give you a little better clue to what is happening. Hide your window and minimize the IDE and see what happens. Thanks for the advice. But that's a bit over my current knowledge. I'm an hardware engineer with lots of experience in assembly code, but a high level programming language novice. I can see that it uses something else as a possible time check? Mind explaining a bit further what exactly is going on with your function, please?
My COM routine writes directly to the COM port, and receives a response a few miliseconds later. When called, everything goes well (or so it seems...). I've been able to determine that, when problem happens, the COM routine is not even called (or exited without doing a thing...). The main program does not freeze though Could give it a try and write everything to a file as you suggested. But for now, I'm more inclined to issues with code flow
Thank you
|
|
|
Post by Rod on Apr 22, 2023 5:50:30 GMT -5
Everywhere you enter a loop, or start a gosub, print a log before you enter the loop or gosub. Anywhere you have a WAIT print a log just ahead of the WAIT. Anywhere you have a SCAN print a log just ahead of the SCAN. These are the branching points for program flow.
|
|
|
Post by Walt Decker on Apr 22, 2023 9:25:43 GMT -5
Exactly. I am a retired engineering geologist. Break your code up into functions instead of GOTOs and GOSUBs and WAITs. They are like miniture programs. You would have one function open the com port, one function to receive the data one function to transmit data, one function to plot data and one function to close the com port. As a person who has an assembler language background I am sure you have used functions in the past. A function in a high level language is the same thing except you do not have to save the registers, push variables onto the stack and pop them off, and restore the stack when the function completes. The high level language takes care of all that. Here is a little pseudo-code example: ' CheckPort = FN.OpenPort(PortNum)
IF CheckPort < 1 THEN PRINT "PORT "; PortNum; " NOT OPEN" END END IF
RetVal = FN.WAIT(150, PortNum) END
FUNCTION FN.WAIT(Ms, PortNum) [AGAIN] ReadData$ = FN.GetDataPack$(PortNum)
IF ReadData$ = "" THEN PRINT "NO MORE DATA" EXIT FUNCTION END IF
'here you could print or plot your data by calling a print or plot function with ReadData$ as the function argument.
CALLDLL #kernel32, "Sleep", Ms AS LONG, RetVal AS VOID 'Sleep releases program time slice for Ms seconds
SCAN : GOTO [ATAIN]'scan determines if there are any events to take care of END FUCNTION
FUNCTION FN.OpenPort(Num)
OPEN PORT Num Check port
FN.OpenPort = Check END FUNCTION
FUNCTION FN.GetDataPack$(Port)
GetData$ FN.GetDataPack$ = GetData$ END FUNCTION '
This breaks your code up into easily manageable modules that will alway return to the same place.
PS: Unless the TIMER is disabled an event is triggered every timer ms regardless of where the code pointer is. The FN.WAIT() function allows for an event only after other tasks are completed.
|
|
Nuno
Junior Member
Posts: 64
|
Post by Nuno on Apr 22, 2023 10:05:42 GMT -5
Break your code up into functions instead of GOTOs and GOSUBs and WAITs. They are like miniture programs. You would have one function open the com port, one function to receive the data one function to transmit data, one function to plot data and one function to close the com port. As a person who has an assembler language background I am sure you have used functions in the past. A function in a high level language is the same thing except you do not have to save the registers, push variables onto the stack and pop them off, and restore the stack when the function completes. The high level language takes care of all that. High level programming isn't entirely new to me. Learned the basics back in PASCAL times (oldie, but goodie). Functions, Procedures, Sub-routines & Co are well known to me. Liberty Basic, and Windows environment, are the new chalenge!
"CALLDLL #kernel32, "Sleep", Ms AS LONG, RetVal AS VOID 'Sleep releases program time slice for Ms seconds"
I think I got your point with this function. Thank you
|
|
Nuno
Junior Member
Posts: 64
|
Post by Nuno on Apr 23, 2023 5:02:07 GMT -5
I've a new suspect on this issue: As can be seen from my previous post on the structure of my working loops, there's this "inner" cycle that repeats itself every second, and updates the clock. This "inner" cycle is included within a bigger cycle that repeats itself every minute. Within this "bigger" cycle, a #graph, "flush" command was issued every minute. Hugely simplified, would look like this: do ' Hourly cycle . . call COM subroutine call COM subroutine call COM subroutine . do ' OUTER cycle #graph, "flush" . . call COM subroutine . do ' INNER cycle #graph, "|";time$() ' GREATLY SIMPLIFIED. THERE'S ONLY 1 UPDATE EVERY TIME THE time$() CHANGES#graph, "discard" . . until seconds<>previousseconds ' Seconds cycle until minutes<>previousminutes ' Minutes cycle until hour<>previoushour With above code flow, the reported problem of no COM port sub-routine being called was happening. When the outermost "hourly" cycle repeated, the COM routine would be called ONLY if L.B. was in the foreground. And all subsequent COM calls would happen normally, while L.B. stayed in foreground. The "flush" command is now outside the "OUTER" cycle. Within another even longer timed cycle that repeats every hour or so. do ' Hourly cycle . . call COM subroutine call COM subroutine call COM subroutine . #graph, "flush" do ' OUTER cycle . . call COM subroutine . do ' INNER cycle #graph, "|";time$() ' GREATLY SIMPLIFIED. THERE'S ONLY 1 UPDATE EVERY TIME THE time$() CHANGES#graph, "discard" . . until seconds<>previousseconds ' Seconds cycle until minutes<>previousminutes ' Minutes cycle until hour<>previoushour Under these new code flow conditions, problem hasn't happen yet. Several hours of it already. Does this make any sense? Or is it just a matter of more time until it happens again? any ideas of what migth be behind? Note: Regardless of these problems, everytime the COM routine is called, I get exactly what is intended. No missing codes both ways
Thank you *********************************************** EDIT ********************************************************
It did happen.
I made a log file that records when the COM routine is called. It showed that at random intervals, there will be no calls to that routine. These intervals happen at no specific time that I can determine. They also last for an indeterminate amount of time.
The mystery deppens...
Walt Decker,
Your function now seems a good option
CALLDLL #kernel32, "Sleep", Ms AS LONG, RetVal AS VOID
Going to give it a try
|
|