The code can be found here: https://gist.github.com/madgyver/7b09e633503119bd198c8873154a9772
I am currently building a table top demonstration for oversampling and moving average algorithms. The basic idea of oversampling is to increase the resolution of your measurements, by sampling a lot faster then strictly necessary. Using those additional measurements one can increase the signal-to-noise ratio by averaging, which will increase the effective resolution of the ADC. There’s actually an application note by ATMEL (AVR121), which is a light introduction to the topic, but of course can’t be expected to go into a lot of detail about the math.. I’m going to write a more detailed article about that later but for now I just want to show you my current progress.
Normally the LM35 sensor can be used to reliably measure temperatures in 0.2°C steps. By using oversampling we can push that 0.01°C! At first I was not sure if the sensor values would be meaningful, since I wasn’t sure about the precision of the LM35. As it turns out however, the results look like they are usable. The sensor is sensitive enough to detect the temperature increase caused by a nearby hand. Of course the temperature increase is very minimal, about 0.3°C, and you also have to have your hand 5 cm in front of the sensor, but that is still pretty impressive. It is also possible to see the opening of a window in the sensor values, well before the temperature has decreased by even 0.5°C. I have yet to write an automated detection for this.
Although the application note gave me the idea to test this on an Arduino, this code uses a different approach by utilizing a moving average filter and ignoring decimation. The last thing works, because we are using with floating point values and not integers. One challenge was to find a way to calculate the moving average over 2048 values with a limited device like the Arduino. Typical implementations of the moving average use an array to keep track of all the measurements. However 2048 16-Bit values would be way to much for the ATmega328. This was solved by using a cumulative moving average algorithm, which I will present in a greater detail in a later article. The application note avoids this problem by calculating a normal average value, drastically reducing memory usage but also significantly reducing the time resolution. Of course the frequency response of this experiment will also be greatly degraded since it is a massive low pass filter and will also introduce significant lag. Luckily temperature is something that changes very slowly so this won’t be a big issue.