Arduino Uno + SHT15 Breakout - Read Values

I'm doing a project to measure the Dew Point with Arduino and i used the SHT15 Breakout.
It worked fine, and i can read the values with really good accuracy. I can release my the C++ code, if anyone here needs it.

Now i'm trying to create a "digital filter" in the read values, so if i get any noise that can compensate the error. My idea is to implement a read to array system on temperature and humidity values, that store the last 7 values of each, then i can organize the array incrementally, pick the 4th value and serial.print it (Basically, i'm calculating the Median). I've been trying to implement this but it's been really hard because i know almost nothing of programming. I've tried many ways, but i can't even store the read values in a array. Can anyone give me some tips or have any idea how can i do some similar stuff easier?

Thanks in advance

There is much to find on smoothing a signal. like http://arduino.cc/en/Tutorial/Smoothing
Smoothing 4 Temperature Probes - #5 by system - Project Guidance - Arduino Forum

Maybe show us your code and we can give you hints how to make your own smoothing routine.

Tiagofgb:
Now i'm trying to create a "digital filter" in the read values, so if i get any noise that can compensate the error. My idea is to implement a read to array system on temperature and humidity values, that store the last 7 values of each, then i can organize the array incrementally, pick the 4th value and serial.print it (Basically, i'm calculating the Median). I've been trying to implement this but it's been really hard because i know almost nothing of programming. I've tried many ways, but i can't even store the read values in a array.

Basically, you are looking to do an array sort. There are many examples of array sorts out on the web in various different programming languages...

Scratch all that. A quick google search on my part to find references for you, and I stumbled on this in the Arduino playground that seems to be EXACTLY what you are describing. See Arduino Playground - HomePage

FWIW, my google search phrase was "array sort arduino".

Hope this helps, and good luck with your project.

Really thanks for your help, at least i could understand some tips i was doint wrong, but did not solve my problem.
The main problem is that i can't even store a value in a array, and i don't know why. Another problem is that i don't know how to set the time of the clock.

I'm trying to create a For cicle, like "For i to 7" store the "temperature" values in a array, with a delay of 50ms in the cicle, so i can't store diferent values, but the vector stays [0,0,0,0,0,0,0,].
I'll put here my code without my "experiments" so you can see it. If you have any better idea i'll be really grateful to you!

int SHT_clockPin = 3;
int SHT_dataPin  = 2;

void setup(){
  Serial.begin(9600);
}

void loop(){
  float Temperature = getTemperature();
  float Humidity = getHumidity();
  float DewPoint = getDewPoint(Temperature, Humidity);

  Serial.print("Temperature = "); Serial.print(Temperature); Serial.print(" C");
  Serial.print(" | ");
  Serial.print("Relative Humidity = "); Serial.print(Humidity); Serial.print(" %");
  Serial.print(" | ");
  Serial.print("Dew Point = "); Serial.print(DewPoint); Serial.println(" C");
}

float getTemperature(){
  SHT_sendCommand(B00000011, SHT_dataPin, SHT_clockPin);
  SHT_waitForResult(SHT_dataPin);
  int val = SHT_getData(SHT_dataPin, SHT_clockPin);
  SHT_skipCrc(SHT_dataPin, SHT_clockPin);
  return (float)val * 0.01 - 40;
}

float getHumidity(){
  SHT_sendCommand(B00000101, SHT_dataPin, SHT_clockPin);
  SHT_waitForResult(SHT_dataPin);
  int val = SHT_getData(SHT_dataPin, SHT_clockPin);
  SHT_skipCrc(SHT_dataPin, SHT_clockPin);
  return -4.0 + 0.0405 * val + -0.0000028 * val * val; 
}

float getDewPoint(float Temperature, float Humidity){  
  // From: http://wahiduddin.net/calc/density_algorithms.htm
  
    double A0= 373.15/(273.15 + Temperature);
    double SUM = -7.90298 * (A0-1);
    SUM += 5.02808 * log10(A0);
    SUM += -1.3816e-7 * (pow(10, (11.344*(1-1/A0)))-1) ;
    SUM += 8.1328e-3 * (pow(10,(-3.49149*(A0-1)))-1) ;
    SUM += log10(1013.246);
    double VP = pow(10, SUM-3) * Humidity;
    double T = log(VP/0.61078);
    return (241.88 * T) / (17.558-T);
}

void SHT_sendCommand(int command, int dataPin, int clockPin){
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  digitalWrite(dataPin, HIGH);
  digitalWrite(clockPin, HIGH);
  digitalWrite(dataPin, LOW);
  digitalWrite(clockPin, LOW);
  digitalWrite(clockPin, HIGH);
  digitalWrite(dataPin, HIGH);
  digitalWrite(clockPin, LOW);

  shiftOut(dataPin, clockPin, MSBFIRST, command);
  digitalWrite(clockPin, HIGH);
  pinMode(dataPin, INPUT);

  if (digitalRead(dataPin)) Serial.println("ACK error 0");
  digitalWrite(clockPin, LOW);
  if (!digitalRead(dataPin)) Serial.println("ACK error 1");
}

void SHT_waitForResult(int dataPin){
  pinMode(dataPin, INPUT);

  int ack;

  for (int i = 0; i < 1000; ++i){
    delay(2);
    ack = digitalRead(dataPin);
    if (ack == LOW) break;
  }

  if (ack == HIGH) Serial.println("ACK error 2");
}

int SHT_getData(int dataPin, int clockPin){

  pinMode(dataPin, INPUT);
  pinMode(clockPin, OUTPUT);
  byte MSB = shiftIn(dataPin, clockPin, MSBFIRST);

  pinMode(dataPin, OUTPUT);
  digitalWrite(dataPin, HIGH);
  digitalWrite(dataPin, LOW);
  digitalWrite(clockPin, HIGH);
  digitalWrite(clockPin, LOW);

  pinMode(dataPin, INPUT);
  byte LSB = shiftIn(dataPin, clockPin, MSBFIRST);
  return ((MSB << 8) | LSB); //combine bits
}

void SHT_skipCrc(int dataPin, int clockPin){
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  digitalWrite(dataPin, HIGH);
  digitalWrite(clockPin, HIGH);
  digitalWrite(clockPin, LOW);
}

Silly me. I spent a good amount of time studying your code trying to find your use of arrays and read loops, etc. Only to finally notice that it is the code without the experiments. Gotta love selective reading. :wink:

Unless you really want to reinvent the wheel (looks like you have enough of that with having to bitbang the SHT protocol), I'd probably include the runningMedian library. Then create a new instance of the class for each variable you read. So, near the top of your code (before the setup function) I'd define two instances of the class like:

const byte binSize = 7; // change this to the bin size that you want to take the median of.
RunningMedian Temperatures = RunningMedian(binSize);
RunningMedian Humidities = RunningMedian(binSize);

During your setup function you probably want to pre-load the sample bins with something like this:

for (byte i = 0; i < binSize; i++) {
  Temperatures.add(getTemperature());
  Humidities.add(getHumidity());
}  // The first reading here will be thrown out with the first reading in the loop. Probably a good thing to throw out the first reading of an analog sensor after power-up...

Then replace the first three lines of your loop functions with:

Temperatures.add(getTemperature());
Humidities.add(getHumidity());
float DewPoint = getDewPoint(Temperatures.getMedian(), Humidities.getMedian());

Don't forget to change in the serial.print area how to access the classes like I showed for the getDewPoint function. The standard datatype for runningMedian is float, so you shouldn't have any datatype issues...

There is one quirk of this method is there will be a slight lag of up to the binSize number of readings behind reality. Another way is to skip the pre-load in the setup function and every time you take readings you take binSize number of readings. It's up to you to decide which is the least desirable effect, lag behind reality or extended reading times.

Now if you want to roll your own just to learn how to use arrays, remember the syntax is arrayName[index] where index starts with 0. So define the arrays like:

const byte binSize = 7; // change this to the bin size that you want to take the average or median of.
float Temperatures[binSize];
float Humidities[binSize];

And filling the arrays would be:

for (byte i = 0; i < binSize; i++) {
  Temperatures[i] = getTemperature();
  Humidities[i] = getHumidity();
}

But then you are on your own to average, find median, etc.

I tried to implement the code that you told me, but it didn't work.
Maybe there's some error in the code, i don't know.

int SHT_clockPin = 3;
int SHT_dataPin  = 2;
const byte binSize = 7;
RunningMedian Temperatures = RunningMedian(binSize);
RunningMedian Humidities = RunningMedian(binSize);

void setup(){
  Serial.begin(9600);
  for (byte i = 0; i < binSize; i++) {
  Temperatures.add(getTemperature());
  Humidities.add(getHumidity());}
}

void loop(){
 Temperatures.add(getTemperature());
 Humidities.add(getHumidity());
 float DewPoint = getDewPoint(Temperatures.getMedian(), Humidities.getMedian());

  Serial.print("Temperature = "); Serial.print(Temperatures); Serial.print(" C");
  Serial.print(" | ");
  Serial.print("Relative Humidity = "); Serial.print(Humidities); Serial.print(" %");
  Serial.print(" | ");
  Serial.print("Dew Point = "); Serial.print(DewPoint); Serial.println(" C");
}

float getTemperature(){
  SHT_sendCommand(B00000011, SHT_dataPin, SHT_clockPin);
  SHT_waitForResult(SHT_dataPin);
  int val = SHT_getData(SHT_dataPin, SHT_clockPin);
  SHT_skipCrc(SHT_dataPin, SHT_clockPin);
  return (float)val * 0.01 - 40;
}

float getHumidity(){
  SHT_sendCommand(B00000101, SHT_dataPin, SHT_clockPin);
  SHT_waitForResult(SHT_dataPin);
  int val = SHT_getData(SHT_dataPin, SHT_clockPin);
  SHT_skipCrc(SHT_dataPin, SHT_clockPin);
  return -4.0 + 0.0405 * val + -0.0000028 * val * val; 
}

float getDewPoint(float Temperature, float Humidity){  
  // From: http://wahiduddin.net/calc/density_algorithms.htm
  
    double A0= 373.15/(273.15 + Temperature);
    double SUM = -7.90298 * (A0-1);
    SUM += 5.02808 * log10(A0);
    SUM += -1.3816e-7 * (pow(10, (11.344*(1-1/A0)))-1) ;
    SUM += 8.1328e-3 * (pow(10,(-3.49149*(A0-1)))-1) ;
    SUM += log10(1013.246);
    double VP = pow(10, SUM-3) * Humidity;
    double T = log(VP/0.61078);
    return (241.88 * T) / (17.558-T);
}

void SHT_sendCommand(int command, int dataPin, int clockPin){
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  digitalWrite(dataPin, HIGH);
  digitalWrite(clockPin, HIGH);
  digitalWrite(dataPin, LOW);
  digitalWrite(clockPin, LOW);
  digitalWrite(clockPin, HIGH);
  digitalWrite(dataPin, HIGH);
  digitalWrite(clockPin, LOW);

  shiftOut(dataPin, clockPin, MSBFIRST, command);
  digitalWrite(clockPin, HIGH);
  pinMode(dataPin, INPUT);

  if (digitalRead(dataPin)) Serial.println("ACK error 0");
  digitalWrite(clockPin, LOW);
  if (!digitalRead(dataPin)) Serial.println("ACK error 1");
}

void SHT_waitForResult(int dataPin){
  pinMode(dataPin, INPUT);

  int ack;

  for (int i = 0; i < 1000; ++i){
    delay(2);
    ack = digitalRead(dataPin);
    if (ack == LOW) break;
  }

  if (ack == HIGH) Serial.println("ACK error 2");
}

int SHT_getData(int dataPin, int clockPin){

  pinMode(dataPin, INPUT);
  pinMode(clockPin, OUTPUT);
  byte MSB = shiftIn(dataPin, clockPin, MSBFIRST);

  pinMode(dataPin, OUTPUT);
  digitalWrite(dataPin, HIGH);
  digitalWrite(dataPin, LOW);
  digitalWrite(clockPin, HIGH);
  digitalWrite(clockPin, LOW);

  pinMode(dataPin, INPUT);
  byte LSB = shiftIn(dataPin, clockPin, MSBFIRST);
  return ((MSB << 8) | LSB); //combine bits
}

void SHT_skipCrc(int dataPin, int clockPin){
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  digitalWrite(dataPin, HIGH);
  digitalWrite(clockPin, HIGH);
  digitalWrite(clockPin, LOW);
}

I got the following error messages:
TesteMediana:4: error: 'RunningMedian' does not name a type
TesteMediana:5: error: 'RunningMedian' does not name a type
TesteMediana.ino: In function 'void setup()':
TesteMediana:10: error: 'Temperatures' was not declared in this scope
TesteMediana:11: error: 'Humidities' was not declared in this scope
TesteMediana.ino: In function 'void loop()':
TesteMediana:15: error: 'Temperatures' was not declared in this scope
TesteMediana:16: error: 'Humidities' was not declared in this scope

What i'm i doing wrong?

TesteMediana:4: error: 'RunningMedian' does not name a type

Why do you expect it to? You are missing a header file that defines RunningMedian as a type.

I'm tring to implement the code that Sembazuru told me to, but it didn't work.

I have the RunningMedian library, but i got that error. How do i solve it?

I have the RunningMedian library

You need to tell the compiler that. Personally, I don't care.

#include <RunningMedian.h>
int SHT_clockPin = 3;
int SHT_dataPin  = 2;
const byte binSize = 7;
RunningMedian Temperatures = RunningMedian(binSize);
RunningMedian Humidities = RunningMedian(binSize);

Yes, i forgot that!

Now i included this:

#include "Arduino.h"
#include "RunningMedian.h"

int SHT_clockPin = 3;
int SHT_dataPin  = 2;
const byte binSize = 7;
RunningMedian Temperatures = RunningMedian(binSize);
RunningMedian Humidities = RunningMedian(binSize);

And got a new type of error:

RunningMedian\RunningMedian.cpp.o: In function RunningMedian': C:\Documents and Settings\Proprietário\Ambiente de trabalho\arduino-1.0.4\libraries\RunningMedian/RunningMedian.cpp:17: multiple definition of RunningMedian::RunningMedian(unsigned char)'
RunningMedian.cpp.o:C:\DOCUME~1\PROPRI~1\DEFINI~1\Temp\build3281375458719230860.tmp/RunningMedian.cpp:17: first defined here
RunningMedian\RunningMedian.cpp.o: In function RunningMedian': C:\Documents and Settings\Proprietário\Ambiente de trabalho\arduino-1.0.4\libraries\RunningMedian/RunningMedian.cpp:17: multiple definition of RunningMedian::RunningMedian(unsigned char)'
RunningMedian.cpp.o:C:\DOCUME~1\PROPRI~1\DEFINI~1\Temp\build3281375458719230860.tmp/RunningMedian.cpp:17: first defined here
RunningMedian\RunningMedian.cpp.o: In function RunningMedian': C:\Documents and Settings\Proprietário\Ambiente de trabalho\arduino-1.0.4\libraries\RunningMedian/RunningMedian.cpp:23: multiple definition of RunningMedian::RunningMedian()'
RunningMedian.cpp.o:C:\DOCUME~1\PROPRI~1\DEFINI~1\Temp\build3281375458719230860.tmp/RunningMedian.cpp:23: first defined here
RunningMedian\RunningMedian.cpp.o: In function RunningMedian': C:\Documents and Settings\Proprietário\Ambiente de trabalho\arduino-1.0.4\libraries\RunningMedian/RunningMedian.cpp:23: multiple definition of RunningMedian::RunningMedian()'
RunningMedian.cpp.o:C:\DOCUME~1\PROPRI~1\DEFINI~1\Temp\build3281375458719230860.tmp/RunningMedian.cpp:23: first defined here
RunningMedian\RunningMedian.cpp.o: In function RunningMedian::clear()': C:\Documents and Settings\Proprietário\Ambiente de trabalho\arduino-1.0.4\libraries\RunningMedian/RunningMedian.cpp:30: multiple definition of RunningMedian::clear()'
RunningMedian.cpp.o:C:\DOCUME~1\PROPRI~1\DEFINI~1\Temp\build3281375458719230860.tmp/RunningMedian.cpp:30: first defined here
RunningMedian\RunningMedian.cpp.o: In function RunningMedian::add(float)': C:\Documents and Settings\Proprietário\Ambiente de trabalho\arduino-1.0.4\libraries\RunningMedian/RunningMedian.cpp:38: multiple definition of RunningMedian::add(float)'
RunningMedian.cpp.o:C:\DOCUME~1\PROPRI~1\DEFINI~1\Temp\build3281375458719230860.tmp/RunningMedian.cpp:38: first defined here
RunningMedian\RunningMedian.cpp.o: In function RunningMedian::getAverage()': C:\Documents and Settings\Proprietário\Ambiente de trabalho\arduino-1.0.4\libraries\RunningMedian/RunningMedian.cpp:75: multiple definition of RunningMedian::getAverage()'
RunningMedian.cpp.o:C:\DOCUME~1\PROPRI~1\DEFINI~1\Temp\build3281375458719230860.tmp/RunningMedian.cpp:75: first defined here
RunningMedian\RunningMedian.cpp.o: In function RunningMedian::sort()': C:\Documents and Settings\Proprietário\Ambiente de trabalho\arduino-1.0.4\libraries\RunningMedian/RunningMedian.cpp:87: multiple definition of RunningMedian::sort()'
RunningMedian.cpp.o:C:\DOCUME~1\PROPRI~1\DEFINI~1\Temp\build3281375458719230860.tmp/RunningMedian.cpp:87: first defined here
RunningMedian\RunningMedian.cpp.o: In function RunningMedian::getLowest()': C:\Documents and Settings\Proprietário\Ambiente de trabalho\arduino-1.0.4\libraries\RunningMedian/RunningMedian.cpp:66: multiple definition of RunningMedian::getLowest()'
RunningMedian.cpp.o:C:\DOCUME~1\PROPRI~1\DEFINI~1\Temp\build3281375458719230860.tmp/RunningMedian.cpp:66: first defined here
RunningMedian\RunningMedian.cpp.o: In function RunningMedian::getHighest()': C:\Documents and Settings\Proprietário\Ambiente de trabalho\arduino-1.0.4\libraries\RunningMedian/RunningMedian.cpp:56: multiple definition of RunningMedian::getHighest()'
RunningMedian.cpp.o:C:\DOCUME~1\PROPRI~1\DEFINI~1\Temp\build3281375458719230860.tmp/RunningMedian.cpp:56: first defined here
RunningMedian\RunningMedian.cpp.o: In function RunningMedian::getMedian()': C:\Documents and Settings\Proprietário\Ambiente de trabalho\arduino-1.0.4\libraries\RunningMedian/RunningMedian.cpp:45: multiple definition of RunningMedian::getMedian()'
RunningMedian.cpp.o:C:\DOCUME~1\PROPRI~1\DEFINI~1\Temp\build3281375458719230860.tmp/RunningMedian.cpp:45: first defined here

Do you know what is the problem?

Do you know what is the problem?

It looks like you have more than one copy of the RunningMedian library. Both are being compiled, resulting in multiple references.

The RunningMedian library is NOT a core library (yet), so it does not belong in:

C:\Documents and Settings\Proprietário\Ambiente de trabalho\arduino-1.0.4\libraries

I've done it and that worked! Thank you very much!
The program is finally working, but it still not very accurate. The read values are a little "instable".

I guess i'll try something else, like doing a simple bubble sort by myself.
Really thanks to all who helped me!