Serial input via VB.net (2008)

adumas

Member
Hi.. I've gone through several iterations of hair loss... Made some progress, but in some areas I'm moving in large concentric circles. I one VB.net program that correctly receives temperature data that I output - also hyperterminal. So I now the sending out part works.

I have looked and tried debugging Dr Acula's program - and have had a great deal of trouble getting it to work - I'm sure it's something stupid on my part, but I can't figure it out.. I've tried hacking at the buffer statements, but to no avail. (Obviously, the port number has been changed)

My serout command is: serout 6, 9600, ("data", #degrees, #tenthdeg, cr).

Using current Acula program, I only get timeouts and nothing more.. I'm hung up on the array that is being created.. And am wondering if it is requiring more parameters? Or does it matter if the passed parameters are fewer? The program is simple to read, but I'm still new to how the buffers are working and why the data is not outputting...

Moreover, I don't see how to return data back to the picaxe.

If I could get some relief in modifying this code that would be great.

A fully communicating Picaxe would be truly marvelous..
 

therowes

Member
I tried to modify the code as a start to a control program but couldn't get the buffer bit to work either.
The data I needed to send was only ASCII characters so I adopted the send fixed data length to the 8M. It responded ( when Ready ) with a “Start Transmission” byte followed by the message and “ Transmission ended” byte.

Its only a proof of concept / experiment but does prove a simple ( ! ) program can work.

The down side is the PICAXE has to be permanently waiting for the input command !

In the finish ( still working on ) I’ve a dedicated chip ( 40x1 ) to do just the comms and get the data to / from it by making it a I2C slave

The comments haven't been changed so could be misleading !

Picaxe
setfreq em16
main:
low 1
low 2
serin [100,fin] ,0,N4800_16,b0,b1,b2,b3,b4,b5,b6,b7,b8

if b0 = "1" then
if b8 ="1" then
high 1
endif
serout 0,N4800_16,($2,"hello world",$4)
endif
if b0 = "2" then
if b8 ="2" then
high 2
endif
serout 0,N4800_16,($2,"This is a very long message the quick brown fox jumped over the lazy dog. This is a very long message the quick brown fox jumped over the lazy dog." , $4)

endif
fin:
goto main

VBnet

Imports System.IO
Imports Strings = Microsoft.VisualBasic ' so can use things like left( and right( for strings
Public Class Form1
Dim WithEvents serialPort As New IO.Ports.SerialPort ' serial port declare
Dim DataPacket2 As String
Dim count As Integer = 1

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

lp1: Timer1.Enabled = True ' put this in code as defaults to false when created
Timer1.Interval = 4000 ' 4 seconds


End Sub
Sub SerialTxRx()
Dim recchar As Char

If serialPort.IsOpen Then
serialPort.Close() ' just in case already opened
End If
Try
With serialPort
.PortName = "COM1" ' Most new computers default to com1 but any pre 1999 computer with a serial mouse will probably default to com2
.BaudRate = 4800 ' 2400 is the maxiumum speed for small picaxes
.Parity = IO.Ports.Parity.None ' no parity
.DataBits = 8 ' 8 bits
.StopBits = IO.Ports.StopBits.One ' one stop bit
.ReadTimeout = 1000 ' milliseconds so times out in 1 second if no response
.Open() ' open the serial port
'.DiscardInBuffer() ' clear the input buffer
.Write("1therest1") ' send the datapacket array
'Call Sleep(100) ' 100 milliseconds minimum to wait for data to come back and more if data stream is longer
lp1: recchar = Chr(.ReadChar()) ' read back in the data packet array

If recchar <> Chr(2) Then GoTo lp1
'.DiscardInBuffer() ' clear the input buffer
' Pause(1)
DataPacket2 = .ReadTo(Chr(4))
Debug.Print(DataPacket2)

incoming.Text = DataPacket2 ' put the text string on the screen
' Pause(2000)

.Write("2therest2") ' send the datapacket array
'Call Sleep(100) ' 100 milliseconds minimum to wait for data to come back and more if data stream is longer
lp2: recchar = Chr(.ReadChar()) ' read back in the data packet array

If recchar <> Chr(2) Then GoTo lp2
'.DiscardInBuffer() ' clear the input buffer
'Call Sleep(200)
DataPacket2 = .ReadTo(Chr(4))
Debug.Print(DataPacket2)

incoming.Text = DataPacket2 ' put the text string on the screen

.DiscardInBuffer() ' clear the input buffer
.Close() ' close the serial port
End With

Catch ex As Exception
'MsgBox(ex.ToString)' uncomment this if want to see the actual error message
incoming.Text = "Timeout" ' will display this if picaxe not connected etc
End Try
End Sub

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
' timer ticks every 5 seconds


SerialTxRx()

Label1.Text = count
count = count + 1
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

End Sub
End Class
 
Last edited:

moxhamj

New Member
Adumas I posted the answer on the Instructable site, but basically you just need to remove the # that you put in front of b0. Two instances in the code.

Two way comms - see the link at the beginning of the instructable to the other one that sends data via the internet. But maybe just get this working first.
 

adumas

Member
Thank Dr Acula - I really appreciate you trying to help. I like how compact the code is, but I think it needs tweeking - at least based on my limited understanding of VB.net...

For the benefit of people not looking on Instructables, I'm including my results in both places.

I have tried to isolate the differences between 2 results, Acula's and a couple of other programs (Hyperterminal and another vb program. Hyperterminal is fine for those who have it, but I can't modify it and it is only good for testing.. The vb program is quite complex and would take a great deal of extra work to modify - I'm praying I don't have to go down that route).

Acula's will be perfect once I can fix what I'm doing wrong - hopefully the community can help me out...

I'm including all of the code plus the image outputs that shows what is going on...

From VB

form objects:
Text Name
Button1 Button1
Button2 Button2
PictureBox1
Counter lblCounter
Exit btnExit
txtData - multiline text box, with vertial scrolling
plus a timer

Imports System.IO
Imports Microsoft.Win32
Imports Strings = Microsoft.VisualBasic ' so can use things like left( and right( for strings
Public Class Form1
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Integer) ' for sleep statements
Dim WithEvents serialPort As New IO.Ports.SerialPort ' serial port declare
Dim PicaxeRegisters(0 To 13) As Byte ' registers b0 to b13
Dim count As Integer = 1
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Timer1.Enabled = True ' put this in code as defaults to false when created
Timer1.Interval = 5000 ' 5 seconds
PictureBox1.BackColor = Color.Red ' set to position 'red'
Array.Clear(PicaxeRegisters, 0, 13) ' probably not needed as array declared blank
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
' timer ticks every 5 seconds
Call SerialTxRx() ' talk to picaxe
lblCounter.Text = count
count = count + 1
End Sub
Sub SerialTxRx()
Dim LabelString As String = "" ' string to display byte values
Dim DataPacket(0 To 17) As Byte ' entire data packet "Data"+14 bytes
Dim i As Integer ' i is always useful for loops etc
'lblData.Text = "" ' clear the text on the screen
For i = 0 To 3
DataPacket(i) = Asc(Mid("Data", i + 1, 1)) ' add the word "Data" to the packet
Next
For i = 0 To 13
DataPacket(i + 4) = PicaxeRegisters(i) ' add all the bytes to the packet
Next
If serialPort.IsOpen Then
serialPort.Close() ' just in case already opened
End If
Try
With serialPort
.PortName = "COM3" ' Most new computers default to com1 but any pre 1999 computer with a serial mouse will probably default to com2
.BaudRate = 2400 ' 2400 is the maxiumum speed for small picaxes
.Parity = IO.Ports.Parity.None ' no parity
.DataBits = 8 ' 8 bits
.StopBits = IO.Ports.StopBits.One ' one stop bit
.ReadTimeout = 1000 ' milliseconds so times out in 1 second if no response
.Open() ' open the serial port
.DiscardInBuffer() ' clear the input buffer
.Write(DataPacket, 0, 18) ' send the datapacket array
Call Sleep(700) ' 100 milliseconds minimum to wait for data to come back and more if data stream is longer
.Read(DataPacket, 0, 18) ' read back in the data packet array
.Close() ' close the serial port
End With
For i = 4 To 17
LabelString = LabelString + " " + Chr(DataPacket(i)) ' turn into a text string
Next
'lblData.Text = LabelString ' put the text string on the screen
txtData.Text += LabelString + vbCrLf
Catch ex As Exception
'MsgBox(ex.ToString)' uncomment this if want to see the actual error message
'lblData.Text = "Timeout" ' will display this if picaxe not connected etc

txtData.Text += "Timeout" + vbCrLf
End Try
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
PictureBox1.BackColor = Color.Red ' change the box to red
PicaxeRegisters(0) = 120 ' an arbitrary value for the servo
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
PictureBox1.BackColor = Color.Green ' box to green
PicaxeRegisters(0) = 160 ' arbitrary value for the servo
End Sub

Private Sub btnexit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnexit.Click

serialPort.Close()

Close()

End Sub
End Class

From picaxe:

'**************************************************************************
; set picaxe type
#picaxe 28x1 'declarative

#com 4

symbol counter = b0
symbol ledstatus = b1
symbol ledport = b2


counter = 0
ledstatus = 1
ledport = 7

; *****************************************************
; *****************************************************
main:

if counter > 250 then
counter = 0
end if

counter = counter + 1
serout 0,9600,("Data", #counter,"","",b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13)

if ledstatus = 1 then
high portc ledport
pause 500' pause a second
ledstatus = 0
end if
if ledstatus = 0 then
low portc ledport
pause 500' pause a second
ledstatus = 1
end if

goto main
 

Attachments

adumas

Member
I believe the whole problem lies in the streaming / packet construct... The program is arbitrarily grabbing whatever is in the steam at a particular instant, but that doesn't necessarily mean it has maintained the total integrity of the ongoing stream sent by the microcontroller.

In other words, there is gaps in the data. I think data should be picked off the stream as it comes in (using a large buffer), and have it appended to the text box holding the previous extract.

Does that make sense?

Of course, I don't yet know how to read the stream and write from it... Any help?
 

moxhamj

New Member
The hyperterminal printout looks as expected from the code.

Just have a look at this line serout 0,9600,("Data", #counter,"","",b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b1 3)

That last one should be b13 not b1 and then a 3?

The counter will be a variable length string from 1 to 3 characters. That could get complex and there is a command in the picaxe basic to convert a number to a fixed number of bytes so the string length stays constant. bintoascii I think.

So maybe have a look at that first because it makes things a lot easier if your data packet stays the same length.

Next issue is timing. In that instructable I got around the timing issue (and the serin hang issue) by having the picaxe sit in serin and when it gets a data packet it returns a data packet. So the vb.net end knows exactly what it is getting and when it is getting it.

If you want to have the picaxe send out data continuosly and pick out a packet in amongst the stream, have a look at the strings.instr command in vb.net. Then you can search for a known string eg 'Data' and then you know what the next bytes will be.

But you need to be a bit careful with this as you can end up with buffers filling up, or you can end up reading bytes that actually came in an hour ago and have been sitting in the buffer but you think they have just come in. So you might need to keep the port close, open it, clear the buffer, listen for a time (with a timeout), get a string which you know will be longer than x but shorter than y, then take that string and first check it is not zero length (instr will crash if it is zero) and then search for 'data' and then read out the numbers.
 
Top