Subscribe via RSS

Properly reading values from a Sharp GP2D12

Right, my efforts to read an IR Voltage until now have been flawed. It seems that my method of just plugging analogue inputs into my Arduino and expecting a clean reading was pointless. 'Noise' is a huge factor when reading analogue inputs (let alone correct pull-up/down resistors and grounding!) and dirty power supplies + PWM generation circuits really do kill any analogue data floating around.

Before I go into the actual sensors, read the Analogue Input Pin tutorial for the Arduino and also some sample code to read range of Sharp sensor.

So, how do you sort all these noise issues this out? Capacitors!
Based on the references below... you're either to put a ~22uf Capacitor between Vcc and GND or a 4.7uf Capacitor between Vout and GND. Firstly, here's the references:

Arduino + Sharp Sensors:

Other links on the Sharp sensors:

From all this information above I tinkered further with the sensors; but then proceeded to give up. The readings were much more stable, but I simply couldn't get them to do what I wanted as their values would drop off when the distance between the vehicle and sensor was less than 10cm.

Following is the code I used. Note that it does some trickery with caching the last 20 values and averaging them... I'll explain this all further in my next post.

#define NUM_INDEXES 20
class DistanceDetector {
  int min_valid;
  int max_valid;
  int analogPinNumber;
  int latest_max_value;
  int latest_min_value;
  int latest_time_updated;Here is the code I used anyway
  int lastIndex;
  bool full;
  void CalcAverage();
  int lastReadValues[NUM_INDEXES];
  int sensorValue;
  DistanceDetector(int _analogPinNumber);
  void UpdateDetector();
DistanceDetector::DistanceDetector(int _analogPinNumber) {
 min_valid = 100;
 max_valid = 600;
 lastIndex = 0;
 analogPinNumber = _analogPinNumber;
 full = false;
 for (int idx = 0; idx < NUM_INDEXES; idx++) lastReadValues[idx] = 0;
void DistanceDetector::UpdateDetector()
 int latest_value = analogRead(analogPinNumber);
 if (latest_value >= min_valid && latest_value <= max_valid) {
  lastReadValues[lastIndex] = latest_value;
  if (lastIndex > NUM_INDEXES) {
   lastIndex = 0;
   full = true;
void DistanceDetector::CalcAverage() {
 sensorValue = 0;
 for (int idx = 0; idx < NUM_INDEXES; idx++) sensorValue += lastReadValues[idx];
 if (sensorValue > 0) {
  if (full) {
   sensorValue /= NUM_INDEXES;
  } else {
   sensorValue /= (lastIndex+1);
DistanceDetector d1(SENSOR_PIN);
void setup() {
 //nothing required, as the constructor takes the pin number.
void loop() {
 d1.UpdateDetector(); //update the sensor.
 Serial.println(d1.sensorValue); //print out the value.


I still should have bought the GP2D120! But either way, I've decided to go with standard LDR/IR optics in the track base. Sadly, I'm over attempting the distance detection. My next post will cover a less-visible method for occupancy detection in the sleepers.


About stevenh

Trains... trains... trains... + Electronics + Japan.
Comments (2) Trackbacks (0)
  1. That’s a real shame stuff isn’t working out for you! Still, I’m confident you’ll work something out.

    • It’s only those Sharp sensors which didn’t work for me… ok, and maybe the RFID readers are useless when the tag is on an engine as the magnetic fields kill it… (idea just popped up, insulate from engine/motor with some form of foil shielding…)

      But such is life, I installed 10 LDRs last night and then ran out of time… retrofitting LDRs into the track base is a royal bastard, but the ones I have my hands on are much nicer than the standard orange ones. Keep an eye out for them!

Leave a comment


No trackbacks yet.