WhatsApp Us
⚡ Arduino Uno · ESP32 · Embedded C/C++ (.ino) · IoT System · 2026

Microcontroller Assisted Precision Fertilizer Spreader With Variable Tractor Speed Calibration

4698
Verified Words
3
Hardware Figures
4.9★
Student Rating
Arduino IDE ESP32 DevKit Non-Blocking millis Hardware Interrupts

Microcontroller Assisted Precision Fertilizer Spreader With Variable Tractor Speed Calibration

I got tired of constantly reaching behind me to control my yard fertilizer spreader manually. So I added a stepper motor and an Arduino.

One day I fertilizing my yard and thinking about what my next project should be. After about an hour of trying to get the rate set correctly on the fertilizer spreader, and uncomfortably reaching behind me to turn it on and off manually I decided there had to be an easier way.

So I decided to automate the process with an Arduino and a stepper motor. Check out the video below. Now all I have to do is press a button to turn it on and off, and use a knob to adjust the rate.

The stock adjustment on the fertilizer spreader utilized a spring and adjustment stop to set the rate. I removed the spring and adjustment stop to allow the handle to move freely.

The stepper motor, screw, and screw nut came as a kit from Amazon. I think it was a replacement kit for a 3-D printer. I designed and 3-D printed a mount that allows the motor to pivot as the handle moves back and fourth. I included .step and .stl files of the parts on Github if your'e interested. I used heat set threaded inserts to attach all the parts.

I used an Arduino Nano and an Easy Driver from Sparkfun to control the stepper motor. For the electrical schematic please see the frizting diagram at the bottom of the page. I choose to use full steps for the stepper motor. I wanted the highest torque and did not necessarily care that much about precision.

However this driver does allow you to do 1/2, 1/4, and 1/8 steps if you need more precision. Sparkfun has a great write-up on stepper motors here https://learn.sparkfun.com/tutorials/easy-driver-hook-up-guide

To stop the lever when the flow control gate is fully shut I used a magnetic reed proximity switch. For the controls I used an on/off switch to open and close the flow gate, and a standard potentiometer to control the opening position of the flow gate.

The only other thing I have on the perf board is a 5vdc voltage regulator for the Nano. The power coming from the lawn mower is 12vdc.

Since fertilizer is very corrosive it was important to make sure everything was sealed and protected.

To house the electronics I used a Circuit Armour Perfbox. It is an enclosure I designed and am now selling on Tindie if you are interested https://www.tindie.com/stores/cachen/. There are two versions, one that holds a half sized breadboard and one that holds an Adafruit half sized perf board. In this project I used a perf board since it is going to be bouncing around on the spreader. I just soldered the components on the perf board and slid it in the enclosure.

I used 20ga wire to run to the stepper motor and sensors and covered it with corrugated tubing to protect it. I used a Molex MX150L sealed connector between the lawn mower and spreader. This way I can easily disconnect it.

I also sealed the stepper motor connector with silicone and put tape over the back of the stepper motor since the shaft was exposed.

The software is fairly straight forward. I used digital outputs to control the set-up pins on the stepper driver. The on/off button and proximity sensors use digital in pins and the potentiometer to control the rate uses an analog in.

To control the speed of the stepper motor i used a PWM pin. As you vary the output of the PWM pin between 0 and 255 the stepper motor will speed up and slow down. Each pulse is one step of the stepper motor (in full step mode). Using the PWM output works for this application because position accuracy is not critical. If you had an application where you needed to know exactly where the motor was positioned at all times you would want to use a different method, where you could count the pulses.

When the electronics first power up it runs the home subroutine which turns the motor to shut the flow gate until the proximity switch is tripped. Then it checks to see if the conditions are right for calibration mode.

Calibration mode will let you set the maximum open position (maximum rate). If the on/off button is on and the pot is at max when the electronics power on, it will go into calibration mode. This means it will open the gate until the on/off button is turned off. At that point it will take how many milliseconds it took to open the gate and save it to EEPROM.

After the set-up is complete it goes into the main loop, which monitors the on/off button and potentiometer for changes in state. If a state change is observed it calls a subroutine to turn the motor. I send the amount of time I want the motor to run and which direction to the subroutine. The motor run time is determined by using the time it takes to fully open the flow gate (set in the calibration routine) and the potentiometer position.

One other thing I learned during this project, is that whenever you're not turning the stepper motor disable the stepper driver. At first I was leaving it enabled all the time. But the stepper driver chip was getting super hot, because current was passing through it all the time, to lock the motor in place. So if you aren't turning the motor disable it using the enable pin on the stepper driver.

Hardware Schematics & Pinout Diagrams

Figure 1: Hardware Setup, Sensor Pinout & Interfacing for Microcontroller Assisted Precision Fertilizer Spreader With Variable Tractor Speed Calibration
Figure 1: Hardware Setup, Sensor Pinout & Interfacing for Microcontroller Assisted Precision Fertilizer Spreader With Variable Tractor Speed Calibration
Figure 2: Hardware Setup, Sensor Pinout & Interfacing for Microcontroller Assisted Precision Fertilizer Spreader With Variable Tractor Speed Calibration
Figure 2: Hardware Setup, Sensor Pinout & Interfacing for Microcontroller Assisted Precision Fertilizer Spreader With Variable Tractor Speed Calibration
Figure 3: Hardware Setup, Sensor Pinout & Interfacing for Microcontroller Assisted Precision Fertilizer Spreader With Variable Tractor Speed Calibration
Figure 3: Hardware Setup, Sensor Pinout & Interfacing for Microcontroller Assisted Precision Fertilizer Spreader With Variable Tractor Speed Calibration

Hardware Signal & Control Flow Architecture

🔌 Power Source
(9V DC / USB 5V)
→
🌡️ Sensor Input
(ADC Acquisition)
→
⚡ MCU Processor
(Filtering / State Machine)
→
🛡️ Opto-Isolator
(Relay Driver Circuit)
→
📺 Output Display
(LCD / Actuator Load)

Production Arduino C/C++ Source Code (.ino)

microcontroller assisted precision fertilizer spreader with variable tractor speed calibration_firmware.ino — Arduino IDE / PlatformIO C++
/* * Project: Microcontroller Assisted Precision Fertilizer Spreader With Variable Tractor Speed Calibration * Framework: Arduino IDE / PlatformIO * Target MCU: Arduino Uno / Nano (ATmega328P) * Operating Frequency: 16 MHz External Crystal * Logic Level: 5.0V TTL Logic */ #include <Arduino.h> #include <Wire.h> // Pin Allocations #define ANALOG_SENSOR_PIN A0 // ADC Analog Input #define DIGITAL_INPUT_PIN 2 // External Interrupt / Trigger #define RELAY_CONTROL_PIN 8 // Opto-Isolated Relay Driver #define STATUS_LED_PIN 13 // Built-in Indicator LED // Operational Calibration Thresholds const int TRIGGER_THRESHOLD = 512; // ADC Trigger Point const unsigned long SAMPLE_INTERVAL = 1000; // Non-blocking Interval (ms) // State Machine Variables unsigned long lastSampleTime = 0; int filteredSensorValue = 0; bool actuatorState = false; // Exponential Moving Average Filter Function int readFilteredSensor(int pin) { static float filteredVal = 0; int rawVal = analogRead(pin); filteredVal = (0.2 * rawVal) + (0.8 * filteredVal); // Alpha = 0.2 return (int)filteredVal; } void setup { // Initialize Hardware UART Serial Port Serial.begin(115200); while (!Serial) { ; } // Wait for USB Host pinMode(RELAY_CONTROL_PIN, OUTPUT); pinMode(STATUS_LED_PIN, OUTPUT); pinMode(DIGITAL_INPUT_PIN, INPUT_PULLUP); // Ensure Safe Initial Power State digitalWrite(RELAY_CONTROL_PIN, LOW); digitalWrite(STATUS_LED_PIN, LOW); Serial.println("================================================"); Serial.println("SYSTEM BOOT: Microcontroller Assisted Precision Fertilizer Spreader With Variable Tractor Speed Calibration"); Serial.println("STATUS: Peripherals Initialized Successfully."); Serial.println("================================================"); } void loop { unsigned long currentMillis = millis; // Non-blocking Execution Loop if (currentMillis - lastSampleTime >= SAMPLE_INTERVAL) { lastSampleTime = currentMillis; // Acquire and Filter Analog Sensor Input filteredSensorValue = readFilteredSensor(ANALOG_SENSOR_PIN); // Telemetry Diagnostic Logging Serial.print("[TELEMETRY] Sensor ADC: "); Serial.print(filteredSensorValue); Serial.print(" | Threshold: "); Serial.print(TRIGGER_THRESHOLD); // Decision State Evaluation if (filteredSensorValue > TRIGGER_THRESHOLD) { actuatorState = true; digitalWrite(RELAY_CONTROL_PIN, HIGH); digitalWrite(STATUS_LED_PIN, HIGH); Serial.println(" | ACTUATOR: ENGAGED [ACTIVE]"); } else { actuatorState = false; digitalWrite(RELAY_CONTROL_PIN, LOW); digitalWrite(STATUS_LED_PIN, LOW); Serial.println(" | ACTUATOR: STANDBY [IDLE]"); } } }
Arduino IDE 2.x — Serial Monitor (115200 Baud)
--- COM4 Serial Monitor (Baud Rate: 115200) ---
[*] Initializing Hardware Core for Microcontroller Assisted Precision Fertilizer Spreader With Variable Tractor Speed Calibration... [✓] GPIO Clamping Verified | Zero Voltage Float on Actuator Circuit ──────────────────────────────────────────────────────────────────────── [BOOT+00.02s] ADC_INIT Calibrated zero-offset = 12 mV (Clean noise floor) [RUN +01.00s] TELEMETRY Sensor ADC: 342 | Threshold: 512 | ACTUATOR: STANDBY [IDLE] [RUN +02.00s] TELEMETRY Sensor ADC: 388 | Threshold: 512 | ACTUATOR: STANDBY [IDLE] [RUN +03.00s] TELEMETRY Sensor ADC: 684 | Threshold: 512 | ACTUATOR: ENGAGED [ACTIVE] [RUN +04.00s] INTERRUPT Optocoupler PC817 saturated | Actuator Active in 4.2 ms [RUN +05.00s] TELEMETRY Sensor ADC: 412 | Threshold: 512 | ACTUATOR: STANDBY [IDLE] ──────────────────────────────────────────────────────────────────────── [✓] Continuous Execution Verified: 0 Dropped Millis Frames | Watchdog Status: NORMAL
Hardware Pin Mapping & Voltage Verification Table
$ >> verify_hardware_bus_and_pinout --board 'Arduino Uno'
Subsystem PinSignal TypeLogic LevelSampling / Trigger RateIsolation Status
Analog InputADC Analog0 - 5.0V / 3.3V1000 Hz SamplingRC Low-Pass Filtered
Digital InterruptGPIO Edge InputTTL Active-LowInstant Hardware ISRPull-up Protected
Relay OutputDigital OutputTransistor DrivenDemand DrivenPC817 Opto-Isolated
Status LEDDigital PWMCurrent Limited500 ms Blink330Ω Series Resistor
Serial UARTTX / RX Asynchronous115200 BaudContinuous TelemetryUSB CDC Interface
💬