Sine Wave generator with no glitch

frandESS

Lifetime Supporting Member
Join Date
Sep 2022
Location
Norway
Posts
14
Hi dear forum,

I need to create a test sine wave that so that I could check settling time in bidirectional inverters.

Function that needs to run on my Compact Logix L33ER

F=49.7 + 0.1 Sin( (2*PI*t )/ T)

So I already learnt about the 2*PI*60 (0.1649) factor in previous threads to avoid the Roll Over Fault when using seconds as sampling. However I try to alter the Sample interval T from 10- 200 sec.

Still get glitches and i was curious if anybody on the forum would help.

Very grateful for any directions to reach further to goal.

I have attached trends from T=20 and T=118s

Capture.jpg Capture2.PNG Capture3.PNG
 
What do you consider to be the glitch? What I see is typical when the time between calculations is long. The stair step effect can be reduced by making the increments for t smaller. Also, if t >=T then t=t-T will help with the roll over.

It looks like you might be incrementing t every second. Can you put your calculations in a timed interrupt and increment t by 0.01 every 10 milliseconds? This will smooth out the stair step effect.

There are also faster ways to calculate sine waves by rotating vectors, but you shouldn't need to get that tricky.
 
I managed to remember old Sampling rules from Nyqvist.

This code works on any Periodic Time, and the timer is set to be doubled according to Nyqvist

TimerON.PRE:=Periodic_Time*2000;
TimerON.EnableIn:=TimerOn_Start;
TimerON.Reset:=TimerON.DN;

TONR(TimerON);

TimerON_calc:=TimerON.ACC/1000;

FCR_SinWave:= 49.7* 0.1 * SIN((6.28291*TimerON_calc)/Periodic_Time);
 
@Peter_Nachtwey - Thanks for the response. I guess this little code do what you simply says - Thanks for pointing.
 
I managed to remember old Sampling rules from Nyqvist.

This code works on any Periodic Time, and the timer is set to be doubled according to Nyqvist

TimerON.PRE:=Periodic_Time*2000;
TimerON.EnableIn:=TimerOn_Start;
TimerON.Reset:=TimerON.DN;

TONR(TimerON);

TimerON_calc:=TimerON.ACC/1000;

FCR_SinWave:= 49.7* 0.1 * SIN((6.28291*TimerON_calc)/Periodic_Time);


Don't use timers!
Use timed interrupts.
Timers are really delays, not timers, that will delay a little longer than what you specify. This doesn't happen with timed interrupts.
 
It's good you have it working now. @Peter Nachtwey is right that you should not use a self-resetting, repeating TON timer if you want a consistent, good sine wave with respect to real time, but it will probably be close enough with a little hiccup around each time the timer resets. A better approach would be to assign a preset much larger than the target reset time (e.g. .PRE = 200,000ms when the reset time is 118,000ms), and then, instead of resetting the TON, subtract 118,000 from the .ACC whenever .ACC is greater than or equal to 118,000.

Even though the current code works, it is technically incorrect as it uses a wrong value for 2π, but it is probably close enough that the error is not noticeable.

If I were doing this I would simply increment a counter and reduce it MODULO (N x ~1000), for an ~N second period, once per scan cycle, and use that counter as t. If 6.28291 is satisfactory as an approximation for 2π, then such a counter would be good enough as well.

Sidebar/FYI

As noted/hinted at by @Steve Bailey, the problem with the (now obsolete) original codein Post #1 was likely that the code was using second_of_minute for t, which t values ran from 0 to only 59s, and then reset to 0, while the period of the sine wave was 118s. So the formula only ever used values from the first half of the sine curve. It would be more obvious if you calculated and plotted cosine.
 
From the looks of OP's Capture3, he's programming in the Rockwell world. Their Knowledgebase has a nice Ladder Diagram download that provides Sinewave, Sawtooth and Random outputs. I put it in every project for just these sorts of uses, in a 250 mS periodic task.

(Although now I see Rockwell rounded to 6.28 for their Sinewave generator. I'm editing mine to use the more accurate 6.283185.)
 
Last edited:
Rather than the sine function, I use cosine.

That's because COS(0) = 1 and COS(2π) = 1.
Thus, if x = ACC/PRE, x will have a value from 0 to 1, repeating, in a triangular wave.
Thus 2πx will go from 0 to 2π then jump to 0 when the timer is reset at ACC = PRE.
The COS() function will thus produce a nice sinusoidal wave from 1 down to -1 (when ACC = 0.5*PRE) and back to 1.

No "glitches".

Don't get hung up on the fact that it's called a "sine wave" and insist on using SIN().
 
Last edited:
Rather than the sine function, I use cosine.
If you want to get picky.
PI is about 355/113. This works well with long ints. It is more precise than single precision floats. If there are LREALs then use them with the rotating vectors technique.
Never use the POW function unless the powers are not integers or 0.5. Internally it uses the exp() and ln() functions which are very CPU intensive. If you want to square a number simply use number*number. It is much more efficient.
Square roots should use the sqrt() function.
Since the sine() function is basically doing cyclic calculations it is much more efficient to rotate vectors. This calculates the sin() and cos() at the same time with just 4 multiplies and a couple of adds. This is much more efficient than calculating sin() or cos() using a Taylor series.
 
This may be a silly suggestion, but why don't you instead set your timer to 2,147,483,648.

This provides you with 24 days (I may have gotten my math wrong) until you see a glitch which should be far longer than your motor settling time.

Then you just use the timer.ACC variable and feed it into your Sine/Cosine instruction and be done with it.
 

Similar Topics

Hello Experts, I am trying to create a SINE Wave generator and i cannot seem to make it smoother. I have done this before but i forgot the exact...
Replies
6
Views
294
Hi does any one have or know where I can obtain a function to generate a slow sine wave output of 4-20 ma with variable frequency and amplitude...
Replies
3
Views
3,452
Hi, Any idea how can a generate a sine wave signal of 2Hz where the output is an analogue 4-20mA? This is required for a proportional pressure...
Replies
27
Views
7,110
Anyone have an examplen on how to generate a sine wave in Structured text. Help much appreciated, thanks in advance!
Replies
10
Views
6,623
Hi, I am trying to produce a sine wave from an omron plc model : CJ1H I want to do it in ST if possible. I am only learning Structured Text...
Replies
4
Views
2,692
Back
Top Bottom