Data and Images from sensor with Arduino/IoT in agricultural field

Project Overview: TechFarming - Revolutionizing Agriculture with Data-Driven Precision

Introduction:
Greetings, dear readers! I am Lungchuingam, the mind behind "TechFarming," an ambitious agricultural e-commerce project aimed at transforming the industry through cutting-edge technologies. This endeavor seeks to create a data-driven marketing system, seamlessly integrating hardware and software to enhance farming practices.

Technical Stack:

  1. Technology Stack: MySQL for the database, React for the front-end, and Express/Node for the server from the robust foundation of TechFarming.

  2. Rover Design:

    • Equipped with sensors, the rover's mission is to gather crucial soil parameters (pH, NPK, Moisture) and environmental data (temperature, humidity, rain).
    • YOLOv5 technology powers an AI/HD camera, detecting pests and monitoring plant health.
  3. Rover Control:

    • Manual Operation: Implemented with a camera for user oversight and algorithms for crop avoidance.
    • Autonomous Control: Utilizing LiDAR and GPS modules, the rover navigates fields, collecting valuable gray value data for analysis.
  4. Data Processing:

    • Computer Vision: Images and data collected by the rover are processed using CNN algorithms and TensorFlow.
    • Data Storage: Continuous improvement is ensured by storing images and data for further model training and expanding datasets for enhanced learning.

Arduino Code - Rover Control:

#include <Servo.h>
#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include <Adafruit_PWMServoDriver.h>
#include <SoftwareSerial.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>

SoftwareSerial voiceSerial(10, 11);

Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_DCMotor *frontLeftMotor = AFMS.getMotor(1);
Adafruit_DCMotor *frontRightMotor = AFMS.getMotor(2);
Adafruit_DCMotor *backLeftMotor = AFMS.getMotor(3);
Adafruit_DCMotor *backRightMotor = AFMS.getMotor(4);
Adafruit_DCMotor *additionalLeftMotor = AFMS.getMotor(5);
Adafruit_DCMotor *additionalRightMotor = AFMS.getMotor(6);

const int buzzer = 9;
const int additionalMotorSwitchPin = 7;
Servo cameraServo;

const char *ssid = "YourWiFiSSID";
const char *password = "YourWiFiPassword";
const String serverUrl = "http://localhost:9000/api/rover-control";

void setup()
{
  AFMS.begin();
  frontLeftMotor->setSpeed(255);
  frontRightMotor->setSpeed(255);
  backLeftMotor->setSpeed(255);
  backRightMotor->setSpeed(255);
  voiceSerial.begin(9600);
  cameraServo.attach(9);

  // Set up additional motor switch
  pinMode(additionalMotorSwitchPin, INPUT);
  pinMode(buzzer, OUTPUT);


  // Connect to WiFi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");

  // Initialize LiDAR, GPS, and computer vision components here
}

void loop()
{
  // Check for voice commands
  if (voiceSerial.available() > 0)
  {
    String voiceCommand = voiceSerial.readStringUntil('\n');
    processVoiceCommand(voiceCommand);
  }

  void checkServerCommands() {
  // Implement code to check for commands from the server
  // Example: You can use the HTTPClient to send a request to the server
  // and parse the response to get the rover control command.
  // Use the sendRoverControlRequest function for communication.
}

   checkServerCommands();

  // Implement autonomous navigation using computer vision, LiDAR, and GPS
  // Add code to handle motor control based on the autonomous navigation results

  // Check the additional motor switch state
  if (digitalRead(additionalMotorSwitchPin) == HIGH)
  {
    activateAdditionalMotors();
    additionalLeftMotor->setSpeed(255);
    additionalRightMotor->setSpeed(255);
  }
}

void processVoiceCommand(String command)
{
  command.toLowerCase();

  if (command.startsWith("hope"))
  {
    if (command.indexOf("move forward") != -1)
    {
      moveForward();
    }
    else if (command.indexOf("backward") != -1)
    {
      moveBackward();
    }
    else if (command.indexOf("turn right") != -1)
    {
      turnRight();
    }
    else if (command.indexOf("turn left") != -1)
    {
      turnLeft();
    }
    else if (command.indexOf("stop") != -1)
    {
      stop();
    }
    else if (command.indexOf("sound horn") != -1)
    {
      soundHorn();
    }
  }
  else if (command.startsWith("hope! this is lucky your master, good morning"))
  {
    greetMaster();
  }
}

void greetMaster()
{
  // Implement actions when the master is greeted
  // For example, you can make the rover respond in some way
}

void soundHorn()
{
  for (int i = 0; i < 3; ++i) {
    tone(buzzer, 1000);
    delay(3000);
    noTone(buzzer);
    delay(2000);
  }
}

void moveForward()
{
  frontLeftMotor->run(FORWARD);
  frontRightMotor->run(FORWARD);
  backLeftMotor->run(FORWARD);
  backLeftMotor->run(FORWARD);
}

void moveBackward()
{
  frontLeftMotor->run(BACKWARD);
  frontRightMotor->run(BACKWARD);
  backRightMotor->run(BACKWARD);
  backRightMotor->run(BACKWARD);
}

void turnLeft()
{
  frontLeftMotor->run(BACKWARD);
  frontRightMotor->run(FORWARD);
  backLeftMotor->run(BACKWARD);
  backRightMotor->run(FORWARD);
}

void turnRight()
{
  frontLeftMotor->run(FORWARD);
  frontRightMotor->run(BACKWARD);
  backLeftMotor->run(FORWARD);
  backRightMotor->run(BACKWARD);
}

void stop()
{
  frontLeftMotor->run(RELEASE);
  frontRightMotor->run(RELEASE);
  backLeftMotor->run(RELEASE);
  backRightMotor->run(RELEASE);
}

void activateAdditionalMotors()
{
  void moveForward()
  {
    additionalLeftMotor->run(FORWARD);
    additionalRightMotor->run(FORWARD);
  }
  void moveBackward()
  {
    additionalLeftMotor->run(BACKWARD);
    additionalRightMotor->run(BACKWARD);
  }
  void turnLeft()
  {
    additionalLeftMotor->run(BACKWARD);
    additionalRightMotor->run(FORWARD);
  }
  void turnRight()
  {
    additionalLeftMotor->run(FORWARD);
    additionalLeftMotor->run(BACKWARD);
  }
  void stop()
  {
    additionalLeftMotor->run(RELEASE);
    additionalRightMotor->run(RELEASE);
  }
}

void sendRoverControlRequest(String command)
{
  HTTPClient http;
  http.begin(serverUrl);
  http.addHeader("Content-Type", "application/json");
  String requestBody = "{\"command\": \"" + command + "\"}";
  int httpResponseCode = http.POST(requestBody);
  http.end();
}

Arduino Code - Soil Parameters:

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <SoftwareSerial.h>
#include <WiFiClient.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>

SoftwareSerial espSerial(2, 3);  
DHT dht(7, DHT22);

const char* ssid = "YourWiFiSSID";
const char* password = "YourWiFiPassword";
const char* serverUrl = "http://localhost:9000/api/soil-data"; 

void setup() {
  Serial.begin(9600);
  espSerial.begin(9600);

  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");
}

void loop() {
  float temperature = dht.readTemperature();
  float humidity = dht.readHumidity();

  // Read data from other soil sensors
  float npkValue = readNPKSensor();  
  float phValue = readPHSensor();  
  float moistureValue = readMoistureSensor();
  float waterValue = readWaterSensor();

  if (isnan(temperature) || isnan(humidity)) {
    Serial.println("Failed to read from DHT sensor");
    return;
  }

  String data = "temperature=" + String(temperature) +
                "&humidity=" + String(humidity) +
                "&npk=" + String(npkValue) +
                "&ph=" + String(phValue) +
                "&moisture=" + String(moistureValue) +
                "&water=" + String(waterValue);

  sendDataToServer(data);
  delay(60000); 
}

float readNPKSensor() {
  int npkSensorValue = analogRead(A1);
  float npkValue = map(npkSensorValue, 0, 1023, 0, 10);
  return npkValue;
}

float readPHSensor() {
  int phSensorValue = analogRead(A2);
  float phValue = map(phSensorValue, 0, 1023, 0, 14); 
  return phValue;
}

float readMoistureSensor() {
  int moistureSensorValue = analogRead(A3);
  float moistureValue = map(moistureSensorValue, 0, 1023, 0, 100); 
  return moistureValue;
}

float readWaterSensor() {
  int waterSensorValue = analogRead(A4);
  float waterValue = map(waterSensorValue, 0, 1023, 0, 100);
  return waterValue;
}

void sendDataToServer(String data) {
  WiFiClient client;
  HTTPClient http;

  http.begin(client, serverUrl);
  http.addHeader("Content-Type", "application/x-www-form-urlencoded");

  int httpResponseCode = http.POST(data);

  if (httpResponseCode > 0) {
    String response = http.getString();
    Serial.println("HTTP Response Code: " + String(httpResponseCode));
    Serial.println(response);
  } else {
    Serial.println("Error on HTTP request");
  }

  http.end();
}

Server Code - Rover Control:

<!-- ControllingPage.html -->
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hope--Rover Control</title>
    <script src="https://unpkg.com/nipplejs@0.11.0/dist/nipplejs.min.js"></script>
    <script src="https://kit.fontawesome.com/a076d05399.js" crossorigin="anonymous"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"
        integrity="sha384-FfE5i1BgBpNBvKU8a4P3o2NBsKbRjIo4gg5ZUnkQXa3q2j50QC3rWUE5Xl8qDWfP" crossorigin="anonymous">
    <style>
        body {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        .rover-controlling-container {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            height: 100%;
            width: 100%;
        }

        .rover-controlling-container h1 {
            color: #744bdd;
        }

        .rover-controlling-container h1 span:nth-child(1) {
            color: #43d843;
        }

        .rover-controlling-container h1 span:nth-child(2) {
            color: #f5d20b;
        }

        #video-stream {
            width: 640px;
            height: 480px;
        }

        .rover-controlling-container .rover-controlling-buttons {
            margin-top: 30px;
        }

        .rover-controlling-container .rover-controlling-buttons .controls table tr td button{
          height: 100px;
          width: 100px;
          background-color: #43d843;
          border-radius: 50%;
          border: none;
          color: #fafafa;
          cursor: pointer;
          transition: all .5s ease-in-out;
        }

        .rover-controlling-container .rover-controlling-buttons .controls table tr td button:hover{
            background-color: #15ca15;
            box-shadow: 5px 5px 10px #555;
        }
    </style>
</head>

<body>
    <div class="rover-controlling-container">
        <h1><span>Tech</span><span>Farming</span> &nbsp; Rover - Hope</h1>

        <!-- Live video stream -->
        <video id="video-stream" autoplay></video>

        <!-- Rover controls -->
        <div class="rover-controlling-buttons">
            <div id="controls" class="controls">
                <table>
                    <tr>
                        <td></td>
                        <td><button onclick="sendCommand('moveForward')">Forward</button></td>
                        <td></td>
                    </tr>
                    <tr>
                        <td> <button onclick="sendCommand('turnLeft')">Left</button></td>
                        <td> <button onclick="sendCommand('stop')">Stop</button></td>
                        <td> <button onclick="sendCommand('turnRight')">Right</button></td>
                    </tr>
                    <tr>
                        <td></td>
                        <td> <button onclick="sendCommand('moveBackward')">Backward</button></td>
                        <td></td>
                    </tr>
                </table>
            </div>
            <button onclick="sendCommand('activateAdditionalMotors')">Activate Additional Motors</button>
        </div>
        <!-- Camera servo control -->
        <div id="joystick-container" class="joystick">
            <div id="joystick-handle"></div>
        </div>
    </div>

    <script>
        // Function to send rover control commands to the server
        function sendCommand(command) {
            fetch(`http://localhost:9000/api/rover-control?command=${command}`, {
                method: 'POST',
            });
        }



        // Function to start the video stream from the rover camera
        async function startVideoStream() {
            const videoElement = document.getElementById('video-stream');

            try {
                const stream = await navigator.mediaDevices.getUserMedia({ video: true });
                videoElement.srcObject = stream;
            } catch (error) {
                console.error('Error accessing camera:', error);
            }
        }

        function initializeJoystick() {
            const joystickContainer = document.getElementById('joystick-container');
            const joystickHandle = document.getElementById('joystick-handle');

            // Create a joystick using nipplejs
            const joystick = nipplejs.create({
                zone: joystickContainer,
                mode: 'static',
                position: { top: '50%', left: '50%' },
                color: 'blue',
            });

            function moveJoystickHandle(data) {
                const normalizedX = data.vector.x / 50;
                const normalizedY = data.vector.y / 50;

                // Calculate angle and magnitude
                const angle = Math.atan2(normalizedY, normalizedX) * (180 / Math.PI) + 180;
                const magnitude = Math.min(100, Math.sqrt(normalizedX ** 2 + normalizedY ** 2) * 100);

                // Adjust the position of the joystick handle based on joystick movements
                const handleRadius = 25; // Half of the joystick handle width/height
                const handleX = magnitude * Math.cos(angle * (Math.PI / 180)) - handleRadius;
                const handleY = magnitude * Math.sin(angle * (Math.PI / 180)) - handleRadius;

                // Update the position of the joystick handle
                joystickHandle.style.transform = `translate(${handleX}px, ${handleY}px)`;

                // Use JavaScript to send the camera control command to the server
                fetch(`http://localhost:9000/api/rover-control?command=adjustCamera&angle=${angle}&magnitude=${magnitude}`, {
                    method: 'POST',
                });
            }

            joystick.on('move', (event, data) => {
                moveJoystickHandle(data);
            });

            // Handle mouse move event for desktop
            joystickContainer.addEventListener('mousemove', (event) => {
                if (event.buttons === 1) {
                    // Only move joystick handle if the left mouse button is pressed
                    const rect = joystickContainer.getBoundingClientRect();
                    const x = event.clientX - rect.left;
                    const y = event.clientY - rect.top;
                    const normalizedX = (x - rect.width / 2) / (rect.width / 2);
                    const normalizedY = (y - rect.height / 2) / (rect.height / 2);
                    moveJoystickHandle({ vector: { x: normalizedX * 50, y: normalizedY * 50 } });
                }
            });

            // Handle touch move event for tablets and phones
            joystickContainer.addEventListener('touchmove', (event) => {
                event.preventDefault(); // Prevent default touch behavior (e.g., scrolling)
                const touch = event.touches[0];
                const rect = joystickContainer.getBoundingClientRect();
                const x = touch.clientX - rect.left;
                const y = touch.clientY - rect.top;
                const normalizedX = (x - rect.width / 2) / (rect.width / 2);
                const normalizedY = (y - rect.height / 2) / (rect.height / 2);
                moveJoystickHandle({ vector: { x: normalizedX * 50, y: normalizedY * 50 } });
            });
        }



        // Start the video stream when the page loads
        window.onload = () => {
            startVideoStream();
            initializeJoystick();
        };
    </script>
</body>

</html>

Professional Collaboration:
For collaboration opportunities, please visit my GitHub repository. Your insights and collaboration are invaluable to the success of TechFarming.

Conclusion:
I extend my sincere gratitude for your time and consideration. Your response will undoubtedly propel TechFarming towards achieving its ambitious goals. For inquiries or collaborations, feel free to reach out.

Best regards,
Lungchuingam

moved this post to the Product and Services category.

1 Like

I am glad for your reply and spending your precious time with my posts. However this is still my confusion how do I move the topic to another category.

I did move it for you. This seems the right place. elsewhere it would be considered like advertising / spam.

1 Like

Thank you Jackson, I remember you last time you helped me in one of my project I was doing doing my diploma back then. Now I have completed my graduation as a bachelor in electronic and communication. And the idea I posted is my startup idea.

congrats for your diploma and fair winds for your startup idea (not sure this forum is the best place for doing business)

1 Like

I understand that, can I atleast get data of sensors from agricultural fields from the rover to my local server. And what are the required framework to obtain so.

is that a question?

Yes can I collect data from the sensors, capture images, send it to the local server so there I can run my ML algorithms.??
I want to know what additional framework are required to do so??

yes you can collect data and export them

sending them to the server depends on your networking technology of choice (Lora, WiFi, 4G, Zigbee, Bluetooth, Ethernet, ...) and protocol (HTTP, ...) and what's on the server side to get the data.

How you process the data is also up to you and your server's capabilities; Python is pretty powerful there to apply ML stuff.

1 Like

I am using http protocol to import data and images over 4g network.
And also is there any Arduino controller which allows me to embed camera or or i will have to go with raspberry pi for that??

The ESP32-CAM can be programmed with the Arduino IDE.

Photo web server example

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.