Pages: [1] 2   Go Down
Author Topic: Citrus Freeze Protection  (Read 1576 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,

I'm working to program an Arduino to control a solenoid irrigation valve to protect citrus trees from freezes.  In case your not familiar with agriculture, farmers spray water on crops in freezing temperature.  The water freezes on the plants, releasing latent heat that actually keeps the plant tissue above freezing (odd to think freezing water on a plant keeps it warm, huh?)

Currently, farmers turn sprinkler on at a predetermined temperature without regard to other important variables.  A lot of water (and I mean millions and millions of gallons) of water are wasted by turning on the sprinklers too early.  The wet-bulb temperature is the true indicator of when it is time to turn the sprinklers on. The wet-bulb temp is found using the normal dry-bulb temp and the relative humidity. The optimal time to turn the sprinklers on is when the wet-bulb temp is at or below the danger temp for the crop.

I have a DHT22 combination dry-bulb temp and relative humidity sensor.  This came with the programming to use the sensor and I need to add to it to calculate the wetbulb, display the wetbulb, and turn on the solenoid valve when the wetbulb is below the predetermined critical temp. (I'm turning on valve via relay or transistor).

This is my first taste of programming or using an arduino.  I read the first half of "Beginnning Arduino Programming", so don't think I came straight to you guys without trying it myself first.

The biggest snag I've hit is solving the equation for the wet-bulb as it requires iteration to solve. I also need help getting the humidity and temp from the sensor into the equation. Those 2 are what I would appreciate help with most of all. Plus anything else I'm missing in my code (lots certainly). I've attached the code given with the sensor and my current file so you can see what I have added.

Thanks!!

* freezeprotection.ino (2.01 KB - downloaded 11 times.)
* DHTtester.ino (1.26 KB - downloaded 9 times.)
Logged

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

They are small enough to paste directly:

freezeprotection.ino:

Code:
// Example testing sketch for various DHT humidity/temperature sensors
// Written by ladyada, public domain

const int critical = -3 //critcal plant freezing temp in degree C
const int relay = 5 //soleniod relay 
float wetbulb = 0

#include "DHT.h"

#define DHTPIN 2     // what pin we're connected to

// Uncomment whatever type you're using!
//#define DHTTYPE DHT11   // DHT 11
#define DHTTYPE DHT22   // DHT 22  (AM2302)
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

// Connect pin 1 (on the left) of the sensor to +5V
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor

DHT dht(DHTPIN, DHTTYPE);



void setup() {
  Serial.begin(9600);
  Serial.println("DHTxx test!");
 pinMode(relay, OUTPUT);
  dht.begin();
}

void loop() {
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  float t = dht.readTemperature();
 
   h*(2.71828^(15.22t/(269.3+t)))=1.404*(2.71828^(15.22*wetbulb)/(269.3+wetbulb))+.184*(t-wetbulb)*(.000038*wetbulb-1) //need to solve this iterative equation for wetbulb,
                                                                                                                        //t and h are temp and relative humidity from sensor
 
  if (wetbulb <= critical) {
  digitalWrite (relay, HIGH);   //wetbulb below critical trips relay

  // check if returns are valid, if they are NaN (not a number) then something went wrong!
  if (isnan(t) || isnan(h)) {
    Serial.println("Failed to read from DHT");
  } else {
    Serial.print("Humidity: ");
    Serial.print(h);
    Serial.print(" %\t");
    Serial.print("Temperature: ");
    Serial.print(t);
    Serial.println(" *C");
     
     Serial.print("Wetbulb");
     Serial.print(wetbulb);
     Serial.print("*C");
     Serial.print("Critical");
     Serial.print(critical);
     Serial.print(*C);
  }
}


DHTtester.ino:

Code:
// Example testing sketch for various DHT humidity/temperature sensors
// Written by ladyada, public domain

#include "DHT.h"

#define DHTPIN 2     // what pin we're connected to

// Uncomment whatever type you're using!
//#define DHTTYPE DHT11   // DHT 11
#define DHTTYPE DHT22   // DHT 22  (AM2302)
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

// Connect pin 1 (on the left) of the sensor to +5V
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor

DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(9600);
  Serial.println("DHTxx test!");
 
  dht.begin();
}

void loop() {
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  float t = dht.readTemperature();

  // check if returns are valid, if they are NaN (not a number) then something went wrong!
  if (isnan(t) || isnan(h)) {
    Serial.println("Failed to read from DHT");
  } else {
    Serial.print("Humidity: ");
    Serial.print(h);
    Serial.print(" %\t");
    Serial.print("Temperature: ");
    Serial.print(t);
    Serial.println(" *C");
  }
}
Logged


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

Apart from the syntax errors, this is the problem line, I gather:

Code:
//need to solve this iterative equation for wetbulb,
//t and h are temp and relative humidity from sensor

   h*(2.71828^(15.22t/(269.3+t)))=1.404*(2.71828^(15.22*wetbulb)/(269.3+wetbulb))+.184*(t-wetbulb)*(.000038*wetbulb-1)
Logged


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

This might help:

http://www.theweatherprediction.com/habyhints/170/

And this:

http://www.4wx.com/wxcalc/formulas/wetBulbTdFromRh.php
Logged


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

What might work for you is a simple look-up table. Say you have around 20 temperatures where a decision is critical (eg. -10C to +10C) and 40 humidity values. A simple X/Y table where you enter the temperature and humidity and look up the wet-bulb temperature could do it. You only need to store a byte per entry (basically whether or not to turn the watering on).

The table could be kept in program memory, so you'd have plenty of space.
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A lookup table would be great.  I didn't know that was an option.  It actually requires 2 tables because the solution to the equation requires iteration.  This means a value is found in one table and that value then put into another table to find the final value. The tables near the bottom of this page is what I would use http://biomet.ucdavis.edu/frostprotection/Principles%20of%20Frost%20Protection/FP005.html

In case you are unfamiliar with mathematical equations requiring iterative methods, they cannot be simply solved, but require a special methods. A lookup table would be a good way to avoid it.  But just incase, how would I use iterative methods to solve the equation?
Logged

Dallas, TX
Offline Offline
Sr. Member
****
Karma: 10
Posts: 318
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This paper describes a method of calculating wet-bulb temperature directly with an absolute error of about 0.25 degrees C, if you are interested. Note that the atan() function must be one that returns its value in radians and the one in AVR libc <math.h> does.

https://circle.ubc.ca/bitstream/handle/2429/39211/Stull_AMS_2011_JAMC-D-11-0143.pdf?sequence=1

I
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks! That equation completely circumvents my problem. The error associated with it is acceptable too, I'm sure my sensor is off many times as much.
Logged

Dallas, TX
Offline Offline
Sr. Member
****
Karma: 10
Posts: 318
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You're welcome! Good luck with your project. It sounds like a very worthwhile one. As a child, I helped my father put out the smudge pots and cover the citrus plants with wet burlap bags whenever a hard freeze was predicted so I understand why it would be nice to have an automated solution.
Logged

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

But just incase, how would I use iterative methods to solve the equation?

That's a very general question. The answer would be "with a loop". For example I have seen calculations that work out pi, or the square root of a number, by iterating until the solution arrived this time is either the same as last time, or close enough.
Logged


Dallas, TX
Offline Offline
Sr. Member
****
Karma: 10
Posts: 318
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

But just incase, how would I use iterative methods to solve the equation?

That's a very general question. The answer would be "with a loop". For example I have seen calculations that work out pi, or the square root of a number, by iterating until the solution arrived this time is either the same as last time, or close enough.

I didn't find the equations that needed to be solved iteratively in the article OP cited. Maybe they are hidden amongst all the tables and charts. I'm curious what they are, just because.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

rh*e^(15.22T/(269.3+T))=1.404*e^((15.22T_w)/(269.3+T_w ))+.184(T+T_w)(.000038T_w-1)
Rh= relative humidity from sensor
T = dry-bulb temp from sensor
Tw = wet-bulb temp (what is being solved for)

This is the "correct" way to calculate wet-bulb. The shortcut PapaG gave me will work though.


* wetbulb.png (2.19 KB, 435x59 - viewed 21 times.)
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, I think I've got it all together. This is all so new to me, but I like it and have already ordered my own UNO (can anyone recommend a kit with various components and jumpers?) .

 I do have some operand errors in my code I would appreciate some guidance in...


freezeprotection.cpp:42:76: error: invalid digit "9" in octal constant
freezeprotection.cpp: In function 'void loop()':
freezeprotection:38: error: invalid operands of types 'double' and 'double' to binary 'operator^'
freezeprotection:38: error: expected primary-expression before '.' token
freezeprotection:38: error: expected unqualified-id before '(' token
freezeprotection:38: error: invalid operands of types 'float' and 'int' to binary 'operator^'
freezeprotection:40: error: expected `;' before 'if'
freezeprotection:61: error: expected `}' at end of input


Code:
// Example testing sketch for various DHT humidity/temperature sensors
// Written by ladyada, public domain

const int critical = -3; //critcal plant freezing temp in degree C
const int relay = 5; //soleniod relay  
float wetbulb = 0;

#include "DHT.h"

#define DHTPIN 2     // what pin we're connected to

// Uncomment whatever type you're using!
//#define DHTTYPE DHT11   // DHT 11
#define DHTTYPE DHT22   // DHT 22  (AM2302)
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

// Connect pin 1 (on the left) of the sensor to +5V
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor

DHT dht(DHTPIN, DHTTYPE);



void setup() {
  Serial.begin(9600);
  Serial.println("DHTxx test!");
 pinMode(relay, OUTPUT);
  dht.begin();
}

void loop() {
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  
    wetbulb=(t*atan(.151977*(h+8.313659)^.5))+atan(t+h)-atan(h-1.676331)+.(00391838*(h^(2/3)))*atan(.023101*h)-4.686035

  if (wetbulb <= critical) {
  digitalWrite (relay, HIGH);   //wetbulb below critical trips relay

  // check if returns are valid, if they are NaN (not a number) then something went wrong!
  if (isnan(t) || isnan(h)) {
    Serial.println("Failed to read from DHT");
  } else {
    Serial.print("Humidity: ");
    Serial.print(h);
    Serial.print(" %\t");
    Serial.print("Temperature: ");
    Serial.print(t);
    Serial.println(" *C");
    
     Serial.print("Wetbulb");
     Serial.print(wetbulb);
     Serial.print("*C");
     Serial.print("Critical");
     Serial.print(critical);
     Serial.print("*C");
  }
}}
Logged

Dallas, TX
Offline Offline
Sr. Member
****
Karma: 10
Posts: 318
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

First clue: replace the "^" with pow(x,y). Look it up in the reference.
2nd clue: that 2/3 exponent should be 3/2.
Double check your equation.
« Last Edit: November 22, 2012, 07:30:55 pm by PapaG » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 634
Posts: 50243
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
00391838
When a literal constant starts with a 0, the compiler knows that the value is octal (base 8). No digit in an octal value can be greater than 7. Why are the leading 0s there?
« Last Edit: November 24, 2012, 03:18:56 am by Coding Badly » Logged

Pages: [1] 2   Go Up
Jump to: