DIY Android / Arduino planter monitor

Seed Meter Testing

If youíre a farmer you probably know about some of the recent precision farming improvements to our planters. Farmers are looking at such things as seed placement, singulation, skips, doubles, down pressure, smooth ride, movable trash whips, row shut-offs, variable rate planting, dual variety planting, planting prescriptions, auto-steer, auto-swath. If youíre not a farmer, these will mean little to you. I thought you might like to see what can be developed using open source products.

Buiding a test stand


In 2012, I wanted to test my corn planter units to see that they are working properly without paying $30 per row just to have them looked at. Two years before I spent over $800 to have my precision units tested and repairs made. SoÖa trip to Colfax (Iowa) to the local farm implement salvage yard yielded the guts of one row off a John Deere 7000 planter. A couple of days later, legs were added to make it a stand alone test stand. With a trip to the cousins to torch off stuff I didnít need and weld on a bracket for a motor, the thing got motorized. A 107.5 RPM gear motor from and a new sprocket from John Deere simulates driving the planter at 5 mph. A good spreadsheet and a bunch of math figured out the seeds per second. The test stand senses seed from the meter with a conventional high speed seed sensor (electric eye). I've now found that the old style red LED sensors will work as well. The seed sensor is connected to an Arduino ( board which acts as a digital-to-serial interface. This is connected to a PC via a standard USB port. With programming for the Arduino and the PC you get a test stand that can test for skips, multiple seeds dropped at the same time, singulation, and even problems from individual finger pickups. With seed population displayed itís giving the similar information as the expensive stands that implement dealers and precision ag companies have produced.

After I got the test stand working and tested my meters and a few others, I definitely wanted to see if I could modify the program to monitor all eight rows of my planter and run the monitor in the cab while I was planting. That turned out to be more difficult than I thought and I did not get the electronic interface to work by the time I started planting on April 11th. I did get it all together by the 22nd when I planted the remainder of my corn. It definitely helped as I could adjust the brushes on my meters to work best with different size and shape seed. It also showed me problems with two rows that I was able to resolve. The video is quite shakey at first. It was difficult holding my cell phone still while the tractor was bouncing. The display at the bottom is the tractor and planter with seed coming out behind the planter. Yellow squares indicate a skip. Blue squares a double. So you can see my planter has room for improvement.

By Spring of 2014 I switched to an Android tablet mounted in the cab of my tractor with a RAM mount. I had multiple planter problems that plagued me the first three days of corn planting. Even after spring meter testing and planter upgrades, a row sensor failed the first day of planting. The first new row sensor didn't work which lead to further frustrations trying to figure out what was wrong. My planter monitor showed all sorts of skips even though I didn't see them digging in the soil behind the planter. It was extremely dusty. Driving west, I had to stop at the end of the field to let the dust blow by me before I could turn. I was using auto steer to drive straight as I could not see the marker half the time.

Control box for my planter monitor test stand

This is the circuit for my planter test stand used to test seed meters for uniform seed placement. The blue board on the left is an Arduino Uno Rev.3. On the right is an Arduino Proto Shield that mounts on top of the Uno with "headers". I've added the wiring illustrated. Where I have drawn the row sensor wires, I actually have a piece of cable cut off an old row sensor that has a male weather-pack connector where the row sensor connects. The Arduino is supplying +5v power to the row sensor through the red and black wires. For interfacing to a PC via USB cable, take off the Bluetooth module and wiring but keep the 10K resistor that holds the seed sensor signal wire high (to +5V). The Arduino needs to be powered from its round power connector or through the USB cable to a PC.

The Arduino code:

/* Each time the a row's input pin goes from LOW to HIGH (e.g. because of a seed
passing the sensor), the output pin is toggled from LOW to HIGH. There's
a minimum delay between toggles to debounce the circuit (i.e. to ignore noise).

created 27 April 2013 by modifying the Example / Digital / Debounce
updated 6 August 2017
by James K. Poyzer

long millisAtGPS = 0;
String rowinfo = "";
long debounceDelay = 3; // the debounce time; increase if the output flickers
int systemResetDelay = 1000;
int reading = 0;
int takeAction = 0;
int sensorState = 0;
int newSensorState = 0;
int lastSensorState = 0;
long lastDebounceTime = 0;
long millisAtLastSeed = 0;
int millisSinceLastSeed = 0;
long seedGap = 0;
void setup() {
Serial.begin(9600); // Initialize serial communications on serial port

pinMode(2, INPUT_PULLUP);
lastDebounceTime = 0;
millisAtLastSeed = millis();
digitalWrite(2, HIGH);/
delay (systemResetDelay);
} //void setup

void loop() {
if ((millis() - lastDebounceTime) > debounceDelay) {
// don't take a reading everytime, wait for
// the delay time before checking to see if something
// changed
takeAction = 1;
} // delayed long enough for reading to be stable

if (takeAction == 1) {
reading = digitalRead(2); // read will be high or low (1 or 0)
if (reading != lastSensorState) { // not equal
newSensorState = reading;
if (newSensorState == LOW) {
// okay to write record
seedGap = (millis() - millisAtLastSeed);
rowinfo = ("R01");
if (seedGap < 10) {
rowinfo = rowinfo + "0";
if (seedGap < 100) {
rowinfo = rowinfo + "0";
if (seedGap > 999) {
seedGap = 999;
rowinfo = rowinfo + String(seedGap) + "X";
Serial.println(rowinfo); // output looks like "R01057X" - row 1 with 57 milliseconds between seeds
takeAction = 0; // delay next time it comes to this row
millisAtLastSeed = millis(); //to be used when next seed comes
lastDebounceTime = millis(); // for delaying next look
} // sensorState = LOW
lastSensorState = reading;
} // reading != old one
} // end where takeAction was 1

} // end of void loop