-
• #2
Wow, that's a pretty serious noise issue. What's the other side of the thermistor connected to? GND and 3.3v would be best as that is what the microcontroller is also using. When I was doing the stuff for http://www.espruino.com/Thermistors it was pretty stable.
As far as software filters, the simplest is:
var amt =0.1; var average = first_temperature_we_have; function step() { average = average * (1-amt) + new_temperature * amt; filtered_temperature = average; }
But you can also do a median filter, which is the kind that's used for noise reduction in digital cameras, TVs and stuff like that:
var history = new Uint16Array(50); // or whatever level of filtering var sortedHistory = new Uint16Array(history.length); var historyPtr = 0; function step() { history[historyPtr] = new_temperature*256; historyPtr = (historyPtr+1) % history.length; // choose a new history item sortedHistory.set(history); // set history values to the new ones sortedHistory.sort(function(a,b) { return a-b; }); filtered_temperature = sortedHistory[sortedHistory.length/2]/256; }
Hope that helps! While doing this I found a bug in Float32Array.set, so you won't be able to use that until 1v65 I'm afraid. However if you need floats you can always use the normal Array - it'll just take up a bit more memory.
-
• #3
Thanks Gordon that's a huge help.
I did manage to get to a reasonable point by logging temperatures to an array. That was until the array got too large and crashed the Espruino! So now when I get to the max array size I 'unshift' the first value off the array.
Mode appears to work better than median. I will investigate further using your post above.
The noise may be down to the thermistor I am using. I'm using a 10K thermistor with a 10K resistor as the divider all on a small board next to the Espruino.
To test the readings I was using a 10K resistor in place of the thermistor so in theory I should be reading bang on 25°C but it was fluctuating around too much.
The response doesn't need to be super fast so I think some sort of array and average should work okay.
-
• #4
Well this is slightly embarrassing!
It helps if I put the 100nF capacitor in the right place in the circuit!! Doh! What an idiot!! -
• #5
:) Ahh, well that's good to hear anyway!
Were you running out of memory using Uint16Array from the example? That's quite a big array!
-
• #6
You can use a moving average with an interval of 8 or 16 samples .
I used the following code to get stable readings from a 10-bit encoder.
Using the dithered noise resolution is in fact improved to 1 1bits.setInterval(function() { enc_deg = sma16(degree(C1).toFixed(1)); // console.log("Encoder Angle[°] = "+enc_deg.toFixed(1)); }, 100 ); function degree( pin ) { var ratio = 4.0; var offset = 0.5; var factor = 0.73333333333; var phys = analogRead(pin) * 3.3; // *E.getAnalogVRef(); var meas = 360.0 * ( phys / factor - offset ) / ratio ; console.log("Input[V] = "+phys.toFixed(3)+" Angle[°] = "+meas.toFixed(1)); return meas; } // ------------------------------------ // simple parametric moving averager // ------------------------------------ function sma(period) { var nums = []; return function(num) { nums.push(num); if (nums.length > period) nums.splice(0,1); var sum = 0; var n = period; function sum_num (n) { sum+=Number(n); }; nums.forEach(sum_num); if (nums.length < period) n = nums.length; return(sum/n); } } var sma16 = sma(16);
Input[V] = 0.494 Angle[°] = 15.6 Next reading = 15.6, SMA = 15.6
Input[V] = 0.496 Angle[°] = 15.9 Next reading = 15.9, SMA = 15.7
Input[V] = 0.495 Angle[°] = 15.8 Next reading = 15.8, SMA = 15.8
Input[V] = 0.495 Angle[°] = 15.8 Next reading = 15.8, SMA = 15.8
Input[V] = 0.495 Angle[°] = 15.7 Next reading = 15.7, SMA = 15.7
Input[V] = 0.498 Angle[°] = 16.1 Next reading = 16.1, SMA = 15.8
Input[V] = 0.497 Angle[°] = 16.0 Next reading = 16.0, SMA = 15.8
Input[V] = 0.495 Angle[°] = 15.7 Next reading = 15.7, SMA = 15.8
Input[V] = 0.496 Angle[°] = 15.9 Next reading = 15.9, SMA = 15.8
Input[V] = 0.495 Angle[°] = 15.7 Next reading = 15.7, SMA = 15.8
Input[V] = 0.495 Angle[°] = 15.7 Next reading = 15.7, SMA = 15.8
Input[V] = 0.494 Angle[°] = 15.6 Next reading = 15.6, SMA = 15.8
Input[V] = 0.494 Angle[°] = 15.6 Next reading = 15.6, SMA = 15.8
Input[V] = 0.495 Angle[°] = 15.8 Next reading = 15.8, SMA = 15.8
Input[V] = 0.495 Angle[°] = 15.7
I have a thermistor connected to one of the ADC's but I am having quite a bit of trouble with noise.
As a test I have setup the circuit with another resistor in replacement of the thermistor bead but I cannot seem to get the readings to a stable state. I have in addition tried using a 100nF capacitor across the input which helps to some degree but not enough.
Ideally I would like to stabilise the temp to at least one decimal place.
I would assume some sort of software filter, any suggestions?