View previous topic :: View next topic |
Author |
Message |
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
DS18B20 Oversampling and Decimation?? |
Posted: Thu Dec 07, 2017 11:32 am |
|
|
Hi All,
I have a lot of DS18b20 temperature loggers deployed and over the last 2 years I've been playing with different Filter methods, averages, etc.
I'm up to a point where I can resolve down to the 0.0625°C as per the datasheet(at least i think so), with surprising stability, using a simple median filter: take 9 readings into a buffer, Sort, take the median.
Its the best method I've found with this sensor, with no "Averaging Delay".
The DS18B20 takes AGES to provide a reading... somewhere in the 500 to 700ms range.. i know.
My temperature curves look nice except for the 0.0625 steps, which I would like to eliminate as it looks and probably is quantization error of the Sensors ADC.
much like this: https://i.stack.imgur.com/AvOf6.png
I would like to gain a few bits more of resolution via oversampling and decimation of the readings but all I've read involves injecting triangular wave noise to get those LSB's flipping and I cant wrap my head around how to inject noise to a DS18B20.
At this point you ask: "But why?"... to which i answer: "For Science!" and basically a learning exercise.
I'm logging refrigerators with very slow cycles with less than 1°C peak to peak.
as an example this is 1 hour of data:
Code: |
12/7/2017 11:01 4.93
12/7/2017 11:03 5
12/7/2017 11:04 5
12/7/2017 11:06 5
12/7/2017 11:07 5
12/7/2017 11:09 5
12/7/2017 11:10 5
12/7/2017 11:12 5
12/7/2017 11:14 5
12/7/2017 11:15 5.06
12/7/2017 11:17 5.06
12/7/2017 11:18 5.06
12/7/2017 11:21 5.06
12/7/2017 11:23 5.06
12/7/2017 11:25 5.06
12/7/2017 11:26 5.06
12/7/2017 11:28 5.06
12/7/2017 11:29 5.06
12/7/2017 11:31 5.12
12/7/2017 11:32 5.12
12/7/2017 11:34 5.12
12/7/2017 11:36 5.12
12/7/2017 11:37 5.12
12/7/2017 11:39 5.12
12/7/2017 11:40 5.12
12/7/2017 11:42 5.18
12/7/2017 11:43 5.18
12/7/2017 11:45 5.18
12/7/2017 11:46 5.18
12/7/2017 11:48 5.18
12/7/2017 11:50 5.18
12/7/2017 11:51 5.18
12/7/2017 11:53 5.25
12/7/2017 11:54 5.25
12/7/2017 11:56 5.25
12/7/2017 11:57 5.25
12/7/2017 11:59 5.25
|
The 0.0625°C steps should be obvious on this data sample.
Any idea on how to improve this situation?
G. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9282 Location: Greensville,Ontario
|
|
Posted: Thu Dec 07, 2017 11:55 am |
|
|
hmm...
1 reading per second is 60 per minute, 3600 per hour so why not just sample 1 per second? I recall that'd give 12bit reading. The way I rememeber that is I read the sensor when the DS1307 gave an interrupt at 1Hz rate. |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Thu Dec 07, 2017 12:53 pm |
|
|
That would result in signal full of 0.0625C jitter....and averaging merely rounds off the steps. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19605
|
|
Posted: Thu Dec 07, 2017 1:21 pm |
|
|
There is a balancing act between how much you average, lag, and oversampling.
By not averaging, you don't have any oversampling.
To get oversampling and so smooth the steps, you have to average.
The more you average, the greater the lag.
I'd suggest using a combination of Olympic, and cumulative filters. This will give you lag, but also smooth the steps:
Code: |
//start with an integer reading in 0.0625 steps
float oversample(int16 value)
{
static int8 ctr=0;
static int16 sum-0;
static int16 max=0, min=4096;
static int32 over=0;
static int16 result;
static int1 have_sampled=FALSE;
static float final;
int16 temp;
if (have_sampled)
{
sum+=value;
if (value>max)
max=value;
if (value<min)
min=value;
ctr++;
if (ctr==3)
{
sum=sum-max;
sum=sum-min;
result=sum;
max=0;
min=4096;
sum=0;
ctr=0;
}
}
else
{
max=value; //start the average
min=value;
result=value;
ctr++;
over=(value*8);
final=over*0.0078125;
over-=value;
have_sampled=TRUE;
}
if (ctr==0)
{
over+=value; //rolling sum
final=over*0.0078125;
temp=over/8;
over-=temp;
}
return final;
}
|
This takes the centre value from each three readings, then sums the result into a rolling sum. This has the average removed each time. The return is a float in 0.0078125 steps.
In fact to get a genuine 3 extra bits you would have to oversample more, but you may be surprised at how this works.
Display it to only two decimals as you currently do.
Last edited by Ttelmah on Thu Dec 07, 2017 1:29 pm; edited 1 time in total |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1912
|
|
Posted: Thu Dec 07, 2017 1:21 pm |
|
|
http://www.atmel.com/images/doc8003.pdf
I used the technique in the app note to squeeze another 2 bits of resolution from a dsPIC's 12 bit A/D converter. You can do the same thing to increase your temperature resolution from its current 1/16th of a degree C to a 32nd or probably even a 64th.
The biggest issue is time, as you mentioned, since the temperature sensor is relatively slow to convert. To get a 32nd C resolution you'll need 4 samples, and to get 64th, you'll need 16 samples. |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Thu Dec 07, 2017 3:38 pm |
|
|
HA!
Newguy seems we are reading the same stuff... that is precisely what im trying to achieve.
My noodle is noodled because i have no control over the DS18B20 ADC raw bits so i dont know how to perform the Decimation procedure.
All the DS18B20 give me is the temperature converted to a Celsius value represented in binary which i doubt i can just add 4 samples and shift. even worse I convert my results to float which might not be so cool to shift either.
if i was using the ADC on the chip directly the solution in the document is clear.
how do i implement this App note using the temperature values only since i dont have the raw ADC values to add and shift?
G. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19605
|
|
Posted: Thu Dec 07, 2017 4:02 pm |
|
|
The raw value from the chip is a binary ADC reading. It is just 12bits, with each count representing 0.0625 degrees.
Look at what I posted. This expects to receive the raw value from the chip. It then rejects the high and low readings from each group of three (to get rid of noise), and averages these using a rolling average, giving a result that is 8* the reading.
Feed it with the raw reading, and try it. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9282 Location: Greensville,Ontario
|
|
Posted: Thu Dec 07, 2017 5:45 pm |
|
|
I had a glance at that Atmel info and you need 4x the samples for every extra bit. If you went '9 bit ' mode for the sensor, you'll need 12x the samples which overall is longer than just one 12bit sample.
Frankly 1 reading a second is overkill for most temperature controllers or alarms. I did remote energy control and sampling was once per 15 seconds,never had a complaint about 'too hot or too cold'.
If you want 'finer' readings you'll need another sensor,probably analog(thermister or pt) but that opens up a HUGE can of worms.I used LM34s (that was in 1985),well filtered to kill EMI. I didn't care if it was 70.1 or 70.15 as long as the customer was happy.
Going analog means being real careful of board layout, 'balance' between filter vs precise readings, glitch removal, ultra clean power and super stable references,yeesh..it can get ugly.....
jay |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Fri Dec 08, 2017 4:12 pm |
|
|
I want finer readings for prettier graphs... sounds stupid but i learned something this week due to this here topic.
For my loggers the 0.0625 is more than enough but one day i might meet "that one customer" and the lesson here might save me.
I have had another project in my head for a while that hit a mental technical wall... this topic made it possible again!
Ttelmah do i call your function in a loop? How many calls do i need before i can trust the reading... i havent yet fully understood how the function works.... i know what it does... just not how yet.
G. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Fri Dec 08, 2017 4:16 pm |
|
|
"have_sampled" is always false.... it becomes true in the first else but then the function exits?? What?
Im guessing the static declaration might be the trick here right? _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19605
|
|
Posted: Sat Dec 09, 2017 1:32 am |
|
|
The static means it will still have the last value, when the function is called the second time.
It is set 'FALSE' at the start, so the first time the routine is called it 'pre-loads' the sum used for the rolling average, otherwise it'll take several minutes for this to catch up. It is then set 'TRUE', so this part of the code is never called again.
Code: |
//If 'have_sampled' is FALSE
else
{
max=value; //start the average
min=value;
result=value;
ctr++;
over=(value*8); //pre-load the sum
final=over*0.0078125;
over-=value;
have_sampled=TRUE; //and set 'have_sampled'
}
|
The variables that are declared as static, _must_ be static. Otherwise the sum will be lost, and have_sampled will be reloaded etc.. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
Re: DS18B20 Oversampling and Decimation?? |
Posted: Sat Dec 09, 2017 12:18 pm |
|
|
Gabriel wrote: | Hi All,
I have a lot of DS18b20 temperature loggers deployed and over the last 2 years I've been playing with different Filter methods, averages, etc.
.
.
.
I would like to gain a few bits more of resolution via oversampling and decimation of the readings but all I've read involves injecting triangular wave noise to get those LSB's flipping and I cant wrap my head around how to inject noise to a DS18B20.
.
.
Any idea on how to improve this situation?
G. |
Maybe you could modulate the sensor temperature.
A Peltier module would enable deviation both up and down.
From a quick glance at the data sheets you should not need much power to modulate the temperature by a fraction of a degree.
The difficulty will be getting a long enough time constant.
That could involve a substantial heat absorber and thermal insulation.
My gut feeling is that the any improvement will go as the square root of the number of samples taken.
I.e. getting 4 times better resolution will require ~16 times more samples.
The whole thing will slow down.
Mike |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9282 Location: Greensville,Ontario
|
|
Posted: Sat Dec 09, 2017 12:55 pm |
|
|
Ok, I just got a dumb idea... seeing how these things are '1-wire'. Why not add say 3 more sensors then take the average of all 4.
or
Better yet, stagger the reading of the sensors by 1/4 second? 1st sensor on the second, 2nd, 1/4 sec later, 3rd 1/2 sec, later, 4th 3/4 sec later
If you do this, you effectively quadruple your 'reading rate' thus smoothing out the data.
If you have 3 extra pins left over, each sensor connects to its own 1-wire bus. You'll need to copy the driver 3x so it takes some code space BUT it saves the hassle of coding for 'looking for devices, ID's, checksums, etc.
Just thinking 'outside the box'...
Jay |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Sun Dec 10, 2017 3:47 am |
|
|
A second thought on the Peltier option.
Make the temperature go up and down quickly.
That way you'll get sort of random noise in the readings.
Just be careful to avoid locking between the readings and the noise.
Mike |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Sun Dec 10, 2017 11:40 am |
|
|
Hi All,
I will give Mr. Ttelmah's code a whirl and see how it goes, now that i actually understand the code flow.. (hard to test something i didn't quite get myself)
I will also, try writing my own oversampling and decimation code now that some of my doubts have been cleared here.
Temtronic: great minds think alike!
I've already have 3 loggers deployed with 3 sensors each.I however take 3 readings from each into a 9 space buffer, sort and take the median.
The results are similar as the single sensor, hitting that 0.0625 wall as well, but it "looks" cleaner but that's just cause the cooler has a faster compressor cycle.
This is an hour of that 3 sensor logger data:
Code: |
Time Temp Absolute diff
12/10/2017 11:00 5.12 0.06
12/10/2017 11:02 5.06 0.00
12/10/2017 11:04 5.06 0.06
12/10/2017 11:06 5.00 0.07
12/10/2017 11:07 4.93 0.12
12/10/2017 11:09 4.81 0.00
12/10/2017 11:11 4.81 0.06
12/10/2017 11:13 4.75 0.00
12/10/2017 11:14 4.75 0.07
12/10/2017 11:16 4.68 0.06
12/10/2017 11:18 4.62 0.06
12/10/2017 11:20 4.56 0.00
12/10/2017 11:21 4.56 0.06
12/10/2017 11:23 4.50 0.00
12/10/2017 11:25 4.50 0.07
12/10/2017 11:27 4.43 0.06
12/10/2017 11:28 4.37 0.00
12/10/2017 11:30 4.37 0.06
12/10/2017 11:32 4.31 0.06
12/10/2017 11:33 4.25 0.07
12/10/2017 11:35 4.18 0.07
12/10/2017 11:37 4.25 0.12
12/10/2017 11:39 4.37 0.13
12/10/2017 11:41 4.50 0.12
12/10/2017 11:42 4.62 0.13
12/10/2017 11:44 4.75 0.06
12/10/2017 11:46 4.81 0.12
12/10/2017 11:47 4.93 0.07
12/10/2017 11:49 5.00 0.06
12/10/2017 11:51 5.06 0.06
12/10/2017 11:53 5.12 0.06
12/10/2017 11:54 5.18 0.13
12/10/2017 11:56 5.31 0.06
12/10/2017 11:58 5.37
|
Maybe someone has a better idea on how use the 3 sensors in a more "efficient" way.
I must admit, i have had ABSOLUTELY NO ISSUES, with this configuration at over 200 feet of CAT5 unshielded in an industrial environment! (in 3 different locations, provinces, buildings and temperatures).
I did have issues with a single sensor though.
G. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
|