Sharp IR sensor Color feedback

I need help with my senior design project. I am currently design a collision avoidance system using the sharp ir sensor. I am using two LEDs one red and one green. In my prototype, I have that the green LED is always on unless the sensor sees something then the red LED will come on. What I want to do is have the red LED come on if I move my hand towards the sensor and then turn off if I move it away from the sensor but at the same time, allow the green LED to turn on if I move my hand away from the sensor. All this is happening while my hand is front of the sensor.

Please help me.

This is pretty crude description of what you want. You should focus on describing one LED at a time. Do you know you need to define what it means by "sees something" or "move hand towards/away sensor"? Quantifying these vague terms is the first step in turning your vague ideas into something a processor can execute.

Some hints are to use a boolean variable that describes the 'state' of the IR sensor - for instance '0' for not seeing your hand and '1' for seeing it. Search for an example of an IR sensor for how to do that.

You can use the boolean variable to switch on the LEDs or not using a single conditional but with a logical flip on one of the LED lines. Search for 'switch on LED with conditional' or similar for an example of that.

But until you show your first attempt in code I don't think I, or most others I've seen regularly round here are going to give you many more hints than that :wink:

dinosaurj:
the sharp ir sensor

You'll need to be more specific. I have this one which is digital and triggers at ~10cm, but they have others like this which give an analog reading for the actual distance.

It's not clear if you mean you want to know if your hand is moving closer or has just become close. In the first case you would need the analog one and compare successive readings to see which way the hand is moving.

Good point re. position vs. velocity - I assumed the simple case ...

Here is the code I have so far:
int sensorpin=0; // The signal pin for the sensor
int val=0; // The value that the sensor returns

int active = 0; // Whether the light is active

int RedPin = 13; // The pin the LED is connected to
int GreenPin = 12; // The pin the LED is connected to

void setup() {
Serial.begin(9600);

pinMode( RedPin, OUTPUT ); // Sets the led pin to an output mode
pinMode( GreenPin, OUTPUT);

}

void loop() {

val = analogRead(sensorpin); // reads the value of the sharp sensor
Serial.println(val); // prints the value of the sensor to the serial monitor
delay(1000);
if( val >= 250 ) // If an object is fairly close (around 25 centemetres or closer for me)
{
digitalWrite (RedPin, LOW);
digitalWrite (GreenPin, HIGH);
}

else if (val)
{
digitalWrite (GreenPin, LOW);
digitalWrite (RedPin, HIGH);
}
}

I want the sensor to see if my hand is moving closer or further from it

So your main loop needs to update a global variable to record how far away the last detection was and compare it to the next one.

Try this code. First notice two things about it:

  1. I don't use 'magic numbers' like 250 anywhere in the actual code. The numbers are collected together near the top. This makes it very easy to change the parameters without doing a search-replace. Use comments to describe what the numbers mean; are they milliseconds or centimeters?
  2. The loop runs continuously, thousands of times per second. I don't use delay() to make it stop and wait. But we want to detect some kind of velocity: distance moved over a period of time. So we need to periodically check the sensor reading, maybe every 100 milliseconds, which is 10 times per second. This remembers the last time that it looked at the sensor and keeps looking at its watch to see if it's time to do it again.
//new variables, in addition to the ones declared in the previous complete sketch
#define DelayTime 100 //milliseconds between checking the sensor for approaching/departing
#define SpeedThreshold 25 //analog counts used to decide if the speed is moving 'fast enough'
#define DistanceThreshold 250 //ignore values less than this - the object is too far away or there is no object detected
int PreviousVal = 0;
unsigned long PreviousReadTime = 0; //must be unsigned, to match the millis() type

void loop() {
  //okay, remember this loop runs continuously, thousands of times per second
  //Has enough time elapsed since the last time we checked the sensor?
  if(millis() - PreviousReadTime > DelayTime) 
  {
    //okay, now it's time to read the sensor
    val = analogRead(sensorpin);       // reads the value of the sharp sensor
    Serial.println(val);            // prints the value of the sensor to the serial monitor
    if( val >= DistanceThreshold ) // If an object is fairly close (around 25 centemetres or closer for me)
    {
      if(PreviousVal == 0) 
      {
        //This is the first time an object has come into range - just record its position
        PreviousVal = val;
      } 
      else
      {
        //has it moved far enough since our previous detection?
        if(val - PreviousVal > SpeedThreshold) 
        {
          //Yes! it has moved closer
          digitalWrite (RedPin, LOW);
          digitalWrite (GreenPin, HIGH);
        }
        if(val - PreviousVal > SpeedThreshold) 
        {
          //Yes! it has moved away
          digitalWrite (GreenPin, LOW);
          digitalWrite (RedPin, HIGH);
        }
        PreviousVal = val;
      }
    } 
    else 
    {
      //the value was outside the distance threshold - reset previous
      PreviousVal = 0;
    }
    //record the time that we read the sensor
    PreviousReadTime = millis();
  } //else we don't need to read the sensor on this cycle
  
  //maybe some more code here to do other stuff on every loop cycle?
  //...        
}
  1. You may also notice that at the end of the big if(){...} statement, I put a comment which identifies the end of that block. When the blocks get bigger than one screenful, this makes it easier to work out where you are in the code.

Moving closer or moving away is velocity, not position, as MorganS pointed out. What you were doing is straight position. According to physics, velocity is the change of position vs. the change of time. You should do what MorganS did, sense position and sense again. Subtract the two values and divide by time. This gets you velocity.

MorganS’ Reply#7 is a good example of the “blink without delay” approach in action in a real situation… it’s not just for blinking leds as folk sometimes cry, it’s for timing stuff without blocking.

What I would like to do is to be able to calculate the actual velocity on the arduino as well. How could I do that?

Hi
As has been asked before, what is the type of sensor, what is its part number.
Before we go any further we need to know if you have a threshold output or a proprotional voltage output.
Is your sensor capable of giving distance measurements.

What values are you getting on the monitor?

Also can you post your code in code tags and post a copy of your circuit diagram, either in a CAD or hand drawn photograph in jpg or png format.

Thanks Tom........ :slight_smile:

dinosaurj:
What I would like to do is to be able to calculate the actual velocity on the arduino as well. How could I do that?

When you say"velocity" do you really mean velocity the vector, or do you actually mean speed?

The speed part of velocity's straightforward: take the distance from the sensor twice, noting the time (say using millis() ) at each instant, then subtract the two to get the distance traveled. Divide that by the time difference.

The direction part of velocity's a bit more difficult, unless of course it's merely straight towards and away from. In that case, the direction is inherent in the speed being +ve or -ve.

If the motion can be across the sensor, then that's a different thing totally and might need a compass or something.

I mean the speed.
The type of sensor I have is a sharp ir sensor. The values I am getting from the sensor are units of measurement. In my case centimeters

The part number is GP2Y0A21YK

dinosaurj:
I mean the speed.
The type of sensor I have is a sharp ir sensor. The values I am getting from the sensor are units of measurement. In my case centimeters

Just take two readings and note millis() for each, then it's just some arithmetic....

speed in cm/sec =( (second_distance - first_distance) / (second_millis - first_millis) ) * 1000

The sign will tell you if it's coming or going.

Hi;

So you are using Fig 5 graph as calibration.
250 analog value does not mean 25cm.

Have you read;

The response is not linear. Volts vs Distance is an inverse and non-linear so to calculate speed you will need to use a conversion equation to get your distances.

Tom..... :slight_smile:
You haven't told us what values you are getting on your monitor.
Please post a circuit diagram.

JimboZA:
Just take two readings and note millis() for each, then it's just some arithmetic....

speed in cm/sec =( (second_distance - first_distance) / (second_millis - first_millis) ) * 1000

The sign will tell you if it's coming or going.

Agree, and pre-empting the potential noise/flicker issue around the crossover from positive to negative you might want to implement a moving average filter on the output...

Not a huge issue but it is nice :slight_smile: