Evan Rust
Published © GPL3+

Determining a Plant's Health with TinyML

Scan the leaves of a plant with an Arduino Nano 33 BLE Sense and train a model to detect if it's diseased.

IntermediateFull instructions provided10 hours12,409
Determining a Plant's Health with TinyML

Things used in this project

Hardware components

Arduino Nano 33 BLE Sense
Arduino Nano 33 BLE Sense
×1
Stepper Motor
Digilent Stepper Motor
×1
Driver DRV8825 for Stepper Motors for Theremino System
Driver DRV8825 for Stepper Motors for Theremino System
×1

Software apps and online services

VS Code
Microsoft VS Code
Arduino IDE
Arduino IDE
Edge Impulse Studio
Edge Impulse Studio

Hand tools and fabrication machines

3D Printer (generic)
3D Printer (generic)
Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Custom parts and enclosures

Parts to 3D Print

Schematics

DRV8825 Wiring

Code

leafReader.ino

C/C++
#include <Arduino_APDS9960.h>
#include <AccelStepper.h>
#include <MultiStepper.h>
#include "pinDefs.h"

int r, g, b, c, p;
float sum;

AccelStepper xStepper(AccelStepper::DRIVER, STEPPER_1_STEP, STEPPER_1_DIR);
AccelStepper yStepper(AccelStepper::DRIVER, STEPPER_2_STEP, STEPPER_2_DIR);

MultiStepper steppers;

// a random location will be chosen within the bounding box
const long boundingBox[2][2] = 
{
    {0, 0},
    {40, 40}
};

void setup()
{
    Serial.begin(115200);
    while(!Serial);

    if(!APDS.begin()) {
        Serial.println("Could not init APDS9960");
        while(1);
    }

    pinMode(X_AXIS_HOMING_SW, INPUT_PULLUP);
    pinMode(Y_AXIS_HOMING_SW, INPUT_PULLUP);
    //Serial.println(digitalRead(X_AXIS_HOMING_SW) + digitalRead(Y_AXIS_HOMING_SW));

    xStepper.setPinsInverted(X_AXIS_DIR);
    yStepper.setPinsInverted(Y_AXIS_DIR);

    xStepper.setMaxSpeed(150);
    yStepper.setMaxSpeed(150);

    steppers.addStepper(xStepper);
    steppers.addStepper(yStepper);
    homeMotors();
}

void loop()
{
    long randomPos[2];
    randomPos[0] = random(boundingBox[0][0], boundingBox[1][0]) * STEPS_PER_MM;
    randomPos[1] = random(boundingBox[0][1], boundingBox[1][1]) * STEPS_PER_MM;

    steppers.moveTo(randomPos);
    while(steppers.run())
    {
        if(!APDS.colorAvailable() || !APDS.proximityAvailable()){}
        else {
            APDS.readColor(r, g, b, c);
            sum = r + g + b;
            p = APDS.readProximity();

            if(!p && c > 10 && sum >= 0)
            {
                float rr = r / sum, gr = g / sum, br = b / sum;
                Serial.printf("%1.3f,%1.3f,%1.3f\n", rr, gr, br);
            }
        }
    }
}

void homeMotors()
{
    // home x
    //Serial.println("Now homing x");
    while(digitalRead(X_AXIS_HOMING_SW))
        xStepper.move(-1);
    // home y
    //Serial.println("Now homing y");
    while(digitalRead(Y_AXIS_HOMING_SW))
        yStepper.move(-1);
    xStepper.setCurrentPosition(0);
    yStepper.setCurrentPosition(0);
}

pinDefs.h

C/C++
#define STEPPER_1_STEP 2
#define STEPPER_1_DIR 3
#define STEPPER_2_STEP 4
#define STEPPER_2_DIR 5
#define X_AXIS_HOMING_SW 6
#define Y_AXIS_HOMING_SW 7

// true if inverted
#define X_AXIS_DIR false
#define Y_AXIS_DIR false

#define MICROSTEPS 1

#define STEPS_PER_MM 160 * MICROSTEPS

Credits

Evan Rust

Evan Rust

120 projects • 1054 followers
IoT, web, and embedded systems enthusiast. Contact me for product reviews or custom project requests.

Comments