Summary
This document completely describes the humidity sensor: the motivation for creating it, its technical specifications and how it is being currently used.
Background
After spending time at home during the first 2020 lockdown in the UK (between March and August 2020), I developed the hobby of taking care of the garden and sowing flowers.
At some point, I realized the need of a sensor to indicate how dry the soil was.
I first came up with the idea of a simple sensor where an indicative LED would light up according to the condition of the soil, so I could see it from a distance, as my desk was at a straight line from the window that opens to the garden.
As the sensor would be very simple, I thought about making it with the simplest microcontroller I knew – the Attiny85 from ATMEL.
Sure as the product was being developed I came up with more ideas to improve it, such as adding wireless communications. I also bumped with problems, such as how I would provide power in order to make it portable.
Technical specifications
In this section I describe both the software and the hardware I used to create the sensor.
The hardware
The hardware has the following modules:
The power supply module
A coin battery Adafruit 20mm coin cell breakout with on-off switch was used as an input voltage.
A 3V lithium coin cell CR2032 is currently being used.
The Pololu S10V4F5 5V Step-up/step-down voltage regulator was used to convert 3V to 5V.
This switching regulator supplies a constant 5V at its output from an input of 3V from the coin battery.
The sensor
In the end there is the Seeed Studio Moisture sensor, which has the following specifications:
- Input supply voltage ranges between 3.3VDC and 5VDC
- Operating current is 35mA
- Soil moisture sensor based on soil resistivity measurement.
From the sensor’s description label,
“The Seeed studio single-channel, grove moisture sensor kit is a soil moisture detector that can judge if there is dampness around the sensor. This sensor has two probes that allow the current to pass through the soil and then obtain resistance values to measure soil moisture content. It can be easily installed by inserting the sensor into the soil and reading the output using ADC.”
The LEDs
Three 10mm LEDs were used to signal the state of the soil: one red, one green and one yellow, which have the following specifications:
- Forward current: 20mA
- Peak forward current: 30mA
- Reverse current at Vr = 5V: 10uA
- Power dissipation: 105mW
- Operation temperature: betweem 40 and 85 degrees Celsius
- Luminous intensity at If = 20mA: between 100 and 150 mcd
- 50% viewing angle at If = 20mA: between 40 and 60 degrees.
The microcontroller connections
The microcontroller used is the ATMEL Attiny85.
For the IO ports, we have:
PB0 → red LED → pin 5 (PB0 at the Attiny85)
PB1 → yellow LED → pin 6 (PB1 at the Attiny85)
PB2 → green LED → pin 7 (PB2 at the Attiny85)
PB4 → ADC → pin3 (PB4 at the Attiny85)
The pinage for the Attiny85 is depicted below:
The software
The software was written in bare metal C.
The Arduino IDE was used because the project was supposed to be very simple and use the tools I had availabe at the moment, without me taking time to search for a better IDE or setting other IDEs to do the same job.
The simplicity of the project is also why I chose to use polling instead of interrupts: Once the microcontroller is very simple and not too restrictive, and the task to be done is very limited, I thought polling would just do the job at the shortest time possible.
The code works the following way:
The ADC keeps doing polling to the sensor port.
If the value of the ADC is less than 301, that indicates that the soil is dry, so the red LED will toggle for 200ms.
If the ADC value lies between 302 and 402, that means the soil is still ok but it will soon be dry, requiring thus to be watered soon. The yellow LED will then toggle slower, at 400ms.
If the ADC value is between 403 and 702, the soil is humid and no further action from the gardiner is required. The green LED will be turned on indefinitely until the soil condition changes.
For values greater than 703, the yellow and red LEDs will flash, indicating that the soil is filled with water. But this condition is rare and almost never happens.
These values were taken from the sensor datasheet.
The code is written as follows:
#include <avr/io.h>
#include <util/delay.h>
void redLEDToggle(void);
void greenLEDON(void);
void yellowLEDToggle(void);
void greenLEDOFF(void);
void toggleRedAndYellow(void);
void initADC(void);
int main(void)
{
DDRB |= (1 << 0); //set PB0 as output -->red led
DDRB |= (1 << 1); //set PB1 as output --> yellow led
DDRB |= (1 << 2); //set PB2 as output --> green led
initADC();
uint8_t adc_lobyte; // to hold the low byte of the ADC register (ADCL)
uint16_t raw_adc;
uint16_t adcValue;
while (1)
{
ADCSRA |= (1 << ADSC); //start ADC measurement
while(ADCSRA & (1 << ADSC)); //wait until the conversion is completed - polling
// for 10-bit resolution:
adc_lobyte = ADCL; // get the sample value from ADCL
raw_adc = ADCH << 8 | adc_lobyte; // add lobyte and hibyte
// adcValue = (raw_adc * 1023)/5;
if((raw_adc > 0) && (raw_adc < 301)) //dry soil
{
greenLEDOFF();
redLEDToggle();
}
else if((raw_adc > 302) && (raw_adc < 402)) //attention!
{
greenLEDOFF();
yellowLEDToggle();
}
else if((raw_adc > 403) && (raw_adc < 702)) //humid soil
{
greenLEDON();
}
else if(raw_adc > 703) //sensor in water
{
greenLEDOFF();
toggleRedAndYellow();
}
}
}
void redLEDToggle() //PB0
{
PORTB |= 0x01;
_delay_ms(200);
PORTB &= ~0x01;
_delay_ms(200);
}
void greenLEDON() //PB2
{
PORTB |= 0x4;
}
void greenLEDOFF()
{
PORTB &= ~(0x4);
}
void yellowLEDToggle() //PB1
{
PORTB |= 0x02;
_delay_ms(400);
PORTB &= ~0x02;
_delay_ms(400);
}
void toggleRedAndYellow()
{
PORTB |= 0x01;
PORTB |= 0x02;
_delay_ms(200);
PORTB &= ~0x01;
PORTB &= ~0x02;
_delay_ms(200);
}
void initADC()
{
/* this function initialises the ADC
// 10-bit resolution
// set ADLAR to 0 to disable left-shifting the result (bits ADC9 + ADC8 are in ADC[H/L] and
// bits ADC7..ADC0 are in ADC[H/L])
// use uint16_t variable to read ADC (intead of ADCH or ADCL)
*/
ADMUX =
(0 << ADLAR) | // left shift result
// (0 << REFS2) | // Sets ref. voltage to Vcc, bit 2
(0 << REFS1) | // Sets ref. voltage to Vcc, bit 1
(0 << REFS0) | // Sets ref. voltage to Vcc, bit 0
(0 << MUX3) | // use ADC2 for input (PB4), MUX bit 3
(0 << MUX2) | // use ADC2 for input (PB4), MUX bit 2
(1 << MUX1) | // use ADC2 for input (PB4), MUX bit 1 (single ended input)
(0 << MUX0); // use ADC2 for input (PB4), MUX bit 0
ADCSRA =
(1 << ADEN) | // Enable ADC
(1 << ADPS2) | // set prescaler to 16, bit 2
(0 << ADPS1) | // set prescaler to 16, bit 1
(0 << ADPS0); // set prescaler to 16, bit 0
}
Usage
The sensor was built to be very simple and to have a +-20% accuracy.
A typical use of this sensor is to monitor the state of the soil in normal and rainy weather. It was observed that the sensor performed according to the specifications when used in such conditions.
The sensor was used in snow but performed poorly.
In normal conditions (either dry, during summer, and during autumn), the sensor has a satisfactory operation. It is helping me to monitor the health of my tomato plant, my flowers and my flowers pots that I keep indoors.
Videos
I uploaded a video in Youtube about this sensor and its usage. Please check