VB.net serial and ftp code

moxhamj

New Member
From time to time questions get posted about writing software to interface to a picaxe. This is a work in progress and is heading towards a system that can control devices anywhere in the world using a picaxe to interface to a PC and the internet to ftp some simple data packets to and from a common location (a free website).

Link to working Serial interface demo is at http://www.instructables.com/id/Control-real-world-devices-with-your-PC/

Link to working FTP worldwide interface demo is at
http://www.instructables.com/id/Worldwide-microcontroller-link-for-under-20/

This code uses VB.net. I must say that VB.net is horrible. There is minimal help. It is almost impossible to code unless you know ordinary basic so it is not a language for beginners. Not much code exists on the internet and what is out there seems to only half work. Many commands simply don't work any more. Things like strings don't work unless you say Imports Strings = microsoft.visualbasic at the beginning. Simple things like an FTP batch file end up being far too complicated. There is far too much unnecessary jargon (we don't have run time errors any more, we "throw an exception").

But on the upside - it is free. Errors are easy to catch which is why it is worth coding the ftp in vb.net rather than shelling out to a batch file. Slabs of C and Java can be pasted in. There seem to be no licence error messages like vb6 has. Building an exe seems simpler. Serial port interfacing has timeouts. So all in all I suspect it is going to be worth trying to learn this new language.

This code comes with a form with two picture boxes, two labels and two buttons so the form is as simple as possible. The website password and username are in this code and I'm more than happy if anyone wants to use that site for testing. For just serial interfacing much of the code can be deleted.

The forum says this has exceeded the 10000 character limit so am posting in three parts.
 
Last edited:

moxhamj

New Member
Imports System.IO
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 Filename As String
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load ' need all this rubbish stuff - .net puts it in automatically when go form1events above/load
Timer1.Enabled = True ' put this in code as defaults to false when created
Timer1.Interval = 5000 ' 5 seconds
PictureBox1.BackColor = Color.Gray
PictureBox2.BackColor = Color.Gray
End Sub
Sub SerialTxRx()
Dim SendString As String
Dim ResponseString As String = ""
Dim LabelString As String
Dim i As Integer
SendString = "Data"
For i = 0 To 13
SendString = SendString + Chr(PicaxeRegisters(i))
Next
If serialPort.IsOpen Then
serialPort.Close()
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 = 2400
.Parity = IO.Ports.Parity.None
.DataBits = 8
.StopBits = IO.Ports.StopBits.One
.ReadTimeout = 1000 ' milliseconds
.Open()
.DiscardInBuffer()
.Write(SendString)
Call Sleep(300) ' 100 milliseconds minimum to wait for data to come back and more if data stream is longer
ResponseString = serialPort.ReadExisting
.Close()
End With
If Len(ResponseString) <> 0 Then
'got a response so store in array and display
PictureBox1.BackColor = Color.Green
For i = 0 To 13 ' string is Data+14 bytes - store in array
PicaxeRegisters(i) = Asc(Mid(ResponseString, i + 5, 1))
Next
' display to, from and the data
LabelString = "To: "
For i = 0 To 2
LabelString = LabelString + Str(PicaxeRegisters(i)) + "."
Next
LabelString = LabelString + Str(PicaxeRegisters(3))
LabelString = LabelString + " From: "
For i = 4 To 6
LabelString = LabelString + Str(PicaxeRegisters(i)) + "."
Next
LabelString = LabelString + Str(PicaxeRegisters(7)) + " Data:"
For i = 8 To 13
LabelString = LabelString + " " + Str(PicaxeRegisters(i))
Next
Else
' no response - maybe not connected or not powered up or chip not programmed
PictureBox1.BackColor = Color.Red
For i = 0 To 13
PicaxeRegisters(i) = 0 ' returns zeros
Next
LabelString = "Picaxe disconnected"
End If
Label1.Text = LabelString
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Sub FTPGetDirectoryListing()
Const host As String = "ftp://ftp.0catch.com" ' note the 0 is a zero not a character O
Const username As String = "picaxe.0catch.com"
Const password As String = "picaxetester"
Dim URI As String
URI = host
Dim ftp As System.Net.FtpWebRequest = CType(System.Net.FtpWebRequest.Create(URI), System.Net.FtpWebRequest)
ftp.Credentials = New System.Net.NetworkCredential(username, password)
ftp.KeepAlive = False
ftp.UseBinary = True
ftp.Method = System.Net.WebRequestMethods.Ftp.ListDirectoryDetails
Using response As System.Net.FtpWebResponse = CType(ftp.GetResponse, System.Net.FtpWebResponse)
Using responseStream As IO.Stream = response.GetResponseStream
Using fs As New IO.FileStream("c:\listfiles.txt", IO.FileMode.Create)
Dim buffer(2047) As Byte
Dim read As Integer = 0
Do
read = responseStream.Read(buffer, 0, buffer.Length)
fs.Write(buffer, 0, read)
Loop Until read = 0
responseStream.Close()
fs.Flush()
fs.Close()
End Using
responseStream.Close()
End Using
response.Close()
End Using
End Sub
Sub FTPUpload(ByVal Filename As String)
Dim localFile As String 'place to store data
Dim remoteFile As String ' filename is case sensitive this is really important
Const host As String = "ftp://ftp.0catch.com" ' note the 0 is a zero not a character O
Const username As String = "picaxe.0catch.com"
Const password As String = "picaxetester"
Dim URI As String
localFile = "C:\" + Filename ' store in root directory but can change this
remoteFile = "/" + Filename
URI = host + remoteFile
Try
Dim ftp As System.Net.FtpWebRequest = CType(System.Net.FtpWebRequest.Create(URI), System.Net.FtpWebRequest)
ftp.Credentials = New System.Net.NetworkCredential(username, password)
ftp.KeepAlive = False
ftp.UseBinary = True
ftp.Method = System.Net.WebRequestMethods.Ftp.UploadFile
Dim fs As New FileStream(localFile, FileMode.Open)
Dim filecontents(fs.Length) As Byte
fs.Read(filecontents, 0, fs.Length)
fs.Close()
Dim requestStream As Stream = ftp.GetRequestStream()
requestStream.Write(filecontents, 0, filecontents.Length)
requestStream.Close()
Catch 'can't connect
PictureBox2.BackColor = Color.Red
Label2.Text = "FTP disconnected"
End Try
End Sub

Sub ftpdownload(ByVal Filename As String)
' downloads remotefile to localfile
Dim localFile As String 'place to store data
Dim remoteFile As String ' filename is case sensitive this is really important
Const host As String = "ftp://ftp.0catch.com"
Const username As String = "picaxe.0catch.com"
Const password As String = "picaxetester"
Dim URI As String
localFile = "C:\" + Filename ' store in root directory but can change this
remoteFile = "/" + Filename
URI = host + remoteFile
Try
Dim ftp As System.Net.FtpWebRequest = CType(System.Net.FtpWebRequest.Create(URI), System.Net.FtpWebRequest)
ftp.Credentials = New System.Net.NetworkCredential(username, password)
ftp.KeepAlive = False
ftp.UseBinary = True
ftp.Method = System.Net.WebRequestMethods.Ftp.DownloadFile
' read in pieces as don't know how big the file is
Using response As System.Net.FtpWebResponse = CType(ftp.GetResponse, System.Net.FtpWebResponse)
Using responseStream As IO.Stream = response.GetResponseStream
Using fs As New IO.FileStream(localFile, IO.FileMode.Create)
Dim buffer(2047) As Byte
Dim read As Integer = 0
Do
read = responseStream.Read(buffer, 0, buffer.Length)
fs.Write(buffer, 0, read)
Loop Until read = 0
responseStream.Close()
fs.Flush()
fs.Close()
End Using
responseStream.Close()
End Using
response.Close()
End Using
Catch ' put error codes here
End Try
End Sub
Sub TestFTP()
' send a blank file and read it back then send a file with data and check it comes back
Dim Filename As String
Filename = "Test.txt"
Dim fullfilename As String
fullfilename = "C:\" + Filename
Call Deletelocalfile(Filename)
Dim fs As New FileStream(fullfilename, FileMode.Create, FileAccess.Write)
Dim s As New StreamWriter(fs)
's.BaseStream.Seek(0, SeekOrigin.End)
s.WriteLine("Echo to ftp")
s.Close()
Call FTPUpload(Filename)
Call Deletelocalfile(Filename) ' make sure local one is gone
Call ftpdownload(Filename)
Dim readline As String
Try
Dim fr As New FileStream(fullfilename, FileMode.Open, FileAccess.Read)
Dim r As New StreamReader(fr)
readline = r.ReadLine()
r.Close()
Catch ' file doesn't exist
readline = ""
End Try
If readline = "Echo to ftp" Then
PictureBox2.BackColor = Color.Green
Label2.Text = "FTP connected"
Else
PictureBox2.BackColor = Color.Red
Label2.Text = "FTP disconnected"
End If
End Sub
Sub Deletelocalfile(ByVal Filename As String)
Dim Location As String = "C:\"
Try
Kill(Location + Filename)
Catch ex As Exception
' MsgBox(ex.ToString)
End Try
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Static counter As Integer
Call SerialTxRx() ' talk to picaxe
If counter < 0 Then ' one minute
counter = 11
Call TestFTP()
End If
counter = counter - 1
End Sub
 

moxhamj

New Member
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
Call FTPGetDirectoryListing()
MsgBox("done")
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Call MessageToFTP()
End Sub
Sub MessageToFTP()
' if picaxe is connected and if ftp is active then send the data to
Dim Filename As String = ""
Dim CompleteFileName As String
Dim i As Integer
Call CreateFileName(Filename)
CompleteFileName = "c:\" + Filename
' save picaxe data to filename
Dim fs As New FileStream(CompleteFileName, FileMode.Create, FileAccess.Write)
Dim s As New StreamWriter(fs)
For i = 8 To 13 ' no need to send the from and to address as these are in the filename.
s.WriteLine(Str(PicaxeRegisters(i)))
Next
s.Close()
' upload this file
Call FTPUpload(Filename)
MsgBox(Filename)
End Sub
Public Sub CreateFileName(ByRef Filename As String)
'note can't pass variables unless use public sub, not sub, and also byref, not byval
Dim i As Integer
Filename = ""
For i = 0 To 7
filename = filename + Strings.Right("000" + Trim(Str(PicaxeRegisters(i))), 3) + "x"
Next
filename = Strings.Left(filename, Len(filename) - 1)
filename = filename + ".txt"
End Sub

End Class



*************** Picaxe code *********************
' physical leg 2 is grounded
' pin3 (physical leg 4) = the data input
' pin0 (physical leg 7) = the data output
' data protocols
' address of device is 255.255.255.255 eg a.b.c.d where a and b are device numbers, c is the local bus and d is the device number
symbol device0 = 1' device 1.1.1.1
symbol device1 = 1
symbol device2 = 1
symbol device3 = 1


main:serin 3,N2400,("Data"),b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13
' b0.b1.b2.b3 is the device this message is for - can add code to ignore other messages if using multiple devices on a bus
' b4.b5.b6.b7 is the device the message came from
' b8 to b13 are the data bytes
b0=1' send to device 1.2.1.1
b1=2
b2=1
b3=1
b4=device0' from me
b5=device1
b6=device2
b7=device3
readadc 2,b8' read a pot
serout 0,N2400,("Data", b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13)
goto main
 

benryves

Senior Member
Good idea to post some sample code for VB.NET!

I'm a .NET developer so would have to respectfully disagree with some of your comments about VB.NET being a horrible language! I will agree that as it's very easy to write very sloppy code in VB6 there's a lot of bad documentation out there, but what's on MSDN should be good.

With that in mind, I hope you don't take offence to a couple of suggestions and/or tips (others might find these useful?)

When using unmanaged resources (such as FileStreams; basically anything that implements IDisposable) you should dispose them when you're finished with them. VB.NET makes this easy with the Using statement;

Code:
Using fs As New FileStream(CompleteFileName, FileMode.Create, FileAccess.Write)
    ' Do stuff.
End Using
The resource is disposed automatically when you leave the block; even better, if an exception is thrown inside the block the resource is still disposed for you.

If you're going to be manipulating file paths, use the static methods in the Path class (eg Path.Combine) rather than string manipulation functions. They're generally more reliable (and handle things like .. to go up a directory level) and also work on operating systems that have different file system conventions (eg the forward slash instead of backslash on Linux).

.NET uses Unicode throughout. If you want to convert a string to an array of bytes, or want to do the opposite (convert some bytes received from the PICAXE into a string) the Encoding class will do what you need. For example;

Code:
' Iterate over each byte in PICAXE:
For Each b As Byte In Encoding.ASCII.GetBytes("PICAXE")
    ' Do something with b.
Next

' Assuming DataReceived is an array of bytes;
Dim Message As String = Encoding.ASCII.GetString(DataReceived)
Rather than using VB6-compatibility functions (like Str()) there are often more powerful .NET equivalents; each object will expose .ToString() which can be used to format the data (eg, if Value is an integer then Value.ToString("X") will return a hexadecimal string rather than a decimal one). This is more a personal preference thing; I try not to use VB6 functions as the code can then be easily translated between any .NET language.
 
Dr Acula,

It looks like you missed part of the code when you copied and pasted the source. All of the .NET generated code that creates the components is missing, there's no definition for Timer1, for example. I tried copying and pasting the code above into Sharp Develop (a free .NET IDE alternative) and it doesn't have the component definitions.

On a side note, I wrote the documentation for System.Net.WebRequest, WebResponse, FtpWebRequest and FtpWebResponse. I apologize if it's difficult to understand. You're not alone in your feelings about VB.NET. The biggest critics of VB.NET are VB6 developers, for most of the reasons you outline above.

Because you have to learn a whole new language anyway, I suggest that instead of learning VB.NET you instead look at learning C#. That way you're moving to the language that the .NET Framework is written in, and you don't have the frustration of trying to do something that you know should be easy in VB6 but just doesn't work in VB.NET.
 

moxhamj

New Member
I'll post the bit of code that generates the components, but I deliberately kept them simple - a timer and a couple of labels/buttons/pictureboxes. Apologies if I forgot any others. I'm still trying to find the bit of text that describes the buttons etc - I found it once but I can't find it again.

The bit I don't like aboout .net is complexity for the sake of complexity. URI in ftp transfers ought to be hidden from the user. OK, you put it in and it works but actually it took me a lot of work to find the correct syntax - there was a lot of .net code on the internet that didn't quite have the correct syntax. But compare with the equivalent dos/unix ftp commands that do the same thing with less lines of code.

But I'm going to persevere with it and I would suggest to others to have a go because .net is likely to become the de-facto programming language for windows. It's a steep learning curve - probably steeper than machine code to 1978 Micro-Soft Basic and from Qbasic to Visual Basic.

Perhaps we can brainstorm some more simple subroutines?
 
Certainly. After looking over your code, this is what I've come up with...

We need to create three objects (collections of subroutines and data):

One object, PicaxeNetworkConnector, is responsible for communicating with the Picaxe. It basically implements your SerTxRx method, only it breaks it into two parts: SendData that sends data out to the Picaxe and a DataReceived event that occurs when the Picaxe sends data to the PC, ie. instead of asking the Picaxe "do you have any data" we let the Picaxe tell us when we have data.

The second object, PicaxeFTPSiteConnnector, implements your send and receive via FTP methods, again primarily as a SendData method and a DataReceived event. It takes data from the PicaxeNetworkConnector, aggregates it, and sends it up to the FTP site either manually or at configurable intervals. It also checks the FTP site at configurable intervals and raises a DataRecieved event when the FTP site has data for us.

The third object is a PicaxeNetworkMessage object that represents the data sent, received, and passed between the other two objects and the application.

Applications then become the "glue" that connect these two objects together, receiving data from one or the other Connector objects, deciding whether or not to pass it on, and then passing it from one network to the other.

How does that sound to you?
 

kranenborg

Senior Member
I (and i assume many forum members) would be very much interested in the first part, the PicaxeNetworkConnector, as I have seen several code examples on this forum for VB6 but never seen a good example using SerialPort for VB.NET (or I have missed it, because although I have an interest in it, I have never applied it). A clean implementation and documentation would serve many applications that have been discussed throughout the years.

I could in return think of a special version of a PicaxeNetworkConnector version for my SerialPower network. As a requirement on this module I subscribe to puddlehaven's remark: " instead of asking the Picaxe "do you have any data" we let the Picaxe tell us when we have data "

Best regards,
Jurjen
 

hippy

Technical Support
Staff member
I forgot about that - I have VB3, VB6, VB.Net (2005) and RealBasic (2007r4) examples of a simple serial port terminal emulator which shows serial port control. I intended to publish that, so will get round to that in the next few days. I got stuck on the C# version, but I can foget about that for the present.
 

moxhamj

New Member
Have put the complete code up at http://drvernacula.topcities.com/ftpserial.htm

Also a link to a quick list some common commands and how they have changed from vb6 to vb.net http://www.pharfruminsain.com/Teach/VB.NET.aspx

Puddlehaven, I think as a start a very simple routine - serial interface to a picaxe using vb.net? I think there are people wanting to do this - just send a "Hello" to a picaxe and get back a "Yes, I'm here"? I might cull out some code and get this down to as simple as I can make it. I'd very much appreciate your help soon on a few other vb.net things. Meanwhile, anyone who is interested in this might like to start downloading vb.net coz it is a few hundred Mb. Grab it while it is free! Click on the download button at the top right http://msdn2.microsoft.com/en-us/express/aa718406.aspx
 

hippy

Technical Support
Staff member
Grab it while it is free! Click on the download button at the top right http://msdn2.microsoft.com/en-us/express/aa718406.aspx
That probably installs a small bootstrap program which then downloads the modules as required.

If you don't want to mess with Passport, registering with Microsoft, getting Activation Keys and so on, or want to create a CD-Rom which can be taken to other PC's or copied for others for easy installation, see ...

http://msdn2.microsoft.com/en-us/express/aa718401.aspx

You need to burn the image to CD-Rom. You should also get SP1 as well, although it may be bundled with that download.

I always prefer creating an installable CD. It then works without needing an internet connection. Saves downloading after every OS re-install or new PC purchase. If anything changes in the download you know the CD hasn't. There's nothing worse than finding software which was free is no longer available or is a new version when you need it. I use a lot of old version software because it's still licensed as free or better than the new. My CD library of essential software isn't that large ( one product per CD ) and its a good habit to get into. I find it's often easier to hand a copy of a CD to a friend than try and talk them through a download process, and they are more likely to try it.
 
I started working on this on the train in to work this morning, so I have the Message object started. One of the things I thought of early was to make the size of the address fields and data fields configurable, so out of the box it can support Dr. Acula's 4 byte address and 6 byte data message format as well as Jurjen's 1 byte address and 2 byte data message format, as well as any other format people come up with.

I'm working on the FTP connector during my commute (the train has WiFi) and the Picaxe connector at home (where I have a Picaxe). I'll keep you posted on my progress.

Dr. Acula, can I use your FTP site to put up zip files of the program as I go along? I'd like to keep the files together if I can. If not I can put them on my Web site.

Thanks,
Chuck
 
Last edited:

moxhamj

New Member
Sure you can put zip files on the ftp site. You can even edit the index.htm page if you like and put in links etc for zip files. I have no need for the index.htm - I just put it there so the people running the website would be happy.

I'm excited about the possibilities here. Agree that need flexibility re the number of byte addresses. Getting two picaxes talking to each other anywhere in the world would be quite an achievement and I think we are almost there. I have a protoboard with a servo driving a switch to turn on a lamp. It is a demo system to show a picaxe actually doing something mechanical. It would be great to see it controlled by someone else.
 
I have the message object written, and the communicator object about 3/4 done. I thought I was done 'til I realized I was doing everything with ASCII strings, and that means that any value greater than 127 would come in as 63 (?). I'll do a rewrite and some testing tonight and tomorrow night, and hopefully have something up on the Web site by the end of the weekend.

It's funny, one of the reasons I want my Picaxe to talk to a PC is so I can have people push a button on my Web site and have a servo-controlled hand wave at me. Thinkin' alike there.

Chuck
 
Library uploaded

Following the precept "release early, release often", I uploaded the first version of the a serial communications library to the Web site (File removed by the Web site. See later messages for the new location.) tonight. The zip file contains a single directory, within which you will find a VS 2005 solution that includes all the files, and 4 subdirectories, each containing a VS 2005 VB or C# project. I also attached the VB source files for the objects in the projects as text files to this message (the event arguments have to wait for another message -- two file limit).

This version includes two objects, Message and Listener in both VB and C# versions, as well as test programs for each. The C# version includes complete documentation, unfortunately I couldn't convince my computer to generate help files from the C# sources. Maybe next time. I also need to admit that I wrote these in objects in C# and then used Lutz Roeder's Reflector to translate them to VB. If there are any real VB.NET programmers out there, that's why it's not in idiomatic VB.

The Message object represents a message sent to or from a Picaxe. You can set the length of the source address, destination address, and message data to conform to your network protocol. The test programs are set to read the 1 byte destination, 1 byte source, and 2 byte message data frame for Jurjen's serial power network. To make it work with Dr. Acula's 14 byte packet, you just need to change the address and data lengths.

Note: The destination address must come before the source address, which must come before the message data. I need to add that to the docs...

The Message object has properties that expose the source address, the destination address, and the message data as either byte arrays, un-delimited hex formatted strings, or as delimited hex strings. For example, the string "Hello" would appear as "Hello", "48656C6C6F", or as a delimited address as "48.65.6C.6C.6F", or as delimited data as "48 65 6C 6C 6F". You can also get the entire message as a byte array, or as a string. For fun the ToString method of the object prints out the message in the same format Dr. Acula used: "To: AA.BB From: CC.DD Data: EE FF 00 11 22 33"

The Listener object does just that, it listens on the serial port for an incoming message from a Picaxe and then constructs a Message object that contains it. The biggest difference between the Listener and the other code that I've seen is the Listener can handle binary data, it isn't limited to ASCII data only the way listeners based on terminal programs are.

You must set the destination address, source address, and data length before you call the Open method to start listening to the Picaxe. If you are only interested in the data, not in addresses, you only need to set the data length. The Listener needs to know the length of the network message so it can properly frame the message -- unlike text data that can be displayed as it comes in.

Once the Message object is created, there are two ways to get it. Your application can poll the DataAvailable property until it turns true and then get the message either as a Message object, a byte array, or as a string. When you read the message from one of these properties the DataAvailable property is set false until the next message arrives.

The other method is to create an event handler for the Listner object's MessageReceived event, and then handle those events. There is a MessageReceivedEventArgs object that contains the message, you use that Message object in your application.

When you use the SerialPort DataReceived event, as I have in the Listener, you have created a multithreaded application. Because of that, you have to be careful not to try to cross threads, and not to have two threads try to access the same variable at the same time.

In the Listener object I used thread locking to protect access to the DataAvailable and Message properties. Only one thread should be able to access the storage variables for these properties at a time, but I haven't extensively tested it.

The other issue is crossing thread boundaries when updating a UI, like I do in the two test applications. There are lots of ways to use Control.Invoke to cross boundaries, the one that I've picked here seems to be able to handle the Listener. I've marked the code in the test programs that is necessary for updating the UI in a thread-safe manner.

The Listener object descends from System.ComponentModel.Component, so it shows up in the Toolbar when you are creating a Windows form, and after you've dragged one to the form you can set properties in the Properties pane.

Next up I'm going to create a descendant of the Listener that will be able to send messages to the Picaxe as well as receive them. Look for that sometime next week.

Let me know what you think, I'm interested in your feedback, and to hear if this is the kind of object you were looking for.

Chuck
 

Attachments

Last edited:

moxhamj

New Member
Puddlehaven - can you post the syntax for serialport.read please? I've spent a hour on the bug where ascii characters over 127 come back as 63. I'm not sure why this should be since characters from 128 to 255 are all valid ascii characters, but working in text mode does not work. Is there a declare to work in the old ascii mode, or is it better to just read the bytes into an array? I'd prefer the latter - it is cleaner with less code but I can't seem to find the syntax for .read anywhere. vb.net wants a buffer, offset and a count and I'm sure the code is simple!
 
By default the SerialPort class returns everything ASCII encoded, and any byte over 127 comes in as "?", or $63. Makes it easy to use pure text, but harder for everything else.

The trick is to use a BinaryReader object to read the stream of bytes coming from the serial port into a byte array. Try something like this:
Code:
Dim incomingBuffer as new Byte(<dataPacketSize>)

Dim port as new SerialPort()
Dim reader as new BinaryReader(port.BaseStream)

incomingBuffer = reader.Read(incomingBuffer.Length)
(Or you can use the PicaxeListener object I posted last night.)

Code:
Dim incomingBuffer as Byte(<dataPacketSize>)

Dim listener as New PicaxeListener()
listener.DataLength = <dataPacketSize>

listener.Open()

' Continuous polling loop. Or use events.
While true
  If (listener.DataAvailable) Then
    incomingBuffer = listener.DataBytes
   ' do stuff here.
Do
Chuck
 
PicaxeConnector posted

I just uploaded the next version of the code library to Dr. Acula's FTP site (The file was removed by the Web site, see later messages for a link to the actual file.). This version of the library adds the Connector object that provides two-way serial port communications with a Picaxe chip. As with the last upload there is are VB and C# versions of both the code library and the demonstration programs that exercise the code.

The Connector object descends from the Listener object, so it inherits all the properties and methods of the listener, and all of the comments above apply to the connector as well. The Connector object adds three overloads of the SendMessage method. Each overload takes a message destined for your Picaxe and sends it over the serial port. An overload is available for Message objects, byte arrays, and strings.

I've also updated the included test applications to include test drivers for the Connector object. Simple click the Listener button to test the Listener object or press the Connector button to test the Connector object.

I've also attached the VB source code for the Connector to this post for your amusement.

Share and enjoy, and please let me know what you think.

Chuck
 

Attachments

Last edited:

moxhamj

New Member
Last edited:

benryves

Senior Member
If you want to send characters that are outside the ASCII range (0..127) you will need to set the SerialPort's Encoding property accordingly (it defaults to ASCII). Windows-1252 is fairly appropriate (New Encoding(1252) or New Encoding("Windows-1252") will create an instance that can be used).
Code:
serialPort.Encoding = New Encoding(1252)
(Rather that P/Invoking Sleep, you can also use the .NET equivalent System.Threading.Sleep()).
 

moxhamj

New Member
"New Encoding" sounds like a bug fix to me! It is great there are several solutions to this - I ended up using the method of directly writing a byte array because it then removed the step of cutting up a string into pieces. http://www.instructables.com/id/Control-real-world-devices-with-your-PC/ shows the steps. The 127 problem also seems to apply to sending strings as well as receiving them but sending and receiving a byte array works out simpler. I still haven't quite worked out how 'offset' works but arrays can easily be copied to add headers and/or checksums at the end and leave the offset in the final array at zero.

Thanks for the tip re Sleep. Just a quick dumb question re sleep in vb.net (using either method) - do background tasks keep running?
 
Last edited:
PicaxeWebSender posted

Next up in my series of posting is the WebSender object. This object queues messages sent from the Picaxe and then sends them to the FTP message repository at a defined, configurable interval.

The message queue is kept in an in-memory queue, so it does not need to create files on your local hard drive before sending the file to the message repository. I'm planning an enhancement that will enable you to send files to a local disk-based message repository (primarily for testing) and one that will enable using an HTTP server to manage the repository.

Both of these enhancements should be straight-forward, I'm taking advantage of the System.Net.WebClient object. This object is everything that I wish the WebRequest object could have been. After creating a WebClient object, you can upload data to an FTP site with this line of code:
Code:
   WebClient client = new WebClient()
   client.UploadData("ftp://ftp.host.com/Test.txt", data<string,file,byte array>);
To send the same data to a Web site, you write:
Code:
client.UploadData("http://htp.host.com/handler.aspx?Test.txt", data<string,file,byte array>);
Want to save it to the file system? Here's the line:
Code:
   client.UploadData("file://c:\\temp\\Test.txt", data<string,file,byte array>);
As usual, I've uploaded the solution containing the C# and VB versions of the code to ftp.0catch.com, but as usual the zip file was removed by the Web site. See later postings for a pointer to the actual location. The test driver program has been updated to include a new button, click the "Send to FTP site" button and every message received will be forwarded on to the FTP site at ftp.0catch.com.

The VB code for the WebSender is attached as a text file, as is an updated version of the Message object. I needed to add another property to the Message object, it now has the FileAddressString property that returns the destination and source address bytes as 3-digit integers separated by "x" characters ("000x000x000x000x000x000x000x000", the same as Dr. Acula's original program.

As usual, share and enjoy, and let me know what you think.
 

Attachments

Last edited:
Thanks for the tip re Sleep. Just a quick dumb question re sleep in vb.net (using either method) - do background tasks keep running?
Depends. If it's truly a background task running on another thread, then it keeps running. In your case, using the SerialPort object, you can put your UI thread to sleep and the background serial port listener code will keep on running.

Actually, the System.Threading.Thread.Sleep is just the .NET Framework wrapper to the same System32 sleep call you were using, just all wrapped up in pretty code by the folks at Microsoft.

"New Encoding" isn't a hack. By default the SerialPort encodes everything coming past it using an Encoding object called "ASCII". port.Encoding = New Encoding() just means "create a new Encoding object and use it instead of the ASCII Encoding object."

It's just how you change the data encoding coming over the wire. I usually use UTF-8 nowadays, but that's just me.

Chuck
 
PicaxeWebReceiver posted

I've finished the final piece of an end-to-end Picaxe to Web to Picaxe transfer system. The WebReceiver object retrieves messages from a Web repository and returns them to the PC where they can be passed on to the connected Picaxe network.

Like the Listener object, you can either handle the MessageReceived event or you can poll the DataAvailable property and read messages out of the WebReceiver's queue. Use of the queue is configurable by the UseMessageQueue property, this property should only be set true if your application will read messages out of the queue, typically if you are handling the MessageReceived event you are not reading messages out of the queue, and the UseMessageQueue property should be set to false.

The Web receiver polls the Web message repository at a configurable interval for new messages. You should set the interval to meet the expected traffic needs of your application.

The only "tricky" property on the Web receiver is the MessagePrefix property. You set this to the leading characters of the destination addresses that you want to download messages for. For example, if messages with the destination addresses "112x104x110x000" to "112x104x110x255" are destined for my network I would set the MessagePrefix property to "112x104x110x". That way I only download messages intended for my network, saving processing and bandwidth.

Here's the processing flow for the PicaxeWebReceiver object:

  • The WebReceiver object uses FTP to get a directory listing of all waiting messages that have the configured prefix.
  • For each message in the Web repository, the WebReceiver
    • Fetches the message from the repository via FTP.
    • Raises the MessageReceived event.
    • If using the queue to store messages, places the messages in the receive queue.
    • Removes the message from the Web repository.
    • Pauses for a configurable interval before getting the next message.
  • Waits until it's delay interval is up before connecting to the FTP site and starting again.

Once again I've made changes to the Message object to make creating message objects from the data downloaded from the Web easier. And as usual I've attached the VB versions of the WebReceiver and the Message objects to this e-mail.

Unlike usual I have not uploaded the Visual Studio solution to ftp.0catch.com. For some reason, probably due to a use restriction on the free Web site Dr. Acula is using for the Web repository, the zip file is being removed from the server. I've uploaded the file to my personal Web site, you can retrieve the file from this link:


And in another exciting development, I've figured out how to transfer documentation comments from the C# source files to the VB source files, so now all the VB source files are fully documented.

I've made some changes to the Visual Studio solution. I've renamed some objects, and removed the test application and replaced it with a Windows application that will act as a bridge between the Picaxe network and the Web repository. I've also started work on a Windows service that will run in the background on your PC to handle the bridge function, although that application is not ready yet. Please see the ReadMe.txt file in the Zip file for additional details.

As usual, share and enjoy, and let me know if you have any question, comments, kudos or brickbats.

Chuck
 

Attachments

Last edited:

moxhamj

New Member
This is really moving forward at a great pace!
Bit of a "oh darn" that OCatch are removing the zip files - but www.puddlehaven is better!
I got a couple of picaxes chatting to each other via the web working last night - a picaxe in my shed was able to turn a led on and off on a picaxe in my office inside. Could have been anywhere in the world. Also can link quite a number of picaxes (within the capacity of the ftp server) Am going to write it up in the next day or too - it needs commenting and documenting. The system I have is very simple but I think it can grow into the one Puddlehaven is building so we can grow this step by step.
I'm going to take back some of my negative comments about vb.net after I discovered that ftp has a timeout function. This turns out to be imperative as about 1 in 20 ftp's to the server were hanging the program. Now it times out after 10 seconds.
A question I might put on the main forum once we get all this working is to ask Stelios if he can link his little web server into this system.

Addit: picaxe worldwide microcontroller link is now published at http://www.instructables.com/id/Worldwide-microcontroller-link-for-under-20/
 
Last edited:

rbright

Member
Dr Acula & Puddlehaven I'm sure I'm not the only one following this post with great interest. Dr Acula I hope your still "going to write it up in the next day or too".
Thanks guys.....
 
New library posted

I've posted a new version of the network connector library to my Web site. This new version adds support for sending messages via UDP packets to support the Internet gateway mentioned in this thread:


I made two changes to the library for this version:

  1. I refactored the WebSender object into two objects, Sender and WebSender. The new Sender object implements all the methods and properties that are shared between the Web sender and UDP sender, the WebSender object only implements the methods and properties required to send data via FTP or HTTP.
  2. I created the new UDPSender object. Because of the refactoring, I only had to write one new method to implement UDP sending, and most of the code was in looping through the message queue.
Here's the two lines of code that it takes to send a UDP message using C# or VB.NET and the .NET Framework (I'm not including the lines that set up the message array, or that set the host and port addresses. Those are three more lines...):

Code:
DIM client as new System.Net.Sockets.UdpClient
client.Send(messageBytes, messageBytesLength, Host, Port)
You can find the new version (and the old version) on my Web site at:


As always, share and enjoy.

Chuck
 
Last edited:

lbenson

Senior Member
Dr_A above: "Getting two picaxes talking to each other anywhere in the world would be quite an achievement and I think we are almost there. I have a protoboard with a servo driving a switch to turn on a lamp. It is a demo system to show a picaxe actually doing something mechanical. It would be great to see it controlled by someone else."

Any chance of making it so that a UDP message could accomplish this?

What other items did you have in mind as examples of things which could be turned on by others? How would the sender know that the request has been fulfilled?
 

lbenson

Senior Member
BB--I have wanted to do a pan and tilt web-cam. The camera would, of course, take more horsepower than a picaxe possesses (Brietech's effort notwithstanding)--I've thought about the NSLU2 as a controller. Perhaps hippy's researches on the dark side have revealed a microprocessor-only path. Maybe Stelio's wireless device has the capability.
 

BeanieBots

Moderator
All of this web page stuff is outside my comfort zone but I was thinking of just using the PICAXE to control the pan/tilt side of things. The camera itself could be on a different address.
 

lbenson

Senior Member
BB--can you suggest a good platform for the pan and tilt side of things--something not entirely made from scratch?
 

BeanieBots

Moderator
Have a browse around the robotic sites.
There are several specifically for the CMUcam which could be modified for a webcam.
 
MicroConnector library uploaded to SourceForge

Hi everyone,

Sorry that I've been silent for a while, but life gets in the way of the things we like to do from time to time.

I removed the serial connector library a few months ago to rename the library. It's been a while since I've been able to work on it, but I now have the source code for the C# version of the library available again. It's now called the "MicroConnector .NET" library, and the source is available for download.

Instead of putting the source on my personal Web site I've created a SourceForge project containing the source. That way anyone interested in contributing to the library can make arrangements to check out the source code and check changes in. (If you're interested, please contact me through SourceForge and we'll talk).

Thanks for your patience, and for all the folks who've hit my Web site looking for this code over the last few months. I'm sorry that it wasn't there, but at least now the sources are available if you need them.

Here's a link to the project on SourceForge: https://sourceforge.net/projects/microconnector
 

Gee_Ock

New Member
Puddlehaven, will you be doing any further developing and updating of the source code at any point, or have you stopped working on this? I downloaded the code from sourceforge and you mentioned about adding more features and also a VB.NET version of the MicroBridge.
 

adumas

Member
Hi.. I just read over this thread - great stuff... I'm a bit late to the "meeting" and have tried to get up to speed. I downloaded the code from SourceForge - and installed Visual Studio 2008 - 2005 was not available. It tried to convert the solution from SourceForge but "gagged" at some point and did not convert everything - something about missing files...

Is there any chance that puddlehaven, you could try and regenerate this project under 2008?

I hope I am not alone in being bummed that each new release of VB causes a lot of excitement but also dispair when projects don't convert...

Dr_Acula I also like your work... I posted a reply on instructables yesterday. I created a little bit of picaxe code and posted it with my reply... In the message I am having issues with passing data and getting back the correct response... I am also concerned about pause time collisions...

Incidentally, I have successfully used Hyperterminal to see that the data is correctly being passed by picaxe...

Look forward to your help.
 
Top