Results 1 to 15 of 15

Thread: oscilloscope example,how to add a square wave on the canvas

  1. #1
    Join Date
    Apr 2012
    Posts
    10
    Thanks
    1
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Question oscilloscope example,how to add a square wave on the canvas

    hi,everyone
    oscilloscope program give me methods to sample the voltage from ADC of s3c2440 platform.Now I have got it.
    Then I want to add a square wave on the canvas which could be a comparison with the sampling curve.
    I don't know how to implement it.
    I know how to add a curve in plot.cpp:
    Qt Code:
    1. p_curve = new QwtPlotCurve();
    2. p_curve->setStyle(QwtPlotCurve::Steps);
    3. p_curve->setPen(QPen(Qt::green));
    4. p_curve->setRenderHint(QwtPlotItem::RenderAntialiased, true);
    5. p_curve->setPaintAttribute(QwtPlotCurve::ClipPolygons, false);
    6. p_curve->setData(SquareWaveData());
    7. p_curve->attach(this);
    To copy to clipboard, switch view to plain text mode 
    The problem is how to produce the data for the square wave which is synchronous with the sampling curve?

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,323
    Thanks
    316
    Thanked 871 Times in 858 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: oscilloscope example,how to add a square wave on the canvas

    The problem is how to produce the data for the square wave which is synchronous with the sampling curve?
    This isn't a Qwt question, it's a data processing question.

    If you are sampling the ADC voltage, then you need to find each zero crossing of the sample data and set up your square wave data so it has steps at each sample zero crossing, and amplitude equal to the maximum (or minimum, depending on which direction the zero crossing goes) between zeroes.

    If the sample data are supposed to be periodic with a fixed frequency, then simply find the first zero crossing (so you know where to start your model curve) and create a regular square wave at the expected frequency. If the sample matches the model, then the zero crossings for both of them will be in alignment, and the amplitudes should be the same as well. If the sample frequency varies, then the zero crossing won't all match up; if the sample amplitude varies, then the maxima of the sample and model curves won't match, either.

    If your sample data are noisy, you may need to do some signal averaging (like a 3- or 5-point moving window average) to avoid detecting zero crossings that occur simply due to noise.
    Last edited by d_stranz; 11th April 2012 at 04:42.

  3. #3
    Join Date
    Apr 2012
    Posts
    10
    Thanks
    1
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: oscilloscope example,how to add a square wave on the canvas

    thanks for your reply,the sample data is periodic with a fixed frequency when the program is running.while next time I may need to change the frequency.
    I just want to produce a square wave with alterable frequency and duty,which should be synchronous with the sampling curve.In other words,the square wave is the ideal curve,the sampling curve is the actual one.
    the following shows how I implement the sampling thread:
    Qt Code:
    1. #include "samplingthread.h"
    2. #include "signaldata.h"
    3. #include <qwt_math.h>
    4. #include <math.h>
    5.  
    6. #include <stdio.h>
    7. #include <unistd.h>
    8. #include <stdlib.h>
    9. #include <sys/types.h>
    10. #include <sys/stat.h>
    11. #include <sys/ioctl.h>
    12. #include <fcntl.h>
    13. #include <linux/fs.h>
    14. #include <errno.h>
    15. #include <string.h>
    16.  
    17. SamplingThread::SamplingThread(QObject *parent):
    18. QwtSamplingThread(parent)
    19. {
    20. fd = open("/dev/adc", 0);
    21. if (fd < 0) {
    22. perror("open ADC device:");
    23. }
    24. }
    25.  
    26. SamplingThread::~SamplingThread()
    27. {
    28. close(fd);
    29. }
    30.  
    31. void SamplingThread::sample(double elapsed)
    32. {
    33. const QPointF s(elapsed, value(elapsed));
    34. SignalData::instance().append(s);
    35. }
    36.  
    37. double SamplingThread::value(double) const
    38. {
    39. int value = -1;
    40. char buffer[30];
    41.  
    42. int len = read(fd, buffer, sizeof buffer -1);
    43. if (len > 0) {
    44. buffer[len] = '\0';
    45. sscanf(buffer, "%d", &value);
    46. } else {
    47. perror("read ADC device:");
    48. }
    49. const double v = (double)value;
    50. return v;
    51. }
    To copy to clipboard, switch view to plain text mode 

  4. #4
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,323
    Thanks
    316
    Thanked 871 Times in 858 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: oscilloscope example,how to add a square wave on the canvas

    Well, how hard is that? The code below assumes you use the same calling convention for the model data as you do for the sample data.

    Qt Code:
    1. SquareWave::SquareWave( double periodInSec, double amplitude )
    2. {
    3. // Member variables of SquareWave class
    4. d_period = periodInSec;
    5. d_amplitude = amplitude;
    6. d_offset = 0.0; // offset in sec of first signal zero from square wave
    7. }
    8.  
    9. void SquareWave::sample(double elapsed)
    10. {
    11. const QPointF s(elapsed, value(elapsed));
    12. ModelData::instance().append(s);
    13. }
    14.  
    15. double SquareWave::value( double elapsed ) const
    16. {
    17. // This assumes that the sample starts out by going in the positive direction.
    18. // So, it returns an amplitude based on which half of the period the sample is on
    19. // by computing how many periods have elapsed so far. If the number of periods
    20. // is even (%2 == 0), then it returns the positive amplitude, otherwise if it is
    21. // odd (%2 == 1), then it returns the negative amplitude.
    22.  
    23. bool bEven = ( int( (elapsed - d_offset) / d_period ) % 2 == 0 ? true : false );
    24. if ( bEven )
    25. return d_amplitude;
    26. else
    27. return -d_amplitude;
    28. }
    To copy to clipboard, switch view to plain text mode 

    Obviously, I haven't compiled or tested this, but you should get the idea. Might need to multiply (d_period * 2.0) in the line that computes bEven.

  5. The following user says thank you to d_stranz for this useful post:

    jetsu (13th April 2012)

  6. #5
    Join Date
    Apr 2012
    Posts
    10
    Thanks
    1
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: oscilloscope example,how to add a square wave on the canvas

    Quote Originally Posted by d_stranz View Post
    Well, how hard is that? The code below assumes you use the same calling convention for the model data as you do for the sample data.

    Qt Code:
    1. SquareWave::SquareWave( double periodInSec, double amplitude )
    2. {
    3. // Member variables of SquareWave class
    4. d_period = periodInSec;
    5. d_amplitude = amplitude;
    6. d_offset = 0.0; // offset in sec of first signal zero from square wave
    7. }
    8.  
    9. void SquareWave::sample(double elapsed)
    10. {
    11. const QPointF s(elapsed, value(elapsed));
    12. ModelData::instance().append(s);
    13. }
    14.  
    15. double SquareWave::value( double elapsed ) const
    16. {
    17. // This assumes that the sample starts out by going in the positive direction.
    18. // So, it returns an amplitude based on which half of the period the sample is on
    19. // by computing how many periods have elapsed so far. If the number of periods
    20. // is even (%2 == 0), then it returns the positive amplitude, otherwise if it is
    21. // odd (%2 == 1), then it returns the negative amplitude.
    22.  
    23. bool bEven = ( int( (elapsed - d_offset) / d_period ) % 2 == 0 ? true : false );
    24. if ( bEven )
    25. return d_amplitude;
    26. else
    27. return -d_amplitude;
    28. }
    To copy to clipboard, switch view to plain text mode 

    Obviously, I haven't compiled or tested this, but you should get the idea. Might need to multiply (d_period * 2.0) in the line that computes bEven.
    thanks for your help.

  7. #6
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,323
    Thanks
    316
    Thanked 871 Times in 858 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: oscilloscope example,how to add a square wave on the canvas

    Sure. Take a screen shot and post it so we can see if it worked.

  8. #7
    Join Date
    Apr 2012
    Posts
    10
    Thanks
    1
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: oscilloscope example,how to add a square wave on the canvas

    hello,d_stranz.here questions come.
    in samplingThread.cpp,I add these code:
    Qt Code:
    1. void SamplingThread::sample(double elapsed)
    2. {
    3. const QPointF s(elapsed, value(elapsed));
    4. const QPointF s2(elapsed, value2(elapsed));
    5. SignalData::instance().append(s,s2);
    6. }
    7. double SamplingThread::value2(double timeStamp) const
    8. {
    9. const double period = 1.0 / 5.0;//here 5.0 is the frequency
    10.  
    11. const double x = ::fmod(timeStamp, period);
    12. bool bEven = ( int(x) % 2 == 0 ? true : false );
    13. if ( bEven )
    14. v = 400.0;//400.0 is the amplitude
    15. else
    16. v = 0;
    17. return v;
    18. }
    To copy to clipboard, switch view to plain text mode 
    then I make changes in signaldata.h,signadata.cpp,curvedata.h and curvedata.cpp.
    signaldata.h:
    Qt Code:
    1. #ifndef _SIGNAL_DATA_H_
    2. #define _SIGNAL_DATA_H_ 1
    3.  
    4. #include <qrect.h>
    5.  
    6. class SignalData
    7. {
    8. public:
    9. static SignalData &instance();
    10.  
    11. void append(const QPointF &pos,const QpointF &pos2);
    12. void clearStaleValues(double min);
    13.  
    14. int size() const;
    15. QPointF value(int index) const;
    16. QPointF value2(int index) const;
    17. QRectF boundingRect() const;
    18.  
    19. void lock();
    20. void unlock();
    21.  
    22. private:
    23. SignalData();
    24. SignalData(const SignalData &);
    25. SignalData &operator=( const SignalData & );
    26.  
    27. virtual ~SignalData();
    28.  
    29. class PrivateData;
    30. PrivateData *d_data;
    31. };
    32.  
    33. #endif
    To copy to clipboard, switch view to plain text mode 
    signaldata.cpp:
    Qt Code:
    1. #include "signaldata.h"
    2. #include <qvector.h>
    3. #include <qmutex.h>
    4. #include <qreadwritelock.h>
    5.  
    6. class SignalData::PrivateData
    7. {
    8. public:
    9. PrivateData():
    10. boundingRect(1.0, 1.0, -2.0, -2.0) // invalid
    11. {
    12. values.reserve(1000);
    13. }
    14.  
    15. inline void append(const QPointF &sample,const QPointF &squarewave)
    16. {
    17. values.append(sample);
    18. values2.append(squarewave);
    19. // adjust the bounding rectangle
    20.  
    21. if ( boundingRect.width() < 0 || boundingRect.height() < 0 )
    22. {
    23. boundingRect.setRect(sample.x(), sample.y(), 0.0, 0.0);
    24. }
    25. else
    26. {
    27. boundingRect.setRight(sample.x());
    28.  
    29. if ( sample.y() > boundingRect.bottom() )
    30. boundingRect.setBottom(sample.y());
    31.  
    32. if ( sample.y() < boundingRect.top() )
    33. boundingRect.setTop(sample.y());
    34. }
    35. }
    36.  
    37. QVector<QPointF> values;
    38. QVector<QPointF> values2;
    39. QRectF boundingRect;
    40.  
    41. QMutex mutex; // protecting pendingValues
    42. QVector<QPointF> pendingValues;
    43. QVector<QPointF> pendingValues2;
    44. };
    45.  
    46. SignalData::SignalData()
    47. {
    48. d_data = new PrivateData();
    49. }
    50.  
    51. SignalData::~SignalData()
    52. {
    53. delete d_data;
    54. }
    55.  
    56. int SignalData::size() const
    57. {
    58. return d_data->values.size();
    59. }
    60.  
    61. QPointF SignalData::value(int index) const
    62. {
    63. return d_data->values[index];
    64. }
    65. QPointF SignalData::value2(int index) const
    66. {
    67. return d_data->values2[index]
    68. }
    69. QRectF SignalData::boundingRect() const
    70. {
    71. return d_data->boundingRect;
    72. }
    73.  
    74. void SignalData::lock()
    75. {
    76. d_data->lock.lockForRead();
    77. }
    78.  
    79. void SignalData::unlock()
    80. {
    81. d_data->lock.unlock();
    82. }
    83.  
    84. void SignalData::append(const QPointF &sample,const QPointF &squarewave)
    85. {
    86. d_data->mutex.lock();
    87. d_data->pendingValues += sample;
    88. d_data->pendingValues += squarewave;
    89.  
    90. const bool isLocked = d_data->lock.tryLockForWrite();
    91. if ( isLocked )
    92. {
    93. const int numValues = d_data->pendingValues.size();
    94. const QPointF *pendingValues = d_data->pendingValues.data();
    95. const QPointF *pendingValues = d_data->pendingValues2.data();
    96. for ( int i = 0; i < numValues; i++ )
    97. d_data->append(pendingValues[i],pendingValues2[i]);
    98.  
    99. d_data->pendingValues.clear();
    100. d_data->pendingValues2.clear();
    101. d_data->lock.unlock();
    102. }
    103.  
    104. d_data->mutex.unlock();
    105. }
    106.  
    107. void SignalData::clearStaleValues(double limit)
    108. {
    109. d_data->lock.lockForWrite();
    110.  
    111. d_data->boundingRect = QRectF(1.0, 1.0, -2.0, -2.0); // invalid
    112.  
    113. const QVector<QPointF> values = d_data->values;
    114. const QVector<QPointF> values2= d_data->values2;
    115. d_data->values.clear();
    116. d_data->values2.clear();
    117. d_data->values.reserve(values.size());
    118. d_data->values2.reserve(values2.size());
    119. #if 0
    120. int index;
    121. for ( index = values.size() - 1; index >= 0; index-- )
    122. {
    123. if ( values[index].x() < limit )
    124. break;
    125. }
    126.  
    127. if ( index > 0 )
    128. d_data->append(values[index++]);
    129. d_data->append2(values2[index++]);
    130.  
    131. while ( index < values.size() - 1 )
    132. d_data->append(values[index++]);
    133. d_data->append2(values2[index++]);
    134. #endif
    135. d_data->lock.unlock();
    136. }
    137.  
    138. SignalData &SignalData::instance()
    139. {
    140. static SignalData valueVector;
    141. return valueVector;
    142. }
    To copy to clipboard, switch view to plain text mode 
    curvedata.h:
    Qt Code:
    1. #include <qwt_series_data.h>
    2. #include <qpointer.h>
    3.  
    4. class SignalData;
    5.  
    6. class CurveData: public QwtSeriesData<QPointF>
    7. {
    8. public:
    9. const SignalData &values() const;
    10. SignalData &values();
    11.  
    12. virtual QPointF sample(size_t i) const;
    13. virtual size_t size() const;
    14.  
    15. virtual QRectF boundingRect() const;
    16. };
    17. class CurveData2: public QwtSeriesData<QPointF>
    18. {
    19. public:
    20. const SignalData &values2() const;
    21. SignalData &values2();
    22.  
    23. virtual QPointF sample(size_t i) const;
    24. virtual size_t size() const;
    25.  
    26. virtual QRectF boundingRect() const;
    27. };
    To copy to clipboard, switch view to plain text mode 
    curvedata.cpp:
    Qt Code:
    1. #include "curvedata.h"
    2. #include "signaldata.h"
    3.  
    4. const SignalData &CurveData::values() const
    5. {
    6. return SignalData::instance();
    7. }
    8. const SignalData &CurveData2::values2() const
    9. {
    10. return SignalData::instance();
    11. }
    12. SignalData &CurveData::values()
    13. {
    14. return SignalData::instance();
    15. }
    16. SignalData &CurveData2::values2()
    17. {
    18. return SignalData::instance();
    19. }
    20. QPointF CurveData::sample(size_t i) const
    21. {
    22. return SignalData::instance().value(i);
    23. }
    24. QPointF CurveData2::sample(size_t i) const
    25. {
    26. return SignalData::instance().value2(i);
    27. }
    28. size_t CurveData::size() const
    29. {
    30. return SignalData::instance().size();
    31. }
    32. QRectF CurveData::boundingRect() const
    33. {
    34. return SignalData::instance().boundingRect();
    35. }
    To copy to clipboard, switch view to plain text mode 
    I compile it then the error come in signaldata.h:QQ截图20120416120826.jpg
    I don't know how to do,the program drive me insane.
    Last edited by jetsu; 16th April 2012 at 07:11.

  9. #8
    Join Date
    Apr 2012
    Posts
    10
    Thanks
    1
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: oscilloscope example,how to add a square wave on the canvas

    Now I can draw a square wave with fixed number of points on the canvas.
    But I want to turn it into a dynamic one,like the sampling curve.
    The frequency of the square wave is much slower than the sampling curve.
    for example,the sampling frequency of the ADC is 200Hz,while the frequency of the dynamic square wave maybe 5Hz.
    What should I do?

  10. #9
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,323
    Thanks
    316
    Thanked 871 Times in 858 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: oscilloscope example,how to add a square wave on the canvas

    Quote Originally Posted by jetsu View Post
    Now I can draw a square wave with fixed number of points on the canvas.
    But I want to turn it into a dynamic one,like the sampling curve.
    The frequency of the square wave is much slower than the sampling curve.
    for example,the sampling frequency of the ADC is 200Hz,while the frequency of the dynamic square wave maybe 5Hz.
    What should I do?
    Then simply ask for the ModelData point 1/40 as often as you sample the signal data. The problem with your SampleData implementation is that it requires both a signal and a model point in each call to append(). So the way you have designed it, there is no way to sample the signal at a different rate than the model.

    Instead of an append() method that requires two values, make two append methods: appendSignal() and appendModel(), each one taking one value as the argument. Then in your sample method, you can append a signal point with every call, but you only have to append a model point whenever the square wave goes from high->low or low->high. Put a member variable in your SamplingThread class that keeps track of the current value of the model. Initialize it to -1 or some other impossible value. When you enter the sample() method, compute the new value of the model point. If it is different from the value you have in the member variable, append the new model point and set the member variable equal to that. If it is not different, then do nothing. This will give you a square wave that follows the sample as closely as possible using this method - at the worst, it will be off by one sample period. (That is, if the model should go from high to low just after sample() is called, you won't find out until the next sample() call (1 / 200 second later). So you square wave will lag by at most 1 sample period, but it has 40x fewer points.

    Qt Code:
    1. void SamplingThread::sample(double elapsed)
    2. {
    3. const QPointF s(elapsed, value(elapsed));
    4. SignalData::instance().appendSignal( s );
    5.  
    6. double newValue = value2( elapsed );
    7. if ( newValue != savedValue )
    8. {
    9. const QPointF s2(elapsed, newValue);
    10. savedValue = newValue;
    11.  
    12. SignalData::instance().appendModel(s2);
    13. }
    14. }
    To copy to clipboard, switch view to plain text mode 
    All of this assumes that your sample has a fixed frequency (or fixed period). If your signal does not have a fixed frequency (that is, transitions high->low or low->high can occur at any time), then you need to add more member variables that keep track of when the sample crosses zero. Your square wave has to track these transitions, and make the same transitions (high->low or low->high) when the sample does. You can't use the modulus arithmetic, because that assumes a fixed frequency.
    Last edited by d_stranz; 22nd April 2012 at 23:38.

  11. #10
    Join Date
    Apr 2012
    Posts
    10
    Thanks
    1
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: oscilloscope example,how to add a square wave on the canvas

    if we use two append() methods,there is only only one signaldata class and curvedata class,how should I set the data for p_curve?
    Qt Code:
    1. p_curve->setData(new curvedata());
    To copy to clipboard, switch view to plain text mode 

  12. #11
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,325
    Thanked 879 Times in 827 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: oscilloscope example,how to add a square wave on the canvas

    You can't share a CurveData instance as each curve takes ownership of the data bridge, when it has been assigned.

    Uwe

  13. #12
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,323
    Thanks
    316
    Thanked 871 Times in 858 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: oscilloscope example,how to add a square wave on the canvas

    if we use two append() methods,there is only only one signaldata class and curvedata class,how should I set the data for p_curve?
    Your SignalData::PrivateData class has *two* QPointF arrays: values and values2. You are using one of these for the sample and one of them for the model, right? appendSignal() should put a new point onto the end of values, and appendModel() should put a new point onto the end of values2. What is the problem?

    Have you made your design so complicated that you don't understand it any more?

    When I originally offered you a solution to this, I gave you another class: ModelData. You decided to combine the sample and the model into one class, SignalData, and now you are getting confused because you are using one class to hold two different things, and your design makes that class a Singleton. It is getting you into trouble, because now you can have values and values2 with different lengths, but there is only one size() member function, and that is returning the length of values. Likewise for the other member functions - they are using values, and same property for values2 might be different. If you are depending on size() to set the points into the curves, then one curve will be wrong.

  14. #13
    Join Date
    Apr 2012
    Posts
    10
    Thanks
    1
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: oscilloscope example,how to add a square wave on the canvas

    thanks a lot. I have got the idea.
    I change the program with the method you told me. And I add a Plot::update2() in plot.h and plot.cpp.there are indeed two dynamic lines on the canvas now.
    I will add a screen shot function in the program later.Then I will post the photo here to share my joy with you.
    Thanks again.

  15. #14
    Join Date
    Aug 2012
    Posts
    1
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: oscilloscope example,how to add a square wave on the canvas

    Hello,I also want to add another wave,but i can't do it.I think we have the same problem.So can you give me your succeed code?Thank you!

  16. #15

    Default Re: oscilloscope example,how to add a square wave on the canvas

    Hello, I have the same problem. Can you post your code? thank you very much

Similar Threads

  1. Replies: 1
    Last Post: 11th April 2012, 08:50
  2. Oscilloscope
    By P@u1 in forum Qwt
    Replies: 1
    Last Post: 1st July 2011, 15:21
  3. QWT oscilloscope example
    By Pablo220372 in forum Qwt
    Replies: 2
    Last Post: 10th June 2011, 08:19
  4. Replies: 8
    Last Post: 2nd August 2006, 16:19

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Qt is a trademark of The Qt Company.