Go Down

Topic: Temperature average (digital) (Read 7345 times) previous topic - next topic

MichaelW1998

Hi there,

So I'm trying to get the average temperature, I already tried the 'Smoothing' tutorial with digitalRead instead of analogRead, but it only prints '0' and '1', not the average temperatures haha.

This currently is my code:
Code: [Select]
#include <OneWire.h>
#include <DallasTemperature.h>
 
// Data wire is plugged into pin 2 on the Arduino
#define ONE_WIRE_BUS 2
 
// Setup a oneWire instance to communicate with any OneWire devices
// (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
 
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
const int numReadings = 10;

int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average

void setup() {
  // start serial port
  Serial.begin(9600);
  Serial.println("Temperatuur sensor by MAIĀ©: 1min");

  // Start up the library
  sensors.begin();
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}

void loop() {
   // subtract the last reading:
  total = total - readings[readIndex];
  // read from the sensor:
  readings[readIndex] = digitalRead(2);
  // add the reading to the total:
  total = total + readings[readIndex];
  // advance to the next position in the array:
  readIndex = readIndex + 1;

  // if we're at the end of the array...
  if (readIndex >= numReadings) {
    // ...wrap around to the beginning:
    readIndex = 0;
  }

  // calculate the average:
  average = total / numReadings;
  // send it to the computer as ASCII digits
  Serial.println(average);
  delay(1000);        // delay in between reads for stability
}


Currently only working with seconds (delay of 1000), but at the end I'll calculate the average of 15 minutes (where the sensor measures every 1 mintute).

Thanks!

el_supremo

#1
Dec 03, 2016, 08:43 pm Last Edit: Dec 03, 2016, 08:43 pm by el_supremo
Quote
but it only prints '0' and '1'
That's not surprising.
Code: [Select]
  // read from the sensor:
  readings[readIndex] = digitalRead(2);

You aren't reading the temperature from the sensor. You are reading the state of the digital pin to which the sensor is connected - not the same thing at all.
There are any number of examples on this forum of how to read the temperature using the Dallas Temperature library. Search.

Just to clarify. Are you using a DS18B20 or other sensor that the Dallas library is designed to work with?

Pete
Don't send me technical questions via Private Message.

krupski

#2
Dec 03, 2016, 09:01 pm Last Edit: Dec 03, 2016, 09:04 pm by Krupski
Hi there,

So I'm trying to get the average temperature, I already tried the 'Smoothing' tutorial with digitalRead instead of analogRead, but it only prints '0' and '1', not the average temperatures haha.
First of all, you are reading your temperature sensor wrong. A simply digitalRead of a pin will only give you a LOW or HIGH (that is, only a 0 or a 1).

For averaging, try this:

Code: [Select]
// these are OUTSIDE the functions to be public accessable
double accumulator = 0.0;
uint32_t readings = 0;

double collect_data (double value)
{
    accumulator += value; // add to accumulator
    readings++; // increment count
    return (accumulator / readings); // return current average
}


This will accept any number of readings (up to 4 billion!) and return the average whenever you want it.

You can even read the CURRENT average, then let it keep running and read ANOTHER average LATER.

Hope this helps.
Gentlemen may prefer Blondes, but Real Men prefer Redheads!

MichaelW1998

First of all, you are reading your temperature sensor wrong. A simply digitalRead of a pin will only give you a LOW or HIGH (that is, only a 0 or a 1).

For averaging, try this:

Code: [Select]
// these are OUTSIDE the functions to be public accessable
double accumulator = 0.0;
uint32_t readings = 0;

double collect_data (double value)
{
    accumulator += value; // add to accumulator
    readings++; // increment count
    return (accumulator / readings); // return current average
}


This will accept any number of readings (up to 4 billion!) and return the average whenever you want it.

You can even read the CURRENT average, then let it keep running and read ANOTHER average LATER.

Hope this helps.

So, I add the double accumulator and uint32_t above my void setup, and the double collect_data below my loop. So, what should I put in my loop to do this?
I'm sorry, little bit noob with Arduino coding haha.

BTW, my sensor is a Dallas DS18B20. So as seen in my original code, I can print the temperature with:
Code: [Select]
Serial.print(sensors.getTempCByIndex(0)); //

Thanks!

gfvalvo

#4
Dec 04, 2016, 12:59 am Last Edit: Dec 04, 2016, 02:56 am by gfvalvo
BTW, my sensor is a Dallas DS18B20. So as seen in my original code, I can print the temperature with:
Code: [Select]
Serial.print(sensors.getTempCByIndex(0)); //
Yes, that's how you would get (and print) the temperature value (in degC) from the DS18B20. But, that's not what you're doing in the original code that you posted. As pointed out by @el_supremo, you're simply reading a DIGITAL value from DIGITAL PIN 2. The only possible results are 1 or 0. I'd concentrate on getting the right temperature reading first before worrying about averaging.
No technical questions via PM. They will be ignored. Post your questions in the forum so that all may learn.

MichaelW1998

Yes, that's how you would get (and print) the temperature value (in degC) from the DS18B20. But, that's not what you're doing in the original code that you posted. As pointed out by @el_supremo, you're simply reading a DIGITAL value from DIGITAL PIN 2. The only possible results are 1 or 0. I'd concentrate on getting the right temperature reading first before worrying about averaging.
Yes I got it to print and show the temperature reading. I even got it to print 2 readings with 2 sensors, on the same pin (with one_wire).
But I still have the same question:

So, I add the double accumulator and uint32_t above my void setup, and the double collect_data below my loop. So, what should I put in my loop to do this?

MarkT

#6
Dec 05, 2016, 12:13 am Last Edit: Dec 05, 2016, 12:14 am by MarkT
Averaging an array of readings has the disadvantage of using up RAM for the array, and having to
sum all the values everytime (though there are tricks to finesse that).

There's a much simpler way to low-pass filter an incoming value by using a simple
digital filter with a single value as state.

Code: [Select]

float average ;
#define k 0.1  // the filter coefficient, 0.1 means a scale of 10 samples, 0.01 would be 100 samples

void loop ()
{
  float reading = ???? ; // whatever code reads the current value
  average += k * (reading - average) ;  // simple 1st order digital low pass filter
  delay (10) ;    // sample rate set by a delay
}


If you want to average N values everytime you read the sensor, there's no need
to store them:
Code: [Select]

float take_averaged_reading ()
{
  float sum = 0.0 ;
  for (byte i = 0 ; i < N ; i++)
    sum += ???? ; // whatever code reads the sensor
  return sum / N ;
}
[ I DO NOT respond to personal messages, I WILL delete them unread, use the forum please ]

Lassska

#7
Feb 19, 2020, 02:44 am Last Edit: Feb 19, 2020, 03:33 am by Lassska
After 10 reads - very stable median values for DS18B20 with  ESP8266 Web Server
Data wire is connected to GPIO 2
Show one decimal in the web server (see attach)
EXAMPLE:  // tempC+/-x.xx calibration value =+0.50 celsius
               // tempF+/-x.xx calibration value =+0,82 fahrenheit

04:14:49.453 ->
04:14:49.487 -> Connecting to WiFi
04:14:49.977 -> ..
04:14:50.485 -> 192.168.0.106
04:14:51.241 -> Temperature Celsius: 20.79
04:14:51.309 -> Temperature Fahrenheit: 69.46
04:14:51.377 -> Temperature Celsius: 20.78
04:14:51.445 -> Temperature Fahrenheit: 69.45
04:14:51.648 -> Temperature Celsius: 20.77
04:14:51.716 -> Temperature Fahrenheit: 69.44
04:15:02.128 -> Temperature Celsius: 20.77
04:15:02.162 -> Temperature Fahrenheit: 69.43
04:15:12.127 -> Temperature Celsius: 20.76
04:15:12.161 -> Temperature Fahrenheit: 69.42
04:15:14.099 -> Temperature Celsius: 20.76
04:15:14.133 -> Temperature Fahrenheit: 69.41
04:15:19.505 -> Temperature Celsius: 20.74
04:15:19.539 -> Temperature Fahrenheit: 69.41
04:15:24.972 -> Temperature Celsius: 20.74
04:15:25.006 -> Temperature Fahrenheit: 69.40
04:15:35.167 -> Temperature Celsius: 20.73
04:15:35.201 -> Temperature Fahrenheit: 69.40
04:15:41.778 -> Temperature Celsius: 20.73
04:15:41.812 -> Temperature Fahrenheit: 69.36
04:15:52.029 -> Temperature Celsius: 20.74
04:15:52.064 -> Temperature Fahrenheit: 69.36
04:15:54.678 -> Temperature Celsius: 20.74
04:15:54.745 -> Temperature Fahrenheit: 69.36
04:16:04.870 -> Temperature Celsius: 20.73
04:16:04.904 -> Temperature Fahrenheit: 69.37
04:16:14.859 -> Temperature Celsius: 20.73
04:16:14.927 -> Temperature Fahrenheit: 69.35
04:16:24.869 -> Temperature Celsius: 20.73

Go Up