## Introduction

Welcome back to the Vibrations All Around Us blog series, where we will be learning about fundamental signal analysis algorithms and using them for real-world applications. In this blog post, we will develop a crude leveler. The goal of this lab is to be able to move the Nicla chip around in space, and get feedback once the chip is within 1° of level. We will use the fact that the accelerometer is sensitive to gravity, and align the Z-axis of the accelerometer with gravity. Let’s get into it.

## Very Crude Leveler

At it’s core, to make a leveler we need to check the angle formed between the angle formed by the Nicla and the unit Z vector. Here’s what our leveler psuedo-code looks like:

- Calculate the angle formed between the Nicla and the Unit Z vector
- Check that this angle is below 1°

A naive solution would be to simply check for With a 3 axis accelerometer, we should be able to look at a single axis, in this case the Z axis, and once it’s above a threshold angle, we can say the Nicla is level. The threshold for degrees converted to radians is:

1\degree \frac{\pi}{180} = .017 \text{ rad}

Then, we can determine what that gravity threshold

1 \text{G} * cos(0.017 rad) = 0.9939 \text{G}

So whenever the Z-acceleration is less than 0.9939 the device isn’t level and when the Z-acceleration is greater than or equal-to 0.9939 the device is level. This would work if we had a perfect accelerometer with high resolution and no scaling errors (1G doesn’t equal 4096 counts). Let’s make a more robust leveler that takes advantage of the other 2 axes. Let’s check the angle formed by the *resultant* acceleration against the unit vector. We can take the angle between 2 vectors using the following formula:

\theta = cos^{-1}(\frac{a \cdot b}{\left| a\right| \left| b \right|})

where *θ *is the angle and *a* and *b* are vector 1 and 2, respectively.

Better? Well, not quite. All signals in engineering applications are contaminated by some level of *noise*, which refers to undesired and random variations in data that don’t carry meaningful information. Accelerometers are notoriously noisy instruments, and we have a pretty small margin for error, so it’s likely that our current algorithm will give us a flickering level-to-non-level signal even though the chip might be perfectly level. Let’s give it a shot. I’ve done an experiment where I have slowly rotated the device around the “level” position, moving it in and out of the level state. If I run the previous code on my experiment I see the following:

and let’s take a closer look at the region that’s close to the level mark:

I want to manufacture a leveler using this algorithm and sell it to the public. The device will have a LED on it that flips between red and green when the device is non-level and level, respectively. I’m going to have a lot of 1-star, “wouldn’t recommend” reviews from frustrated customers that are going to buy a device which never shows a solid green light even if they have it on a perfectly level surface!

In reality, Digital Signal Processing (DSP) is needed to have an acceptable performance. In the below plot we have filtered the raw angle signal using DSP which should solve the problem we mentioned above. Of course, were this a real product, there are several other sources of error that should be addressed, if you’d like to know more, please reach out!

## Finite Vs. Infinite Impulse Response Filter (FIR Vs. IIR)

A finite impulse response (FIR) filter is an algorithm that filters a signal based on a finite history of the signal. The moving average filter implemented in this blog post is FIR, because the output of the filter is only dependent on the previous *b* signal points, any signal history beyond this is “forgotten” to the filter. An Infinite Impulse Response (IIR) filter, is an algorithm that filters a signal as a function of the entire history of the signal. An example of an IIR Filter is the Exponential Filter, which is written as follows.

y(t) = (\alpha - 1) * y(t-1) + \alpha*x(t)

Where falls between 0 and 1. Unlike FIR filters, the output, *y(t)*, of the filter is dependent on* previous outputs* of the filter. The reason this is considered as an “infinite response” is because the above equation can be rewritten as a weighted sum of previous points:

y(t) = \alpha \sum_{n=0}^{\infty}{(\alpha - 1)^{n} * x(t-n)}

In other words, the infinite response filter never forgets! Ironically, the Finite response filter is typically more memory intensive, as the signal history for the entire length of the filter must be remembered. In this example, the exponential filter only needs to remember the filter’s previous output (you would implement this using the previous equation).

Congratulations, you have completed the first steps of building a leveler. Speaking of steps, don’t forget to join us next week, where we will be building a crude pedometer to demonstrate some time-series techniques. See you then!