Prop Communicating with VB2010
eagletalontim
Posts: 1,399
Good Evening! I am working on some communication issues with a VB10 program I am using to communicate with the Prop. Right now, I have run into a strange problem and maybe I am going about it the wrong way. What I am attempting to do is to send a string from the Prop to the VB program and visa versa. Right now, I am just trying to read from prop which is working, but is not constant. Sometimes the "string is empty". I was thinking it was because I am sending each string via Ser.tx("x") instead of using Ser.str(string("stuff to send")).
The problem with using Ser.str() is that I cannot add variable values to this string. Example (x = 20, y = 50) : Ser.str(string("The value of x =" : x : " and the value of y = " : y)) This is only an example and is not what the string consists of. I was also thinking of sticking with the Ser.tx() and just send a "start character" like "^" and an end character like "#". The VB program will just store any value after the "^" and then display the info once the "#" is received which determines the end of line.
So what I am trying to determine is how to send a string to VB from the prop as quickly as possible without losing data.
The problem with using Ser.str() is that I cannot add variable values to this string. Example (x = 20, y = 50) : Ser.str(string("The value of x =" : x : " and the value of y = " : y)) This is only an example and is not what the string consists of. I was also thinking of sticking with the Ser.tx() and just send a "start character" like "^" and an end character like "#". The VB program will just store any value after the "^" and then display the info once the "#" is received which determines the end of line.
So what I am trying to determine is how to send a string to VB from the prop as quickly as possible without losing data.
Comments
If the data length varies you might include the data length in the first byte rather than transmit a fixed length array, you may also want to include a checksum.
Other things to take into consideration are the type of data, how much data and how it's handled by your Visual Basic application.
Can you give an example of the data to be transmitted.
Parallax also have an application note on Prop + Vb communications, I dont remember the AN number off hand.
Jeff T.
Post your code!
Prop (Just the code that is processed to send information to the VB program) :
Then the VB Receiving and processing code :
The VB code above is receiving data and putting the characters it into a string. As soon as the Beginning character "^" is found and the End character "#" is found in the string, everything before the string is stripped and the string is parsed as only usable data. This appears to be working great for me so far. If there is a better way, please let me know!
Jeff T.
Be aware of the encoding property when you want to send/receive the full range of bytes (0 to 255).
If the encoding is not set, it will only process ascii characters. Other codes are ignored.
If it were me, I'd stay away from converting to ASCII and send actual values. 1) It's less processing 2) The value byte lengths (data type) within the packet are always the same.
Pseudocode for what you should be doing:
This way if you get half a message or two messages in one read attempt, you parse and process them all.
With regard to receiving ASCII from the Prop, if you are still interested in examining how this performs, I have a few ideas you might find helpful. There is more than one way to do this so what I write is my own personal opinion for this situation.
Firstly I have never been a fan of ReadExisting, I prefer ReadLine when reading ASCII strings. ReadLine reads a string that is terminated with a NewLine character (decimal 10) so already the need for the hash/pound character is eliminated. Using the carat as a start character and decimal 10 as the termination value we can force the DataReceived event handler to "block" until all the string has arrived.
The only modification your Prop code needs is to replace Ser.tx("#") with Ser.tx(10)
Jeff T.
If the Prop is transmitting data faster than the methods in VB are able to handle it the serial port buffer will over run and your app will hang or crash, if there is a predetermined amount of data to transmit you might possibly get away with just increasing the SerialPort1.ReadBufferSize, (worth trying to see the effect), the second option is to improve the methods VB is using to handle the data, such as creating separate threads.
Jeff T.
Here is some code I am trying :
VB Code :
Any ideas on why "Label19" is empty most of the time. On first start, some of the data is sent, but is mostly lost.
Attached is an echo demo. Make sure to set the port and baud.
Spin
VB.Net console
See... I posted all the code. That's not so hard, right?
And the VB Code :
The serial port demo in post 16 is designed to help understand the DataReceived event and what to expect. As well as, provide a light weight unit test. I'm guessing you did not try the demo?
Suggestion, create a packet protocol and send word sized data as opposed to ASCII characters. [Start][Start][PacketLength][Command][Data(0).Highbyte][Data(0).LowByte][Data(1...n)][Checksum]
Create code in Spin and VB that understands how to parse the packet. Do NOT put this code in the DataReceived event!
Test your code!!! If you do it right you will able to test the code without having to send serial data.
IMO, the DataReceivedHandler code is doing too much and needs to be abstracted to a class or classed or methods. All DataReceivedHandler should be doing is getting the serial port buffered data and passing the bytes to another code block preferably a class. The class will contain all the logic to parse the bytes and alert subscribers. The same goes for the Spin logic, create methods or an object to deal with the serial packets.
Now that I have the VB program talking to the Prop and visa versa, I have run into yet another issue. This time, I am attempting to send a bunch of variables to the Prop from the VB program, then the Prop will put these values into an array and then set a specified "User_Setting" with that index value. The problem is, the variables must all be LONG when assigned to the "User_Setting" variable.
and the VB code is sent like this :
What is sent back is the "failed" message which shows the pointer variable to be 51 and the array[2] to equal 58 when it should be 1500. Any ideas on how I can fix this?
If you use the Uint64 data type for your values in VB .Net and use the "BitConverter.GetBytes(value)" method then every value you send from VB will be transmitted as the four consecutive bytes of a Long.
Using this method it does not matter what the value is it will always be transmitted as a long. This may not be what your looking for but it is certainly worth reading about as it works very nicely in the kind of application you are designing.
Jeff T.
Edit: oops, didn't see the replies on the next page...
1) How do you send a LONG from the Prop to VB in 4 Bytes?
2) How do you read these 4 bytes and convert them to a readable "LONG" in VB?
3) How do you send a numerical value of a combobox selection (Selected value of 15000) to the prop in 4 bytes?
4) How do you receive this data on the Prop and save the value to a LONG?
Lets take the first four byte locations of the Props EEPROM, 0,1,2 and 3.
If I want to put a long value of 12345678 into the EEPROM it would fit in the first four byte locations like this
location 0 = value 0 (HEX 0)
location 1 = value 188 (HEX BC)
location 2 = value 97 (HEX 61)
location 3 = value 78 (HEX 4E)
12345678 converted to HEX is 00BC614E, providing you write your EEPROM a byte at a time into four consecutive bytes you can also read them a byte at a time , a word at a time or a long at a time it does not matter it's your preference.
You probably know that already so your thinking how do I write this data from VB. This is where the BitConverter class becomes so useful, it splits a long into four bytes for you, the values I have given come straight from the MSDN example at this link http://msdn.microsoft.com/en-us/library/system.bitconverter(v=vs.110).aspx
The two lines of interest are
this code fills four bytes of the array called "bytes" with the long value 12345678, there is no other calculation required. So all you have to do to transmit this long (which fills locations 0-3) is
and just keep repeating the above in a loop, incrementing the EEPROM address by 4 each time, until all your longs are sent.
Don't get discouraged, it might seem like greek but when you play around with it you will see just how simple it is and because it is simple you are able to understand whats going on and modify it to suit your own use.
I do actually have some code on the Parallax forums that does a similar job, I'll post the link when I find it.
Jeff T.
I am not sure how it is stored in the eeprom. I just know it works So, converting the "User_Setting" to 4 bytes to send through via the FullDuplexSerial so the VB program reads the 4 bytes and then converts it back to a readable string / integer is what I am trying to figure out.
I use hex notation here for explanation purposes only.
I found a couple of threads where the BitConverter is used, I'll name the post # but you will probably want to read the whole thread.
These threads contain Visual Basic examples and Spin files to test the VB application, please build the apps and see how they work.
Post #15 of the following
http://forums.parallax.com/showthread.php/145187-VB.net-to-Prop-communication
Post #18 of the following
http://forums.parallax.com/showthread.php/122891-Help-with-a-EEPROM-boot-loader
These programs will lead you away from using ASCII strings for your data but when you think about it your taking a numeric value and converting it to a string transmitting the string and then converting it back to a numeric value, doing it this way eliminates the conversions.
Jeff T.
For transmitting 3 longs on a Propeller this is untested but this is probably how I would go about it. This sends the most significate byte first. You will have to declare a small array to hold the 3 longs and assign your values to each long.
To send the value 123 to user_seetings[15], VB just sends the following string
$15,123=
To send the value 15000 to user_seetings[3], VB just sends the following string
$3,15000=
This makes it simple from the VB end as well.