Click here to Skip to main content
15,881,172 members
Articles / Programming Languages / C#
Article

Simple Signal Generator

Rate me:
Please Sign up or sign in to vote.
4.98/5 (58 votes)
28 Oct 2008CPOL5 min read 295.3K   18.1K   134   48
Useful software equivalent for a real, simple signal generator device
SignalGenerator_bin

Introduction

The Simple Signal Generator is a C# class designed to generate four simple periodic waveforms including sine, square, triangle, and sawtooth. The class is provided for testing software and hardware components during the development of measurement applications. A generated signal varies across time domains, and by default, is normalized by the amplitude A € [-1,1] and period T € [0,1]. It is possible to set an arbitrary amplitude, frequency, DC-offset, and phase shift, and to invert the signal.

Background Display

There are a couple of articles on The Code Project that describe in detail about developing different user defined components for dynamically changing single values or signal shapes such as bars, graphs, charts, gauges, and a diversity of other instruments.

For testing those components, functions like y=F(x) are very often used. These functions are typically periodical, mostly sine, and their variable x will be modified in a loop with constant steps across an interval [x0,xn].

Hardware developers use a totally different technique. For analyzing and troubleshooting electronic systems, they use an additional external device called signal or function or waveform generator. The signal generator is an important piece of electronic test equipment, and should not be missed in any electronics laboratory.

On the device, we can select a built-in periodical function like y=F(t); the variable t represents real time, and we can change some parameters like frequency, amplitude, and the DC-offset. Typically, there are four basic signal types.

After customization, the desired output signal can be wired on to the input of the component that should be tested, and we monitor their response function in the time domain using an oscilloscope.

SignalGeneratorDevice

Displayed here is a typical low-cost signal generator that has on its front panel, a radio-button with four positions to choose signal types and three potentiometers to adjust frequency, amplitude, and DC-offset. It is no big problem for hardware dudes to make something such as this, especially with tips from the book [1].

Of course, there are much better and more expensive devices on the market with more functions, more parameters to choose, better range and a finer scale for these parameters, integrated display to show selected settings, user-defined functions, on-board memory, better stability, and two or more independent channels.

Note that, there are two very significant differences between the hardware and the software approach. Hardware developers use an external device, and a test signal is in the time domain, which implies that the test signal varies totally independent from the assembly that will be tested.

The class presented offers a software equivalent for the above described real, simple signal generator device.

C#
public class SignalGenerator
{
    #region [ Properties ... ]

    private SignalType signalType = SignalType.Sine;
    /// <summary>
    /// Signal Type.
    /// </summary>
    public SignalType SignalType
    {
        get { return signalType; }
        set { signalType = value; }
    }

    private float frequency = 1f;
    /// <summary>
    /// Signal Frequency.
    /// </summary>
    public float Frequency
    {
        get { return frequency; }
        set { frequency = value; }
    }

    private float phase = 0f;
    /// <summary>
    /// Signal Phase.
    /// </summary>
    public float Phase
    {
        get { return phase; }
        set { phase = value; }
    }

    private float amplitude = 1f;
    /// <summary>
    /// Signal Amplitude.
    /// </summary>
    public float Amplitude
    {
        get { return amplitude; }
        set { amplitude = value; }

    }

    private float offset = 0f;
    /// <summary>
    /// Signal Offset.
    /// </summary>
    public float Offset
    {
        get { return offset; }
        set { offset = value; }
    }

    private float invert = 1; // Yes=-1, No=1
    /// <summary>
    /// Signal Inverted?
    /// </summary>
    public bool Invert
    {
        get { return invert==-1; }
        set { invert = value ? -1 : 1; }
    }

    #endregion  [ Properties ]

    #region [ Private ... ]

    /// <summary>
    /// Time the signal generator was started
    /// </summary>
    private long startTime = Stopwatch.GetTimestamp();

    /// <summary>
    /// Ticks per second on this CPU
    /// </summary>
    private long ticksPerSecond = Stopwatch.Frequency;

    #endregion  [ Private ]

    #region [ Public ... ]

    public SignalGenerator(SignalType initialSignalType)
    {
        signalType = initialSignalType;
    }

    public SignalGenerator() { }

    #if DEBUG
    public float GetValue(float time)
    #else
    private float GetValue(float time)
    #endif
    {
        float value = 0f;
        float t = frequency * time + phase;
        switch (signalType)
        { // http://en.wikipedia.org/wiki/Waveform
            case SignalType.Sine: // sin( 2 * pi * t )
                value = (float)Math.Sin(2f*Math.PI*t);
                break;
            case SignalType.Square: // sign( sin( 2 * pi * t ) )
                value = Math.Sign(Math.Sin(2f*Math.PI*t));
                break;
            case SignalType.Triangle:
            // 2 * abs( t - 2 * floor( t / 2 ) - 1 ) - 1
                value = 1f-4f*(float)Math.Abs
                    ( Math.Round(t-0.25f)-(t-0.25f) );
                break;
            case SignalType.Sawtooth:
            // 2 * ( t/a - floor( t/a + 1/2 ) )
                value = 2f*(t-(float)Math.Floor(t+0.5f));
                break;
        }

        return(invert*amplitude*value+offset);
    }

    public float GetValue()
    {
        float time = (float)(Stopwatch.GetTimestamp() - startTime)
                        / ticksPerSecond;
        return GetValue(time);
    }

    public void Reset()
    {
        startTime = Stopwatch.GetTimestamp();
    }

    #endregion [ Public ]
}

#region [ Enums ... ]

public enum SignalType
{
    Sine,
    Square,
    Triangle,
    Sawtooth
}

#endregion [ Enums ]

Using the Code

For using the class, we have a public function in the form y=F(t). The parameter t is the real time here.

C#
private float GetValue() 

After a lot of consideration, I added another overload of the function in the form y=F(x). The Parameter x is explicitly given as a time here.

C#
#if DEBUG
public float GetValue(float time)
#else
private float GetValue(float time)
#endif

This should be used publicly only for DEBUG purposes, eventually during tests by adding new signal types!

All signals have a normalized period T € [0,1] in cycles, and not the usual T € [0,2Pi] in radian. In this case, a value 1 corresponds to a full cycle. The basis for this is an easier deal with normalized values, for example, for scaling operations by fitting in a window.

The signal generator is given as a class, but it is quite easy to transform it to a non-visual, or yet to a visual component, or maybe to a form like a front panel.

For generating all the given signals, very simple functions are used, but they are not the simplest. Some functions can be made simpler, but a development goal of this project was to generate signals exactly like the following example on Wikipedia:

Sine, square, triangle, and sawtooth waveforms

Sine, square, triangle, and sawtooth waveforms. Enlarge!

The included TB.Instruments solution contains two test examples:

The first example uses a compiled Simple Performance Chart, a component from eclipse2k1. It is a piece of homework to select one of four different signal types. Here, we can see how the selected signal can be adjusted and what trouble can occur with signals in real time. You should try out what happens with higher frequencies and lower sampling rates, and how to find an optimal refresh rate.

SignalGenerator.Example1

For the second example, a light modified Sliding Scale Gauge, a component from Tefik Becirovic, is used. Here, five instances of the signal generator class are defined. All these generate sine waves with the same (default!) parameter settings. The generated signals have a small phase shift. A prize question is how to synchronize all the five signals.

SignalGenerator.Example2

Conclusion

Any suggestions/comments/feedback is welcome and highly appreciated.

If you like it, please vote, and if you use it commercially, describe your success story in the discussion board below.

References

  1. Delton T. Horn, Build Your Own Low-Cost Signal Generator, McGraw-Hill/TAB Electronics, 1994, ISBN 0070304289
  2. R.A. Penfold, How to Use Oscilloscopes and Other Test Equipment, Bernard Babani Publishing, 1989, ISBN 0859342123
  3. Introduction to the Function Generator
  4. Using a Basic Function Generator
  5. C# and Electronic Test Instruments

History

  • 15.10.2008 - Version 1.0 released
  • 16.10.2008 - Version 2.x released
    • Added some new functions
  • 27.10.2008 - Version 3.x released
    • Added synchronization possibility
    • Synchronized sliding scales example
    • Added user defined functions example

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Systems Engineer
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Questionsampling rate for the signal generator Pin
Member 1489711323-Jul-20 3:23
Member 1489711323-Jul-20 3:23 
AnswerRe: sampling rate for the signal generator Pin
Tefik Becirovic25-Sep-20 10:51
Tefik Becirovic25-Sep-20 10:51 
QuestionUnderstanding the Code Pin
Member 1418930123-Jun-19 23:59
Member 1418930123-Jun-19 23:59 
PraiseExcellent, 5/5 Pin
Member 403001827-Jun-17 17:28
Member 403001827-Jun-17 17:28 
QuestionWant to show continuous sine waves in windows application Pin
Member 1286844227-Dec-16 23:50
Member 1286844227-Dec-16 23:50 
Questionhow to compare the output or measure using oscilloscope Pin
Member 106838508-Apr-15 11:30
Member 106838508-Apr-15 11:30 
QuestionSignal generator using HS-SR04 in c# Pin
tomi150015-Mar-15 9:14
tomi150015-Mar-15 9:14 
AnswerRe: Signal generator using HS-SR04 in c# Pin
Tefik Becirovic16-Mar-15 10:53
Tefik Becirovic16-Mar-15 10:53 
GeneralMy vote of 5 Pin
Boris Evstatiev26-Oct-14 21:01
Boris Evstatiev26-Oct-14 21:01 
QuestionOutput Signal to Soundcard Pin
Bassman7112-Feb-13 12:09
Bassman7112-Feb-13 12:09 
AnswerRe: Output Signal to Soundcard Pin
Tefik Becirovic14-Feb-13 0:11
Tefik Becirovic14-Feb-13 0:11 
GeneralRe: Output Signal to Soundcard Pin
i006-Nov-14 13:04
i006-Nov-14 13:04 
GeneralRe: Output Signal to Soundcard Pin
Tefik Becirovic10-Nov-14 0:41
Tefik Becirovic10-Nov-14 0:41 
QuestionSome Comments Pin
fzec114-Dec-12 9:47
fzec114-Dec-12 9:47 
AnswerRe: Some Comments Pin
Tefik Becirovic15-Dec-12 0:15
Tefik Becirovic15-Dec-12 0:15 
QuestionQuestions?????????? Pin
mojtabaNava8-Nov-12 21:34
mojtabaNava8-Nov-12 21:34 
QuestionRole of Oscillator.cs Pin
sgxxx25-Sep-12 23:45
sgxxx25-Sep-12 23:45 
AnswerRe: Role of Oscillator.cs Pin
Tefik Becirovic26-Sep-12 1:36
Tefik Becirovic26-Sep-12 1:36 
GeneralRe: Role of Oscillator.cs Pin
sgxxx28-Sep-12 17:51
sgxxx28-Sep-12 17:51 
GeneralMy vote of 5 Pin
Björn Friedrich8-Sep-12 0:42
Björn Friedrich8-Sep-12 0:42 
GeneralRe: My vote of 5 Pin
Tefik Becirovic26-Sep-12 1:34
Tefik Becirovic26-Sep-12 1:34 
GeneralMy vote of 5 Pin
martinfwf10-Aug-12 2:29
martinfwf10-Aug-12 2:29 
GeneralRe: My vote of 5 Pin
Tefik Becirovic26-Sep-12 1:31
Tefik Becirovic26-Sep-12 1:31 
Generalmaybe last question Pin
NikolayNikolaev10-Jul-09 0:43
NikolayNikolaev10-Jul-09 0:43 
Generalfrom Nikolay Pin
NikolayNikolaev9-Jul-09 22:01
NikolayNikolaev9-Jul-09 22:01 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.