Serial communication between PC and picaxe 28X2

santhoshR

New Member
Hi,
I am having problem in communicating with PC with Picaxe 28x2. Please help me in solving this problem as it is a very important project

My aim is to send the values of w1 and w2 variables ( values of the ultrasonic range sensors 1 and 2 ) to the PC and display them with the help of VB

my picaxe code is ...,

#picaxe 28x2
main:
pulsout C.1,2
pulsin C.1,1,w1
pause 10

pulsout C.2,2
pulsin C.2,1,w2
pause 10

sertxd(#w1,#w2)
pause 100

goto main

and my VB code is ,


Imports System.IO
Imports Strings = Microsoft.VisualBasic
Public Class Form1
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Integer)
Dim WithEvents serialPort As New IO.Ports.SerialPort
Dim PicaxeRegisters(0 To 1) As Byte

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Timer1.Enabled = True
Timer1.Interval = 5000
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick

Call SerialTxRx()
End Sub
Sub SerialTxRx()
Dim labelstring As String = ""
Label1.Text = ""
If serialPort.IsOpen Then
serialPort.Close()
End If
Try
With serialPort
.PortName = "COM1"
.BaudRate = 9600
.Parity = IO.Ports.Parity.None
.DataBits = 8 ' 8 bits
.StopBits = IO.Ports.StopBits.One
.ReadTimeout = 1000
.Open()
.Read(PicaxeRegisters, 0, 2)
.Close()
End With
For i = 0 To 1
labelstring = labelstring + " " + Str(PicaxeRegisters(i))
Next
Label1.Text = labelstring
Catch ex As Exception
MsgBox(ex.ToString)
Label1.Text = "Timeout"
End Try


End Sub

End Class

I have not included the write command, since I have not included qualifiers in the picaxe code.

The Picaxe chip is sending the values ( I used the terminal in picaxe programming editor to realise this) but the visual basic is not displaying me the actual values sent by the picaxe chip. It is showing random values instead ... So i think that there is an error in the VB code.


PLEASE HELP AS SOON AS POSSIBLE ..
Thank You
 

nick12ab

Senior Member
  1. A problem I find with Visual Basic is that it doesn't want to work with binary vales - just ASCII codes whether you put a number in quotation marks or not. EDIT: You are sending ASCII values. May I suggest that you use BINTOASCII as the amount of bytes you are sending will vary with the value of the word.
  2. Use [code][/code] tags to retain the tabs and spaces in your code which will make it A LOT easier to read and understand.
 
Last edited:

lbenson

Senior Member
Also, if you are sending with "sertxd(#w1,#w2)", the values will appear as an undifferentiated string of digits. If w1 is 12 and w2 is 345, then what you are sending will be "12345". You will need to use something like "sertxd("#w1," ",#w2,cr,lf)--then what VB would get is "12 345" followed by carriage return and line feed.

If you want fixed length, then you need something like bintoascii (as suggested by nick12ab) so you receive "[space][space][space]12[space][space][space]345".
 

eggie

Member
I am working on a PC to picaxe communication at the moment but have found that the baud rate needs to be quite slow - I am having to use 2400 as anything faster gives random results. I am hoping to increase the speed in time once the programme is fully functioning. Try slowing it down and see what happens.
 

nick12ab

Senior Member
If you want fixed length, then you need something like bintoascii (as suggested by nick12ab) so you receive "[space][space][space]12[space][space][space]345".
With BINTOASCII, leading zeroes aren't automatically blanked so you'll receive 00345, which is better because then you can do, for example: (lets say that predefined variables varA-varE have those values in with varA having the least significant byte)
Code:
dim result as Integer
sub makenumber()
        result = varA + (varB * 10) + (varC * 100) + (varD * 1000) + (varE * 10000)
end sub
so that code forms the integer from the five received bytes.
 

nick12ab

Senior Member
Thank You ... :D
Wait a minute - I forgot to tell you how to use BINTOASCII at the PICAXE end - the code above is for the Visual Basic application. The BINTOASCII command simply requires you to give it the variable you want to convert and either three more (for a byte) or five more (for a word) byte variables in which to put the ASCII codes.
Code:
bintoascii w0,b2,b3,b4,b5,b6     'Puts ASCII characters into b2-6
Visual Basic should automatically handle the ASCII-to-integer conversions for use in that code I gave you.
 

hippy

Ex-Staff (retired)
The two key things with any serial communications software is to define the data sent so that it can be parsed and the receiving software to parse that.

On the PICAXE side that general means separating and terminating numbers ( as lbenson suggests ) and I'd simply use -

SerTxd( #w1, "," , #w2, CR. LF )

Then on the receiving side it just means parsing that to extract the numbers and most programming languages can fairly easily do that. For example, if rxData$ contains "123,45" then the following would extract both values ...

i = Instr(rxData$, "," )
w0value = Val( Trim$( Left$( rxData$, i - 1 ) ) )
w1value = Val( Trim$( Right$( rxData$, Len(rxData$) - i ) ) )


The real challenge is in how to read the incoming stream that may not arrive as a whole. Somewhere on the forum I have an example on that for VB6 but the concept would be similar for VB.Net and even other languages. I always use event driven code where as most examples seem to use blocking commands and timeouts which in my experience leads to unanticipated problems and incorrect data. Unfortunately I can't immediately find the thread in which my examples were posted.
 

santhoshR

New Member
Thank You everyone for your replies .. !! I have solved the problem .. I ve used sertxd(w1," ", w2) ....
my corrected picaxe code is ...

#picaxe 28x2
main:
pulsout C.1,2
pulsin C.1,1,w1
pause 10
let w1 = w1 * 10/62

pulsout C.2,2
pulsin C.2,1,w2
pause 10
let w2 = w2 * 10/62

sertxd (w1," ",w2)


goto main

AND MY VB CODE IS ....


Imports System.IO
Imports Strings = Microsoft.VisualBasic
Public Class Form1
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Integer)
Dim WithEvents serialPort As New IO.Ports.SerialPort
Dim PicaxeRegisters(0 To 2) As Byte

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Timer1.Enabled = True
Timer1.Interval = 1000
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick

Call SerialTxRx()
End Sub
Sub SerialTxRx()
Dim labelstring As String
Dim labelstring1 As String
If serialPort.IsOpen Then
serialPort.Close()
End If
Try
With serialPort
.PortName = "COM1"
.BaudRate = 9600
.Parity = IO.Ports.Parity.None
.DataBits = 8 ' 8 bits
.StopBits = IO.Ports.StopBits.One
.Open()
.DiscardInBuffer()
Call Sleep(100)
.Read(PicaxeRegisters, 0, 3)

.Close()
End With

labelstring = PicaxeRegisters(0)
labelstring1 = PicaxeRegisters(2)
Label1.Text = labelstring
label2.text = labelstring1

Catch ex As Exception
MsgBox(ex.ToString)
Label1.Text = "Timeout"
End Try


End Sub

End Class

Thank You all ... :)
 

westaust55

Moderator
@santhoshR,

please use the [code] and [/code] tags around your program code listings when it is more than a few lines as dsiscussed in the sticky "Read Me First" thread at the start of the forum.

The easiest way to do this is to paste you code into the post window and with the code selected (you may need to click on "Go Advanced" button at the bottom right of the window) click on the hash (#) icon in the toolbars above the post/edit window.
 

hippy

Ex-Staff (retired)
Thank You everyone for your replies .. !! I have solved the problem
Are you sure you have or is it that you've been lucky so far and it appears to work but may not under all circumstances ?

I don't know the answer to that but what would happen if you were sending "12345 6789" and you opened the serial port or .DiscardInBuffer were invoked after "123" had been sent; would you not then receive and display "45 6789" ?

Worse perhaps is what if "12345 6" had been sent; would the code 'get confused' and take the next number seen as the second to the first, end up showing "789 12345" ?
 

inglewoodpete

Senior Member
VB Code for processing 8-bit serial bytes.

Sending and receiving 8-bit binary numbers in Visual Basic (I use VB2008) can be a challenge.

To save you the many hours of grief that I had getting it to work properly, read up on the following excerpts of a comms programme that I wrote.

When defining (opening) the port:
Code:
SerialPort1.Encoding = System.Text.Encoding.GetEncoding(28591)
To receive bytes and put them in a character array
Code:
Private Sub Receiver(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
Dim bRXByte As Byte
Dim RXArray(2047) As Char
Dim I As Integer = 0
        Do
            bRXByte = SerialPort1.ReadByte
            RXArray(I) = Chr(bRXByte)
             I = I + 1
        Loop Until (SerialPort1.BytesToRead = 0)
        Dim RxString As New String(RXArray, 0, I)
To get the value of an incoming byte
Code:
Dim iChar As Integer
Dim I As Integer = 1
    iChar = Asc(Mid(sInData, I, 1))
    Select Case iChar
        Case Is > 127
        'etc etc
To combine 2 integers received from serial port in this way.
Code:
Dim iRec(10) As Integer
Dim iReqdPos As Integer = iRec(I) + iRec(I + 1) * 256    'It depends on which order you send the bytes
The PICAXE code should just sent the 2 bytes, so don't include the # symbol.

Sorry if the code is a bit disjointed. The program is quite specialised and it could be more confusing if I post the whole Class.
 
Top