THE SELF-LEARNING WATERING SYSTEM
Smart Gardener
REST Server API
The SmartGardener Core provides some of its functionalities to
other applications and services by means of a REST Server. This allows easy
extension and integration with other services and software. Data can be
obtained from the core and commands as well can be sent to it.
In
development mode (which can be enabled using the options in the Settings
module) additional commands and data are available. Development features are
those underlined and red in the list below.
All
commands are currently implemented as GET requests.
In order to
use the REST server the Core must be running on the Controller, which, in turn,
needs to be connected to a Local Area Network.
Command
|
Description
|
/system
|
Returns a JSON formatted dictionary
containing the following keys:
- Version:
a string which indicates which version of the Core is currently running on
the controller;
- Build
: a string which indicates which build of the Core is currently running on
the controller;
- Boards
Connected : an integer corresponding to the number of boards detected
during the last self-discovery cycle; This string will not contain a value
unless the I2C module has been started and initialized;
-City:
a String which indicates the closest city to the location detected by the Geolocation module; This string will not contain a value
unless the Geolocation module has been started and
initialized and a connection to the Internet is present;
-IP:
a String which indicates the current IP address of the Internet connection
available to the controller; This string will not contain a value unless the Geolocation module has been started and initialized and a
connection to the Internet is present;
-Longitude:
a String which indicates the longitude detected by the Geolocation
module; This string will not contain a value unless the Geolocation
module has been started and initialized and a connection to the Internet is
present;
-Latitude:
a String which indicates the latitude detected by the Geolocation
module; This string will not contain a value unless the I2C module has been
started and initialized and a connection to the Internet is present;
Example of response:
{
"City": "Torino",
"IP": "2.230.90.xx",
"Longitude": 7.6667,
"Version": "alpha
0.2",
"Build": "24/05/2014
17:00",
"Latitude": 45.05,
"Boards_Connected":
3
}
|
/system/boards
|
Returns a JSON formatted dictionary
containing a listing of the features and the data of all the sensor boards
discovered during the discovery procedure. The structure returned is
organized in the following way:
….
Board(n-1):
{
[…]
},
Board(n):
{
[…]
},
Board(n+1):
{
[…]
}
….
The internal
structure […] is structured in the same way as the single board data. Please refer
to the following section for further information.
Example of response:
{ "Board1": { [...] }, "Board2": { [...] }, "Board3": { [...] } }
|
/system/boards/[N]
|
Returns a JSON formatted dictionary containing
the list of the features and the data of the N sensor board discovered during
the discovery procedure. The structure returned is organized in the following
way:
- Board_model: an integer which indicates which
version of the Board is connected to the bus;
- Cal_data_available: a Boolean which indicates if the
given boards supports and provides calibration data. If true the data
provided in the Data section will
Be displayed already calibrated. If false only raw data will be
presented: this is the case when sensor boards host only sensors whose
content is raw (e.g. water excess).
-Data: a JSON formatted dictionary containing the data from
the sensors present on the board.
-Format: a JSON
formatted dictionary containing Booleans listing which sensors are present on
the board.
-Protocol_version: an
integer which indicates which protocol version is supported by the board.
-UID: an integer value which is unique identifier for the
given board. This allows to internally identify sensors regardless of their
self-discovery addresses.
Example of a response:
{ "Board_model": 1, "Cal_data_available": true, "Data": { "Temperature": 23.52, "Water_excess": true }, "Features": { "Extra": false, "Humidity": false, "Light": false, "Rain": false, "Soil_humidity": false, "Temperature": true, "Water_excess": true }, "Protocol_version": 2, "UID": 1 } |
/status
|
Returns a JSON formatted object containing
information pertaining to the status of the system .
The structure returned is organized in the
following way:
-Connected
to internal network: a boolean value which
is true if a connection to the internal sensor network has been correctly estabilished.
-Connected
to internet: a boolean value which is true
if a connection to the internet has been detected.
-Internal
Network OK: a boolean value which is true
if no faults have been encountered during transactions with the sensor
boards.
-Pump
available: a boolean value which is true if
no faults have occurred during the initialization or during the activation of
the water delivery system.
-REST
service available: a boolean value which is
true if no faults have occurred during the set-up of the REST server.
-Sensor
boards available: an integer value which represents the number of
sensor boards connected to the system.
-Weather
forecasts available: a Boolean value which is true if the system is
able to retrieve updated weather information.
Example of a response:
{
"Connected to internal
network": true,
"Connected to internet": true,
"Internal Network OK": true,
"Pump available": true,
"REST Service available": true,
"Sensor boards available": 5,
"Weather forecasts available":
true
}
|
/status/weather
|
Returns a JSON formatted dictionary
containing the current weather forecast obtained by means of the weather
module. This data is only available if an Internet connection is available to
the controller and requires initialization of both the weather and the geolocation modules .
The structure returned is organized in the
following way:
-Description:
a string containing a short description of the current weather for the
location determined by the geolocation system.
-Humidity:
an integer which presents the current humidity value expressed as a percentage.
-Max_Temperature:
a floating point number which represent the maximum temperature forecast in
Celsius degrees for the next 3 hours.
-Min_Temperature:
a floating point number which represent the minimum temperature forecast in
Celsius degrees for the next 3 hours.
-Precipitation:
a floating point number which represent the rainfall forecast for the next 3
hours in millimeters of rain.
-
Temperature: a floating point number which represent the temperature
at the time of the last update in Celsius degrees.
Example of a
response:
{ "Description": "overcast clouds", "Humidity": 100, "Max_Temperature": 27.03000000000003, "Min_Temperature": 27.027000000000044, "Precipitation": 0.0, "Pressure": 1.0123858869972728, "Temperature": 27.03000000000003 }
|
/status/waterdb
|
Returns a JSON formatted dictionary
containing the record, for the last 30 days, of the seconds of activation of
the water delivery system.
- WDMonth: the current month for which the record
is intended expressed as an integer value.
Example of a
response:
{
"1": 302,
"10": 240,
"11": 243,
"12": 225,
"13": 288,
"14": 238,
"15": 180,
"16": 135,
"17": 148,
"18": 187,
"19": 180,
"2": 230,
"20": 233,
"21": 142,
"22": 228,
"23": 152,
"24": 0,
"25": 261,
"26": 0,
"27": 0,
"28": 0,
"29": 0,
"3": 242,
"30": 0,
"4": 256,
"5": 180,
"6": 143,
"7": 135,
"8": 186,
"9": 204,
"WDMonth":
6
}
|
/status/lightdb
|
Returns a JSON formatted dictionary
containing the record, for the last 30 days, of the seconds of activation of
the light delivery system.
- WDMonth: the current month for which the record
is intended expressed as an integer value.
Example of a
response:
{
"1": 2430,
"10": 2405,
"11": 2439,
"12": 2610,
"13": 1768,
"14": 1650,
"15": 1820,
"16": 1560,
"17": 1849,
"18": 1967,
"19": 2048,
"2": 2230,
"20": 1789,
"21": 2470,
"22": 2459,
"23": 0,
"24": 0,
"25": 113,
"26": 0,
"27": 0,
"28": 0,
"29": 0,
"3": 1890,
"30": 0,
"4": 1649,
"5": 2039,
"6": 2203,
"7": 1780,
"8": 1970,
"9": 2093,
"WDMonth":
6
}
|
/led/on
|
Activates the lighting system (if the SmartGardener system supports the functionality).
This command allows
to specify the number of seconds that the lighting system is requested to be
activated by using the following syntax:
/led/on?seconds=XXX
The seconds value can also be omitted. In this case the system
will activate the light for a default time of one hour.
On success returns
the number of seconds the system is to be activated. If the operation fails
the string “Failure” is displayed.
|
/led/off
|
Deactivates the lighting system (if the SmartGardener system supports the functionality)
overriding previous commands or automatic activations.
|
/pump/on?seconds=XXX
|
Activates the water delivery system for the
specified amount of seconds.
This command overrides
the manual scheduling of the watering systems and forces the system to
immediately activate the water delivery system for an XXX number of seconds.
Updates of the learning algorithm for the intelligent controller will be
inhibited, disregarding the next iterations, for the next 3 hours after an
override has been performed. On success returns the number of seconds the
system is to be activated. If the operation fails the string “Failure” is
displayed.
Warning: no feedback
is provided with respect to the actual success of the operation, since this
would require waiting for a XXX number of seconds!
|
/blink/[N]
|
Sends a command to the sensor board with UID
N which causes the activation of the blink functionality on that given board.
To enable the user
to easily identify boards a led is installed on each sensor board. This
command can be used to activate the blinking functionality on a desired
board.
On success returns
the string “board N will blink for 5 seconds”. If the operation fails the
string “Failure” is displayed.
|
/rename/[N]?new_name=[name]
|
This command sets the name of a sensor board
to a given string specified by the user.
This command enables
renaming of the sensor boards so that they can be more easily identified by
the user. On success returns the string “board N renamed name.”. If the operation
fails the string “Failure” is displayed.
|
/devel/kill
|
This command requests a shutdown of the
system.
[Requires settings.DEVEL=1]
This command terminates, if the operation
can be safely executed, the execution of the SmartGardener
Core and modules. Complete switch off is ensured within 10 seconds unless a
watering operation is in process. In such a case the watering operation is
first completed to ensure a safe shut down of the system.
No answer is sent back from the service when
this command is executed.
|
/devel/update_boards
|
This command forces an immediate update of
the sensor board data.
[Requires settings.DEVEL=1]
This command forces
the system to perform an immediate update of the data from all the boards,
disregarding the current update scheduling. On success returns the string
“Sensor data updated”. If the update operation fails the string “Failure” is
displayed
|
/devel/update_weather
|
This command forces an immediate update of
the weather data.
[Requires settings.DEVEL=1]
This command forces
the system to perform an immediate update of the data from the weather
module, disregarding the current update scheduling. On success returns the
string “Weather data updated”. If the update operation fails the string
“Failure” is displayed.
|
/settings/natural_light/on
|
This command enables, on SmartGardener
versions supporting the functionality, the natural lighting functionality.
The natural lighting
functionality tries to duplicate outdoor conditions in an indoor environment
by synchronizing the lighting cycle with the natural sunset and sunrise.
On success it
returns the string “Natural Lighting enabled”. If the feature is not
supported the string “Feature not supported” will be returned. Finally if the
operation fails the string “Failure!” is displayed.
|
/settings/natural_light/off
|
This command disables, on SmartGardener
versions supporting the functionality, the natural lighting functionality.
On success it
returns the string “Natural Lighting disabled”. If the feature is not
supported the string “Feature not supported” will be returned. Finally if the
operation fails the string “Failure!” is displayed.
|
/settings/correction?factor=[factor]
|
This command sets the watering correction
factor to a user-defined value.
This setting allows
further irrigation time tailoring by the user which can specify a correction
factor to be applied to the computed irrigation time. On success it returns
the string “System wide correction factor set to [factor]”. If the command
fails the string “Failure” is returned instead.
|
/settings/location?lat=[latitude]&
lon=[longitude]
|
This command sets the current latitude and
longitude to a user specified value.
This setting allows
the user to improve the accuracy of the system by manually specifying the
coordinates of the system installation, thus overriding the setting computed
by the geolocation module.
On success it
returns the string “Location data set: Latitude [latitude], Longitude
[longitude]”. If the command fails the string “Failure” is returned instead.
|
Logic Architecture
SmartGardener was designed to be
modular. This is a feature which allows flexibility during the development and
easier integration of new features. The different modules are then
interconnected by means of the Core, which performs integrity check, schedules
updates and manages the irrigation of the plants.
The table reports a brief overview of the functionalities
offered by each module:
Module
|
Functionality
|
Core
|
The core module is the heart of the SmartGardener,
binding together all the other modules. It loads, at start-up, all the
settings and the modules required by the system from local storage. Checks on
the modules and on the connectivity to both the internal sensor network and
the internet are also performed to ensure that the system is functional.
During the start-up sequence this module also gathers all the required information
from the other modules which is required by the various system
functionalities. When the start-up sequence is completed the Core starts coordinating the
activities of the other modules, scheduling watering sessions, gathering and
refreshing sensor and weather data and performing updates to the data in the
system. The core, during its operation, provides and receives data from the
REST service, allowing users to override its decisions and to monitor the
overall status of the system. Internally it also provides an interface to
both the LED controller and to the Pump controller.
|
Geolocation
|
This module provides information on the current location of the
board. Information such as latitude, longitude, City and IP address are
provided to the Core, which, in turn, makes them available for other modules
by storing them in the Shared Variables module. It requires an internet
connection to provide its services.
It is normally initialised by the Core during the Start-up routine.
If the initialisation succeeds the corresponding initialisation flag is set
to true in the shared variables module, so that users of the content provided
by the Geolocation module can know whether the data
is available and reliable or not.
The geolocation data does not need to be
updated periodically, since, by nature, the controller requires a connection
to a power supply. Nonetheless the data is freshly loaded every time the
controller is started, to allow further flexibility and adaptation to the
different environment.
|
I2C
|
This module provides internal connectivity services by implementing a
custom I2C-based communication protocol which allows exchange of data between
the controller and the sensor-hosting boards. Functionalities such as board
discovery, data calibration, version detection and error management are
provided in-module to allow more flexible development. After an initial
self-discovery (which must be initiated by the core) the module queries all
the boards connected to the bus in order to gather information on which
features are available. The actual data is then fetched and stored in a
dictionary in the shared variables module, so that other modules are able to
access it.
The data needs to be updated frequently: the core, therefore,
schedules new updates at regular intervals. For development purposes the
module offers a self-contained testing routine, provides additional data by
using the VERBOSE_I2C option in the setting module and allows asynchronous refresh
(for more information see REST API).
|
Led
|
This module provides an interface between the Core and the LED light
hardware, timing the illumination interval and providing the means to shut
down, at any time, the LED. This allows to override commands issued by the
system or erroneous commands sent by the user. In comparison to the pump
module it is less robust due to the less serious implications of a possible
malfunction.
|
Pump Interface
|
This module provides an interface between the Core and the low-level
instructions used to control the pump. Testing functionality is also provided
so that the Core can perform checks on the pump functionality, reporting
possible anomalies.
The module performs internal checks so that possible failures during
the irrigation can be detected.
|
Settings
|
This module, not accessible by an end-user, contains:
- several options to help during the development of the system
- constants
- settings for various modules
- error strings
In the current implementation the system loads the settings from a
YAML-formatted file (settings.yaml) at start up.
This allows to modify the predefined default values to custom ones.
|
Shared Variables
|
This module hosts a wide variety of variables and flags that need to
be shared between several modules.
|
Weather
|
This module provides information on the weather forecasts in the
current location of the board. Information such as temperature, humidity,
rainfall and pressure are provided to the Core, which, in turn, makes them
available for other modules by storing them in the Shared Variables module.
It requires an internet connection to provide its services.
It is normally initialised by the Core during the Start-up routine.
If the initialisation succeeds the corresponding initialisation flag is set
to true in the shared variables module, so that users of the content provided
by the Weather module can know whether the data is available and reliable or
not.
The data needs to be updated periodically in order to obtain reliable
data. This operation is performed by the Core, which schedules periodical
updates. The data is also loaded during the controller start-up routine.
An asynchronous refresh functionality is provided when the controller
is in debug mode. For further information refer to the REST API
documentation.
|
Webserver
|
This module provides an external interface to the functionalities and
the data held by SmartGardener. This is achieved by
running a REST server which provides both data and commands to external
services. For a detailed list of the functionalities provided please refer to
the REST API documentation.
|
Requirements
Functional Requirements
The System MUST be able to:
1.1 Deliver water to plants in a domestic environment
1.2 Collect weather data
1.2.1 Wind
speed and degree
1.2.2 Precipitation
forecast for the next 3 and 6 hours
1.2.3 Air
temperature as a minimum, maximum and average temperature for the next 3 hours
1.2.4 Barometric
pressure
1.2.5 Relative
humidity
1.2.6
Short descriptor of the weather
1.3 Collect local data about plants
1.3.1 Soil humidity
1.3.2 Air humidity
1.3.3 Air temperature
1.3.4 Water level under pots
1.3.5 Amount of sunlight
1.3.6 External water delivery,
either due to rain or user delivered
1.4 Take into account weather data and sensor data to decide
the optimal amount of water to be given to the plants
1.5 Log past actions and the reaction of the system
1.6 Improve its decision making by learning from previous
actions
1.7 Present information about the plants to the user:
1.7.1 Soil humidity
1.7.2 Air humidity
1.7.3 Air temperature
1.7.4 Water level under pots
1.7.5 Amount of sunlight
1.7.6 External water delivery,
either due to rain or user delivered
1.8 Give the user the possibility for manual control of
watering plants
1.9 Give the user the possibility to manually configure the
system:
1.9.1
Allow the user to set a system wide correction factor for the water delivery
system
1.9.2
Allow the user to manually operate the water delivery system
1.9.3
Allow the user to manually operate the lighting system (in the indoor version)
1.10 Inform the user if any part of the system fails or
malfunctions
1.11 Automatically go into a “failsafe” mode if some parts
of the system fail or malfunction
1.11.1 Have limited functionality
even if network connectivity is lost
1.11.2 Minimize the negative
effect of malfunctioning sensors
1.12 Distinguish between automatic and user generated
commands
1.12.1 Grant precedence to manual
(user-generated) commands over automatic ones
1.13 Be able to connect to the internet
1.13.1 Have limited functionality
without internet access
The System MUST NOT:
1.14 Provide excessive amounts of water to the plants, thus
causing flooding
1.15 Block or freeze in a state in which water is being
delivered to the plants
Non-Functional Requirements (constraints)
The system MUST:
1.1 Be able to water up to 15 plants
1.2 Use, whenever possible, low voltages (<12V) so as not
to cause harm to users
1.3 Adapt to different balconies set-ups up to 5m² without
requiring user intervention
1.4 Present data to the user by means of a web application
and/or mobile application in an acceptable time frame (< 2 seconds)
1.5 Respond to commands sent by the user in under 5 seconds.
1.6 Be able to water up to 15 plants
1.7 Consume less than 10W while no operation is being
performed
1.8 Be silent (<40dB) while no operation is being
performed and never above 60dB when in operation
1.9 Be compatible with a wide range of pre-existing watering
solutions
1.10 Require minimal maintenance by the user
1.11 Have a minimum possible watering frequency of once an
hour
1.12 Have a minimum sensor update frequency to collect data
about plants’ status of at least once every 30 minutes
1.13 Be modularly designed, so as to allow the addition of
extra plants to the system and of extra modules to the Core
1.14 Be able to operate continuously in environments with
temperatures ranging from 0 °C to 50 °C
1.15 Be able to filter out commands which may harm the
system of the plants and advise the user against possibly dangerous actions
1.16 Be able to provide, if the Geolocation
module is correctly functioning, the location of the device within a 20 Km
radius
1.17 Be able to provide, if the Geolocation
module is correctly functioning, the local sunset and sunrise hours with a
maximum error of 5 minutes
Sensor Network architecture
SmartGardener works both on forecasts and on local data. This requires the
installation of many sensors in order to gather the required information to
compute watering times and overall system health. For each plant to be managed
by the system several information such as soil moisture levels, temperature,
light exposure, water excess and rain presence need to be periodically obtained
and processed by the Core.
While it is
true that on the consumer and professional level many devices providing part of
this set of sensors exists on the other hand their cost would not allow a
full-fledged implementation: they are mainly designed to support one single
plant.
For this
reason it was required to develop a network of sensors with a high level of
modularity, an extensive set of local sensors and a low power consumption but
having an inexpensive bill of materials.
The high
overall number of sensors to be installed presented the problem of connecting
all of them with a central controller. A direct connection to the controller
was not possible. Furthermore this solution would have represented a hindrance
to the modularity problem.
The design
choice was made to employ microcontrollers to act as a physical gateway between
each individual sensor and the main controller. For additional modularity each
sensor board is connected to a bus architecture, so as to be easily expandable.
Several
solutions tailoring this problem exist. For ease of development and
cost-effectiveness it was decided to use Atmel’s AT line of
microcontrollers. With respect to the
development phase one can benefit from the existing resources available for Arduino boards and, subsequently, port the code to ATTiny microcontrollers. With respect to cost-effectiveness
this family of microcontrollers has a highly integrated architecture (ADCs,
on-board voltage regulation, memory, clock generators, etc.) which contributes
to a shorter BOM and, in the end, to the overall cost of the sensor board.
This design
choice, however, poses limitations when it comes to the complexity of the
operations that can be performed on the board. This requires careful selection
of the internal bus network architecture to contain, as much as possible, the
size of the firmware to be loaded on the microcontrollers while still retaining
all the aforementioned features.
With
respect to the lower level protocol the I2C standard was preferred over the
other ones due to the good support already present for both Python and Arduino. This was the leading factor in the decision
process due to time constraints. This design choice presented a problem when
the upper layer protocol was to be decided since the I2C stack implementation
consumes a good part of the small memory present on the microcontroller.
For this
reason it was decided to implement a custom solution rather than resorting to
preexisting ones. This allows to tailor the protocol to our specific needs
rather than adapting and slimming down existing ones.
Nonetheless,
to allow further expansion and integration with other products, the Internal
Networking core was separated from the controller core so that, in future,
other products can be integrated with SmartGardener.
The
protocol uses messages with a size multiple of a byte to exchange data between
the controller and each sensor board. Furthermore coefficients and constants
related a particular set of sensors on a board are stored internally on the
boards to improve expansions of the network.
To the bus,
whose master is the controller, several sensor boards are connected. On each of
them, internally, a Unique Identifier is stored as well as protocol version
supported and address. The master can set the communication mode, to avoid
waste of resources, in 4 modes:
1) Handshake only
2) Header only
3) Header and Body
4) Blink mode
After a
mode has been set on a sensor board the corresponding reply will be sent the
next time the board will be queried. The last mode does not set a reply mode
but blinks an LED for 5 seconds on the board on which the mode was set up. This
allows easy visual identification by the user of a given board.
The
protocol can be easily adapted, with backward compatibility, to support other
features by exploiting the protocol version identifier.
In the
third version of the protocol, support for long measurements has been
introduced: this allows both to perform more accurate measurements, averaging
multiple readings, and to perform capacitance readings. Furthermore the
addition of this fifth mode allows to improve power-saving capabilities of the
sensor boards, which can turn on sensors only when required. This has been
possible thanks to the introduction of a new transaction procedure used to
request data: the operation has been divided into two phases instead of
performing everything at the same time.
The third
iteration of the internal network protocol is fully compatible with the
previous ones: this allows mixed protocol version to co-exist on the same
network.
Component Selection
Sensor boards
The sensor board must, for economical and practical
reasons, developed: on the current date no low cost solutions can be found that
would allow a full-fledged development with the required specifications and the
level of ubiquity required. The closest match to our requirements would be the Parrot
Flower Power Plant Sensor, which retails for 50€ and would require additional
modules to be interfaced with the controller, therefore not representing a
viable solution. An appropriate alternative must, therefore, be devised,
designed and built.
The main constraint on the design is given by the low
price which the final solution must have. Also paramount requirements in the
design are a low power consumption, flexibility in the number of sensors and
modularity in the design.
First of all a network architecture must be decided.
The most suitable for this design case is a bus architecture having the
controller as the master and the sensor boards as slaves. This requires the
selection of a suitable network protocol to enable communication from the
master to the sensor boards and vice versa.
Before this selection is made a first draft of the
sensor boards’ hardware must be made. Given the economical and time constraint
Atmel’s line of MCU was chosen. While their prices are relatively close to the
desired design budget (and are comparable to other manufacturers’
microcontrollers) their main advantage is the fact that the firmware can be
tested on Arduino boards and, only subsequently,
ported to a given microcontroller. This allows faster development with respect
to the competing solutions and enables to exploit the vast amount of code and
know-how of the Arduino community.
At this point a lower level network architecture
selection can be made. The time constraint forced us to operate a selection
only on well-known protocols: I2C and 1-Wire. These competing solutions offer
similar capabilities given our design target. The choice was made to use I2C,
which has very good documentation and libraries implementing the network stack
on both Arduino and Python and has less strict
licensing conditions.
This choice has, however, consequences on the software
architecture of the sensor board. In order to remain within the spending
limitation MCU were limited to a very small memory size. The I2C protocol stack
is, however, rather conspicuous in size. This entails that very little space
can be left for data acquisition and manipulation, and for the rest of the
networking protocol.
For this reason a custom upper layer protocol was
designed and most of the data processing was deferred to the controller module.
At this point the hardware requirements due to sensors
can be considered. While some sensors do not require accurate data (e.g. rain
presence, water excess) others types require a degree of precision. The number
of inputs and the number of external components required is also a relevant
factor in the design choices.
Temperature Sensors:
Given the required temperature range and economical requirements several
options are possible. The most common ones are thermistors and
Temperature-measuring ICs. Given the calibration problems and the non-linear
characteristic of thermistors is was decided to use an integrated circuit to
perform this task. A wide variety of sensors is present on the market. One of
the most commonly available ones is the LM35 precision centigrade temperature
sensor. While its cost is relatively high with respect to other solutions it
also presents several important advantages: an output voltage linearly
proportional to the Centigrade temperature (which does not require dealing with
offsets and non-linearity), factory calibration, a typical accuracy of ¼ °C and
a low power consumption.
Soil Humidity sensors
This sensor must be precise due to the importance of the data that it provides
in the design of the controller. In the technical literature two possible
solutions can be identified: a resistive-one based on two plaster-of-Paris
coated electrodes and a capacitive one. The latter one is the more modern and
precise one. It also presents the useful advantage of easy integration in the
PCB manufacturing process leading, in turn, to significant cost saving. For
this reason it is the most suitable solution. Due to time constraint, since the
design process requires manufacturing a PCB and testing it, the initial
prototype was build using an inexpensive and less precise resistive sensor.
Water Excess and Rain sensors
These modules are very similar (which is to be expected since they need
to perform the same measurement) and only differ in their position on the
sensor board. They only need to output a binary value and, therefore, do not
require a high degree of accuracy and precision. Most sensor of this type are
voltage divider based: they feature intertwined and exposed gold-plated tracks
which are not directly in contact between themselves. When water is present an
electrical contact is made and between the terminals a voltage can be read.
This design can, again, be directly implemented on the main sensor board PCB,
leading to additional savings.
Luminosity sensor:
While high precision is not required this sensor still needs to be able
to provide an output proportional to the light exposure of the sensor board. A
simple voltage divider can be used in conjunction with a light-dependent resistor
as a sensor. This solution is very inexpensive and therefore was the one used
in the design.
Humidity sensor:
High precision sensors of this family are fairly expensive. In our
application, however, data from local sensors is only used when no accurate
forecasts are present. For this reason trading precision for price is an
acceptable compromise. Humirel’s HS 1101 capacitive
relative humidity sensor was chosen due to its price, reliability and
stability. This sensor needs only to be present in one sensor board within the
whole network.
Microcontroller
Having defined the sensors required the
microcontroller can be chosen among the initial selection.
The main requirements are
-Low price
-Few external component count
-Multiple digital inputs
-Integrated ADC, preferably >8 bits
-Low power consumption
-At least 8KBytes of programmable flash memory
A very low price and the fact that many
requirements are satisfied makes the ATTiny family a
possible candidate. A severe problem is, however, the scarcity of input pins
available.
A more suitable candidate, at a slightly higher
price, is the ATMega family, in particular the
microcontrollers which have 8Kbytes of flash memory. A choice has to be made
considering price, availability and minimum order quantities. Among the viable
options an ATMega8A was chosen. This is a high-performance, low-power 8-bit microcontroller
using a RISC architecture and having a throughput of 16MIPS at 16MHz. It
features 8KBytes of In-System Self-programmable Flash program memory, a
512Bytes EEPROM and a 1KByte Internal SRAM. It also has an 8-channel 10-bit ADC
(in TQFP and QFN/MLF packages) and offers a byte-oriented 2-wire Serial
Interface (Philips I2C compatible). Furthermore it operates in a wide range of
power supply voltages (1.8 - 5.5V), a wide temperature range (-40°C to 85°C)
and has a very low power consumption (Active Mode: 0.2mA, Power-down Mode:
0.1µA).
For the development of the prototype the 28 DIL
PDIP package version was chosen.
Schematic of the sensor board prototype
Main controller
As a development platform for the controller the
Raspberry Pi was chosen. This was primarily because of its high availability,
low price, wide documentation and breadth of low-level interfaces. In order to
enable the system to perform the required actions an interface had to be
provided to enable signals sent over the GPIO header to control the water
delivery system, fan and lighting system. It was decided to design a custom
solution due to the intrinsic economic advantages and the relatively low
complexity of the circuit required to perform this task.
In order to maintain wide compatibility with
pre-existing watering systems this additional circuitry uses mechanical relays,
driven by logic-glue circuitry directly connected to the GPIO header of the
raspberry pi (which provides protection to the Raspberry Pi’s SoC, since the GPIO header is directly connected to it). This
solution electrically isolates the low voltage circuitry of the controller and
sensor bus from the higher voltages required to operate both the lighting and
water delivery systems.
Schematic of the main interface board