Using a global Variable

I know Global variables are discouraged, but I need one…just one. My app is reading lines of data from a serial port and displaying them in a TextArea and that is working fine. I wanted to add the ability to also send those lines of code to a text file on the fly. So I setup a Global variable, G-cur_line, so that my file send routine can see the data lines and write them to the file. Well, I don’t get much in the file send routine. I get one line and then nothing and the code hangs there waiting for the file stream to be complete. (last line the text is a string “Cmd;”

I couldn’t see much with the debugger, so I put a second TextArea in the window and appended the data into it I could see what was coming through. Well, I see only one line there too! Here is a clip of the code, this is in the DataAvailable Event on the serial controller.

Dim buline as Integer = Instr(Me.LookAhead(Encodings.ASCII), Chr(13) ) If buline >0 Then buline = buline+ 1 G_cur_line = Me.Read(buline,Encodings.ASCII) DebugText.AppendText(G_cur_line) OutputArea.AppendText(G_cur_line)

The window on the left is the OutputArea and the one on the right is my added debug text area. All of the lines of data make it to the OutputArea on the left and only a couple of lines make it to the other textarea. Both get their strings from the same Global Variable. I don’t understand why the same data isn’t going to both text areas. Ideas anyone. Did I miss something?

Where did you add your global variable? App? A Module? Even the window?

Added it in as a property in a module, type string, scope global.

Are there any invisible characters in your data? Would a 0 char screw up showing data in a text area? Have you looked at the data in the debugger? How do you write the data?

There are some CR/LF sequences but otherwise straight ASCII text in the data stream. The two TextAreas have the same properties, so I would think they should handle the .AppendText the same way. Yes, I looked at the data in the Debugger and the only thing I see is printable ASCII characters and the CR/LF sequence at the end of the line.

The original code never got to the writing to the file, cause there was only one line and never got to the last line send from the device, but it looks like this:
Do
If Len(G_cur_line) > 0 Then
t.Write(G_cur_line)
End If
Loop Until Instr(G_cur_line, “Cmd:”) > 0

The idea was to write each line to the file until it sees the device go back to the “Cmd:” prompt then exit the do loop. My thinking was that it would hang in the Do Loop and the DataAvailable being an Event is like an interrupt to read data from the serial port and save each line in the G_cur_line Global Variable for processing in the Do Loop

There is my Global variable. The idea is to read a line at the time from the Serial Port, using seriallookahead and the Instr Function to look for the CR/LF at the end of the line. And that works well as you can see on the TextArea on the left. Since the DataAvailable is the only place to read data from the serial port I thought saving each line in a Global Variable would allow other pieces of code to have access to the data stream (line by line) from the serial port.

So that is when I just stuck another TextArea in the Window, and AppendText the same variable to it. For some reason, the second TextArea doesn’t see but one line of data the same way my file writing routine did.

Very Strange!

I seems weird that “cmd:” is a string that acts differently in the current version of your program. The 4 character “cmd:” disappears from the second text area.

You show some code (original) where “Cmd:” means something but imply that that code is not used now. Are you sure that “Cmd:” does not appear anywhere in your code at the present time?

You might try declaring another variable and add one line of testing code:

Dim testString As String … testString.AppendText(G_cur_line)

Then you look at testString in the debugger see how it behaves. Is it like the DebugArea text or the OutputArea text?

If you put a breakpoint here–> G_cur_line = Me.Read(buline,Encodings.ASCII
and inspect the contents of G_cur_line
does it change as you step through? Are there any strange characters that you can see?

Also, I note that you have a button called “Cmd” at the bottom of your screen. Is it possible that the second iteration of the contents of G_cur_line are somehow activating that button?

Good luck

Instead of using a lookahead and Read(), using only ReadLine() may solve the issue.

Robert L,
The “Cmd:” missing from Line 3 is not an issue. Also on line 3 is the “disp” is an echo from the serial port of the command that was sent to cause the device to dump its settings via the serial port. My file saving routine sends that to the device, the device then responds with a number of lines of text with a CR/LF. There are some other “Cmd;” in the code, but only as string values. The button you refer to name is actually CmdButton. The “Cmd:” string tells me the device is stopped sending and is ready for input. I tried a local variable, assigning G_cur_line to it and it looked fine in the debugger.

Michel B,
Readline doesn’t work because DataAvailable fires as soon as there is a character in the Serial In buffer, and their may not be full line in the buffer at that time. The LookAhead and Instr() lets me wait for a full line. I tried reading a character at a time and it ran to slow on some computers. The LookAhead works well. The issue is that for some reason the G_cur_line variable works on the one TextArea and not on the other.

Phillip C,
I did that, and looking at the G_cur_line variable in the binary mode where I can see the hex characters I see the line string from the device just fine. No bad characters, just the string and a CR/LF at the end. Just what I would expect to see.

Could it be a timing issue? The dataAvailable event fires again and resets the variable before it has a chance to write to the second textArea?

What you need to do is buffer what is coming in (aka appending) and reading from the buffer.

[quote=388665:@Robert Cheek]Michel B,
Readline doesn’t work because DataAvailable fires as soon as there is a character in the Serial In buffer, and their may not be full line in the buffer at that time. The LookAhead and Instr() lets me wait for a full line. I tried reading a character at a time and it ran to slow on some computers. The LookAhead works well. The issue is that for some reason the G_cur_line variable works on the one TextArea and not on the other.[/quote]

Try to switch the lines that fill up the TextAreas :

Dim buline as Integer = Instr(Me.LookAhead(Encodings.ASCII), Chr(13) ) If buline >0 Then buline = buline+ 1 G_cur_line = Me.Read(buline,Encodings.ASCII) OutputArea.AppendText(G_cur_line) DebugText.AppendText(G_cur_line)

If the DebugText gets filled up and not OutputArea, chances are as serial communication is much slower than Xojo’s execution, the first time around the read is not complete, and the second time around the read is complete.

You may want to use a timer.

Markus Winter,
YES! It is a timing problem! You got me to thinking. I put some more debug code in, showing the LenB of the G_cur_line in my Debug Window and it sees a line or two then nothing. It got me to thinking the LookAhead for CR wasn’t working the way I thought it was.

So, there is another test I do looking for that “Cmd:” reply from the device. Well, putting a DebugText.AppendText(Str(Len(buline)) in the code where I look for the “Cmd:” and there was the rest of my data, 288 characters worth.

Looks like the code looking for the CR/LF can keep up for a line or two (the device is running at 9600 Baud) and it sends all the data and “CR/LF Cmd:” where my test for the “Cmd:” string goes true and gobbles all the rest of the data out of the Serial Buffer and puts it in my OutputText area!

I can figure out how to fix this now. The tricky part is the lines all have a CR/LF at the end of them until it send the “Cmd:” prompt which has no CR/LF so the cursor on the terminal would be just to the right of the prompt.

Thanks for making me think! As a poster I once had said, “Sometimes I sits and thinks, and sometimes I just sits!”

Have a look at this tutorial to see how to implement a buffer: http://developer.xojo.com/serial-port-tutorial

You need to slightly adjust the example …

Also are you sure you can assume that data come in in line sized chunks …?