Introduction: Arduino LDR Motion Tracking

About: I have been working in IT since the mid 1980's. Most of that has been database and application development. I've been working on Internet application development since the late 1980's. And, we're back in Tass…

I've been toying with the idea of doing something with motion tracking. I'd like to build a little motion tracking Nerf gun turret (or similar) so I thought I'd start with some basics, nothing too flash, nothing too expensive so I started to look around on the Interweb for ideas.

I found a load of stuff for using PIR (passive infra-red sensor) modules on the Arduino and several for dedicated video processing boards, but that seems a little overkill to me. And then I found a Makezine article "Motion Tracking Halloween Props" by the author Jason Poel Smith who uses LDR (light dependent resistors) instead.

The article was pretty good, so I decided to use this as a starting point.

Before going on, I thought that it would be a good idea to build a simple circuit that I can use to learn using LDR for my goals.

For this article I'm using:

  • Arduino UNO;
  • 6 x 10k ohm resistors (eBay for $0.02 each);
  • 6 x LDR (photoresistor GL5528 which I picked up on eBay for $0.36 AUD each);
  • a bunch of jumper

Step 1: Wiring the Board

The board itself is very, very simple.

The Arduino GND and 5V are connected to the power rails of the breadboard.

Each of the 6 LDR are connected:

5V > 10K Resistor > Jumper to Analog Pin > LDR > GND (the second image shows the detail of the LDR "column").

That is, we are creating a voltage splitting circuit that will split the voltage between the 10K resistor and the variable resistance of the LDR.

We'll use the Arduino to read the voltage as it is affected by the resistance variability of the LDR.

That's it. Simple!

Step 2: Code It Up

Before I go into the code of the sketch, you need to know that there is a lot of variability in the resistance values for each LDR (well, certainly at $0.36 each), and I want the readings to be as close to each other as possible, in terms of scale. So, part of the code is intended to weight the readings for each of the LDR to level the readings.

My approach may be clunky, but it seems to work.

I'm using for loops to initialize the Arduino analog pins:

for(int indexA = 0; indexA < 6; indexA++)  {
  pinMode(indexA, INPUT);  
 }

then I work out the average for all LDR and the weighting for each LDR (against that average)

void averageLDR()<br>{
  int tmpAvg = 0;
  for(int indexA = 0; indexA < 6; indexA++)
  {
    int tmpVal = 0;
    for(int indexB = 0; indexB < 100; indexB++)
    {
      tmpVal += analogRead(indexA);
    }
    LDR[indexA] = tmpVal / 100;
    ldrAvg += LDR[indexA];
  }
  ldrAvg = ldrAvg / 6;
  for(int indexA = 0; indexA < 6; indexA++)
  {
    LDR[indexA] = ldrAvg - LDR[indexA];
  }
}

The average is done by taking 100 reads for each LDR, adding the values up and dividing by 100. The average is written to a 6 element array. The array values are added together and divided by 6 to give an overall average for the LDR, finally, the individual LDR value is added back to the array as the overall average - the individual average. So, you end up with an overall average (ldrAverage) and 6 weightings (LDR[6]) that will be applied to each analogRead, thus:

void loop()<br>{
 for(int indexA = 0; indexA < 6; indexA++)
 {
  inputValue = analogRead(indexA) + LDR[indexA];
  String se = String("LDR: " + String(indexA) + " Value: " + String(inputValue));
  Serial.println(se);
 }
 Serial.println("------------------------------");
 delay(3000);
}

The sketch look simply keeps on reading each of the LDR sequentially.

What you end up with is a serial output that gives you some initialization information about the averaging process and then the LDR readings.

You can see how this can then be applied to a motion tracking sketch.

Get the highest value reading, that's where the center of the motion is, you could get the next highest neighbor to see if the motion is just left or just right of the LDR.

If two LDR are equivalent, the motion is centered between these two LDR ... and so on.

So, instead of just sending the output to Serial, you can do something nifty with them ... and go rotate a gun turret!