[RESOLVED] Displaying data graphically (Ultrasonic radar)
Hi all, a beginner here
I'm working on an ultrasonic sonar and I would like to use the computer to display a standard green radar system detecting the objects.
I'm using a micro controller with the software written in C to send out the sensor's angle and position and it works fine.
On the computer side, I'm using Visual Basic 2010 to read the COM port which then contains the sensor's data in numbers (sensor's angle and distance between sensor and object) which is a constant stream. On the debug screen (Textbox) I can already see all the data coming through.
Now my question is: How do I convert those numbers into graphics?
More explanations about these numbers I want to convert:
I have a step motor to rotate the ultrasonic sensor, and it works that way:
The motor advances 1 step forward, then measure distance between sensor and object, then send these 2 values out.
So, if you see the attached file, those numbers on the text box mean:
000032 -> 000: step number & 032: 32cm between sensor and object
001031 -> 001: step number & 031: 31cm between sensor and object
002032 -> 002: step number & 032: 32cm between sensor and object
003007 -> 003: step number & 007: 7cm between sensor and object
and so on...
So those are the numbers I wish to convert into graphics. The scan line would need to rotate clockwise at same speed of the step motor. And then I would like to display dots when an object is detected.
Thanks in advance!
My O.S.: Windows Vista 32 bits.
Softwares: MPLAB IDE v8.53 (microcontroller part) and Microsoft Visual Basic 2010 Express (computer part)
Last edited by Alex83UK; April 12th, 2012 at 08:42 AM.
Re: Displaying data graphically (Ultrasonic radar)
GremlinSA: Thanks for your reply, however I believe the author of that article is hard-coding the coordinates of the drawings. So, how can I plot real-time data from the COM port?
Thanks again!
Special thanks to Lothar "the Great" Haensler, Chris Eastwood , dr_Michael, ClearCode, Iouri and
all the other wonderful people who made and make Codeguru a great place.
Come back soon, you Gurus.
Re: Displaying data graphically (Ultrasonic radar)
Cimperiali: No, I can open the COM port, read the data, and display it in the Textbox.
My question is: How do I plot the real-time data coming through?
and so on.
Or your question was about how to translate the numbers you got in 2d coordinates on your bitmap?
...at present time, using mainly Net 4.0, Vs 2010
Special thanks to Lothar "the Great" Haensler, Chris Eastwood , dr_Michael, ClearCode, Iouri and
all the other wonderful people who made and make Codeguru a great place.
Come back soon, you Gurus.
Re: Displaying data graphically (Ultrasonic radar)
Hmmmm did you actually read the article, and look at the code...
But before I go on... You've not let us know how many Degrees each step of the motor is (or how many steps in a 360 turn).. So for now I'll assume that one step is 1 degree....
Now lets look at one piece of code from the article...
Code:
With Ship
.Location.X = .Location.X - .Speed * Sin(.Direction * PI / 180)
.Location.Y = .Location.Y + .Speed * Cos(.Direction * PI / 180)
All the calculations you need are in those two lines...
First we know that we working from the center, so we get our center X and Y cords... (which normally is 1/2 width and 1/2 Height)..
Now we take your data and split it into Direction and Range and plug them into the above calculations...
Code:
Dim CenX as Integer = width/2
Dim CenY as Integer = height/2
Dim Range as integer 'Our array of the ranges
Dim Direction as integer 'Our array of direction
Dim Xloc as Integer 'Our Plotting points.
Dim Yloc as Integer
Private Sub PlotPoints()
Xloc = CenX - Range * Sin(Direction * PI / 180)
Yloc = CenY + Range * Cos(Direction * PI / 180)
MyGraphic.DrawRectangle(Mypen, Xloc - 1, Yloc - 1, 2, 2) ' Plot a small Square..
End Sub
And there you now have the code needed to plot the points......
WOW .. The article did have what you needed to get going, and the Author (ME) is not hardcoding cords, but recalculating them for each frame....
Re: Displaying data graphically (Ultrasonic radar)
Originally Posted by GremlinSA
[...]and the Author (ME)....
Ehy! I had to come back to the article and look at author and at picture of the author...Why did not you write under your name your nick too?
btw, great article and great post.
...at present time, using mainly Net 4.0, Vs 2010
Special thanks to Lothar "the Great" Haensler, Chris Eastwood , dr_Michael, ClearCode, Iouri and
all the other wonderful people who made and make Codeguru a great place.
Come back soon, you Gurus.
Re: Displaying data graphically (Ultrasonic radar)
GremlinSA: Sorry if I offended you. That is a great article and I just didn't understand it all
Anyway I have found another way of drawing my scan line (step motor angle (and by the way there's 250 steps in a full rotation))
This is what I have:
Code:
Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
e.Graphics.RotateTransform(angle * 360 / 250, MatrixOrder.Append)
e.Graphics.TranslateTransform(Me.PictureBox1.Width / 2, Me.PictureBox1.Height / 2, MatrixOrder.Append)
e.Graphics.DrawLine(New Pen(Color.Green, 3), 0, 0, 100, 100)
End Sub
But what is happening is: It draws the step 0 every time just before drawing the new step/angle. For example:
on step 1: it draws steps 0 and 1
on step 2: it draws steps 0 and 2
on step 3: it draws steps 0 and 3
on step 4: it draws steps 0 and 4
and so on... All the way to step 249.
Do you guys know how to fix this? By the way, I'm drawing on the top of the PictureBox which contains my background image.
Thanks!
Re: Displaying data graphically (Ultrasonic radar)
dglienna: Thanks for your reply! I figured out what was wrong.
I have done some progress since my last post but now I have another problem.
The Visual Basic program is not fast enough to display the real-time data. My motor takes about 4.5 seconds to complete a full rotation (which is 250 steps) but in my Visual Basic display it takes about 10 seconds to complete the full rotation.
I have already changed the Baud rate from my microcontroller but it doesn't improve a lot.
I am planning to do the sweep and display the data at same time (is that possible?) Because I aiming to build a real-time data 'radar'.
And this is how I am receiving the data, splitting it into angle and distance, and plotting the angle (snapshots):
Code:
'from mySerialPort subroutine
inputData = mySerialPort.ReadChar
'from data handling subroutine
Dim data As String
data = Chr(inputData)
If data = " " Then
Temp = ""
Else
Temp &= data
End If
If Temp.Length = 6 Then
angle = Val(Mid(Temp, 1, 3))
radius = Val(Mid(Temp, 4, 3))
PictureBox1.Invalidate()
End If
'from PictureBox1_Paint subroutine
e.Graphics.RotateTransform(angle * 360 / 250, Drawing2D.MatrixOrder.Append)
***EDIT: I am using If data = " " Then Temp = "" and If Temp.Length = 6 because every string has 6 numbers (3: step angle + 3: distance of object detected) and the strings are separated by a " " (space) as I explained in my first post.
Last edited by Alex83UK; March 26th, 2012 at 04:23 AM.
Reason: Code explanations
Re: Displaying data graphically (Ultrasonic radar)
A few things you'll need to to ...
#1: Double buffer the image.. Work's a load faster this way.. (check the article again for sample code)
#2 : PictureBox1.Invalidate() Is not the best method to use here.. it forces the Picturebox to completely redraw itself( not just update the bit you want..) and this is where your code is now slowing down..
#3 :
Code:
Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
e.Graphics.RotateTransform(angle * 360 / 250, MatrixOrder.Append)
e.Graphics.TranslateTransform(Me.PictureBox1.Width / 2, Me.PictureBox1.Height / 2, MatrixOrder.Append)
e.Graphics.DrawLine(New Pen(Color.Green, 3), 0, 0, 100, 100)
End Sub
Is also slower than the code sample i posted... WHY ??? well the Red highlighted bits are doing calculations and memory allocations that only need be done once (at the beginning), and not for every iteration ....
Time now to optimise your code properly.. Go back to the projects in the article and check how I'm able to LINEDRAW up to 30 objects on to a picture box with upto 60 frames per second, without even a little flicker..
The Framerate your project is looking for is 55 frames per second, Very Very doable with the right code.. but even if we do a frame after every second point, we get a comfortable 27 frames per second, which is easier on the hardware...
I think it's time you read all the articles in the series...
Re: Displaying data graphically (Ultrasonic radar)
Hi GremlinSA, I have done all the changes you suggested and the program is still slow.
#1: Done - (Set DoubleBuffered = True in the System.Windows.Forms.Form properties)
#2: I am now using PictureBox1.Invalidate(New Region(New Rectangle(167, 141, 251, 251))) which redraws only the area that my scan line is being draw.
#3: Now I have:
Code:
Mypen = New Pen(Color.Green, 3)
Dim x As Integer = PictureBox1.Width / 2
Dim y As Integer = PictureBox1.Height / 2
e.Graphics.RotateTransform(angle * 360 / 250, Drawing2D.MatrixOrder.Append)
e.Graphics.TranslateTransform(x, y, Drawing2D.MatrixOrder.Append)
e.Graphics.DrawLine(Mypen, 0, 0, 150, 150)
Do you think it should work fine even if my code is a single thread, with a cycle of sitting on a read from the serial port, processing the data, triggering the drawing, and doing the drawing?
Re: Displaying data graphically (Ultrasonic radar)
Originally Posted by Alex83UK
Hi GremlinSA, I have done all the changes you suggested and the program is still slow.
#1: Done - (Set DoubleBuffered = True in the System.Windows.Forms.Form properties)
#2: I am now using PictureBox1.Invalidate(New Region(New Rectangle(167, 141, 251, 251))) which redraws only the area that my scan line is being draw.
#3: Now I have:
Code:
Mypen = New Pen(Color.Green, 3)
Dim x As Integer = PictureBox1.Width / 2
Dim y As Integer = PictureBox1.Height / 2
e.Graphics.RotateTransform(angle * 360 / 250, Drawing2D.MatrixOrder.Append)
e.Graphics.TranslateTransform(x, y, Drawing2D.MatrixOrder.Append)
e.Graphics.DrawLine(Mypen, 0, 0, 150, 150)
okay lets get some things straight here....
#1 : Double Buffering : Setting a form's double buffering DOES NOT speed up the rendering of a form. It's used to prevent the artifacts that occur when a big form with many objects and a long rendering time starts to render.. (Ever had a proggy run where you can actually sit and watch it render each control one at a time and 'build' the form while you watch), So the DblBuffer was introduced that allowed the form painter to render the forms image in-memory, and when done, transfer the final form image to screen.. (Experience has shown that a form with DBL buffering set runs slower)
For Proper DBLBuffering, you need to set up a secondary in-memory image, render your bitmap on it, then for each frame simply transfer it to the picturebox...
#2 : PictureBox1.Invalidate is not the method to use, Even with specifying the region to 'invalidate' there are many underlying events and subs that are called that slow the whole thing down...
Setting up the correct method of dbl buffering will allow you to use 'PictureBox1.Image = Buffer.image'
#3 : These line of code ..
Code:
Mypen = New Pen(Color.Green, 3)
Dim x As Integer = PictureBox1.Width / 2
Dim y As Integer = PictureBox1.Height / 2
Where in your code are they... are they still inside your 'PictureBox1_Paint' sub. If they are then is does not help as they are still Create and calculated each time the sub is called...
it should be more like this..
Code:
Public Class Form1
Private Mypen As Pen = New Pen(Color.Green, 3)
Private x As Integer
Private y As Integer
Private xLoc As Integer
Private yLoc As Integer
Private Div As Double = PI * 2 / 250
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
x = PictureBox1.Width / 2
y = PictureBox1.Height / 2
End Sub
Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
xloc = X - Range * Sin(angle * Div)
yloc = Y + Range * Cos(angle * Div)
e.Graphics.DrawRectangle(Mypen, xloc - 1, yloc - 1, 2, 2)
End Sub
* The Best Reasons to Target Windows 8
Learn some of the best reasons why you should seriously consider bringing your Android mobile development expertise to bear on the Windows 8 platform.