Interfacing MathCad Data Smoother Worksheet from VB6 Application
I have a measurement data file within a folder which holds a VB6 Project, and a MathCad Data Smoother worksheet. I would like to "talk" to the Mathcad worksheet from the VB Project, telling it to smooth the data in the data file specified by a textbox on the VB Form, and then write the smoothed data file back to the same folder, with afile name specified by a second textbox on the Form for later call and use within the VB project. My selected approach uses OLE Automation, by placing the MathCad Data Smoother worksheet inside an OLE container drawn on the VB Project Form.
1. How do I make contact to the Mathcad Smoother worksheet from the VB project form?
2. How do I tell the Mathcad Smoother what file to smooth from the VB project form?
3. How do I tell the MathCad Smoother what file to write back into the folder?
As a standalone application, the Mathcad Smoother does this automatically.
None of the rather simple examples provided by MathCad seemed applicable to this problem, hence this request for help.
I attach the VB Project Form, plus the data file, and the Mathcad Smoother application as Word documents
Re: Interfacing MathCad Data Smoother Worksheet from VB6 Application
Hi VB_Basher,
I don't see your actual smoothing algorithm, but it sounds like you're doing some kind of cubic spline on the data, or possibly a low-pass filter. I guess I'm not clear on why you wouldn't just do it all in VB6, rather than a "worksheet" to do it. There are several smoothing algorithms floating around these forums, possibly the same one Mathcad is using.
Just my two-cents.
Also if you want to stick with using a "worksheet" (I'm assuming an Excel worksheet, but not certain), you'd just need to use Office (specifically Excel) automation from VB6. With automation, you can make Excel do just about anything you want from VB6.
Good luck with it,
Elroy
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
Re: Interfacing MathCad Data Smoother Worksheet from VB6 Application
Elroy: Thanks for the comments. I have used MathCad since 1988 and have grown accustomed to using its suite of curve smoothing functions, such as SuperSmooth in this case. The attached VB project is a subset of a Poor Man's automated measurement project under the control of a set of VB commands that drive a signal generator and oscilloscope to excite measure the response of a specified circuit on a lab bench. The smoother puts the final touches on the measured phase values.
I am significantly less dangerous to the measured data when smoothing it using MathCad. I am not enough of a VB guru to attempt to do same in VB at this time. I have used VBA in the past, but prefer to use VB6 for the current application. If you have links to some VB6 data smoothing applications, I would like to see them, since I would learn some useful techniques.
Re: Interfacing MathCad Data Smoother Worksheet from VB6 Application
Hi Vb_Basher,
The following is code for a low-pass Butterworth filter. I don't remember all the details, but I worked this out with help from some of the folks here. I believe Olaf Schmidt was involved, but I'll take responsibility for any bugs, as I reworked it all for my own needs.
The following code is intended to be put into a Class module, and then used:
Code:
Option Explicit
'
Private mOrder As Long ' This is the order of the filter.
Private mFreq As Double ' This is the frequency to filter.
Private mSampleRate As Double ' This is the sample rate of the data.
'
Private c(5, 8) As Double ' Internal to filter.
Private d1(8) As Double ' Internal to filter.
Private d2(8) As Double ' Internal to filter.
'
Private Sub Class_Initialize()
mFreq = 10
mSampleRate = 120
mOrder = 2
SetupFilter
End Sub
Friend Property Get Order() As Long
Order = mOrder
End Property
Friend Property Let Order(ByVal NewVal As Long)
mOrder = NewVal
If mOrder < 1 Then mOrder = 1
If mOrder > 8 Then mOrder = 8
SetupFilter
End Property
Friend Property Get Freq() As Double
Freq = mFreq
End Property
Friend Property Let Freq(ByVal NewVal As Double)
mFreq = NewVal
SetupFilter
End Property
Friend Property Get SampleRate() As Double
SampleRate = mSampleRate
End Property
Friend Property Let SampleRate(ByVal NewVal As Double)
mSampleRate = NewVal
SetupFilter
End Property
Friend Sub Filter(Buf() As Double)
' Strictly set for low pass. Other code would be needed for a high pass filter.
' Butterworth also has edge issues (where it goes a bit berzerk at the beginning and end).
' To fix this, 100 elements are added to the beginning and end.
' To add these, for the beginning, the first 100 elements are mirrored backwards,
' and, for the end, the last 100 elements are mirrored forward.
' Arrays smaller than 200 elements are NOT processed.
'
Dim n As Long
Dim LB As Long
Dim UB As Long
Dim i As Long
Dim j As Long
Dim NSections As Long
'
Dim w As Double
Dim r As Double
Dim NOdd As Boolean
Dim Csum As Double
Dim DC As Double
Dim b2() As Double
'
UB = UBound(Buf)
LB = LBound(Buf)
'
' Must have at least 200.
If (UB - LB) + 1 < 200 Then Exit Sub
'
ReDim b2(LB - 100 To UB + 100)
' Mirror bottom 100.
For i = LB To LB + 99
b2((LB - 1) - (i - LB)) = Buf(i)
Next i
' Mirror top 100.
For i = UB To UB - 99 Step -1
b2((UB + 1) + (UB - i)) = Buf(i)
Next i
' Copy all the rest.
For i = LB To UB
b2(i) = Buf(i)
Next i
'
' Initialize.
NSections = (mOrder + 1) \ 2
NOdd = (mOrder Mod 2) <> 0
DC = b2(LB)
For j = 1 To NSections
d2(j) = DC / (1 - c(1, j) - c(2, j))
d1(j) = d2(j)
Csum = 0
For i = 1 To 4
Csum = Csum + c(i, j)
Next i
DC = c(5, j) * (DC + d2(j) * Csum)
Next j
'
' Now execute the filter.
For n = LB To UB
For j = 1 To NSections
If (j = NSections) And NOdd Then
r = b2(n) + c(1, j) * d1(j)
w = c(5, j) * (r + c(3, j) * d1(j))
Else
r = b2(n) + c(1, j) * d1(j) + c(2, j) * d2(j)
w = c(5, j) * (r + c(3, j) * d1(j) + d2(j))
End If
d2(j) = d1(j)
d1(j) = r
b2(n) = w
Next j
Next n
'
' Put back into original buffer.
For i = LB To UB
Buf(i) = b2(i)
Next i
End Sub
Private Sub SetupFilter()
Dim i As Long
Dim NSections As Long
Dim o As Double
Dim O2 As Double
Dim temp As Double
Dim W0 As Double
Dim W1 As Double
Dim m As Double
'
If mOrder Mod 2 = 0 Then temp = 0.5 Else temp = 0
'
o = Tan((Atn(1) * 4) * mFreq / mSampleRate)
O2 = o * o
NSections = (mOrder + 1) \ 2
Erase c
'
For i = 1 To mOrder \ 2
W0 = 2# * o * Cos((Atn(1) * 4) * (i - temp) / mOrder)
W1 = 1# + W0 + O2
c(1, i) = -2# * (O2 - 1#) / W1
c(2, i) = (W0 - O2 - 1#) / W1
c(3, i) = 2#
c(4, i) = 1#
c(5, i) = O2 / W1
Next i
'
If temp = 0# Then ' Odd order.
c(1, NSections) = (1# - o) / (1# + o)
c(3, NSections) = 1#
c(5, NSections) = o / (1# + o)
End If
End Sub
And here's a trivial example how how it'd be used:
Code:
Dim oButter As clsButterworth
Set oButter = New clsButterworth
oButter.Filter X() ' Where X() is the data points to be smoothed.
Set oButter = Nothing
Also, you'll see that it has Order, Frequency, and SampleRate settings. The SampleRate is most important. Basically, this tells it the Hertz (how much time between data points) of your data.
The Order and Frequency have to do with how the filter works. Frequency can be thought of as very similar to a Fourier transformation. It's basically the cutoff between signal (what you want) and noise (the high frequency stuff you'd like to filter out). The order is (roughly) how hard you want the filter to work to filter out the noise. Basically, a higher order will result in more smoothing.
You'll see that my code is set to second-order and a 10 hertz frequency filter. And the data is assumed to be sampled at 120 points per second (i.e., hertz). You can change those either in Class_Initialize or after you've instantiated the class.
Butterworth is just one of many filter "types". I've also got a cubic spline filter in VB6 code. However, it's a bit more work to setup to use the cubic spline (at least the way I've got it organized. I could throw the code at you though, if you'd really like that instead.
Good Luck,
Elroy
EDIT1: Here are a couple of links I found on Google to show what a Butterworth filter can do:
EDIT2: Also, just an FYI, the way I've got it setup, it modifies the data "in place". If you wish to save your original data, be sure to make a copy of it before sending it into the filter.
Last edited by Elroy; Apr 17th, 2018 at 02:08 PM.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.