A sequence of trigger switches

Hi.

Firstly i am very new to arduino, so i very much apologise for the un professional nature.

I am trying to build a touchless control unit, a very basic idea, but with different styles of functions on it.

Firstly i have set up a distance reader to change between lights depending on how close your hand is to it.

I am now looking to set up a sequence of sensors that depending on which order of 2, either from left to right or right to left, they are triggered it will create a different output. I am just looking for some advice on how to set up a series of say 2 or 3 either LDR (not ideal due to them being analogue) or PIR sensors (not ideal because of their field of view being 5m, which also adds another question, does anyone know if i can ristrict this with programming or is this purely a hardware issue?) or an ultrasonic sensor (which i dont know much about). So firstly i am a bit unsure on what sensor to actually use, if anyone has any ideas it would be much appreciated, i need it to sense a hand travelling over it within 100mm, and am really unsure on what to use.

What i want to do is build some programming that can tell in which order these sensors are triggered, either left to right, so say sensor 1 then 2 then 3, or right to left, say sensor 3, then 2, then 1. The programming then registers this... and depending on the order lights an led, say either red for left to right and green for right to left. So its fairly simple in principle but i am very very unsure at the moment on how to go about it and what sensors would be suitable. I have been reading some of these forums and everyone seems really helpful and impressively knowledgable and would be excellent if even a tiny bit of light or guidence to another post if someone has tried the same thign would be much appreciated.

Kind regards

Matt

You have two separate issues here. The first is the choice of sensor to use. There are pros and cons to each of the sensors you mentioned. Cost, interference for ambient lighting, sensitivity, range, and field of view are all factors that need to be considered.

Without knowing more about what you're trying to do, it's hard to say which will work best. You'll probably need to try them all, and determine for yourself which one(s) work best, for your particular application.

The second issue is that of determining the order that the sensors were triggered. Than one is fairly easy. You can use the millis function to determine when the sensor changed. You can do something, or nothing, when an individual sensor changes. When more than one sensor changes, compare the times that the changes occur.

If you have two sensors, the code might look like this:

boolean sensorLeftTriggered = false;
boolean sensorRightTriggered = false;

int sensorLeft = LOW;
int sensorRight = LOW;

long sensorLeftTime = 0;
long sensorRightTime = 0;

int sensorLeftPin = 2;
int sensorRightPin = 3;

void setup()
{
   pinMode(sensorLeftPin, INPUT);
   pinMode(sensorRightPin, INPUT);
}

void loop()
{
   int sensorLeftValue = digitalRead(sensorLeftPin);
   int sensorRightValue = digitalRead(sensorRightPin);

   if(sensorLeftValue == HIGH && sensorLeftValue != sensorLeft)
   {
       // Sensor triggered, and was not triggered before
       sensorLeftTime = millis();
       sensorLeftTriggered = true;
   }
   sensorLeft = sensorLeftValue;

   if(sensorRightValue == HIGH && sensorRightValue != sensorRight)
   {
       // Sensor triggered, and was not triggered before
       sensorRightTime = millis();
       sensorRightTriggered = true;
   }
   sensorRight = sensorRightValue;

   // See if both sensors have been triggered
   if(sensorLeftTriggered && sensorRightTriggered)
   {
       if(sensorLeftTime - sensorRightTime > 0)
       {
           // Sensor right was triggered, then sensor left
       }
       else
       {
           // Sensor left was triggered, then sensor right
       }
   }
}

You could expand this concept with more than two sensors. You'll need to be sure to reset everything in the "do something" blocks, too.

PaulS

I really appreciate your help here and I apologise for the late reply, I am currently doing this project amongst several others and time is very short. I have done a lot of thinking about the sensor I want to use and I have chosen to use a distance measuring sensor (http://www.rapidonline.com/Electronic-Components/Sensors/Proximity-Optical/Distance-measuring-sensor-digital-output/81725 ) 2 to be precise.

This will then create an output when the user passes there hand through the beam. From what it looks like they are very accurate and will be able to sense this change and movement and then using your code and adapting it where needs be I can hopefully have 2 sensor so when you pass you hand from right to left it will trigger right then left and skip back a track on a cd player.

I am also developing a volume sensor which I am struggling with too. It also uses a distance measuring sensor and so when a user moves there hand down towards the sensor this will decrease the volume in proportion to how close they were to the sensor. The challenge here is to make the sensor remember the level that the users hand was at when they removed it from the sensors field of view as the sensor, when the users hand is removed, will return to a 'resting' value will it not?

I am sorry if this explanation is very poor, I really feel lost with this technology so I am really appreciating the help you are providing. Thank you very much.

The explanation was fine. The problem is not an easy one, though. The sensor will output a voltage based on the distance to the nearest object.

The product description says that the output is a one bit value. I don't think that that is correct. The output is a voltage between 0.6V and 3.3V; the Arduino will compare that voltage to Vref, and map the ratio to a range from 0 to 1023.

If you were to plot the values read from the sensor, you would see a discontinuity when the person's hand moved sideways, out of view of the sensor. You'll need to remember the last good value before that discontinuity.

A similar problem will occur when the sensor first sees something. You would not want the volume to jump when a hand is seen by the sensor two feet away, when the volume is based on the last sighting that was 6" away.

Indeed, that is the issue, a small solution that I have thought to combat this is when a user holds their hand still at the 6” I will plan for it to register this stop in changing measurement and program the arduino to then remember this value. This issue of the sensor first seeing something will be cleverly solved through my design. I aim to have an indication on the product to inform the user what level the volume is currently at. This level will be shown at the height the user last held their hand. Therefore indicating to the use to place their hand above the sensor at this level to then drag up the scale and increase the volume or down to decrease. I think that solves some of the issues in theory, obviously the problem coming when trying to convert that to code.

The other issue I have is connection. I am aiming for this product to be wireless to allow them to control their stereo from other rooms etc and there is so much tech for me to choose from. A rechargeable lithium ion battery will be used as a power source in the unit but then the difficulty comes when working out how to connect this to my stereo I am building to allow for portability.

Once again thankyou PaulS for your help, really appreciated.

Hi everyone…
So i have set up my circuit with the Infrared sensor in it taking a reading of where your hand is and then lighting up a bar graph style set of LEDs so that as you get closer to the sensor, more are lit, very simple, my circuit and code is as follows:

CODE

// these constants won’t change:
const int analogPin = 0; // the pin that the potentiometer is attached to
const int ledCount = 6; // the number of LEDs in the bar graph

int ledPins = {
2, 3, 4, 5, 6, 7 }; // an array of pin numbers to which LEDs are attached

void setup() {
// loop over the pin array and set them all to output:
for (int thisLed = 0; thisLed < ledCount; thisLed++) {
pinMode(ledPins[thisLed], OUTPUT);
}
}

void loop() {
// read the potentiometer:
int sensorReading = analogRead(analogPin);
// map the result to a range from 0 to the number of LEDs:
int ledLevel = map(sensorReading, 0, 255, 0, ledCount);

// loop over the LED array:
for (int thisLed = 0; thisLed < ledCount; thisLed++) {
// if the array element’s index is less than ledLevel,
// turn the pin for this element on:
if (thisLed < ledLevel) {
digitalWrite(ledPins[thisLed], HIGH);
}
// turn off all pins higher than the ledLevel:
else {
digitalWrite(ledPins[thisLed], LOW);
}
}
}

(PS SORRY I DONT KNOW HOW TO ISOLATE THE CODE IN THE FORUM)

The problem that im having is that the reading that is given (on the leds 1-6) isnt equally proportional to the distance the user is away from the sensor (4-30cm) … as the user gets closer… the rate that the LEDs light up gets quicker, a rough example to show the principle is that in the first 26cm LEDs 1 and 2 seem to light up and then in last 10 cm, LEDs 3,4,5,6 light up.

It seems odd. Is this due to my coding or the way the Infrared distance meter (Sharpe GP2d120 4-30cm analogue http://www.rapidonline.com/Electronic-Components/Sensors/Proximity-Optical/Distance-measuring-sensor-analogue-output/81724) reads my hand and creates the voltage?

It seems weird that this would happen as it is ideally used to determine distances so seem weird that the results would change proportionally? Can anyone help on this qiuery?

My next stage is also to create it so that as a user moves their hand out of the focus of the sensor it remembers the left they left it at, the way i see this working is having the arduino board see this suddent change from the level the hand was at to the maximum ‘resting’ level of the sensor and ignoring this change… keeping the level sat at what the user moved it too… i hope that makes sense.

If anyone has any ideas it would be much appreciated.

Thank you in advance

Matt

(PS SORRY I DONT KNOW HOW TO ISOLATE THE CODE IN THE FORUM)

highlight your code and use the # icon in the editor ;)

Cheers bud, i will know for the future :)

One thing I notice is that analogRead returns a value between 0 and 1023, inclusive. Yet, you are mapping the value from a range of 0 to 255 to a range of 0 to 6.

The product description says that the output is linear, from 4 to 30 cm.

I'd add a Serial.print statement to print out the actual sensor reading, to see if the problem is with the sensor data or with the mapping. I'd suspect the mapping, first, though.

when i had the reading between 0 and 1023 it wasnt working as well. Will that effect my results? would that not simply reduce the range to say 4 - 20cm?

Ive tried to look up serial.print and there seems to be so many options (http://www.arduino.cc/en/Serial/Print). Can i just add another void loop into the mapping or do i re-write the code?

The first thing you need to do is determine if the sensor output is reasonable. The Serial.print method will let you know the value read from the sensor.

There are several overloads for the print method, depending on what is being printed. There are optional arguments that define how the data is printed.

You want this:

Serial.print(sensorReading, DEC);

This prints the value out as a number. The numbers that printout as you move your hand closer to the sensor should increase. As you move away, they should decrease.

Once you know the actual range of values - from holding your hand against the sensor to being on the other side of the room, you can map the actual reading using the from range defined by the min. and max. readings you observed and the to range based on the number of LEDs you have.

No, you can't add another loop method.

Wow... cheers PaulS.

So when i can work out these readings and determine them dependant on height, i can work out at what height i want my levels and then create a formula to help this :).

Even though it seems odd that the reading would be linear when it says it should be? do you think this is due to the sensor being faulty?

Also i pressume i just replace my whole code with the serial.print or can i just add it on to the end of my current code controlling the LEDs? Do these readings just show up on my computer in the arduino program or do i have to connect another form of display?

Once again, thanks you.

void loop() {
  // read the potentiometer:
  int sensorReading = analogRead(analogPin);
  // Print the value of the sensor reading
  Serial.print(sensorReading, DEC); // <----- Add this
  // map the result to a range from 0 to the number of LEDs:
  int ledLevel = map(sensorReading, 0, 255, 0, ledCount);

  // loop over the LED array:
  for (int thisLed = 0; thisLed < ledCount; thisLed++) {
    // if the array element's index is less than ledLevel,
    // turn the pin for this element on:
    if (thisLed < ledLevel) {
      digitalWrite(ledPins[thisLed], HIGH);
    }
    // turn off all pins higher than the ledLevel:
    else {
      digitalWrite(ledPins[thisLed], LOW);
    }
  }
}

Add the statement shown above (// <— Add this).

Also add:

Serial.begin(9600);

somewhere in setup().

Without knowing what values are actually read from the sensor, we don’t know (yet) whether the sensor is linear, or not. The manufacturer says it is, so I would assume that is is at least relatively linear. The serial.print statements will let us know with more certainty.

Open the serial monitor, using the rightmost button in the IDE.

Thank you very much.

i will test this tomorrow and inform of some results. Tomorrow i am also connecting up (hopefully) the 2 sequence sensors and 2 led's and, 2 other analogue sensors to light up leds to show some principles. Hopefully i will have some photos :).

Again, paulS this has been huge help with this project, really appreciate it.

Hi PaulS. So i have set up my system to read the sensor using the code you sent above. I found within the serial monitor this gave me a long line of numbers which didnt really give me much benefit. So i did some research and have used this code

 void loop() {
   // read the potentiometer:
   int sensorReading = analogRead(analogPin);
     // Print the value of the sensor reading
  Serial.println(sensorReading, DEC);  // print as an ASCII-encoded decimal
   // map the result to a range from 0 to the number of LEDs:
   int ledLevel = map(sensorReading, 0, 255, 0, ledCount);

to give a new line for each piece of data. Im struggling to do anything with this data though.

I have also changed the rate to

 // start serial port at 300 bps:
    Serial.begin(300);
   }

so i can view them a lot easier but im still getting really odd results when compared to a ruler and against the 4-30 cm range it specifies.

[u]Results are, roughly using my hand, as follows:[/u]

The first LED is lighting up without even putting anything infront of it with a value fluctuating between 40-50 very speradically.

The 2nd LED lights with a reading of 90-100 at about 25 cm's

The 3rd LED = 130 at 20cm.

The 4th LED = 170-175 at 17cm.

The 5th LED = 220 at 13cm.

The 3rd LED = 260-270 at 11cm.

Max value is roughly 640 at 4 cm

These were quiet rough but i was wondering if i could restrict the range between 15-4 cm for thr 6 LED's to do some more accurate testing? Do you know if this is possible.

Currently the range of 4 cm to infinite is far too large :)

You could leave the Serial.begin() value at 9600 or larger, and add a delay at the end of loop, to reduce the amount of data, until you get it working.

Your sensor readings range from roughly 40 to 640, but you are still mapping the values as though they were in the range of 0 to 255.

Simple test. Change the 255 to 1023. Add a 1 second delay, and run the program again. See if that doesn't do a better job of lighting the appropriate number of LEDs.

should the range currently be 40 to 255 then?

When i change the value to 1023 i only get 3 lights lit up :s its odd

Can i narrow the range if i know the values coming out and then use that range to spread across the 6 LED's?

I suppose we are still trying to work out why it isnt linear?

Yes, you can. If you know that you'll never get readings of 700 to 1023, by all means, shorten the range.

Yes, we are still trying to determine if the sensor is indeed linear.

I am currently getting exactly the same readings from a more accurate test using card and ruler attachement.

Also the delay of a second finishes the second i change the value the sensor read (ie get closer) where should i put the delay in the code to slow down the serial monitor values?