Twitter icon
Facebook icon
LinkedIn icon
Google icon
Reddit icon
StumbleUpon icon
Del.icio.us icon

Cloud Hosted Intelligent Sprinkler System

Added to IoTplaybook or last updated on: 07/01/2019
Cloud Hosted Intelligent Sprinkler System

Story

The project runs on the general basis of overall improving the average home user’s sprinkle system. We observed that there is much room for improvement over a basic mechanical sprinkler timer. Our design will be an autonomous sprinkler system capable of monitoring outdoor conditions and adjusting sprinkler settings accordingly. The system will measure soil humidity, weather data, and watering schedules to determine which sprinklers in our network should run. Using local network connections, TI's CC1310 Launchpads, a Beagle Bone Black, Amazon Web Services, and the OpenWeatherMap weather API, we will communicate moisture data, weather data, and user preferences to determine when to sprinklers on and off. The system will run both indoors and outdoors and will be able to remain running with little to no physical maintenance. Devices running outside will be solar powered and switch on to transmit information periodically and minimize power usage. Using a cloud hosted web interface, a user will be able to input desired watering options and view live data of their outdoor conditions. The web interface will also allow the user to schedule watering and override computer settings. The current system status will also be provided. Using our on-board program for the hub, the system will save water by not allowing the system to run when the soil is saturated, when it is currently raining, or when it is predicted to rain soon.

General system diagram
General system diagram

 

 

 

 

 

 

 

 

 

 

 

Demonstration Video: Team DNE Cloud Hosted Intelligent Sprinkler System

 

Team DNE Cloud Hosted Intelligent Sprinkler System DEMO

 

Things used in this project

Hardware components

LAUNCHXL-CC1310 SimpleLink CC1310 Sub-1GHz LaunchPad
Texas Instruments LAUNCHXL-CC1310 SimpleLink CC1310 Sub-1GHz LaunchPad
Microcontroller for wireless sensor nodes.
× 4

 Buy

LAUNCHXL-CC1310 SimpleLink CC1310 Sub-1GHz LaunchPad
Texas Instruments LAUNCHXL-CC1310 SimpleLink CC1310 Sub-1GHz LaunchPad
Microcontroller as part of the sprinkler relay hub.
× 1

 Buy

BeagleBone Black
BeagleBoard.org BeagleBone Black
Microcontroller for the logical portion of the sprinkler hub.
× 1

 Buy from Newark

 Buy from Adafruit

 Buy from CPC

 Buy from 
 Beagelboard.org

SparkFun Snappable Protoboard
SparkFun Snappable Protoboard
Assembly structure for relays and connections.
× 1

 Buy from SparkFun

 
Rhino PSA-CA004 2Amp 12V DC Adapter
Delivers power to the solenoids.
× 1

 Buy

 
LDO Voltage Regulator
Regulates power from the charging circuit to the CC1310.
× 4

 Buy

 
Adafruit Lithium Ion Polymer Battery
Power supply for wireless sensor nodes.
× 4

 Buy

 
Adafruit USB / DC / Solar Lithium Ion/Polymer charger - v2
Regulated power from the solar panel to the battery and to the CC1310.
× 4

 Buy

Gravity: Analog Capacitive Soil Moisture Sensor- Corrosion Resistant
DFRobot Gravity: Analog Capacitive Soil Moisture Sensor- Corrosion Resistant
Moisture sensor for reading ground moisture levels in backyard.
× 4

 Buy

 
Adafruit Medium 6V 2W Solar panel - 2.0 Watt
Source of charging power for the Lithium Ion Battery to maintain extended periods of run time.
× 4

 Buy

 
Adafruit Power Relay FeatherWing
Switched power to solenoids.
× 4

 Buy

 
2N3904 NPN BJT
Allowed digital pin control of relays.
× 4

 Buy

Software apps and online services

Code Composer Studio
Texas Instruments Code Composer Studio
Programming for CC1310 hub and sensor nodes.
   IDE
SimpleLink SDK
Texas Instruments SimpleLink SDK
 
   SDK
 
Texas Instruments Sensor Controller Studio
Used to read values from the moisture sensors.
   Studio
 
Texas Instruments SmartRF Studio
Used to set up RF communications.
   Studio
Android Studio
Android Studio
Used to create smartphone app for user sprinkler controls.
   Studio
AWS EC2
Amazon Web Services AWS EC2
Service used to host website to access user controls.
   EC2
 
Creo
Used for 3D modeling of sensor node casing and hub casing.
   Order
 
Debian Linux
Operating system for Beagle Bone Black
   
 
Python
Development software for data management and weather logic.
   Python
 
Wordpress
Site development platform for easy-to-use user interface.
   Build
 
OpenWeatherMap API
Weather data provider to use with sprinkler logic.
   API

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Used to put together relays, transistor circuit, and CC1310 connections onto protoboard.
   
3D Printer (generic)
3D Printer (generic)
Used to fabricate sensor and hub casings.
   
Mastech MS8217 Autorange Digital Multimeter
Digilent Mastech MS8217 Autorange Digital Multimeter
Used during testing phase to measure current consumption and voltage I/O for the system.
 

 Buy

Electronics

Our system is divided into 4 major components. Each component serves a crucial purpose in ensuring the integrity of the system.

TI CC1310 Launchpad

The CC1310 Launchpads provide an efficient, low power communication that will allow us to wirelessly send information back and forth between outdoors and our hub over a large distance. This will benefit us in that our system will typically operate over distances from the backyard to the garage. The ultra-low power mode of the launchpad will also help sustain the system outdoors for long periods of time with minimal power. This will help ensure a longer system uptime for our design.

Beagle Bone Black

With the hub portion of our project resides the Beagle Bone Black. The Beagle Bone Black provides complete access to a Linux terminal which we will access to run higher level access scripts to bridge our website to the CC1310. This will allow us to perform HTTPS queries between our operated website using Python as well as generate and parse API requests to OpenWeatherMap to retrieve local weather information. In additon, we will also utilize Python to talk with the hub’s CC1310 through a direct UART connection. Python will also serve us in parsing information and maintaining the overall program logic of the system.

Capacitive Moisture Sensor

The capacitive moisture sensor provides a robust way to obtain an analog representative value corresponding the moisture level in the surrounding soil. Rather than a simple 0/1 representation of wet vs dry, we are able to read a relative amount of water saturation in the soil with values scaling from 0-100. Additionally, because the sensor is capacitive (unlike its resistive alternatives), it is corrosive resistant and not as likely to deteriorate over a long period of time.

User Controls

The user controls service to give an individual access to their sprinkler system anytime and anywhere. These controls can be accessed on any web-capable device.

Cloud Hosted Service

The cloud hosted service we provide is the gateway between the user and the system. Using a basic UI we allow the user to see a status of the system as it is currently operating. The user will know if the system is on and which sprinklers are running. The weather is provided for convenience. Also provided are a manual override button and the schedule preferences. The user can toggle the override button to enable the sprinklers in the system. The user can also input a scheduled start and end time for the system to designate all possible times the system may run. All of this information gets stored in a database on our server and later gets parsed by the Beagle Bone Black. The website used for our installation is athttp://www.dnedesign.us.to

 Website Screenshot

Website Screenshot

 

Assembly

Transmitter

For the transmitter, a charging circuit was connected to a battery and the micro-controller. A capacitive moisture sensor was read using SensorController Studio and processed with Code Composer Studio to minimize power consumption. This data gets transmitted to the receiver acting as the sprinkler hub. This assembly is capable of lasting 3.7 years on ultra low power mode from full charge without any extra power from the solar panel. With the solar panel, this setup is capable of lasting for the life of the parts.

Prototype assembly of outdoor moisture sensor node without solar panel or enclosure.

Prototype assembly of outdoor moisture sensor node without solar panel or enclosure.

Receiver

For the assembly, all the relays were soldered to a protoboard with inputs from a transistor circuit triggered by the CC1310 digital pins. These relays switched to a 12V 2A DC source used to power the sprinkler solenoids.

Complete assembly of relay board and CC1310 Receiver Module

Complete assembly of relay board and CC1310 Receiver Module

 

Installation

For the installation of the wireless sensor nodes, they only require outdoor placement and for the moisture sensor to be grounded where desired. The enclosures will protect all electronics from the elements through a weather tight seal.

Example of wireless moisture sensor node installation with solar panel.

Example of wireless moisture sensor node installation with solar panel.

To install the hub, remove any old components from the old sprinkler box. Each of the remaining wires can be connected to the relay board. After the connections are placed, plug the system in using a USB power adapter and the AC to DC power adapter. The system can then be tested using the website's scheduling system and manual override buttons. An example is available at http://www.dnedesign.us.to

Picture of hub without enclosure

Picture of hub without enclosure

 

Enclosure

Top and bottom of the moisture sensor enclosure. This was used to keep the electronics sealed and weather proof, permitting a long lasting installation.

Top of the moisture sensor enclosure.

Top of the moisture sensor enclosure.

 

Bottom of the moisture sensor enclosure.

Bottom of the moisture sensor enclosure.

 

Code

sender.c

C/C++

Code for the outdoor sensor nodes to enable low power capabilities and send moisture data, sensor IDs, and error codes to the main hub.

 

// Frequency: 869.52501 MHz @625 bps, Legacy Long Range (10 kchips/s, 2-FSK, conv. FEC r=1/2 K=7, DSSS SF=8, Tx dev.: 5 kHz, RX BW: 40 kHz
int sensorID=0;
#include <stdio.h>
#include <xdc/std.h>
#include <stdlib.h>
#include <xdc/runtime/System.h>
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/drivers/PIN.h>
#include <ti/sysbios/knl/Swi.h>
#include <ti/drivers/rf/RF.h>
#include "Board.h"
#include "smartrf_settings.h"
#include "scif.h"

#define BV(x)    (1 << (x))
#define TASKSTACKSIZE   512
#define TX_TASK_STACK_SIZE 1024
#define TX_TASK_PRIORITY   2
#define PAYLOAD_LENGTH     30
#define PACKET_INTERVAL    (uint32_t)(4000000*0.5f) /* Set packet interval to 500ms */

static void senderFxn(UArg arg0, UArg arg1);

/***** Variable declarations *****/
static Task_Params txTaskParams;
Task_Struct txTask;    /* not static so you can see in ROV */
static uint8_t txTaskStack[TX_TASK_STACK_SIZE];
Task_Struct task0Struct;
Char task0Stack[TASKSTACKSIZE];
uint32_t capSensorMoisture1 = 0;

static RF_Object rfObject;
static RF_Handle rfHandle;
static PIN_Handle ledPinHandle;
static PIN_State ledPinState;
static Task_Params txTaskParams;
Task_Struct txTask;    /* not static so you can see in ROV */
static uint8_t txTaskStack[TX_TASK_STACK_SIZE];

uint32_t time;
static uint8_t packet[PAYLOAD_LENGTH];
static uint16_t seqNumber;
uint32_t time;
uint8_t errorState=0;
static PIN_Handle pinHandle;

PIN_Config pinTable[] =
{
    Board_LED0 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
    Board_LED1 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
    PIN_TERMINATE
};

void scCtrlReadyCallback(void)
{

}

void scTaskAlertCallback(void)
{
    processTaskAlert();
}

void processTaskAlert(void)
{
    // Clear the ALERT interrupt source
    scifClearAlertIntSource();

    // Acknowledge the ALERT event
    scifAckAlertEvents();
}

void TxTask_init()
{
    Task_Params_init(&txTaskParams);
    txTaskParams.stackSize = TX_TASK_STACK_SIZE;
    txTaskParams.priority = TX_TASK_PRIORITY;
    txTaskParams.stack = &txTaskStack;
    txTaskParams.arg0 = (UInt)1000000;
    Task_construct(&txTask, senderFxn, &txTaskParams, NULL);
}

Void senderFxn(UArg arg0, UArg arg1)
{
    uint32_t time;
    RF_Params rfParams;
    RF_Params_init(&rfParams);
    RF_cmdPropTx.pktLen = PAYLOAD_LENGTH;
    RF_cmdPropTx.pPkt = packet;
    RF_cmdPropTx.startTrigger.triggerType = TRIG_ABSTIME;
    RF_cmdPropTx.startTrigger.pastTrig = 1;
    RF_cmdPropTx.startTime = 0;

    uint32_t standbyDurationUs = 0;

   // Initialize the Sensor Controller
   scifOsalInit();
   scifOsalRegisterCtrlReadyCallback(scCtrlReadyCallback);
   scifOsalRegisterTaskAlertCallback(scTaskAlertCallback);
   scifInit(&scifDriverSetup);

   // Set the Sensor Controller task tick interval to 1 second
   uint32_t rtc_Hz = 1;  // 1Hz RTC
   scifStartRtcTicksNow(0x00010000 / rtc_Hz);

   // Start Sensor Controller task
   scifStartTasksNbl(BV(SCIF_ADC_LEVEL_TRIGGER_TASK_ID));

    while(1)
    {
        //Small delay to allow reset
        standbyDurationUs = 0.5*1000000;
        Task_sleep(standbyDurationUs / Clock_tickPeriod);
        //Reset Variables
        capSensorMoisture1 = 0;

        // Sensor Value Manipulation
        capSensorMoisture1 = scifTaskData.adcLevelTrigger.output.adcValue;


        capSensorMoisture1 = capSensorMoisture1/5; //Wet=89, Dry=207

        capSensorMoisture1 = 207-capSensorMoisture1; //Wet=118, Dry=0

        capSensorMoisture1 = capSensorMoisture1*0.834; //Dry=0, Wet=99


        //Error Check (2.8V Reg.)
        if(capSensorMoisture1 > 150 || capSensorMoisture1 < -50){
            errorState=1;
        }else{
            errorState=0;
        }

        //Clipping (2.8V Reg.)
        if(capSensorMoisture1 > 99){
            capSensorMoisture1 = 99;
        }
        if(capSensorMoisture1 < 0){
            capSensorMoisture1 = 0;
        }


        /* Request access to the radio */
        rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);

        /* Set the frequency */
        RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);

        /* Get current time */
        time = RF_getCurrentTime();

        /* Create packet with incrementing sequence number and random payload */
        packet[0] = (uint8_t)(seqNumber >> 8);
        packet[1] = (uint8_t)(seqNumber++);
        packet[2] = sensorID;
        packet[3] = errorState;
        uint8_t i;
        for (i = 4; i < PAYLOAD_LENGTH; i++)
        {
            packet[i] = capSensorMoisture1;
        }

        /* Set absolute TX time to utilize automatic power management */
        time += PACKET_INTERVAL;
        RF_cmdPropTx.startTime = time;

        /* Send packet */
        RF_EventMask result = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, NULL, 0);
        if (!(result & RF_EventLastCmdDone))
        {
            /* Error */
            while(1);
        }
        //Make sure all LED's are off before going into low power mode
        PIN_setOutputValue(pinHandle, Board_LED0, 0);
        PIN_setOutputValue(pinHandle, Board_LED1, 0);

        //Close RF Communication to reduce current consumption
        RF_close(rfHandle);

        // Stop task to reduce current consumption
        while (scifWaitOnNbl(0) != SCIF_SUCCESS);
        scifStopTasksNbl(BV(SCIF_ADC_LEVEL_TRIGGER_TASK_ID));
        scifStopRtcTicks();

        standbyDurationUs = (1800)*1000000; //seconds******************1800s for 30 min
        Task_sleep(standbyDurationUs / Clock_tickPeriod);

        // Restart task
        scifResetTaskStructs(BV(SCIF_ADC_LEVEL_TRIGGER_TASK_ID), 0);
        scifStartRtcTicksNow(0x00010000 / rtc_Hz);
        scifStartTasksNbl(BV(SCIF_ADC_LEVEL_TRIGGER_TASK_ID));
    }
}

/*
 *  ======== main ========
 */
int main(void)
{
    Board_initGeneral();

    TxTask_init();

    /* Start BIOS */
    BIOS_start();

    return (0);
}

Credits

DNE ENG

 DNE ENG

 Contact

 

Joey Hamad

 Joey Hamad 

 Contact

 

Eric Hill Eric Hill 

Thanks to Saman Gharagozloo, Justin Dy, and Neil Mustafa.

 

Hackster.io

This content is provided by our content partner Hackster.io, an Avnet developer community for learning, programming, and building hardware. Visit them online for more great content like this.

This article was originally published at Hackster.io. It was added to IoTplaybook or last modified on 07/01/2019.