Hi,
I have raised this issue before but it is lying unresolved till now.
The VB application is communicating through serial port for data acquisition from 21 microcontroller based instruments which respond against a ASCII code.Now to keep the main code window clean I have kept the communication in a public function of a module.
The relevant form code looks something like this:
Code:
Option Explicit
Public timeoutdelay As Integer
Public serdatain As Boolean
Public serial_in_buffer As String
Public serial_in_count As String
Public timeoutflag As Boolean
Public errorflag As Boolean
'This button starts the data acquisition process
Private Sub cmd_start_Click()
Dim instrumentstring(20) As String
Dim instrumentdata(20) As Single
Dim instrumentcode(20) As Byte
Dim i As Byte
Dim j As Byte
Dim k As Byte
On Error GoTo errorhandler_1
readdata:
For i = 0 To 20
instrumentcode(i) = Asc(Chr$(97 + i)) 'fil array with "w"
Next
'get all the possible 21 data
For i = 0 To 20
Call get_instrument_data(instrumentcode(i))
instrumentstring(i) = serial_in_buffer
instrumentdata(i) = Val(instrumentstring(i))
Next
.................................................................................
'Here we insert code to populate an excel worksheet with the data
...............................................................................
GoTo readdata 'go on acquiring data
Exit Sub
errorhandler_1:
MsgBox "Fatal error", vbOKOnly + vbExclamation, "Error"
End Sub
'The MSComm event procedure
Private Sub MSComm1_OnComm()
Select Case MSComm1.CommEvent
Case comEvReceive
serial_in_buffer = serial_in_buffer & MSComm1.Input
Debug.Print serial_in_buffer
serdatain = True
serial_in_count = serial_in_count + 1
Case Else
MsgBox "Communication error", vbOKOnly + vbExclamation, "error"
Exit Sub
End Select
End Sub
The instrument calling function looks something like this which is in a separate module:
Code:
Function get_instrument_data(code As Byte) As String
'first clear the strings to hold the data & initialize booleans
frm.serial_in_buffer = vbNullString
frm.serdatain = False
frm.serial_in_count = 0
frm.errorflag = False
frm.MSComm1.PortOpen = True '
frm.MSComm1.Output = Chr$(code)
'at the same time enable timer for timeout protection
frm.Timer1.Enabled = True
frm.Timer1.Interval = frm.timeoutdelay
frm.timeoutflag = True
'wait for reception to start.If it does not start within
'timeout1 period then abort
While frm.serdatain = False
DoEvents
If frm.timeoutflag = False Then 'close port
frm.MSComm1.PortOpen = False
frm.Timer1.Enabled = False 'stop timer
MsgBox "Cannot get data", vbOKOnly + vbExclamation, "Error"
frm.errorflag = True
Exit Function
End If
Wend
'after first character is received stop (& reset) timer
frm.Timer1.Enabled = False
'after start of reception wait for 34 characters which comprise
'each string
While frm.serial_in_count < 34
DoEvents
Wend
frm.MSComm1.PortOpen = False 'close port which also clears receive & send buffers
End Function
My problem is that form unloading is not closing my application which is still shown as running by the windows task manager.I have tried the following:
1.A Boolean in the form unload procedure to close down the data acquisition loop.
2.I have closed the MSComm port & timer1 in the form unload procedure.
Only an "END" statement in the form unload procedure is closing my application which I think is recommended by nobody.
How to properly close my application without "END"?
i do not see any unloading code, how are you closing the program? how many forms in your project? do you have a timer that is still running?, or code running after in the sub you call unload me, after the unload me statement
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
Private Sub Form_Unload(Cancel As Integer)
If MSComm1.PortOpen = True Then
MSComm1.PortOpen = False
End If
If Timer1.Enabled = True Then
Timer1.Enabled = False
End If
'excelfile.Quit
Set excelsheet = Nothing
excelbook.SaveAs "D:\VB_programs\WPIL_vb\test_excel"
excelbook.Close savechanges:=True
Set excelbook = Nothing
excelfile.Quit
Set excelfile = Nothing
'End
End Sub
I have a splash form which is being unloaded by a timer & another "on-demand " form which is loaded & unloaded from one of the menu items.
I have closed all the timers
Hi,
The messagebox says "1". So I think we can assume that only one form is open at the end of the unload procedure.
Another point: This application closing problem is occuring only after I start the MSComm communication from the cmd_start button.If serial port communication is not established then there is no problem in closing the application normally & the "END" statement is not needed.
I assume that "'Here we insert code to populate an excel worksheet with the data" means that you aren't showing us all your code. Can you post it all please?
Hi,
What I am, doing as of now is nothing but opening & closing the excel file in the form load & form unload procedures respectively.I am not populating the excel file with the MSComm data.The opening of the excel file is as follows
Code:
Set excelfile = New Excel.Application
Set excelbook = excelfile.Workbooks.Add
Set excelsheet = excelfile.Worksheets(1)
excelfile.Visible = True
excelfile.WindowState = xlMinimized
I was just thinking since I am new to VB.....does unloading a form also mean unloading of the corresponding modules?If not then perhaps,putting the data acquisition function inside the form code itself then would help unloading?
Hi,
What I am, doing as of now is nothing but opening & closing the excel file in the form load & form unload procedures respectively.I am not populating the excel file with the MSComm data.The opening of the excel file is as follows
Code:
Set excelfile = New Excel.Application
Set excelbook = excelfile.Workbooks.Add
Set excelsheet = excelfile.Worksheets(1)
excelfile.Visible = True
excelfile.WindowState = xlMinimized
I was just thinking since I am new to VB.....does unloading a form also mean unloading of the corresponding modules?If not then perhaps,putting the data acquisition function inside the form code itself then would help unloading?
What do you mean by "the corresponding modules"? Are you setting the three Excel objects to Nothing someplace?
In my first post I have mentioned that to keep my form code window clean I have put the communication code in public function of a separate module.This has also been possible since the communication with the 21 instruments is generic in nature.
This is the "module" that I am talking abouit.When the cmd_start button is clicked the application mainly works in this module waiting for the MSComm data to appear at the port & transferring it to the corresponding string variables. When the form unloads ,does this module also unloads itself?
So what can be the problem?
In the VB6 IDE,when I try to close the application using the windows "x" button, the form window is disappearing ,but the "start" button remains greyed out & the "end" button remains active indicating that the application is still running somewhere in the background.Only after pressing the "end" button twice or thrice can I close the application.Also I cannot detect the position of the "bug" by the debug tools i.e break ,single stepping etc. which become non -functional at this point of time.
Sorry but I'm out of ideas except to say that I just found your other thread and if I had to guess I'd say that your problem still has something to do with the way you are using Excel.
try stepping through the code when you unload and see if any code is still running make sure that your objects are still in scope when the unload code is running as i don't see anywhere you declare the 3 excel objects, is it in the general section of the form?
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
Hi Westconn1,
I tried single stepping through the form unloading code and found the following code module still revolving in the following infinite loop though the form vanishes from the IDE/:
Code:
While frm_wpil_02.serdatain = False
DoEvents
If frm.timeoutflag = False Then 'close port
frm.MSComm1.PortOpen = False
frm.Timer1.Enabled = False 'stop timer
MsgBox "Cannot get data", vbOKOnly + vbExclamation, "Error"
frm.errorflag = True
Exit Function
End If
Wend
Obviously unloading the form is not unloading this particular code module due to some reason.
I declared a public Boolean "endprocess" in the form & modified the form unload procedure & the function in the following way:
Code:
option explicit
public endprocess Boolean
Private Sub Form_Unload(Cancel As Integer)
Unload Me
endprocess = True
If MSComm1.PortOpen = True Then
MSComm1.PortOpen = False
End If
If Timer1.Enabled = True Then
Timer1.Enabled = False
End If
'excelfile.Quit
Set excelsheet = Nothing
excelbook.SaveAs "D:\VB_programs\WPIL_vb\test_excel"
excelbook.Close savechanges:=True
Set excelbook = Nothing
excelfile.Quit
Set excelfile = Nothing
'End
End Sub
Here is the modified module code:
Code:
While frm_wpil_02.serdatain = False
DoEvents
If frm_wpil_02.endprocess = True Then
Exit Function
ElseIf frm_wpil_02.timeoutflag = False Then 'close port
frm_wpil_02.MSComm1.PortOpen = False
frm_wpil_02.Timer1.Enabled = False 'stop timer
MsgBox "Cannot get data", vbOKOnly + vbExclamation, "Error"
frm_wpil_02.errorflag = True
Exit Function
End If
Wend
Even that did not work & though the program exited from the module it the form code started running once again(observed by single stepping) as if the entire form has not been unloaded even a single bit(All this happening with the form vanished from the IDE)
Hi Martin Liss,
Setting the form to nothing did not help.
maybe I have to go on single stepping the form unload procedure untill I get any more ideas.
Thanks anyway.
Regards
Hi Martin Liss,
Sorry for the delay in replying.I am zipping & sending the entire VB project as it is.
But to test the MSComm control properly you shall need another PC in lieu of the microcontroller based instrument which we are using.Can you manage that?
Since I obviously can't actually get any data from the pumps I may not be able to reproduce the problem. In any case while testing I've noticed a few small things.
In get_instrument_data you set errorflag to True but you never test anyplace for the value of the flag
I can enter invalid values such as 150 into the motor efficiency textbox
You have the Excel spreadsheet visible. Did you mean to do that?
I believe I may have found the cause of your problem. Any time you reference a control on a form, that form will be loaded (but not necessarily shown). In your case when you Unload frm_wpil_02 the function get_instrument_data is still looping and in that function you have the line frm_wpil_02.MSComm1.PortOpen = False which since it references a control on the form wiill load the form. I'm now trying to see if I can fix that.
Hi Martin,
Thanks for taking such a keen interest in my codes,which I know you definitely found to be very amateurish.
The errorflag was inserted with an idea which was later on discarded.
I have not written any codes for the motor efficiency textbox as yet.
The excel spreadsheet has to be made visible so that the pump testing operator can enter some typical curves against which the real time acquired parameters shall be checked.
Okay I've made a few changes but since I can't actually run the program properly I can't tell if it fixes the problem of the form reloading but at least they should get you on the right path. Here is what I did.
Code:
Public Sub delay()
frm_wpil_02.Timer1.Interval = frm_wpil_02.timeoutdelay
frm_wpil_02.timeoutflag = True
'new
'frm_wpil_02.Timer1.Enabled = True 'start timer
If Not frm_wpil_02.endprocess Then
frm_wpil_02.Timer1.Enabled = True
End If
While frm_wpil_02.timeoutflag = True
DoEvents
Wend 'wait for timeout
frm_wpil_02.Timer1.Enabled = False 'stop timer
End Sub
At the top of frm_wpil_02.Form_Load
Code:
Private Sub Form_Load()
init_grids 'initialize the grids
timeoutdelay = timeoutdelay_ini 'initialize values
button_true.Value = True
system = True
flow1flag = True
flow2flag = False
flow3flag = False
flow4flag = False
'new
' endprocess = False
If endprocess Then
Exit Sub
End If
Code:
Private Sub Form_Unload(Cancel As Integer)
'new
'Unload Me
'Set frm_wpil_02 = Nothing
'frm_wpil_02.endprocess = True
'
'If MSComm1.PortOpen = True Then
' MSComm1.PortOpen = False
'End If
'
'If Timer1.Enabled = True Then
' Timer1.Enabled = False
'End If
'excelfile.Quit
Set excelsheet = Nothing
'excelbook.SaveAs "D:\VB_programs\WPIL_vb\test_excel"
excelbook.Close savechanges:=True
Set excelbook = Nothing
excelfile.Quit
Set excelfile = Nothing
'Set frm_wpil_02 = Nothing
'End
'new
frm_wpil_02.endprocess = True
Timer1.Enabled = False
End Sub
Code:
Function get_instrument_data(code As Byte) As String
'first clear the strings to hold the voltage data & initialize booleans
frm_wpil_02.serial_in_buffer = vbNullString
frm_wpil_02.serdatain = False
frm_wpil_02.serial_in_count = 0
frm_wpil_02.errorflag = False
frm_wpil_02.MSComm1.PortOpen = True '
frm_wpil_02.MSComm1.Output = Chr$(code)
'at the same time enable timer for timeout protection
'new
'frm_wpil_02.Timer1.Enabled = True
'frm_wpil_02.Timer1.Interval = frm_wpil_02.timeoutdelay
If Not frm_wpil_02.endprocess Then
frm_wpil_02.Timer1.Enabled = True
frm_wpil_02.Timer1.Interval = frm_wpil_02.timeoutdelay
End If
frm_wpil_02.timeoutflag = True
'wait for reception to start.If it does not start within
'timeout1 period then abort
While frm_wpil_02.serdatain = False
DoEvents
If frm_wpil_02.endprocess = True Then
Exit Function
ElseIf frm_wpil_02.timeoutflag = False Then 'close port
frm_wpil_02.MSComm1.PortOpen = False
frm_wpil_02.Timer1.Enabled = False 'stop timer
' MsgBox "Cannot get data", vbOKOnly + vbExclamation, "Error"
Debug.Print "Cannot get data"
frm_wpil_02.errorflag = True
Exit Function
End If
Wend
'after first character is received stop (& reset) timer
frm_wpil_02.Timer1.Enabled = False
'after start of reception wait for 34 characters which comprise
'each string
While frm_wpil_02.serial_in_count < 1
DoEvents
Wend
frm_wpil_02.MSComm1.PortOpen = False 'close port which also clears receive & send buffers
End Function
I also changed this at the bottom of cmd_start because "Fatal error" by itself is not very informative. In my case the fatal error was "port already open".
Hi Martin,
Your detection was bang on target & auto form reloading is definitely the problem.But though the endprocess flag is preventing the form from reloading the program is oscillating between following three areas:
Function get_instrument_data(code As Byte) As String
'first clear the strings to hold the voltage data & initialize booleans
frm_wpil_02.serial_in_buffer = vbNullString
frm_wpil_02.serdatain = False
frm_wpil_02.serial_in_count = 0
frm_wpil_02.errorflag = False
frm_wpil_02.MSComm1.PortOpen = True '
frm_wpil_02.MSComm1.Output = Chr$(code)
'at the same time enable timer for timeout protection
'new
'frm_wpil_02.Timer1.Enabled = True
'frm_wpil_02.Timer1.Interval = frm_wpil_02.timeoutdelay
If Not frm_wpil_02.endprocess Then
frm_wpil_02.Timer1.Enabled = True
frm_wpil_02.Timer1.Interval = frm_wpil_02.timeoutdelay
Else: Exit Function
End If
AND
Code:
Private Sub Form_Load()
If endprocess Then
Exit Sub
End If
It seems to be a vicious circle & the endprocess Boolean can do nothing to prevent it.
Well Martin I am seriously thinking that putting the get_instrument_data in a separate module was not a good idea to begin with.
Try putting it in the form and if that works then great, but if not you may have to get into using Debug. Have you used it? You could start by setting a breakpoint on the first line in get_instrument_data and step through the code to see why it's looping. You probably want to wait 'till you are about to click the form's X before you add the breakpoint.