I am using this code to read from a TMP36 temperature sensor.
The code gets a reading from it, but it jumps up and down with something that looks like 4c in total. Suddenly it can then go from 25C down to 16-17C, then back up to 23C-27C again, and continue to jump around.
When I monitor the voltage from the sensor, using both a multimeter and oscilloscope, it does not seem to flicker as much as the reading from my Imp indicates. Connecting it to a Spark Core also returns a stable (around 0.5c deviation) reading. Even when connecting the sensor to my Electric Imp and Spark Core at the same time gives a stable reading on the Core, but not on the Imp.
I got a capacitor between the output pin and 3v3 to stabilize the output too, but that only seems to work for the Spark Core.
Any idea what else I can try?
`hardware.pin9.configure(ANALOG_IN);
function getTemp()
{
// get the raw voltage value from temp sensor (0-65535)
local reading = hardware.pin9.read();
// needs mapping to the the voltage we are getting from the regulator
local voltage = reading * hardware.voltage();
// divide by the raw value range
voltage /= 65535.0;
// subtract offset and multiply by 100
return (voltage - 0.5) * 100;
My workaround is always to read and discard the first value, then average the next 5 values and use that average for calculation. Mostly that works to reduce the +/- 1LSB sampling error. If you connect your device and run similar code, you should be able to see any variability that is affecting your calculated temperature.
`
hardware.pin9.configure(ANALOG_IN);
function getTemp()
{
// get the raw voltage value from temp sensor (0-65535)
local firstreading = hardware.pin9.read();
server.log("First Reading = " + firstreading );
local reading = 0;
local tempReading = 0;
for( local i=0; i<5;i++)
{
tempReading = hardware.pin9.read();
server.log("Reading #" + i + " = " +tempReading);
reading+= tempReading;
}
reading /= 5.0;
server.log("Average Reading = " + reading + " Delta = " + (firstreading.tofloat()-reading) );
// needs mapping to the the voltage we are getting from the regulator
local voltage = reading * hardware.voltage();
// divide by the raw value range
voltage /= 65535.0;
// subtract offset and multiply by 100
return (voltage - 0.5) * 100;
}
`
When I run that code with pin 9 tied to ground through a 1k resistor, this is the kind of log output I get which shows some level of noise in the sampling. This is normal though since the Imp ADC is 12 bits, scaled to 16 bits. +/- 1 LSB at 12 bits is 16 when scaled to 16 bits
@MikeyDK, that looks a lot better. I got interested enough to connect a potentiometer to the Imp. This is a high quality Bourns ten turn 10K pot. I adjusted to about 0.88V input on pin 9. Now I see a range in a set of 5 readings of 96. That does not look good - very noisy. I suggest you increase your average to 10. Should help stabilize your display reading a bit more. If you want even more stability, a filter will help. I don’t know if this noise is a function of the 3V3 power supply or an issue in general with the ADC.
You can choose your time constant to give you the response you want - it sets the cut-off frequency of the filter. The value will depend on how often you are sampling temperature. For example, I was sampling every 2 seconds and set the filter constant to 0.2.
Notice below how stable the filtered value is even though the samples have high range
@MikeyDK, yes, more samples will decrease the noise. A long term filter will help to stabilize things further and make the display more pleasing to the eye. I edited the post above to include a filter.
If you measure the voltage input to the Imp pin and the voltage input to the Spark Core pin, what do you get?
@MikeyDK, here’s the filter implemented. It will smooth things down for you and also has a re-seed function to track sudden large changes to give realtime responsiveness to real temperature changes (moving a probe from a hot plate to Ice-bath for example… not that anyone ever does that!).
You can see from the output that it’s nice and clean even though the input is jumping around due to the excessive sampling noise. I did a quick turn of the pot to simulate a rapid temperature change and you can see how it tracked the change.
hardware.pin9.configure(ANALOG_IN);
function getTemp()
{
// get the raw voltage value from temp sensor (0-65535)
local firstreading = hardware.pin9.read();
local reading = 0;
for( local i=0; i<10;i++)
{
reading+= hardware.pin9.read();
}
reading /= 10.0;
// needs mapping to the the voltage we are getting from the regulator
local voltage = reading * hardware.voltage();
// divide by the raw value range
voltage /= 65535.0;
// subtract offset and multiply by 100
local temperature = (voltage - 0.5) * 100;
if( math.abs(filteredTemperature - temperature) >0.5 ) {
// Seed the filter if realtime value has changed by a large amount
// If you don't seed the filter, it will take a while
// to get to the correct value.
filteredTemperature = temperature;
}
else
filteredTemperature = filteredTemperature - (filteredTemperature-temperature)*0.05;
server.log(format("Temperature:%4.2f Filtered Temperature:%4.2f ", temperature,filteredTemperature));
return filteredTemperature;
Great, I think that’s about as good as it’s going to get. I would prefer that the ADC sampling was less noisy, but filtering takes care of it. Sorry about the "voltage-0.5 to “voltage-0.4” translation error but well spotted! Fixed it above