Visual Basic

Lliam20789

New Member
--------------------Continue VB Post--------------------

Thankyou for you help Hippy.
So the data is binary for an ascii character?

I tried out the code but I'm not exactly sure what the second part does;

Else
RXArray(I) = "<"
I = I + 1
RXArray(I) = Hex(RXbyte \ &H10)
I = I + 1
RXArray(I) = Hex(RXbyte And &HF)
I = I + 1
RXArray(I) = ">"
I = I + 1
End If

The Cr and Lf commands still show up as small rectangles.
I don't know what "&HF" or "&H10" are?

Thankyou again
 

Technical

Technical Support
Staff member
Not sure if this is the issue in your case, but CR - LF often appear as small boxes if you transmit them in the wrong order (ie LF-CR rather than CR-LF)
 

hippy

Ex-Staff (retired)
In theory the code should have shown printable characters as they are and non-printable as hex numbers in chevrons ...

SerTxd("Hello",CR,LF,"One",1,"Two",2)

should have produced ...

Hello<0D><0A>One<01>Two<02>

I'm not familiar with VB 2005 so maybe it needs more work doing on the code.

&hF and &h10 are hexadecimal numbers in VB, the same as $0F and $10, 15 and 16 for a PICAXE.

Edited by - hippy on 14/05/2007 23:41:43
 

Lliam20789

New Member
Technical, I tried your suggestion, that wasn't it...
Hippy, I saw that to but why doesn't it...?

I'll keep trying...
 

hippy

Ex-Staff (retired)
I have no idea :)

You could try debugging the code, forcing RXbyte to have a value of CR (13) and single stepping the code. Look at where the program flow goes and what values are being put into RXArray().
 

Lliam20789

New Member
I tried this code:

-------------------------------------------

Imports System
Imports System.IO.Ports
Imports System.Threading.Thread
' Imports the System, System.IO.Ports and System.Threading.Thread namespaces so that e.g.
' System.IO.Ports.SerialPort may just be written as SerialPort, and System.EventArgs may just be
' written as EventArgs.

Public Class Form1

Public Delegate Sub StringSubPointer(ByVal Buffer As String)
Dim SpaceCount As Byte = 0
Dim sDataSeparator As String = " "

Dim WithEvents SerialPort As New SerialPort ' Make a new System.IO.Ports.SerialPort instance, which is able to send events

Private Sub Receiver(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs) Handles SerialPort.DataReceived
' Note this subroutine is executed on the serial port thread - not the UI thread.
Dim RXByte, Nibble As Byte
Dim RXArray(2047) As Char
Dim I As Integer = 0
Dim BreakDetect As Boolean
'
Do
BreakDetect = SerialPort.BreakState ' Read COMPort.BreakState as early as possible.
' Note. Break detection above approximately 300 bit/s is not reliable because BreakState may go low again
' before this routine is running (not latched).
RXByte = SerialPort.ReadByte
If BreakDetect And (RXByte = 0) Then ' If RXByte <> 0, the Break is detected too early
RXArray(I) = "B"
I = I + 1
RXArray(I) = "r"
I = I + 1
RXArray(I) = "e"
I = I + 1
RXArray(I) = "a"
I = I + 1
RXArray(I) = "k"
I = I + 1
RXArray(I) = Chr(13) ' CR
I = I + 1
RXArray(I) = Chr(10) ' LF
I = I + 1
SpaceCount = 0
Else
Nibble = (RXByte >> 4) + 48 ' Convert received byte to Hex
If Nibble > 57 Then
Nibble = Nibble + 7
End If

If RXByte >= &H20 And RXByte < &H7F Then
RXArray(I) = Chr(RXByte)
I = I + 1
Else
RXArray(I) = "<"
I = I + 1
RXArray(I) = Hex(RXByte \ &H10)
I = I + 1
RXArray(I) = Hex(RXByte And &HF)
I = I + 1
RXArray(I) = ">"
I = I + 1
End If

Nibble = (RXByte And 15) + 48
If Nibble > 57 Then
Nibble = Nibble + 7
End If
RXArray(I) = Chr(Nibble)
I = I + 1
RXArray(I) = sDataSeparator
I = I + 1
SpaceCount = (SpaceCount + 1) And 31 ' Insert spaces and CRLF for better readability
If SpaceCount = 0 Then ' Insert CRLF after 32 numbers
RXArray(I) = Chr(13) ' CR
I = I + 1
RXArray(I) = Chr(10) ' LF
I = I + 1
Else
If (SpaceCount And 3) = 0 Then ' Insert two extra spaces for each 4 numbers
RXArray(I) = " "
I = I + 1
RXArray(I) = " "
I = I + 1
End If
End If
End If
Loop Until (SerialPort.BytesToRead = 0)
Dim RxString As New String(RXArray, 0, I) ' Convert the first part of the Char Array to a String
' Put the display routine and the RxString on the message queue and return immediately.
txtReceivedLog.BeginInvoke(New StringSubPointer(AddressOf Display), RxString)
End Sub

' Text display routine, which appends the received string to any text in the Received TextBox form.

Private Sub Display(ByVal Buffer As String)
txtReceivedLog.AppendText(Buffer)
End Sub

Private Sub cboPort_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboPort.SelectedIndexChanged
OpenSerialPort()
End Sub

'Handles the opening (or changing) of the port

Private Sub OpenSerialPort()
'Port has been selected or changed via the Combo List box of port names
If SerialPort.IsOpen Then
SerialPort.RtsEnable = False
SerialPort.DtrEnable = False
SerialPort.Close()
Application.DoEvents() ' Empty the message queue before the UI thread goes to sleep.
Sleep(200) ' Wait 0.2 second for port to close as this do not happen immediately.
End If
SerialPort.PortName = cboPort.Text ' Default: 9600 Baud, 8 data bits, no parity, 1 stop bit

' Set the buffer size to 2, which is minimum. The reason for this is that the buffer is only 8 bit wide,
' but the receiver FIFO in the UART is 11 bit wide as it also contains information about any Break or
' error conditions. Because of this difference, a Break condition may be detected too early.
' To minimize the problem, the buffer size is reduced as much as possible.
SerialPort.ReadBufferSize = 2
SerialPort.WriteTimeout = 5000 ' Max time to wait for CTS = 5 sec.
Try
SerialPort.Open()
Catch ex As Exception
MsgBox(ex.Message)
End Try
If SerialPort Is Nothing Then
cboBitRate.Text = ""
cboBits.Text = ""
cboParity.Text = ""
cboHandshake.Text = ""
Else
cboBitRate.Text = SerialPort.BaudRate.ToString
cboBits.Text = SerialPort.DataBits.ToString
cboParity.Text = SerialPort.Parity.ToString
cboHandshake.Text = SerialPort.Handshake.ToString
SerialPort.RtsEnable = True
SerialPort.DtrEnable = True
End If
End Sub

Private Sub cboBitRate_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboBitRate.SelectedIndexChanged
SerialPort.BaudRate = CInt(cboBitRate.Text)
End Sub

Private Sub cboBits_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboBits.SelectedIndexChanged
SerialPort.DataBits = CInt(cboBits.Text)
End Sub

Private Sub cboParity_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboParity.SelectedIndexChanged
SerialPort.Parity = CType([Enum].Parse(GetType(Parity), cboParity.Text), Parity)
End Sub

Private Sub cboHandshake_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboHandshake.SelectedIndexChanged
SerialPort.Handshake = CType([Enum].Parse(GetType(Handshake), cboHandshake.Text), Handshake)
End Sub

Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
If SerialPort.IsOpen Then SerialPort.Close() ' Close COM port when the form is terminated with [X]
End Sub

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
For Each COMString As String In My.Computer.Ports.SerialPortNames ' Load all available COM ports.
cboPort.Items.Add(COMString)
Next
cboPort.Sorted = True
cboPort.SelectedIndex = 0 'Ensure default serial port is selected
'cboBitRate.Items.Add("110")
cboBitRate.Items.Add("300")
cboBitRate.Items.Add("600")
cboBitRate.Items.Add("1200")
cboBitRate.Items.Add("1800")
cboBitRate.Items.Add("2400")
cboBitRate.Items.Add("4800")
cboBitRate.Items.Add("7200")
cboBitRate.Items.Add("9600")
cboBitRate.Items.Add("14400")
cboBitRate.Items.Add("19200") ' Min. FIFO size 3 Bytes (8030 or 8530)
'BaudRateBox.Items.Add("38400")
'BaudRateBox.Items.Add("57600") ' Min. FIFO size 8 bytes
'BaudRateBox.Items.Add("115200") ' Min. FIFO size 16 bytes (16C550)
'BaudRateBox.Items.Add("230400") ' Min. FIFO size 32 bytes (16C650)
'BaudRateBox.Items.Add("460800") ' Min. FIFO size 64 bytes (16C750)
'BaudRateBox.Items.Add("921600") ' Min. FIFO size 128 bytes (16C850 or 16C950)
cboBitRate.SelectedIndex = 5 'Set default bit rate = 4800 for PICAXE
cboBits.Items.Add("5")
cboBits.Items.Add("6")
cboBits.Items.Add("7")
cboBits.Items.Add("8")
cboParity.Items.Add("None")
cboParity.Items.Add("Odd")
cboParity.Items.Add("Even")
cboParity.Items.Add("Mark") ' Leaves the parity bit set to 1
cboParity.Items.Add("Space") ' Leaves the parity bit set to 0
cboHandshake.Items.Add("None")
cboHandshake.Items.Add("RequestToSend")
cboHandshake.Items.Add("RequestToSendXOnXOff")
cboHandshake.Items.Add("XOnXOff")
End Sub
End Class

-------------------------------------------

And the following data list was displayed:
B2 11 0 =D 0 00 <0A>A <0D>D

When the Picaxe output:
b1 = 10 Cr,Lf

Any ideas?
 

inglewoodpete

Senior Member
Liam, It looks as if you've just inserted a block of code instead of <i>replacing </i> it.

Remove (or comment out) the following 2 blocks of code from Sub Receiver()
<code><pre><font size=2 face='Courier'> Nibble = (RXByte &gt;&gt; 4) + 48 ' Convert received byte to Hex
If Nibble &gt; 57 Then
Nibble = Nibble + 7
End If
and...
Nibble = (RXByte And 15) + 48
If Nibble &gt; 57 Then
Nibble = Nibble + 7
End If
RXArray(I) = Chr(Nibble)
I = I + 1
RXArray(I) = sDataSeparator
I = I + 1
</font></pre></code>

As I said previously, using a string array is a bit of an overkill when logging simple text like you're wanting to do.
 

Lliam20789

New Member
Sorry Peter, I'm still learning some of the terms.

I changed to Sub reciver to:

------------------------------------------
<code><pre><font size=2 face='Courier'>
Private Sub Receiver(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs) Handles SerialPort.DataReceived
' Note this subroutine is executed on the serial port thread - not the UI thread.
Dim RXByte, Nibble As Byte
Dim RXArray(2047) As Char
Dim I As Integer = 0
Dim BreakDetect As Boolean
'
Do
BreakDetect = SerialPort.BreakState ' Read COMPort.BreakState as early as possible.
' Note. Break detection above approximately 300 bit/s is not reliable because BreakState may go low again
' before this routine is running (not latched).
RXByte = SerialPort.ReadByte
If BreakDetect And (RXByte = 0) Then ' If RXByte &lt;&gt; 0, the Break is detected too early
RXArray(I) = &quot;B&quot;
I = I + 1
RXArray(I) = &quot;r&quot;
I = I + 1
RXArray(I) = &quot;e&quot;
I = I + 1
RXArray(I) = &quot;a&quot;
I = I + 1
RXArray(I) = &quot;k&quot;
I = I + 1
RXArray(I) = Chr(13) ' CR
I = I + 1
RXArray(I) = Chr(10) ' LF
I = I + 1
SpaceCount = 0
Else
RXArray(I) = Chr(Nibble)
I = I + 1
SpaceCount = (SpaceCount + 1) And 31 ' Insert spaces and CRLF for better readability
If SpaceCount = 0 Then ' Insert CRLF after 32 numbers
RXArray(I) = Chr(13) ' CR
I = I + 1
RXArray(I) = Chr(10) ' LF
I = I + 1
Else
If (SpaceCount And 3) = 0 Then ' Insert two extra spaces for each 4 numbers
RXArray(I) = &quot; &quot;
I = I + 1
RXArray(I) = &quot; &quot;
I = I + 1
End If
End If
End If
Loop Until (SerialPort.BytesToRead = 0)
Dim RxString As New String(RXArray, 0, I) ' Convert the first part of the Char Array to a String
' Put the display routine and the RxString on the message queue and return immediately.
txtReceivedLog.BeginInvoke(New StringSubPointer(AddressOf Display), RxString)
End Sub
</font></pre></code>

------------------------------------------

And got:
B 1 = 0
with two small rectangles following &quot;0&quot; and no Cr or Lf?

I had tried re-wighting the code but Hippy's code produced better data then mine.

I'm sorry to trouble you so much about this,
I'm guessing it's something simple I'm missing or don't understand.

Lliam
 

hippy

Ex-Staff (retired)
I cannot see what's putting spaces between characters and that's likely also putting spaces between CR and LF which stops them being interpreted as a CR/LF pair and is causing them to be displayed as squares.

You can remove everything which uses SpaceCount because that's not relevant as you are no longer displaying in hex, but I don't see how that code is causing the problem.

The problem could be with the &quot;txtReceivedLog&quot; routine elsewhere ( or whatever it is ), or it could perhaps be something treating the text data as unicode, 16-bit characters rather than 8-bit ).

I'm surprised the code prints anything at all as you have &quot;RXArray(I) = Chr(Nibble)&quot; when it should be &quot;RXArray(I) = Chr(RXbyte)&quot;, and Nibble is never assigned a value.

Are you sure that's the actual code you are using ?
 

hippy

Ex-Staff (retired)
No guarantees, but you could try using this code to replace the entire Receiver subroutine -<code><pre><font size=2 face='Courier'>Private Sub Receiver(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs) Handles SerialPort.DataReceived
Dim RXByte As Byte
Dim RXArray(2047) As Char
Dim I As Integer = 0
Do
RXByte = SerialPort.ReadByte
RXArray(I) = Chr(RxByte)
I = I + 1
Loop Until (SerialPort.BytesToRead = 0)
Dim RxString As New String(RXArray, 0, I)
txtReceivedLog.BeginInvoke(New StringSubPointer(AddressOf Display), RxString)
End Sub </font></pre></code> Or even -<code><pre><font size=2 face='Courier'>Private Sub Receiver(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs) Handles SerialPort.DataReceived
Dim RXstring as String
Rxstring = serialPort.ReadExisting
txtReceivedLog.BeginInvoke(New StringSubPointer(AddressOf Display), RxString)
End Sub </font></pre></code>

Edited by - hippy on 15/05/2007 11:36:35
 

benryves

Senior Member
This will no doubt make me wildly unpopular, but here goes anyway;

VB6 and VB8 should really be treated as completely different languages. VB continues to let you use VB6-style functionality, unfortunately (such as VB6's painful file handling). Embrace the .NET framework class library! ;)

In this case, rather than use an array of Char, use a StringBuilder class which will simply let you .Append() the incoming data.

For appending formatted text (in this case, formatting an integral value into hexadecimal) you can use .AppendFormat(), eg .AppendFormat(&quot;&lt;{0:X2}&gt;&quot;, RXByte). This calls the String.Format method. For Break you could just .AppendLine(&quot;Break&quot;).

Working with the framework also gives you the advantage of being able to use other .NET-targetting languages very easily. :)

Look in MSDN for more information. The online version is rather painful and has a poor search; the offline version that installs with the IDE is great, though.

 
 

hippy

Ex-Staff (retired)
benryves, you are correct. There's always an argument on how best to do a particular thing, but what you say is completely sound; what works for VB6 isn't necessarily best for VB8 ( VB 2005 ) and VB8 does things differently to how it would be done in VB6.

I'm a VB6 coder and largely unfamiliar with VB8 so I don't know the new tricks of the trade and haven't broken free of the VB6 way of working. It's good to hear someone with more knowledge giving advice on how it can be done in VB 2005, and that certainly won't make you unpopular in my eyes :)
 

inglewoodpete

Senior Member
Either of hippy's pieces of code compiled and worked, showing non-printing characters as little 'blocks'.

I have rewritten the original code for Sub Receiver as follows, which displays non-printing codes 0-31 and 127-255 in their hex format while including the &lt;CR&gt;&lt;LF&gt; function (ie new line) when the &lt;CR&gt;&lt;LF&gt; sequence is received. This is handy when you want to see evidence of every character that the PICAXE sends.

<code><pre><font size=2 face='Courier'>
Private Sub Receiver(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs) Handles SerialPort.DataReceived
' Note this subroutine is executed on the serial port thread - not the UI thread.
Dim RXByte As Byte
Dim RXArray(2047) As Char
Dim I As Integer = 0
Dim BreakDetect As Boolean
Dim LastWasCR As Boolean
'
Do
BreakDetect = SerialPort.BreakState ' Read COMPort.BreakState as early as possible.
' Note. Break detection above approximately 300 bit/s is not reliable because BreakState may go low again
' before this routine is running (not latched).
RXByte = SerialPort.ReadByte
If BreakDetect And (RXByte = 0) Then ' If RXByte &lt;&gt; 0, the Break is detected too early
RXArray(I) = &quot;B&quot;
I = I + 1
RXArray(I) = &quot;r&quot;
I = I + 1
RXArray(I) = &quot;e&quot;
I = I + 1
RXArray(I) = &quot;a&quot;
I = I + 1
RXArray(I) = &quot;k&quot;
I = I + 1
RXArray(I) = Chr(13) ' CR
I = I + 1
RXArray(I) = Chr(10) ' LF
I = I + 1
SpaceCount = 0
Else
Select Case RXByte
Case Is &lt; 32, Is &gt; 126 'Non printing characters
RXArray(I) = &quot;&lt;&quot; '&lt;******** These 8 lines
I = I + 1 ' can be omitted
RXArray(I) = Hex(RXByte \ &amp;H10) 'if non-printing
I = I + 1 'characters are
RXArray(I) = Hex(RXByte And &amp;HF) 'not required
I = I + 1 'to be
RXArray(I) = &quot;&gt;&quot; 'visible
I = I + 1 '&lt;********
If RXByte = 13 Then
LastWasCR = True
ElseIf RXByte = 10 And LastWasCR Then
RXArray(I) = Chr(13) ' CR
I = I + 1
RXArray(I) = Chr(10) ' LF
I = I + 1
LastWasCR = False
Else
LastWasCR = False
End If
Case Else 'Printable characters
RXArray(I) = Chr(RXByte)
I = I + 1
End Select
End If
Loop Until (SerialPort.BytesToRead = 0)
Dim RxString As New String(RXArray, 0, I) ' Convert the first part of the Char Array to a String
' Put the display routine and the RxString on the message queue and return immediately.
txtReceivedLog.BeginInvoke(New StringSubPointer(AddressOf Display), RxString)
End Sub
</font></pre></code>
 

hippy

Ex-Staff (retired)
<i>Either of hippy's pieces of code compiled and worked, showing non-printing characters as little 'blocks'. </i>

Out of interest, are CR+LF behaving as they should or are they showing up as blocks ?
 

Lliam20789

New Member
Hippy:
Just tried you first code...
b1 = 10
b1 = 10
b1 = 10
It worked!
Very nice thankyou.
I will write up a tutorial on this when I have time.

Thanks again.
 

inglewoodpete

Senior Member
hippy, using either of your routines and using the demo PICAXE code from the SerTxd command in the Manual:
<code><pre><font size=2 face='Courier'>
Main:
for b1 = 0 to 63 ' start a loop
SerTxd(&#8220;The value of b1 is &#8221;,#b1,13,10)
'SerTxd(&#8220;The value of b1 is &#8221;,b1,13,10)
Pause 1000
Next b1 &#8216; next loop
Goto Main </font></pre></code>
....produced the expected printout: each SerTxd string appeared on a new line (ie the 13,10 was treated as a new line by the multiline textbox).

Liam, It's not clear to me if the code is working correctly. As I posted it, the output <i>should </i> display as:
b1 = 10&lt;0D&gt;&lt;0A&gt;
b1 = 10&lt;0D&gt;&lt;0A&gt;
b1 = 10&lt;0D&gt;&lt;0A&gt;
I included some comments:'***********.... to show where to get rid of the non-printing character representation if required. Reading between the lines, you're on a steep learning curve ;o)

For myself, I have written a few applications including a SoundCard-based oscilloscope and the PICAXE Debug logger/terminal in VB2005Ex. VB2005Ex is a difficult beast to get my head around, especially efficiently managing variables and passing them between modules/classes. I am enrolling in a TAFE VB Net programming subject next semester. You're never too skilled, too old (or too young) to learn.
 

hippy

Ex-Staff (retired)
Thanks for the clarification on CR/LF - Seems to be working as I'd expect which is always good to know.
 

Lliam20789

New Member
Just wondering, does anyone have a short sub routine that can separate out values.

For example,
Display:
A=10
B=5
C=12

Then be able to put each value into it's own text box, which would be updated every time the symbol appeared.
So in textA you would see:
10
Thanks everyone.
 

hippy

Ex-Staff (retired)
To do that you are going to need some form of &quot;parsing&quot; code which can identify the data and what that data is, strip it out and then put it where it needs to go. A problem is that not all data may arrive at the same time so you will need to buffer it between calls to Sub Receive; for example, you may receive &quot;b1 = 1&quot; in the first call and &quot;23&lt;CR&gt;&lt;LF&gt;&quot; in the next, not the convenient &quot;b1 = 123&lt;CR&gt;&lt;LF&gt;&quot; you'd like.

There are a number of ways to do that and you might find a Finite State machine to be the best way to approach this, or simply rely on buffering and stripping everything between two sets of &lt;CR&gt;&lt;LF&gt;'s.

Unfortunately you are moving away from a PICAXE topic to a VB 2005 related one, so this is not really the forum in which to get best advice on VB coding and algorithms.
 

inglewoodpete

Senior Member
Quite seriously, you should consider the Debug command. It causes the Programming Editor's debug window to pop up automatically. The values in the debug window will update whenever the PICAXE executes a Debug command.
 

Lliam20789

New Member
I realize this, but this is the first step to graphing information, so using debug seems like a dead end.
Thanks,
Lliam
 

Lliam20789

New Member
For those how wish to follow this more, I have posted the last question here <A href='http:// http://www.devppl.com/forum/here-vp27303.html#27303 ' Target=_Blank>External Web Link</a>

Thankyou for all the help,
and if you have any suggestions don't hesitate to keep poasting here.

Lliam
 

demonicpicaxeguy

Senior Member
if it helps i'm just rewriting my code and activex control i wrote a while ago for data retrieval from a picaxe it the activex simply sends the same byte twice first one to trigger the interupt which sets the picaxe into serin and dumps the byte into b13

it's what i use for some of my datalogers
i'll stick it on my geocities account
 
Top