Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
Gabriel Alejandro Giraldo Santiago
Published © GPL3+

Smart Crops: Implementing IoT in Conventional Agriculture!

Our mission with nature is to preserve it, designing and implementing technologies and monitoring methods with the help of IoT via Helium.

AdvancedWork in progressOver 41 days12,710

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×1
Base Shield V2
Seeed Studio Base Shield V2
×1
Helium Atom Xbee Module
Helium Atom Xbee Module
×1
Grove - Temperature Sensor
Seeed Studio Grove - Temperature Sensor
×1
Grove - Air quality sensor v1.3
Seeed Studio Grove - Air quality sensor v1.3
×1
Grove - Barometer (High-Accuracy)
Seeed Studio Grove - Barometer (High-Accuracy)
×1
Seeed Studio Grove Humidity and Temperature
×1
Seeed Studio Grove Water Sensor
×1
Grove - Sunlight Sensor
Seeed Studio Grove - Sunlight Sensor
×1
Seeed Studio Grove UV Sensor
×1
Grove - Multichannel Gas Sensor
Seeed Studio Grove - Multichannel Gas Sensor
×1
Grove - Dust Sensor(PPD42NS)
Seeed Studio Grove - Dust Sensor(PPD42NS)
×1
Grove - High Temperature Sensor
Seeed Studio Grove - High Temperature Sensor
×1
Helium Element Access Point
×1
Arduino 4 Relays Shield
Arduino 4 Relays Shield
×1
Solar Panel 250W OR +
×6
Inverter 12v
×1
Neodymium magnet generator
Generates approximately twice the energy used
×1
Electric Motor 12V 12000 RPM
×1
12V Random Electric Battery
The goal is to store a total of 2500W
×1
Assembly box Length x Width x Height (mm) 570x 52 x570
×1
Assembly box Length x Width x Height (mm) 57x 52 x70
×1
copper wire # 16 20MTS
×1
Grove - OLED Display 1.12'' V2
Seeed Studio Grove - OLED Display 1.12'' V2
×1
1/2 12vdc Electric Solenoid Valve
The amount varies according to the needs of the farm.
×1

Software apps and online services

Arduino IDE
Arduino IDE
fritzing
Hackster.io
Helium

Hand tools and fabrication machines

Welder
Hand tools
Tin
voltmeter
Computer

Story

Read more

Custom parts and enclosures

BASIC DESIGN OF ENERGY GENERATION SYSTEM CONTAINER BOX

Schematics

CONNECTION FIRST TESTS OF TEMPERATURE AND LIGHT SENSORS

BECAUSE FRITZING DOES NOT MEET ALL SENSORS IT IS A PHYSICAL MODEL

SENSORS CONECTION

BECAUSE FRITZING DOES NOT MEET ALL SENSORS IT IS A PHYSICAL MODEL

CONECTION SIGNAL RX TX HELIUM

Before knowing a bit more about Helium and Google Cloud IoT, in this way we took the data

Code

Programming code Arduino board and Sensors

C/C++
This code will give the order to the agricultural monitoring system to take the data correctly and send them through Helium and through Grove Oled the most relevant
#include "Board.h"
#include <Arduino.h>
#include <ArduinoJson.h>
#include <HeliumUtil.h>
#include <Helium.h>
#include <Wire.h>
#include "AirQuality.h"
#include <TH02_dev.h>
#include <SeeedGrayOLED.h>
#include <avr/pgmspace.h>
#include  "High_Temp.h"
HighTemp  ht ( A3 ,  A2 );
#define CHANNEL_NAME "Helium Smart Farms"
// Delay for one second
#define CHANNEL_DELAY 5000
// Send very 60 cycles (seconds)
#define CHANNEL_SEND_CYCLE 12
int pin = 8;
unsigned long duration;
unsigned long starttime;
unsigned long sampletime_ms = 30000;//sampe 30s ;
unsigned long lowpulseoccupancy = 0;
float ratio = 0;
float concentration = 0;
#define WATER_SENSOR 7
#include "Barometer.h"
float temperature;
float pressure;
float atm;
float altitude;
Barometer myBarometer;
#include  "MutichannelGasSensor.h"


Helium  helium(&atom_serial);
Channel channel(&helium);
int     channel_counter;

void
connect()
{
    while (!helium.connected())
    {
        Serial.print(F("Connecting - "));
        int status = helium.connect();
        report_status(status);
        if (helium_status_OK != status)
        {
            delay(1000);
        }
    }
}

void
channel_create(const char * channel_name)
{
    int8_t result;
    int    status;
    do
    {
        // Ensure we're connected
        connect();
        Serial.print(F("Creating Channel - "));
        status = channel.begin(channel_name, &result);
        // Print status and result
        report_status(status, result);
        if (helium_status_OK != status)
        {
            delay(1000);
        }
    } while (helium_status_OK != status || result != 0);
}

void
channel_send(const char * channel_name, void const * data, size_t len)
{
    int    status;
    int8_t result;

    do
    {
        // Try to send
        Serial.print(F("Sending - "));
        status = channel.send(data, len, &result);
        report_status(status, result);
        // Create the channel if any service errors are returned
        if (status == helium_status_OK && result != 0)
        {
            channel_create(channel_name);
        }
        else if (status != helium_status_OK)
        {
            delay(1000);
        }
    } while (helium_status_OK != status || result != 0);
}


void
setup()
{
    Serial.begin(9600);
    Serial.println(F("Starting"));

    helium.begin(HELIUM_BAUD_RATE);
    channel_create(CHANNEL_NAME);
    channel_counter = 0;
}


#define DRY_VALUE 536 // Taken in air
#define WET_VALUE 303 // Taken in water

#define HUM_RANGE (DRY_VALUE - WET_VALUE)

void
loop()
{
    Serial.print(F("Reading - "));

    float reading = analogRead(A0);//Sensor Humidity & Temperature
    float percent = 100 * (1 - (reading - WET_VALUE) / HUM_RANGE);
    Serial.print(reading);
    Serial.print(" - ");
    Serial.println(percent);

    if (--channel_counter <= 0)
    {
        StaticJsonBuffer<JSON_OBJECT_SIZE(2) + 100> jsonBuffer;
        JsonObject & root = jsonBuffer.createObject();

        root[F("value")]    = reading;
        root[F("percent")] = percent;

        char   buffer[HELIUM_MAX_DATA_SIZE];
        size_t used = root.printTo(buffer, HELIUM_MAX_DATA_SIZE);

        channel_send(CHANNEL_NAME, buffer, used);

        channel_counter = CHANNEL_SEND_CYCLE;
    }

    delay(CHANNEL_DELAY);
}

void loop() 

{
 //Set quality from 0 to 255, with one to 100 being normal
 int sensorValue = analogRead(A1);//Sensor Quality Air
 int quality = map(sensorValue, 0, 1023, 0, 255);
 String dataString = String(quality);
 char data[dataString.length()];
 dataString.toCharArray(data, dataString.length());
 channel_send(&channel, CHANNEL_NAME, data, strlen(data));
 Serial.println(data);
 delay(60000);
}

void  setup () 
{ 
     ht . begin (); 
}

void  loop () 
{ 
    Serial . println ( ht . getThmc ()); 
    retraso ( 100 ); 
}

}

void setup() 
{ pinMode(pin,INPUT);
    starttime = millis();//get the current time;
}

void loop() 
{
    duration = pulseIn(pin, LOW);
    lowpulseoccupancy = lowpulseoccupancy+duration;

    if ((millis()-starttime) > sampletime_ms)//if the sampel time == 30s
    {
        ratio = lowpulseoccupancy/(sampletime_ms*10.0);  // Integer percentage 0=>100
        concentration = 1.1*pow(ratio,3)-3.8*pow(ratio,2)+520*ratio+0.62; // using spec sheet curve
        Serial.print(lowpulseoccupancy);
        Serial.print(",");
        Serial.print(ratio);
        Serial.print(",");
        Serial.println(concentration);
        lowpulseoccupancy = 0;
        starttime = millis();
    }
}

void  setup () 
{ 
    pins_init (); 
} 
void  pins_init () 
{ for ( uint8_t  i  =  0 ; i  <  20 ; i  ++ ) 
    { 
        Serial.print(reading);
    Serial.print(" - ");
    Serial.println(percent);
    } 
}

void setup(){
     myBarometer.init();
}
void loop()
{
    temperature = myBarometer.bmp085GetTemperature(myBarometer.bmp085ReadUT()); //Get the temperature, bmp085ReadUT MUST be called first
    pressure = myBarometer.bmp085GetPressure(myBarometer.bmp085ReadUP());//Get the temperature
    altitude = myBarometer.calcAltitude(pressure); //Uncompensated calculation - in Meters
    atm = pressure / 101325;

    Serial.print("Temperature: ");
    Serial.print(temperature, 2); //display 2 decimal places
    Serial.println("deg C");

    Serial.print("Pressure: ");
    Serial.print(pressure, 0); //whole number only.
    Serial.println(" Pa");

    Serial.print("Ralated Atmosphere: ");
    Serial.println(atm, 4); //display 4 decimal places

    Serial.print("Altitude: ");
    Serial.print(altitude, 2); //display 2 decimal places
    Serial.println(" m");

    Serial.println();

    delay(1000); //wait a second and get values again.
}

void setup()
{   
    gas.begin(0x04);//the default I2C address of the slave is 0x04
    gas.powerOn();

    Serial.println(gas.getVersion());
}

void loop()
{
    float c;

    c = gas.measure_NH3();
    Serial.print("The concentration of NH3 is ");
    if(c>=0) Serial.print(c);
    else Serial.print("invalid");
    Serial.println(" ppm");

    c = gas.measure_CO();
    Serial.print("The concentration of CO is ");
    if(c>=0) Serial.print(c);
    else Serial.print("invalid");
    Serial.println(" ppm");

    c = gas.measure_NO2();
    Serial.print("The concentration of NO2 is ");
    if(c>=0) Serial.print(c);
    else Serial.print("invalid");
    Serial.println(" ppm");

    c = gas.measure_C3H8();
    Serial.print("The concentration of C3H8 is ");
    if(c>=0) Serial.print(c);
    else Serial.print("invalid");
    Serial.println(" ppm");

    c = gas.measure_C4H10();
    Serial.print("The concentration of C4H10 is ");
    if(c>=0) Serial.print(c);
    else Serial.print("invalid");
    Serial.println(" ppm");

    c = gas.measure_CH4();
    Serial.print("The concentration of CH4 is ");
    if(c>=0) Serial.print(c);
    else Serial.print("invalid");
    Serial.println(" ppm");

    c = gas.measure_H2();
    Serial.print("The concentration of H2 is ");
    if(c>=0) Serial.print(c);
    else Serial.print("invalid");
    Serial.println(" ppm");

    c = gas.measure_C2H5OH();
    Serial.print("The concentration of C2H5OH is ");
    if(c>=0) Serial.print(c);
    else Serial.print("invalid");
    Serial.println(" ppm");

    delay(1000);
}

void loop()
{
    int sensorValue;
    long  sum=0;
    for(int i=0;i<1024;i++)// accumulate readings for 1024 times
    {
        sensorValue=analogRead(A8);
        sum=sensorValue+sum;
        delay(2);
    }
    long meanVal = sum/1024;  // get mean value
    Serial.print("The current UV index is:");
    Serial.print((meanVal*1000/4.3-83)/21);// get a detailed calculating expression for UV index in schematic files.
    Serial.print("\n");
    delay(20);

}

void setup() {
 Serial.begin(9600);
 delay(150);
 TH02.begin();
 delay(100);
 Serial.println("TH02_dev is available.\n");    
 DBG_PRINTLN(F("Starting"));
 helium.begin(HELIUM_BAUD_RATE);
 helium_connect(&helium);
 channel_create(&channel, CHANNEL_NAME);
 Wire.begin();
 airqualitysensor.init(14);
}
void loop() {

   int airquality = airqualitysensor.slope();
   //Sound Pollution
   long sound = 0;
   for(int i=0; i<32; i++)
   {
       sound += analogRead(A9);
   }
   float temper = TH02.ReadTemperature(); 
   float humidity = TH02.ReadHumidity();
   String dataString = "air=" + String(airquality) + "&noise=" + String(sound) + "&temperature=" + String(temper) + "&humidity=" + String(humidity);
   char data[dataString.length()];
   dataString.toCharArray(data, dataString.length());
   channel_send(&channel, CHANNEL_NAME, data, strlen(data));
   Serial.println(data);
   setDisplayToOriginalState();
   SeeedGrayOled.clearDisplay();     
   SeeedGrayOled.setNormalDisplay(); 
   SeeedGrayOled.setVerticalMode();  
   SeeedGrayOled.setTextXY(0,0);           
   if (airquality==0)
     SeeedGrayOled.putString("ATENTION: High pollution!!!!");
   else if (airquality==1)
     SeeedGrayOled.putString(" ATENTION: High pollution");
   else if (airquality==2)
     SeeedGrayOled.putString("Low pollution!");
   else if (airquality==3)
     SeeedGrayOled.putString("Fresh Air");
   SeeedGrayOled.setTextXY(2,0);
   String temperaturestring = String(temper) + " C";
   char tempbuffer[temperaturestring.length()];
   temperaturestring.toCharArray(tempbuffer, temperaturestring.length());
   SeeedGrayOled.putString(tempbuffer);
   SeeedGrayOled.setTextXY(3,0);
   String humidstring = "Humid: " + String(humidity);
   char humidbuffer[temperaturestring.length()];
   humidstring.toCharArray(humidbuffer, humidstring.length());
   SeeedGrayOled.putString(humidbuffer);
   SeeedGrayOled.setTextXY(5,0);
   if(sound > 5000)
   {
     SeeedGrayOled.putString("LOUD");
   }
   else if(sound < 4000)
   {
     SeeedGrayOled.putString("QUIET");
   }
   else
   {
     SeeedGrayOled.putString("NORMAL");
   }
   delay(60000);
}
ISR(TIMER1_OVF_vect)
{
 if(airqualitysensor.counter==61)//set 2 seconds as a detected duty
 {
     airqualitysensor.last_vol=airqualitysensor.first_vol;
     airqualitysensor.first_vol=analogRead(A6);
     airqualitysensor.counter=0;
     airqualitysensor.timer_index=1;
     PORTB=PORTB^0x20;
 }
 else
 {
   airqualitysensor.counter++;
 }
}

Credits

Gabriel Alejandro Giraldo Santiago

Gabriel Alejandro Giraldo Santiago

13 projects • 86 followers
Seeed Ranger, AI and Computer Vision expert for key industries. Mentor and speaker on AI, startups, and no-code. Maker enthusiast.

Comments