Friday, February 24, 2012

ATtiny for your garden

Since I have a habit of being not home but still need my water gardened I was trying to find a way to do that. Ofcpourse there are the watering clocks like the Gardena or others that can be programmed to water the garden for a certain time ach day or each week and I have used thoes but the have two drawbacks:

They will water even if it is not necessary + I always feel a bit anxious to use those if I am away for a long time, just in case something goes wrong and the mains waterline will start spraying for days on end.

Therefore I decided to turn to a microcontroller. Ofcourse ‘Arduino’pops to mind but that seemed a bit like overkill for a simple task, but it seemed like a good idea to develop a system on the Arduino an then transfer it to an ATtiny45.

The idea was to let the Arduino measure moisture in my plantbed and then depending on a preset value for moisture or dryness, switch on a pump.

As the ATtiny has several pins that could be used as an output or input, I was thinking to find a use for the other pins a swell and I found the perfect solution. As the watering function will probably only be used in the summertime, after planting, I could use the device earlier alrady for heating up a propagator. yes I know there are heated propagators but I just could not find one in my local gardenshops.

First a bit of theory:

spanningsdelerIn this figure, the voltage Va is a function of the Voltage Vcc and the two resistors R1 and R2. The Current I flowing through R2 and R1 is Vcc/(R1+R2) and therefore the voltage over R1 and thus the voltage Va=I x R1.

If we subsitute I then the formula will be (Vcc/(R1+R2))xR1= Vcc*R1/(R1+R2)=Va.

With a Vcc of 5 V and both resistors being 10 k, the voltage Va therefore will be 2.5 V.

If R2 would be replaced by a variable resistor such as an NTC or a humidity sensor, the voltage over Va will vary dpending on the value of the temperature or the humidity and that voltage Va will subsequently be read by an analog port on the Attiny.

The temperature sensor

NTCThe temperature sensor is quite easy. a 10 k NTC will do the trick. It will come in the place of R2 so with a rising temperature the voltage on Va will rise as well.

The value of an NTC (e.g. 10k)  is usually given at an ambient temperature of 25 degrees Celsius. Therefore, at 25C the voltage on Va should be 1/2 Vcc.
Initially I had the intention to calculate the temperature with the Steinhart-Hart formula but as I only needed two temperatures, one to switch on the heating and one to switch off the heating in the propagator, it made more sense to just measure the Va at these specific temperature as this also takes into account a variation in the Vcc, in the resistor R1 and in the resistance of the leads to the NTC.
I wanted to keep the temperature between 21 and 26 degrees and you will find my values for that in the program. The values that you will need might be different. Mind that the Analogue ports will give you a reading between 0 and 1023. The Arduino can map this with the map command, but it is just as useful to divide by 4. The function that does this is the function ‘sample’. It will take the average of 5 readings and then divide that (‘map it’) by four.

The humidity sensor

Build-Your-Moisture-SensorThe humidity sensor is basically not more than 2 spikes driven into the ground. The citcuit is similar to that of the temperature reader, with the spikes taking the place of the NTC. In my experience, soil that is just sufficiently humid gives a resitence (with my humidity resistor) of  about 10 k. Also here if the soil dries out, the resistence of the sensor will increase and the voltage on the analogue port will rise. A specific dryness or wetness of the soil therefore corresponds with a certain value on the analogue port.
Construction
The construction of a humidity sensor is quite simple although there seem to be various ‘schools’ of thought. Some people willimbed their ‘spikes’ in plaster of paris to give a more even reading of moisture. Most people however will juet take two metal spikes that are inserted in the earth. There are however two things to remember: the spikes need to be attached to eachother, otherwise putting them in another position may cause the distance between the two spiks to cahnage and therefore also the resistance; the spikes need to be made of galvanized material will they stand any chance of surviving being in the soil. Galvanized nails are a popular material, but they ar ehard to solder. Th best way is to dile or sand the place where one wants to solder the wire. Wrap the wire around the spike and solder and then to top it off, pit some shrink wrap around it to ensure a good contact between the wire and the spike.

Metal spikes in the soil. especially if they have a DC current going through them, may corrode very quickly. In practice that has not bothered me that much, but there are some things that one could do to prevent corrosion: only put tension to the pins when the device is actually read. In that case the humidity sensor should not be connected to +Vcc but to digital pin 0 that can be switched on right before the reading and switched off  right after it. Another thing one can do –but in our example we are a pin short- is not to connect the pin and its pull down resistor to + V and earth, but to two digital output pinds that then will feed it with an AC current bij alternating the polarity of the two digital pins and only to read it when the proper pin is high.

The program

The program is fairly simple. First it starts with some descriptions and gives the lay-out for the Attiny. It then defines the pins and sets the variables.
It then reads the humidity sensor with the ‘sample’ function and stores the result in the variable ‘moist’. It compares the value for ‘moist’ with the value that is set for ‘irrigation’. If it is lower or equal to that value, it switches on the pump by setting the ‘pumpPin’ high.
If it is a level of 5 above that value, iyt switches the pump off.
This is done to avoid the pump switching on and off repeatedly and to make the soil wet enough. Depending on the flow of water in your particular set up, you may want to alter that value of ‘5’.
It then reads the temperature, again with the ‘sample’ function and stores the result in the variable ‘ntc’. It then sees if this value is less than ‘142’ (which is 21 degrees in my case)  and if so, it switches on the heating in my propagator. It then compares the value with ‘155’(which is 26 degrees in my case) and if so, switches off the heating.
as a heater I have used a 40 W lamp that is switched via a solidstate relais.

So just to summarize: I use this device in summer outside to water my plantbeds and in  early spring I use it inside to heat a propagator. The device therefore is never controlling both temperature and irrigation at the same time, but if you would use it in a greenhouse, ofcourse it could.
Although the irrigation could be done by switching an electric valve in the main waterline, I have opted to use an immersible pump in a large bucket with water. As immersible pumps should not run dry, I have used a reed switch with a magnet on a floating device to cut the power to the pump if the water level is too low.

Protection

protect

I am not going to point out that if you are switching a pump or a lamp that you have to be careful with the mains voltage that can kill you. If you have no knowledge of these things you should not attempt to fiddle with it. But there is something else I need to point out: If the lines of the of your sensors to your ATtiny are long, they may pick up spikes that could be too high for the ports on your microcontroller and you may want to consider a bit of protection. This can be obtained by adding a 1 k resistor and a 5v1 zener as is shown in the picture. Obviously if you use that you need to recalibrate the values that are read from the sensor. 

/* Garden  
February 2012 

Sensors:   
-NTC  aan analoog  pin1 
-Humidity spike aan analoog pin2   
*---------------------------------NTC-------------------------------
* Schematic:
*   [Ground] -- [10k-pad-resistor] -- | -- [NTC] --[Vcc] 

*                                     | 
*                                Analog Pin 3 
* 
*    Rntc=((Vcc * pad / Vpin1) - pad); 
*   =((1024 * pad / RawADC) - pad); 
*  
*-------------------------------Humid------------------------------ 

* Schematic: 
*   [Ground] -- [10k-pad-resistor] -- | -- [Spikes] --[Vcc] 
*                                     | 
*                                Analog Pin 2 
*  
Als de humidity sensor te droog wordt, stijgt de weerstand en
daarmee daalt de spanning op de analoge poort. Inschakelen relais
om te sproeien De sensor is ca 10 kOhm als de grond vochtig genoeg
is. De reading van de analoge poort moet dus op ca 512 komen (met 
een pull down weerstand van 10 k) 
* Als de temperatuur daalt, stijgt de weerstand van de NTC en 
daarmee daalt de spanning op de analoge poort ->Inschakelen relais 
om te verwarmen de weerstand moet zich tussen 12,5 en 10 kOhm 
bewegen (ca 21-23 graden) de reading van de analoge poort moet dus 
tussen de 512 en 455 gehouden worden. Dwz inschakelen relais bij 
455 en uitschakelen bij 512  (als niet wordt gemapt)

ATTiny pins   
Physical  Analoog  Digital     
1           0          5   Reset, PinChange Interrupt 
2           3          3   INT0,3 
3           2          4   INT0,4 
4           Ground 
5                      0   INT0,0 
6                      1   INT0,1 
7           1          2   INT0,2 
8           Vcc 
*/ 
//Pin definities 
int ntcPin= 3;   //analogue Pin3  ->Physical pin2  NTC 
int humidPin=2;   //analogue Pin2  ->Physical pin3  Humidity spike
int pumpPin =2;  //digital  Pin2  ->Physical pin7  Bevloeiingspomp 
int warmPin=1;   //digital  Pin1  ->Physical Pin6  Verwarming 
int signalPin=0;  //Digital  Pin0  ->Physical Pin5  Extra 

// Variabelen setting 
int moist=0;      // maybe float is not necessary  
int ntc=0;       // maybe float is not necessary 
int ldr=0;        // maybe float is not necessary   
int irrigate=512; // level for irrigation ca 126 after mapping 

//The following function, "setup", must always be present 
void setup()  
{
//Serial.begin(9600);// for debugging only, remove for Attiny 
pinMode(ntcPin,INPUT);// meet temperatuur 
pinMode(humidPin,INPUT);// meet vochtigheid 
pinMode(signalPin,OUTPUT); //Signaallamp oid 
pinMode(warmPin,OUTPUT);//  Output for heating element 
pinMode(pumpPin,OUTPUT);//  Output for Relais/waterpump  
digitalWrite(pumpPin, LOW); 
digitalWrite(warmPin, LOW);
}

void loop() //This function must always be present 
{ 
/* First we read the Humidity sensor. If the sensor is >10 k this
is considered dry 
As the sensor is in a voltage divider of 10k the value read
then will be 1/2 Vcc 
In analogue value this will be about 1/2 *1024=512 
and after mapping it will be 127 

So if the value read ('moist') is smaller than what is
considered dry ('irrigate'), the pump should be switched on 
for a specific time. 
This is done by indicating a higher treshhold for switching 
the pump off 

*/

moist=sample(humidPin);  //read humiditySensor De functie leest 5x en neemt het gemiddelde 
// Serial.print("Value Read: "); 
// Serial.println(moist);   
if (moist <= irrigate) digitalWrite(pumpPin, HIGH); 
if (moist >= irrigate+5) digitalWrite(pumpPin, LOW); 

/* Now read the temperature sensor. 
If  the sensor is 10 k this is considered 26 degrees, 
the analogue reading will be 512 and 128 after mapping 
at a higher value the heating should be switched off 

If the sensor is 12k5 this is considered 21 degrees, 
the analogue reading will be 455 and 113 after mapping this 
is the lower treshhold and the heating should be switched on 

In real life however the values 142 and 155 correponded 
better with those temperatures 
*/ 

ntc=sample(ntcPin); 
// Serial.println(ntc);   
  if (ntc <= 142) digitalWrite(warmPin, HIGH); 
  if (ntc >= 155) digitalWrite(warmPin, LOW);
} //end loop 

// Sample Function
int sample(int z)   
/* This function will read the Pin 'z' 5 times and take an average.
Afterwards it will be mapped by dividing by 4 
*/ 

{
int i; int sval = 0;
for (i = 0; i < 5; i++){   sval = sval + analogRead(z);    // sensor on analog pin 'z'  
}
sval = sval / 5;    // average 
sval = sval / 4;    // scale to 8 bits (0 - 255) 
//sval = 255 - sval;  // invert output  
return sval;
}


Getting the code in the ATtiny

Now this may all be very well, but how to get the program in the ATtiny, as it has no bootloader? Well, there are several ways. One can use the Arduino IDE to generate the hexfile and then program that with either a parallelport programmer or a USBtiny programmer, or if one has an Arduino, the Arduino can be used as a programmer. Several websites have described this and I will refer to the procedure as explained by John Boxal in his blog.

In principle the method is as follows.
  • Connect the 6 pins between the Arduino and the ATtiny that make up the official in line programming header.
  • Add a specific ATtiny board file to yr IDE.
  • Load the Arduino with the ‘ArduinoISP’ sketch.
  • Then choose ‘ATtiny 85 (w/ Arduino as ISP)’ as your board.
  • Load the ‘Garden’ sketch and upload as usual.

Do I really need a microcontroller for this

Some people may wonder if perhaps even using an ATtiny for this is overkill? Well, ofcourse it is because what you are basically doing here is comparing two values. The value for a measured temperature (or humidity) with a set value and there are devices that have been used for doing exactly that for years already: Opamps, like the trusty 741 

opamp

Obviously with this design it is harder to set a low and a high level (one can use two opamps for that) but that means it will keep the temperature (or humidity)  at a narrower level.

For other possible op amp solutions see here and here

No comments:

Post a Comment