Re: Converting voltage level into graphical display
Can you even get the voltage level to begin with? Once you can do that, then you can take the proper steps to retrieving it to a text based display, and finally to a Graphical Display.
Re: Converting voltage level into graphical display
Hi Catherine, Here's a simple dial voltmeter in a picture box. It draws the dial with Graphics.DrawPie and rotates the needle using Graphics.Transform and a graphics matrix (Matrix.RotateAt). Alternatively, you could use Math.Cos etc. to calculate the tip position of the needle. To indicate a voltage, set the volts variable and Refresh the picture box. If you study how it's done you may be able to work out how to add scale markings if required.
vb.net Code:
Private volts As Single
Private maximumVolts As Single = 1.0F
Private dialAngle As Single = 100.0F 'the angular width of the dial
Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
Re: Converting voltage level into graphical display
Hello everyone, thanks for all your help and the time to response to my questions. I'll take note of the references and the codes you guys suggest and i'll try it out today =)
Re: Converting voltage level into graphical display
Hi Catherine,
The problems that you point out, scale markings and correct deflection calculations, are why I suggested the http://www.virtualroadside.com/downl...uments-1.0.zip download. I believe this will do all that you want. These "extras" can get a little messy.
Dick
Richard Grier, Consultant, Hard & Software
Microsoft MVP (Visual Basic)
Re: Converting voltage level into graphical display
@Catherine,
here's some code to add scale markings. Insert it in the Paint sub before the code to draw the needle, and delete the present "Dim pivot" line. You may need to adjust some of the numbers shown below in bold depending on your system font, to make sure the numerals line up nicely.
Code:
'Draw the dial graduations and numbering
Dim font As New Font(Me.Font.FontFamily, 7, FontStyle.Regular)
Dim pivot As New Point(PictureBox1.Width \ 2, PictureBox1.Height \ 2 + 2 * verticalMargin - 10)
Dim innerPoint1 As New Point(PictureBox1.Width \ 2, verticalMargin + 25)
Dim innerPoint2 As New Point(PictureBox1.Width \ 2, verticalMargin + 20)
Dim outerPoint As New Point(PictureBox1.Width \ 2, verticalMargin + 5)
For mark As Integer = -50 To 50
Dim markAngle As Single = dialAngle * mark / 100
Using mtx As New Drawing2D.Matrix
mtx.RotateAt(markAngle, pivot)
e.Graphics.Transform = mtx
End Using
If mark Mod 10 = 0 Then
'draw long line
e.Graphics.DrawLine(Pens.Gray, innerPoint1, outerPoint)
'draw numeral
e.Graphics.DrawString(mark / 10.ToString, font, _
Brushes.Black, innerPoint1.X - 5, innerPoint1.Y + 1)
Else
'draw short line
e.Graphics.DrawLine(Pens.Gray, innerPoint2, outerPoint)
End If
e.Graphics.ResetTransform()
Next
'Add label text
font = New Font(Me.Font.FontFamily, 10, FontStyle.Regular)
e.Graphics.DrawString("Volts", font, _
Brushes.Black, innerPoint2.X - 23, innerPoint2.Y + 35)
font.Dispose()
@Dick, I don't think Catherine will benefit much from downloading a ready-made analog ammeter in Csharp for a school project for a voltmeter in VB.Net. It looks very nice, but its functionality is limited to a trackbar to move the needle; I doubt if anyone here is going help with that. Besides, the code is 500+ lines, compared to about 130 for the functioning apparatus shown below).
Re: [RESOLVED] Converting voltage level into graphical display
Originally Posted by catherine0136
In the mean time, i'll try my best to look for solutions for the moving waveform.
You would just sample the voltage (via digital the interface) and plot that new point (previous to current). Over time you would end up with a graph similar to the image I posted.
Re: [RESOLVED] Converting voltage level into graphical display
Hi Catherine,
OK, you need a variable to hold a voltage value (volts), a timer to sample the data at regular intervals (Timer1) and a data structure to collect enough data to draw a curve. I already suggested using a Queue (VoltsQ) to hold the data, because it's ideal for a periodically updated time series. I don't know what maximum positive or negative voltage you can expect but I suppose something like +/-5 volts will do (maxVolts).
You'll collect the data in the timer's Tick sub. I'll assume the timer is set to 100 ms. interval, and you want your curve to show about 4 seconds of data; in that case the queue needs to hold up to 40 readings. You can change these numbers to alter the display as you wish.
vb.net Code:
Dim volts As Single
Dim voltsQ As New Queue(Of Single)
Dim maxVolts As Single = 5
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
'read the voltage:
volts = 'get value from RS232 interface
'add the new reading to the end of the queue:
voltsQ.Enqueue(volts)
'remove the old reading at the head of the queue, to keep max. 40 data points:
If voltsQ.Count > 40 Then voltsQ.Dequeue()
'update the display with the new data:
Me.Refresh
End Sub
In the last code you posted, you used a Graphics.DrawCurve state to draw a smooth line through an array of 4 predefined points. Instead, we want to draw the curve through the 40 data points collected in the queue. Since they are updated 10 times a second, it will appear as a moving waveform. The question is, how do you convert the Queue(Of Single) into the Array(Of Point) required by DrawCurve? In fact it is mainly arithmetic, based on the sizes of the the x and y axes of the graph. For example, you could put this in the Paint sub:
vb.net Code:
Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
'Put your code for drawing the axes etc. here.
'Details of the graph layout -- fill in your own values here!
Dim Origin As New Point(200, 200)
Dim xAxisLength As Integer = 300
Dim yAxisLength As Integer = 150
'Define an array of data points:
Dim DataPoints(voltsQ.Count - 1) As Point
Dim x, y As Integer
'Fill in the array using the voltage readings:
For i As Integer = 0 To voltsQ.Count - 1
'Get the volts value from the queue:
Dim v As Single = voltsQ.ElementAt(i)
'Find the distance along the x axis:
x = Origin.X + CInt(i * xAxisLength / 40)
'find the height of the data point on the Y axis:
y = Origin.Y + CInt(v * yAxisLength / maxVolts)
'Put the point in the array
DataPoints(i) = New Point(x, y)
Next
'Draw the waveform:
e.Graphics.DrawCurve(Pens.Green, DataPoints)
End Sub
I hope the comments in the code explain everything. The important points for VB.Net are the way you use a For-Next loop to build the array. Note too that the maximum index is always Queue.Count-1 because collection indices start from 0 in VB.Net.
Re: [RESOLVED] Converting voltage level into graphical display
Code:
'Details of the graph layout -- fill in your own values here!
Dim Origin As New Point(200, 200)
Dim xAxisLength As Integer = 300
Dim yAxisLength As Integer = 150
I need to clarify my doubts. =)
For the above, you mentioned that i need to fill in my own values,
so as in:
>>
Code:
Dim Origin As New Point(200, 200)..
i replace the ( , ) value to the values of where the x and y line intersect each other ?
>>
Code:
Dim xAxisLength As Integer = 300
Dim yAxisLength As Integer = 150
The code to draw the vertical and horizontal line is as shown below:
Code:
' Drawing a vertical and a horizontal line
g.DrawLine(BluePen, 50, 225, 50, 15) 'vertical line
g.DrawLine(BluePen, 50, 120, 260, 120) 'horizontal line
So, i'll replace xAxisLength As Integer, yAxisLengthts into the values as shown above ?
Re: [RESOLVED] Converting voltage level into graphical display
@Bruce Fox
I actually thought of that too, as it will look nicer. But, ..erm.. i've got to do more research on that, as i've got no idea how to allow to add real time scale whereby the time will move with the waveform. Haha.
But thanks for the suggestion!
Re: [RESOLVED] Converting voltage level into graphical display
You don't have to animate the scale, as it is just that - a scale. Each large tick for example may represent 2 Seconds. So, you may have 2, 4, 6, 8 etc displayed on the X axis. In that example the sample will take 8 seconds to reach the right hand edge of the display. Then the sample starts again from 0.
One option would be to draw the first sample (0 to 8 seconds for example) then draw a new sample of back at 0 in a different colour. That way you would be continuing to display trend. Then on the third pass remove the first sample line (so two are always displayed) - for example.
Re: [RESOLVED] Converting voltage level into graphical display
@Bruce Fox
Will consider about your suggestion.
But i am still hoping to allow a real time to move along with the waveform. Still researching on that though, and hopefully i'm able to do so.
In the mean time, if anyone have any idea on how to do that, i would really appreciate if you can post your suggestions for my reference.