Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Embedded Systems

Examining the LabOBJX Real-Time Chart Control


October 1996: LabObjx

Examining the LabOBJX Real-Time Chart Control

Developing trending software for real-time applications

Jonathan Williams

Jonathan is president of Scientific Data Systems, a company that specializes in engineering and scientific software development. He can be contacted at [email protected].


System integrators must routinely decide whether to use off-the-shelf software or develop a custom solution using traditional programming languages. Developing custom solutions has usually meant devoting considerably more time to the project. But with the advent of object-oriented techniques and visual-programming tools, the time needed to develop professional-quality custom software has been reduced, making a custom solution more viable and cost effective.

A recent project-a diesel-generator monitoring system developed by Advanced System Integration (Austin, TX)-underscored this dilemma for us. My company was to develop the display and analysis portions of the project. The software displays post-acquisition data of backup diesel generators that are run periodically for two-hour intervals. By analyzing the recorded data, the condition of the generator can be checked to determine when maintenance is needed. The data is acquired from multiple channels at acquisition rates from 100 Hz to several kHz, and stored to disk. The resultant data files are several megabytes in size.

The display software had to perform the following tasks:

  • Display up to five channels at one time, each in its own graph area. (The customer had selected five channels as the maximum to view at once to keep the screen from becoming too cluttered.)
  • Display an upper and lower limit as a horizontal line.
  • Allow users to scroll through large data sets.
  • Allow users to zoom in and out on sections of data.
  • Let users determine the actual value of any data point. (To accomplish this, the software had to provide a vertical cursor for each data channel that could be used to scroll through the data in order to display values of individual points.)
  • Have the analysis routines integrated into the display software.

All of the commercially available trending or analysis software packages either lacked necessary features or were prohibitive in cost. Time constraints ruled out developing the graphing capabilities we needed using low-level Windows API calls, so we opted for Visual Basic and an after-market custom control. We chose Visual Basic for its combination of rapid program development and extensibility through the use of third-party products.

Our search for a third-party graphics control produced a number of candidates. Unfortunately, many of them were oriented more toward presentation graphics, rather than scientific or engineering applications. Although the Professional Edition of Visual Basic contains a graph custom control, it was not fast enough and lacked the necessary features. The graphics control for this project had to have multiple data-set capability, cursor readout of data points, and (most importantly) the ability to plot data very fast. The speed of plotting was paramount because the display had to give the feel of a smoothly flowing strip chart that could be moved in either direction without the screen flashing as the graph was being redrawn.

We ended up selecting Scientific Software Tools' LabOBJX Real-Time Chart, a custom control (VBX) that can be used with Visual Basic, C++, and Delphi. The strength of this control is in its real-time displays of graphics, such as strip charts or oscilloscope emulation. The LabOBJX Real-Time Chart (RTC) control is certainly fast-the vendor claims it will plot up to 200 times faster than the graph control that comes with Visual Basic. LabOBJX RTC also met all of the other design requirements for the project.

Using LabOBJX RTC

LabOBJX RTC defines how data is plotted in terms of Viewports, Windows, and Channels. The physical plotting area of the control can be broken into multiple sections, referred to as Viewports. A Viewport can contain multiple Windows, which will allow the plotting of signals of different scales. A Channel specifies how a set of data is assigned to the LabOBJX RTC. You can define up to 32,767 Viewports, Windows, and Channels. It is difficult to imagine plotting this mind-boggling number of data channels, but it is nice to know that this is not a limiting factor.

For this application, we defined five Viewports-one for each data set to be plotted (see Figure 1). Defining a Viewport for each data set ensures that each will be plotted in a separate portion of the graph area. Each Viewport is associated with one Window. The data set, lower limits, upper limits, and vertical cursors were all implemented as independent data Channels. There are a total of 20 Channels defined in the control: five for the data sets, five for their lower limits, five for their upper limits, and five for the vertical cursors. Looking at it from a different perspective, each Viewport has four Channels associated with it-the data set, lower limit, upper limit, and the cursor.

Although there are five Viewports defined in the control, they do not all have to be displayed at one time. After setting up all of the Viewports, changing the Viewports property of the control will display the desired number. If Viewports is set to 1, then the first Viewport will cover the entire plotting area. Setting Viewports to 2 will cause the plotting area to be divided between Viewports 1 and 2, and so on. Users can easily change the number of Channels on the screen by selecting from a drop-down listbox in the setup screen with the selections of 1 to 5. Setting the Viewports property to the number selected will cause the graph control to redraw itself with the desired number of Viewports displayed; see Listing One. All plotting is done by calling the ChartData function of the control; see Listing Two. The function is passed the control handle, the Channel number to plot, number of points to plot, y-data starting address, and x-data starting address. By setting other control properties, this function can plot y data versus x data, y data versus its indices, or a single array that contains a pair of interleaved x,y data sets. This was the only function call necessary for the graph control. All other characteristics of the control are managed by setting the properties of the control in the standard control.property notation used in Visual Basic.

LabOBJX RTC can plot data in one of two modes, CRT and Scroll. CRT mode is meant to simulate the sweep of an oscilloscope or for use as an x-versus-y plot. CRT mode can plot one array versus another, or a single array versus its indices. Scroll mode is used to simulate a strip-chart recorder. When new data is passed to the control in Scroll mode, it is plotted to the right as the data on the chart scrolls off to the left.

We used CRT-plotting mode for the diesel-generator project. Because we wanted the x-axis scale to represent time in a specific format, we had the control plot each data set versus its indices, and managed the x- and y-axis labeling in the software. The control has the capability to generate labels for both the x- and y-axes, but we disabled this feature.

The LabOBJX RTC has four methods of updating the plotting area:

  • Synchronous mode paints the screen immediately after changing any visual property or assigning new data input.
  • Timed mode paints the screen at timed intervals.
  • Idle mode paints the screen when Windows is idle.
  • Manual mode paints the screen under application control.

We used Synchronous mode because the screen had to be updated immediately each time the user scrolled or moved to another section of the data file. For other uses, such as displaying data while it is being acquired, the Timed or Idle modes may be more appropriate, since they will not interfere with time-critical data-acquisition tasks. Manual control allows you to turn off painting of the screen while you change several control properties, then turn it back on after you've made all your changes.

LabOBJX RTC can plot up to 16,384 data points per channel. The control also has the capability of plotting every nth data point within a set. Although using this approach for zooming in and out of small data sets is adequate, it would not be practical for our project because of the size of the data files. (We decided to always plot 500 points per data set.) Instead, we solved the problem of scrolling and zooming by having the software read the appropriate data from the disk and pass it to the graph control.

Zooming in and out of the data was accomplished by allowing some data points to be skipped in plotting, enabling users to enlarge and shrink the time period covered by the 500 points. Users can select from a drop-down list to plot every 1, 2, 5, 10, 20, 50, or 100 points. By keeping the data sets small and managing the data passed to the control, a user can update the screen very quickly and give the illusion of scrolling the graph, although the entire data set is actually being replotted each time the user scrolls to the left or right.

We used the Visual Basic Spin Button user-input control (a custom control included with the Professional Edition of Visual Basic) to scroll the data to the left or right. This control has two arrow icons (that can be oriented horizontally or vertically) and generates events when users click on the SpinDown or SpinUp. One Spin Button labeled "Scroll" allows users to scroll in small increments, advancing 50 points with each click. Another Spin Button labeled "Frame" moves 500 points forward or backward with each click. Each time users click one of these Spin Buttons, the software retrieves the proper data from the file and plots it; see Listing Three.

LabOBJX RTC can accept data in many formats including signed and unsigned 8-, 16-, 32-bit integers, and 32/64 floating-point numbers. It also has the ability to scale data through the use of Channel Transform Properties. This is useful when quickly plotting data that has just been acquired from data-acquisition boards or laboratory instruments. Such data is often acquired in integer format, then converted to floating-point format. Using the Channel Transform Properties of the control, you can plot integer data and have it scaled to its floating-point representation automatically. The data for this application was already stored in floating-point format, so there was no need to further scale the data.

The horizontal lines representing the upper and lower limits for each data set were plotted by creating a four-element array that contained two x values (the minimum and maximum values for the x-axis) and two y values (the limit value). The control properties were then set to plot an array of interleaved x,y pairs.

The cursors for each of the data sets were implemented in a similar manner (see Listing Four). In this case, the four-element array contained two identical x values and two y values (the minimum and maximum for the y-axis).

Again, the Visual Basic Spin Button control was used to cause user input to move the cursors. The SpinDown and SpinUp events of the control contain the code to increment or decrement the x values for the cursors and to call the ChartData function to replot the cursors; see Listing Five. LabOBJX RTC also supports a hit-detection method that reports when the mouse is near a data point on the graph. Such a function could be used to allow users to grab the cursor with the mouse and drag it to a new position.

Conclusion

Given the choice between using a software package or developing a solution tailored for each customer, most systems integrators would prefer a custom solution. Such a choice, however, is only practical if the project can be developed in a manner that is both time and cost efficient. In our case, the availability of a quality graphing control, such as the LabOBJX RTC, made this possible.

For More Information

Scientific Software Tools

19 East Central Ave.

Paoli, PA 19301

610-889-1354

http://www.sstnet.com

Figure 1: The diesel-generator monitoring application.

Listing One


' Get number of Viewports to display from drop down list box
NumViewports = cmbCharts.ListIndex + 1
' Set control to desired number
frmChart!RtChart1.Viewports = NumViewports

Listing Two

DListing Oneeclare Function ChartData Lib "lortchrt.vbx"(ctl As STT_RtChart,
    ByVal Chn As Integer, ByVal nPts As Integer, yData As Any,
    Xdata As Any) As Integer

Listing Three

' Scrolls the data 1/10 of a frame forwward.
Sub SpinScroll_SpinUp ()
    GetScrollData FORWARD       ' Advance 50 pts in the data file
    PlotData                ' Plot the data
    SetScrollBar            ' Update scroll bar position
End Sub

' Plots the data in the buffers DataBuf1, DataBuf2 ... etc.  These
' correspond to chart channels 1 to 5.  Also sets the time labels.
Sub PlotData ()
    Dim I As Integer
    Dim Result As Integer
    ' Based on the number of viewports displayed call the ChartData
    ' function for the appropriate channels
    Select Case NumViewports
    Case 1
        Result = ChartData(RtChart1, ByVal 1, DataBuf1(0), ByVal 0&)
        If Result <> 0 Then MsgBox "Bad Result : " & Str$(Result)
    Case 2
        Result = ChartData(RtChart1, ByVal 1, DataBuf1(0), ByVal 0&)
        If Result <> 0 Then MsgBox "Bad Result : " & Str$(Result)
        Result = ChartData(RtChart1, ByVal 2, DataBuf2(0), ByVal 0&)
        If Result <> 0 Then MsgBox "Bad Result : " & Str$(Result)
        Result = ChartData(RtChart1, ByVal 3, DataBuf3(0), ByVal 0&)
    Case 3
        Result = ChartData(RtChart1, ByVal 1, DataBuf1(0), ByVal 0&)
        If Result <> 0 Then MsgBox "Bad Result : " & Str$(Result)
        Result = ChartData(RtChart1, ByVal 2, DataBuf2(0), ByVal 0&)
        If Result <> 0 Then MsgBox "Bad Result : " & Str$(Result)
        Result = ChartData(RtChart1, ByVal 3, DataBuf3(0), ByVal 0&)
    Case 4
        Result = ChartData(RtChart1, ByVal 1, DataBuf1(0), ByVal 0&)
        If Result <> 0 Then MsgBox "Bad Result : " & Str$(Result)
        Result = ChartData(RtChart1, ByVal 2, DataBuf2(0), ByVal 0&)
        If Result <> 0 Then MsgBox "Bad Result : " & Str$(Result)
        Result = ChartData(RtChart1, ByVal 3, DataBuf3(0), ByVal 0&)
        If Result <> 0 Then MsgBox "Bad Result : " & Str$(Result)
        Result = ChartData(RtChart1, ByVal 4, DataBuf4(0), ByVal 0&)
    Case 5
        Result = ChartData(RtChart1, ByVal 1, DataBuf1(0), ByVal 0&)
        If Result <> 0 Then MsgBox "Bad Result : " & Str$(Result)
        Result = ChartData(RtChart1, ByVal 2, DataBuf2(0), ByVal 0&)
        If Result <> 0 Then MsgBox "Bad Result : " & Str$(Result)
        Result = ChartData(RtChart1, ByVal 3, DataBuf3(0), ByVal 0&)
        If Result <> 0 Then MsgBox "Bad Result : " & Str$(Result)
        Result = ChartData(RtChart1, ByVal 4, DataBuf4(0), ByVal 0&)
        If Result <> 0 Then MsgBox "Bad Result : " & Str$(Result)
        Result = ChartData(RtChart1, ByVal 5, DataBuf5(0), ByVal 0&)
        If Result <> 0 Then MsgBox "Bad Result : " & Str$(Result)
    End Select

    RtChart1.Refresh    ' Make sure chart repaints
    TimeLabels      ' Display Time labels at bottom
    CursorValues    ' Display Y value at cursors
End Sub

Listing Four

'

 Draw a cursor by doing a x/y plot for the given channel.  This is used
' to draw both the cursors and the limits.
Sub DrawCursor (ByVal Chn As Integer, ByVal X1 As Single, ByVal Y1 As Single,
                                      ByVal X2 As Single, ByVal Y2 As Single)
    Dim Result As Integer
    ' Setup a four element array of interleaved X, Y pairs to plot.
    LineCoord(0) = X1
    LineCoord(1) = Y1
    LineCoord(2) = X2
    LineCoord(3) = Y2
    ' Plot the array
    Result = ChartData(RtChart1, Chn, LineCoord(0), ByVal 0&)
    RtChart1.Refresh
End Sub

Listing Five

' Draws cursors for all active viewports.  The global variable XCursor
' specifies the X (0-499) at which to draw the cursor.
Sub DisplayCursors ()
    Dim I As Integer
    ' Draw a cursor for each viewport currently displayed
    For I = Cursor1 To Cursor1 + NumViewports - 1
        RtChart1.Viewport_Select = I - Maxcharts   ' Select Viewport
        RtChart1.Wnd_Select = I - Maxcharts        ' Select Window
        RtChart1.Chn_Select = I                    ' Select Channel
        ' Draw cursor at X position between min and max of Y axis
        DrawCursor I, XCursor, RtChart1.WndYmin, XCursor,
        RtChart1.WndYmin + RtChart1.WndHeight
    Next I
    CursorValues
End Sub

' Moves the cursor to the left.  The global variable XCursor indicates
' the position in the data arrays that the cursor is plotted over.
Sub SpinCursor_SpinDown ()
    If XCursor <> 0 Then
        XCursor = XCursor - 1   ' Decrement cursor position
        DisplayCursors          ' Plot cursors
        CursorValues            ' Display values at cursors
    End If
End Sub 


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.