Pages: [1]   Go Down
Author Topic: TMP36 Sensor - smooth out readings  (Read 2000 times)
0 Members and 1 Guest are viewing this topic.
Boston
Offline Offline
God Member
*****
Karma: 3
Posts: 575
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
I have a tmp36 sensor with one lead going to ground, one to +5V and one to pin 0.
I am currently taking 10 readings from the sensor.http://www.adafruit.com/products/165

I then use an insertion sort to sort the values in order from low to high, then I drop the highest and lowest values and divide by 8 to get an average. 

This works ok, but my readings are still spikey.
For example, it will go from 52 fahrenheit down to 48 fahrenheit then back up to 55 fahrenheit, all within 2 minutes. 
Any way to smooth out the readings or make them less jumpy?

Thanks.

Thanks.
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 473
Posts: 18695
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Difficult to debug your code, without seeing it.
Logged

Boston
Offline Offline
God Member
*****
Karma: 3
Posts: 575
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Keep in mind this is a work in progress and the calcRain() function is not finished.
Eventually I will remove most or all of the print statements.

Code:
/*
 * A sketch that uses WiServer to send weather data to Cosm.com (Pachube)
 * sprintf() cannot handle floats
 * dtostrf() assistance from Jon at http://dereenigne.org/electronics/arduino/arduino-float-to-string#comment-3831
 * 17 - added insertion sort
 */

#include <WiServer.h>
char * email;
float sensor1;
int sensor2;
int sensor3;
int sensor4;
int r;
int t;
int a[10];
int results;

// Wireless configuration parameters ----------------------------------------
unsigned char local_ip[]    = {
  192,168,1,2};   // IP address of WiShield
unsigned char gateway_ip[]  = {
  192,168,1,1};   // router or gateway IP address
unsigned char subnet_mask[] = {
  255,255,255,0}; // subnet mask for the local network
char ssid[]                 = {
  "MyNetwork"};   // max 32 bytes
unsigned char security_type = 0;               // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2

//IP Address for Cosm.com
uint8 ip[] = {
  216,52,233,121};
char hostName[] = "api.cosm.com\nX-PachubeApiKey: "your pachube key here"\nConnection: close";
//char url[] = "/api/58529.csv?_method=put";
char url[] = "/v1/feeds/58529.csv?_method=put";

POSTrequest postPachube(ip, 80, hostName, url, feedData);

const prog_char security_passphrase[] PROGMEM = {
  "12345678"}; // max 64 characters

// WEP 128-bit keys
prog_uchar wep_keys[] PROGMEM = {
  0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, // Key 0
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 1
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 2
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Key 3
};

// setup the wireless mode; infrastructure - connect to AP; adhoc - connect to another WiFi device
#define WIRELESS_MODE_INFRA 1
#define WIRELESS_MODE_ADHOC 2
unsigned char wireless_mode = WIRELESS_MODE_INFRA;
unsigned char ssid_len;
unsigned char security_passphrase_len;

void printData(char* data, int len) {

  // Print the data returned by the server
  while (len-- > 0) {
    Serial.print(*(data++));
  }
}
#define PIN_TEMP 0
#define PIN_ANEMOMETER  3
#define PIN_RAINFALL 2
#define PIN_VANE        5   
#define NUMDIRS 8
unsigned long   adc[NUMDIRS] = {
  26, 45, 77, 118, 161, 196, 220, 256};

volatile int numRevsAnemometer = 0;
volatile int numBucketTips = 0;

//  Modify 'dirOffset
// to which direction is 'away' (it's West here).
//char *strVals[NUMDIRS] = {
//"W","NW","N","SW","NE","S","SE","E"};
int windDir[NUMDIRS] = {
  1,2,3,4,5,6,7,8};
byte dirOffset=-1;
#define MSECS_CALC_WIND_SPEED 30000
void setup() {

  WiServer.init(NULL);
  pinMode(PIN_RAINFALL, INPUT);
  digitalWrite(PIN_RAINFALL, HIGH);
  pinMode(PIN_ANEMOMETER, INPUT);
  digitalWrite(PIN_ANEMOMETER, HIGH);

  attachInterrupt(0, countBucketTips, CHANGE);
  attachInterrupt(1, countAnemometer, FALLING);

  Serial.begin(57600);
  Serial.println(F("Starting up..."));
  WiServer.enableVerboseMode(true);
}


long updateTime = 0;

void loop(){

  if (millis() >= updateTime) {
    Serial.println(F("Calculating weather..."));
    calcRain();
    calcWindSpeed();
    calcWindDir();
    calcTemp();
    postPachube.submit();   
    // Get another update one 30 sec from now
    updateTime += 1000 * 30;
  }
  // Run WiServer
  WiServer.server_task();
  delay(10);
}

void feedData()
{
  static char sprintfbuffer[15];
  static char dtostrfbuffer[6];
  static char mergedbuffer[15];

  dtostrf(sensor1,5, 2, dtostrfbuffer);
  sprintf(sprintfbuffer, "%d,%d,%d", sensor2, sensor3, sensor4);

  memcpy(mergedbuffer, dtostrfbuffer, 5);
  *(mergedbuffer+5) = ',';
  memcpy(mergedbuffer+6, sprintfbuffer, 10);

  WiServer.print(mergedbuffer);
}
void calcWindDir() {
  int val;
  byte x, reading;
  val = analogRead(PIN_VANE);
  val >>=2;                        // Shift to 255 range
  reading = val;
  // Look the reading up in directions table. Find the first value
  // that's >= to what we got.
  for (x=0; x<NUMDIRS; x++) {
    if (adc[x] >= reading)
      break;
  }
  x = (x + dirOffset) % 8;   // Adjust for orientation
  Serial.print(F("Sensor 3 (vane dir) =  "));
  Serial.println(windDir[x]);
  sensor3= windDir[x];
}

void calcWindSpeed() {
  int s, iSpeed;
  // This will produce mph * 10
  // (didn't calc right when done as one statement)
  long speed = 14920;
  speed *= numRevsAnemometer;
  speed /= MSECS_CALC_WIND_SPEED;
  iSpeed = speed;         
  numRevsAnemometer = 0;
  s = iSpeed / 10;
  sensor2 = s;
  Serial.print(F("Sensor 2 (wind speed) = "));
  s = iSpeed % 10;
  if (s>=.5){
    sensor2 = sensor2 +1;
  }
  Serial.print(sensor2);
  Serial.print(F(" round up # ="));
  Serial.println(s);
}

void calcRain() {
  r = r+ numBucketTips;
  numBucketTips=0;
  int rain =r*.011;
  t++;
  // 30 sec *120  = 1 hour
  Serial.print(F("Sensor 1 Rain =  "));
  Serial.print(rain);
  Serial.println(F(" inches per hour"));
  sensor1=rain;

  if (t>=120)
  {
    t=0;
    r=0;
    rain=0;
  }

}

void calcTemp()                   
{
  float reading;

  for (int i=0; i <= 9; i++){
    reading=analogRead(PIN_TEMP);
    a[i]=reading;
  }
  insertionSort(a,10);

  reading=results;
  results=0;
  float voltage = reading * 5.0;
  voltage /= 1024.0;
  float temperatureC = (voltage - 0.5) * 100 ;
  int temperatureF = (temperatureC * 9.0 / 5.0) + 32.0;
  Serial.print("Sensor 4 ");
  Serial.print(temperatureF);
  Serial.println(" degrees F");
  sensor4 = temperatureF;
}

void countAnemometer() {
  numRevsAnemometer++;
}
void countBucketTips() {
  numBucketTips++;
}
void insertionSort(int arr[], int length) {
  int i;
  int j;
  int tmp;
  for (i = 1; i < length; i++) {
    j = i;
    while (j > 0 && arr[j - 1] > arr[j]) {
      tmp = arr[j];
      arr[j] = arr[j - 1];
      arr[j - 1] = tmp;
      j--;
    }
  }
  // array sorted, now lose low and high values for better average

  a[0]=0;
  a[9]=0;

  for (i = 1; i < 9; i++){
    results= results+a[i];
    Serial.print(a[i]);
    Serial.print(" + ");
  }
  Serial.print(" =   ");
  Serial.println(results);
  results/=8; // divide by 8 as places 0 and 9 = 0
  Serial.print(F("Average = "));
  Serial.println(results);
}
Logged

UK
Offline Offline
Shannon Member
****
Karma: 222
Posts: 12520
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I suggest you write a sketch that does nothing apart from measure the temperature, to reduce the problem to the minimum.

How is the board powered? What is the board supplying power to? Is there anything going on which might cause the regulated voltage to fluctuate? If the reference voltage is dipping, that would cause the returned analog values to fluctuate.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Boston
Offline Offline
God Member
*****
Karma: 3
Posts: 575
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Good suggestion.  I'll try doing just a temperature sketch.
It is currently powered by a 9V wall plug, 
Also attached are the WiShield, an anemometer and a weather vane. I also plan to add a tipping bucket style rain sensor.
Logged

Offline Offline
Edison Member
*
Karma: 8
Posts: 1341
If you're not living on the Edge, you're taking up too much space!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

My results were much more consistent with the same sensor.  Usually within 1 deg when there are no external changes.  Still averaging over time will help.  Taking 10 reading quickly does not seem to for me.
Logged

If you fall... I'll be there for you!
-Floor

Skype Brighteyes3333
(262) 696-9619

Pages: [1]   Go Up
Jump to: