PDA

View Full Version : VB Help



cncmachineguy
- 30th May 2011, 13:42
Anybody know and want to help me through som VB express issues?

In a nut shell, the problem is this:
I know how to make something happen when I push a button. But how to create a "main loop"?

I have a small app that when I press the button, I can get 18 bytes of data from my PIC. But I need to get the data all the time, not just on a button press. Then if I press the stop button, well of course it stops.

this is what I think in the main:


do while getdata = 1
get the data from the com port
put the data in the text boxes
loop

Then my get data button would be :


open serial port
getdata = 1

stop button:


close serial port
getdata = 0


Of course there is more to the code then this, but I am stuck on not understanding the structure of things. Happy to post my code, of course I don't even know if the code I will post is all the code. I know where all I have written is.
I realize I should maybe post in a VB forum, but I know there are folks here that may be able to help, and I like it here better. :)

gadelhas
- 30th May 2011, 13:50
HI;

You want to pull the data from the serial Port?
So, you should use the serial port receive event, like this one;


Private Sub DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
Dim recepcao As String
' do what you want you the recepcao variable



The total code, should be something like this;

First you need to add the serilport class to your project.


Public Class Form1
Dim WithEvents SerialPort1 As New IO.Ports.SerialPort


Then, at Form Load, you need to configure and open your SerialPort;


Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
SerialPort1.PortName = "COM1"
SerialPort1.Parity = IO.Ports.Parity.None
SerialPort1.BaudRate = 9600
SerialPort1.DataBits = 8
SerialPort1.StopBits = 1
SerialPort1.Open()
End Sub


This handles the recetion from the buffer of the com port, and then i have a If statment to do the actions that need to be perfomed acording with the received data.


Private Sub DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
Dim recepcao As String

recepcao = SerialPort1.ReadExisting

If recepcao = "%TE" Then
GetCursorPos(rect)
SetCursorPos(rect.X - 1, rect.Y)
End IF


After you have this working, you sould put some "Try ...Catch" code, to handle the erros!

Hope it can help you!

cncmachineguy
- 30th May 2011, 15:06
Hi Gadelhas, Thanks for your help. Let me assure you first I am completely new to this. Just started learning it yesterday.

I understand your examples, but I am still confused.

I have it reading the serial port now. I have a button set up that when I press it, it sends a char to the pic, and the pic responds with 18 bytes. This seems to work good, everytime I press the button.

What I want to do is set up a timer(I think I can do that based on examples found surfing) to "press the button for me" every 100mS or so.

So the "form1_load" section is where the start of the program is?

I really don't understand how the code "flows". All the beginner tutorals seem to be the same thing: add a button, add a textbox. Add code in the button event to put text in the text box.
None explain how the overall code is executed. Please see that I think in terms of coding a PIC. ie: there is a main loop, inside the loop we check things and gosub or goto different parts of the code, then we get back to the main and return to the beginning. we may even have interrupts that will stop what is happening and run some other code, then return to what it was doing before.

So to me all the button events are like the sub-routines, that get called when we press the button. but where do they return to?

If I used the examples you gave, will the "code" just hang out in lala land until a byte is received?

Am I thinking too hard?

mister_e
- 30th May 2011, 15:19
Yup, in VB, everything is "Event driven", so the software Wait 'till the next event, process the event... and then take a break before the next event.

Should you have any further problem, post your whole project/solution here. I can definitely help on that.

Check the SerialPort settings, you can trigger the SerialPort Event after having receive a certain amount of incoming bytes.

ScaleRobotics
- 30th May 2011, 16:03
Like Mister_e says, Visual Basic is event driven. You have to think a lot differently when using visual basic. Everything needs an event to fire. A button must be pressed, the comm port must have received new data, text must have been typed into the text box, a timer must have timed out, etc. On each one of those events, code can be written to do math, change characters, do lookups, store data into a database ... whatever.

One way to think about it might be to compare it to programming in picbasic, but solely using interrupts. Each event is handled by the interrupt handler for that event. Like Steve mentions, until an event happens, VB just waits.

Attached is a comm port program that acts on comm port data received. http://www.innovatic.dk/knowledg/SerialCOM/SerialCOM.htm

cncmachineguy
- 30th May 2011, 16:04
I assume this is all of it. If not I don't know where to find it.


PublicClass Form1
Dim getdata AsByte


PrivateSub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim namearray() AsString
namearray = IO.Ports.SerialPort.GetPortNames
If namearray(0) = ""Then
TextBox1.Text = "none found!"
Else
'ComboBox1.Text = namearray(0)
SerialPort1.PortName = namearray(0)
TextBox1.Text = SerialPort1.PortName
EndIf

EndSub
PrivateSub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim i AsInteger
Dim datain AsByte
Dim data(20) AsShort
If getdata = 0 Then
SerialPort1.Open()
getdata = 1
EndIf
'Do While getdata <> 0
SerialPort1.Write("k")
For i = 0 To 17
datain = SerialPort1.ReadByte()
data(i) = datain
Next
gxhb.Text = (data(0) * 256) + data(1)
'gxlb.Text = Hex(data(1))
gyhb.Text = (data(2) * 256) + data(3)
'gylb.Text = Hex(data(3))
gzhb.Text = (data(4) * 256) + data(5)
'gzlb.Text = Hex(data(5))
axhb.Text = (data(6) * 256) + data(7)
'axlb.Text = Hex(data(7))
ayhb.Text = (data(8) * 256) + data(9)
'aylb.Text = Hex(data(9))
azhb.Text = (data(10) * 256) + data(11)
'azlb.Text = Hex(data(11))
cxhb.Text = (data(12) * 256) + data(13)
'cxlb.Text = Hex(data(13))
cyhb.Text = (data(14) * 256) + data(15)
'cylb.Text = Hex(data(15))
czhb.Text = (data(16) * 256) + data(17)
'czlb.Text = (data(17))
'Loop


EndSub
PrivateSub Panel2_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs)
EndSub
PrivateSub czlb_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles czlb.TextChanged
EndSub
PrivateSub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
getdata = 0
SerialPort1.Close()
EndSub
PrivateSub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) HandlesMyBase.Load
'Do While 0 < 1
If getdata = 1 Then
TextBox1.Text = "sub ran"
Else
TextBox1.Text = "sub else ran"
EndIf
'Loop
EndSub
EndClass

cncmachineguy
- 30th May 2011, 16:14
Having just read walters post, it seems to me I need a timer, that when it fires it runs the code now in the button_2 press. It would run the code everytime the timer condition is met? Then the button code needs a check for if getdata is 1 or 0. so really the code is inside an if_then.

Then the timer is my event.

BTW, if the code I posted makes no sense, my appalogies.

How to setup the timer for every 50 ms?

Heckler
- 30th May 2011, 16:38
Hey Bert (cncmachineguy),

How did you post code with the color formatting?
I would like to be able to do that... (I think everyone should) as it makes code much more readable.'
Is it the type of editor you copied the code from?? I notice that other posts in this thread do not have color formatting.

thanks

cncmachineguy
- 30th May 2011, 16:51
This code was copied from VB express IDE. The color came with it. Would have been nice if the spacing had also followed along.

I have NO idea why, normally I would have had to highlight and change color for all things not black.

I think the other posts were prolly just typed up on the spot

dhouston
- 30th May 2011, 16:58
Anybody know and want to help me through som VB express issues?I don't have time to help with coding but my advice is to pay $100 for PureBasic (http://www.purebasic.com/)which runs on Windows, Linux & OSX and creates small, fast, standalone executables.

ScaleRobotics
- 30th May 2011, 16:59
You could use the timer, but the best way would be to use a comm port event. That way you are only doing something when data arrives. Its been years (and years) since I wrote a VB program with serial port, so I am sure others can do better than my try at answering this. But here is something I found for a newer version of VB.

http://www.me.umn.edu/courses/me2011/smartprodcourse/technotes/docs/serial-port-vb.pdf Toward the end, it mentions why things get a little complicated: "For receiving data at unexpected times, use the DataReceived event. This is a bit tricky
because it runs in a different thread and requires a handler. (Virtual Serial Port Cookbook,
Chapter 9 for details.)" Of course it is in chapter 9. Chapters 1 - 6 are free: http://www.smileymicros.com/index.php?module=pagemaster&PAGE_user_op=view_page&PAGE_id=50

cncmachineguy
- 30th May 2011, 17:49
I don't have time to help with coding

Are you sure?

awaiting the long-promised Tibbo EM500/GA1000 firmware) and need something to do this afternoon


but my advice is to pay $100 for PureBasic (http://www.purebasic.com/)which runs on Windows, Linux & OSX and creates small, fast, standalone executables.
Looked at it, also real basic and liberty basic. Nothing wrong with any of them and I have no issue paying for the software. But to get started in windoze apps, I figured I may as well use windoze software. For this adventure I have no need for cross platform deployment.

cncmachineguy
- 30th May 2011, 17:53
You could use the timer

Well no really I can't just yet. Haven't figured out how - LOL

@Walter, what you suggest makes the Pic the master and the PC the slave. I guess that works just fine. Although I suppose if I put some code in the pic to be on continusely or to be polled, that would still let the PC be in charge. Then the pic can just watch for the "stop sending data" command.

dhouston
- 30th May 2011, 18:04
Are you sure?.Yeah - while patiently waiting for the long-promised Tibbo EM500/GA1000 firmware, I'm filling the time adding one more ConnectOne WiFi module to the Amicus18/Arduino/Xino shield. Any of three modules - 2 WiFi, 1 NoFi can be plugged into it. (I hope I have room for the EEPROM mackrackit's going to fill with AT codes.:))

cncmachineguy
- 30th May 2011, 18:31
Dave, did you check your spam folder? Sometimes when I am long awaiting stuff, I find it went there. Hahahaha.

Group- I feel like my interpretation of Walters post is prolly the best overall solution, but my root problem remains.

How to setup a timer trigger? Maybe it is in the control toolbox? I will check there next.

rmteo
- 30th May 2011, 18:51
....How to setup a timer trigger? Maybe it is in the control toolbox? I will check there next.

Select the TIMER control from the toolbox and drag it into your project. Click on the control to display its properties. Enable the TIMER and set its interval to whatever you want (in mS) - see below.

5584

Then code whatever you want to happen whenever a trigger occurs as in the example below.


Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
count = Val(Label1.Text) * 100
count = count + 1
HScrollBar1.Value = count
Label1.Text = Format$(count / 100, "#0.00")
NumericUpDown1.Value = count / 100

count = Val(Label3.Text) * 100
count = count + 1
HScrollBar2.Value = count
Label3.Text = Format$(count / 100, "#0.00")
End Sub

cncmachineguy
- 30th May 2011, 18:54
Oh thank you rmteo! I had just found the timer, but didn't get the interval part. That works awesome!!

Ok, now to convert those 2's complimented numbers to show negative values instead of 65533 and such.

gadelhas
- 30th May 2011, 19:43
Hi cncmachineguy;

To receive data from the serial port you should always use SerialPort Event Trigger like the one i posted.



Private Sub DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
Dim recepcao As String

recepcao = SerialPort1.ReadExisting

If recepcao = "%TE" Then
GetCursorPos(rect)
SetCursorPos(rect.X - 1, rect.Y)
End IF
End Sub


Don't use timers to poll the serial port, it is not very efficient!!

If you want to send data to PIC, like a press of a button, then you can use the timer. just put the code that you have inside the button, inside of the timer, and choose the interval!

I wrote this post in a little hurry, later i have more time and i came back here!

cncmachineguy
- 30th May 2011, 22:17
Thanks gadelhas, point taken. Right now the pic is not allowed to send data unless asked for it. The pic side code is modified from the CDC for dummies thread. This part is working great. Thanks to all of you.

Now for the next part (this seems like it should be easy, but of course not). The 18 bytes sent from the pic represent 9 words. From here on, I will just refer to 1 word. The rest will be the same action.
Let's call them data(0) and data(1). To put them together I did this:


detain =(data(0)*256)+data(1))

this works fine with 1 problem. It is really a signed number, so 65533 should read -2.
I have tried all sort of ways to get here, but continue to fail. I am sure it has to do with dim as or the way I am putting the word back together, but I am at a loss.

Anyone know how?

gadelhas
- 30th May 2011, 22:36
What do you receive from PIC, and what do you want to do, can you give me a full example, its just because english is not my native language, and perhaps i'm not understand something

cncmachineguy
- 30th May 2011, 22:42
From PIC:
data(0) and data(1). these 2 bytes are the highbyte and lowbyte of a word. -32768-32767

I need to see the word like that. for example the word may equal 3, or it may be -3. right now I will see 3 or 65533.

So how to put the bytes back together and show signed integer?

mister_e
- 30th May 2011, 22:43
I never had any purpose to justify the use of signed<->unsigned conversion myself, but you may have a look at
http://support.microsoft.com/kb/189323

It's all about how you interpret/display the numbers... like Floating point in PBP... or show decimal on a LCD

cncmachineguy
- 30th May 2011, 22:48
I would normally side with you steve, but on this one I am having issues. The numbers bounce around zero, so I get to watch 3,3,4,2,1,65533,65534,4,1,.....

Seems like it would be better to have the numbers more right

gadelhas
- 30th May 2011, 22:49
From PIC:
data(0) and data(1). these 2 bytes are the highbyte and lowbyte of a word. -32768-32767

I need to see the word like that. for example the word may equal 3, or it may be -3. right now I will see 3 or 65533.

So how to put the bytes back together and show signed integer?

IN VB.Net, signed bytes are Sbyte and signed Words are Short

Exemple;
Dim data0 as Short=-32500
Dim data1 as SByte = -65

But if the PIC is sending the 65533, the PC will see 65533 and not -3. Don't know if can help you.

cncmachineguy
- 30th May 2011, 23:00
Ok, different question. How do I put 2 received bytes back together to make 1 word?

gadelhas
- 30th May 2011, 23:04
Ok, different question. How do I put 2 received bytes back together to make 1 word?
Tell me one thing first, what is the type of you variable where you receive the data from PIC, Integer, String....

mister_e
- 30th May 2011, 23:06
Like you did have to be fine.
WordOut=(MSByte*256)+LSByte

gadelhas
- 30th May 2011, 23:19
Like you did have to be fine.
WordOut=(MSByte*256)+LSByte

That should work;

But if you are showing this result to a textbox you should do
this:
WordOut=(MSByte*256)+LSByte
czhb.Text=WordOut.ToString

Maybe it is not your problem, but you should do this!

cncmachineguy
- 30th May 2011, 23:49
Well not saying its is the best way by any means, but this seems to work:


Dim i AsInteger
Dim t AsUShort
Dim datain AsByte
Dim data(20) AsByte
Dim sign AsString


t = (data(0) * 256) + data(1)
If t > 32767 Then
t = (Not t) + 1
sign = "-"
Else : sign = " "
EndIf
gxhb.Text = sign & t.ToString


Thanks for the help guys, for now this will cover my needs

gadelhas
- 30th May 2011, 23:52
Well not saying its is the best way by any means, but this seems to work:


Dim i AsInteger
Dim t AsUShort
Dim datain AsByte
Dim data(20) AsByte
Dim sign AsString


t = (data(0) * 256) + data(1)
If t > 32767 Then
t = (Not t) + 1
sign = "-"
Else : sign = " "
EndIf
gxhb.Text = sign & t.ToString


Thanks for the help guys, for now this will cover my needs


Yeh, that works, and if it works...GooD:D

cncmachineguy
- 30th May 2011, 23:54
Seems like it should be much easier. :(

mister_e
- 30th May 2011, 23:59
yeah but where would be the fun :)

cncmachineguy
- 31st May 2011, 01:28
Well I guess it would be a little better if that snippet was a sub routine, or function, or module, or object. See, I don't even know what it should be.

To me a sub-routine. I want to call it with values in data1 and data2. it should return with a string in wordout.

But that is just a little above my pay grade right now.

mister_e
- 31st May 2011, 04:03
Once you feel you're ready, have a look at this
http://msdn.microsoft.com/en-us/library/y6yz79c3%28v=vs.80%29.aspx

Then you could use something like
txtResult.txt = ConvertWordToSignedString (WordVariable)

cncmachineguy
- 31st May 2011, 05:11
Hot Dog!! Thanks again, I feel proud :)

new function:


PublicFunction CreateSWord(ByVal data1 AsByte, ByVal data2 AsByte) AsString
Dim t AsUShort
Dim sign AsString

t = (data1 * 256) + data2
If t > 32767 Then
t = (Not t) + 1
sign = "-"
Else
sign = " "
EndIf
Return (sign & t.ToString)
EndFunction


And how to get there:


gxhb.Text = CreateSWord(data(0), data(1))
gyhb.Text = CreateSWord(data(2), data(3))
gzhb.Text = CreateSWord(data(4), data(5))
axhb.Text = CreateSWord(data(6), data(7))
ayhb.Text = CreateSWord(data(8), data(9))
azhb.Text = CreateSWord(data(10), data(11))
cxhb.Text = CreateSWord(data(12), data(13))
cyhb.Text = CreateSWord(data(14), data(15))
czhb.Text = CreateSWord(data(16), data(17))

mister_e
- 31st May 2011, 05:37
See how easy it is now huh?

Well done!