4833

This detector circuit uses just the Arduino Nano itself, no added sensor. Blowing some air from 30cm distance can be detected. It detects via measuring the internal heated chip temperature with 0.01 celsius resolution and finding rapid changes. A demonstration movie shows this high resolution readout. This project uses a technique enabling increased resolution beyond that of an LSB of the ADC (dithering).

The air flow detection concept:
The Arduino processor ( here: ATmega328P), when running,  heats up itself to some 6...10 degrees celsius above ambient. An increase in airflow will then cool it down, this is the principle of detecting a sudden airflow.
This detection is done by comparing the new temperature readout to the previous result and looking for changes two times per second
Apart from detecting airflows it will also detect other temperature changes like moving the board or touching the chip package.
Note: For having it working as a detector, from cold boot you need to give the Arduino some time to warm up (5...10 minutes). Once it has reached a "stable" end-temperature it is possible to start detecting these small sudden airflows.
Note: This is a very senstive detector, readout fluctuations can be <0.02 celsius, but an airflow causes larger fluctuations, so evaluate readout stability while shielding it from airflows (plastic bag).

The temperature readout concept:
The internal ADC can be switched to not only read the analog input pins but it can also be set to read the on-chip temperature sensor.
This voltage will always be <1V. To increase ADC sensitivity the reference voltage is set (in software) to a 1.1V internal source instead of the default 5V supply. The smallest readable step then lowers from 5mV to 1mV (rounded numbers). This smallest step is called the LSB (Least Significant Bit). The datasheet tells us we get 1mV/celsius from the sensor so with 1mV LSB we obtain 1 degree celsius resolution.
The next block explains how this is improved to roughly 0.01 celsius resolution.

Increasing the ADC-readout resolution by dithering:
As mentioned, an ADC is usually limited to detecting changes (steps) that have the magnitude of an LSB.
By lowering the reference voltage to 1.1V we got approximately 1mV magnitude LSB.
The ADC then gives a readout scaled in multiples of 1mV. If, for example, the input is somewhere between 99.5mV and 100.5mV it will always gives "100mV" readings.
So if we have an input signal of 100.1mV  we just read "100mV".
Here the concept of dithering can help us out, this technique is one of the rare applications where noise is improving things.
This is how dithering works for our example:
If we add random noise to the 100.1mV signal (for now: assume noise with 1 LSB=1mV amplitude)  and quickly do a lot of repeated measurements we will get some 90% of "100mV" readings and 10% of "101mV" readings. We can take the average and conclude that we actually had 100.1mV input signal. For larger noise amplitudes the averaged results are also leading towards this value.
The induced fluctuations by the noise are making this result not perfectly stable but as a rule of thumb you get 10 times improvement for 100 times averaging. The improvement is the square root of the number of averages.
In this application 6400 averages are used for each temperature reading. The square root of that predicts 80 times improvement.
We started with 1 degree celsius resolution so we could theoretically improve to 0.0125 celsius resolution. The testdata shows a trend of 0.01- 0.02 celsius fluctuating steps in temperature readout so that indicates we come close in practice.
See the included datafile and the results in the demo-movie.

Precision versus Accuracy:
Note that the readout has high precision (fluctuations to <0.02 celsius) but is not at all accurate to that level, meaning that the low-fluctuation readings (precision) can be offsetted several degrees from the actual value (accuracy). For applications detecting small changes you only need high precision, so this works well here.

Software:
Here an Arduino Nano was used buth other boards with the same processor  ATmega328P  (like  Uno or Pro-Mini) should also work.
Source code included, it is rather straightforward: 
1- Initialise by setting the ADC ref and input mux correct to read internal sensor.
2- Accumulate 6400 ADC readings to determine the temperature with high precision
3- Send the result over USB.
3- Check if readout dropped suddenly, if so switch off indicator LED, if not switch on
4- Goto 2

Limitations:
- This works best on Arduino's with SMD uC chip versions. The larger DIL package changes too slow in temperature and is more thermally isolated.
-Dithering slows down the actual measurement rate because you have to collect a lot of readings, here we use a 10KHz rate ADC and slow down to about 2 readings per second. For temperature measurements this is no problem.
-An ADC is not perfect so if it's smallest steps are unequal (spec: DNL) you get additional errors in the statistics.
For the Pro's: Larger than 1LSB amplitude noise also helps somewhat to average out the ADC DNL errors
-If the noise does not have an equal possibility distribution of all values, then the statistics are also affected.

Q: Where did we add the noise source that is needed for the dithering?
Well, we did not, at these small 1mV LSB levels we get it for free here from the circuit elements like the sensor itself.
As a comparison: when reading an input voltage using the 5V ADC reference I found that the "natural" noise was too low to make the dithering work properly.
How did I come to this conclusion? I could still see most readings centering around the 5mV LSB steps. In a future post I plan to show how this was solved to make a high resolution voltmeter.

Suggestions (not tested):

Make it into a thermometer:
If you bring average dissipation down, you could use this as a thermometer.
Use sleep mode and power-on once every few seconds to measure.

Read external sensors:

You could hook up an external diode to analog input pins and enable WEAK_PULL_UP to bias it with a small current.
This way you could presumably read multiple external temperatures with high precision (and low accuracy) using the same code concept.