sine wave smoothing - childrens swing

I hookedup an MPU6050 sensor to Nodemcu and would like to control the brightness of some led’s with the swing.

I got some raw data from the sensor, naturally it basically looks like a sinewave, I would like to smooth this to ignore spikes in the wave when someone pushes the swing to gain speed.

The data and the chart is here:

Could I get some help regarding smoothing a sine wave, it goes into subjects such as low pass filters and such which I am not familiar with.

What do the connections look like? How are they done?

It's hard to see what is going on in those spikes. Start with a rolling average of the last N values, and see what happens.

Some of the more heinous spikes look like they might be errors, and not due to pushing. You may need to throw out reading that jump by too large a value from the previous one.

For a really sophisticated algorithm I would identify the zero crossings to establish the period, and check for amplitude within each half cycle. Then I'd code a simulated model of the system - basically a sine wave lookup table with variables for frequency and amplitude. On each zero crossing you can take your reading of period and amplitude and add/subtract a fractional amount of that to your equivalent simulation variables.

The smaller the fraction you add, the more smoothed out your simulation response is, but the down side is it lags changes in the real system. The larger the fraction, the quicker the simulation responds to changes, but also it won't be as smooth. Adjust the fractions until you find the sweet spot.

The spikes appears at the top of the envelope. How sturdy is the sensor attached to the swing? That's a possible explanation to the spikes.

You will only get a real "sine wave" if the swing is solidly attached to the pivot point. Using ropes or chains will distort the sine wave due to gravity, oscillations of the rope, and other movements of the rope.


What is the magic in reading a "perfect" sinus signal?

For a number of Arduino projects, I've used the online filter design utility here: It will design the filter and produce a C code implementation which can be copied over to an Arduino sketch with some modification.

For this instance the filter design parameters might be (1) Butterworth/Lowpass, (3) Filter order: 1 (or 2), (4) Sample rate: 100, (5) Corner frequency 1: 5, which produces the code:

#define NZEROS 1
#define NPOLES 1
#define GAIN   7.313751515e+00

static float xv[NZEROS+1], yv[NPOLES+1];

static void filterloop()
  { for (;;)
      { xv[0] = xv[1]; 
        xv[1] = next input value / GAIN;
        yv[0] = yv[1]; 
        yv[1] =   (xv[0] + xv[1])
                     + (  0.7265425280 * yv[0]);
        next output value = yv[1];

Note that your sample rate is probably not 100 per second, but for digital filter design the ratio of the corner frequency to the sample rate is all that matters. From the plot in the original post, it looks like the nominal frequency is about 1 cycle per 100 samples, so this filter is designed to pass frequencies less than 5 cycles per 100 samples.

Ported to Arduino as a function, this would look something like:

#define NZEROS 1
#define NPOLES 1
#define GAIN   7.313751515e+00

static float xv[NZEROS+1], yv[NPOLES+1];

static int filterloop(int xIn) {
  xv[0] = xv[1]; 
  xv[1] = xIn * (1 / GAIN) ;
  yv[0] = yv[1];
  yv[1] =   (xv[0] + xv[1]) + (  0.7265425280 * yv[0]);
  return int(yv[1]) ;

It would be called for each input sample in the processing loop.

 . . .
int x = analogRead(A0) ;
long int y = filterloop(x) ;
. . .

Where "x" is your raw reading and "y" is the low pass filtered version of the same.

The theory behind all this is non-trivial, but generating the code, given this tool is pretty straightforward.

OP here.

The connections are NodeMcu and MPU6050 basically. They are glued on top of each other placed in a box and the box is sturdily attached to a swing however my test swing is kind of light weight so that might be why the spikes are higher during the push phase. But in any case there will be spikes in any swing I believe, cannot test at the moment since parks are closed by covid19

the setup is all placed on the seat of the swing (rather than the top part where the ropes originate).

"a sine wave lookup table " is a great idea however not sure if I can pull that off with 256 values for the brightness of the leds.

I would like to read the wave as good as possible because the effect I want to get with the leds is kind of very sensitive due to the nature of leds. it either gets bright to quick, or dark too long, and together with the noise in readings the setup becomes messy:

I believe my sample rate is actually around 90 readings per second. I will take a longer look at MrMark's suggestion though it does seem a difficult one to implement for me.

Sine waves do not have a "push phase". You are not dealing with a sine wave unless the swing is free and only gravity is slowing it down. Possible a cosine + a sine wave.


Okey. You’ve payd attension to connectors and box being secured. Good. As a true engineer a lockdown shouldn’t stop You. Make any kind of mini swing, clamp a bar in a doorway, 2 strings, a plank, anything, and some load, and You can go on testing. Let it swing!

The code provided by MrMark actually worked pretty good. It generated a pretty good smooth wave output. I think it is great for smoothing a sine wave and filtering out noise. the wave is so smooth that it will hopefully also be easy to find max points in the wave.

Just a note that the motion is not a pure sine wave if the angles of the swing are big , so smoothing against a model sine wave may not work .