Detecting MOTION direction (Left, right,Up,Down) using sensors

My question is really how to program say three pins that will receive HIGH in different times to detect the direction of the object facing the sensors.

I am deliberately avoiding describing the EXACT sensors details.......etc..... to concentrate on the programing side of detecting which pins are high and in what sequence..

To be more specific let us say we arrange the three sensors in a triangle shape.

The pins are Pup Pleft, and Pright

IF I detect Pleft and Pright fire at the same time FOLLOWED by Pup this means motion is UP and so on

If you map the three pins to three bits in a byte, using either masks or bit-fields, you will end up with a value between 0 and 7. You can then create a state machine and use a switch statement (case 0 thru case 7) and divert to functions dedicated to whatever it is you want done in each instance. If one or more states will result in the same action, simply let their respective case statements fall into each other. Got it?

You can use some of the remaining bits in the same byte to record the order in which they occur. With five bits left of the byte used to record the state of each pin, you have 32 values which can be mapped to numbers that will only occur based on the specific order of events, i.e. 1-2-3, 1-3-2, 2-1-3, 2-3-1, 3-1-2, 3-2-1.To give you a hint, assign each even a value (1, 2 or 3) and a weight based on 1st, 2nd or 3rd.

No EXACT code details, etc., so you can concentrate on the programming side.

That is exactly what I am looking for an "algorithm".

Once "I get it" !!!! ........I will provide the EXACT code.....

What is not clear to me....is the sequence part. How can I detect that ? you call it order of events....

Take the up example above ( Pup = 1, Pleft=2, Pright=3)
2 and 3 will fire , then 1 will..... so 2-3-1

Help

How many events?
How many can occur at the same time?
What state can each event be in?
Build a table of the events and their states.

I will assume you are "quizzing me"

Externally ....it is ONE event ; the object moves
Internally ....we have 3 pins that can fire in multiple ways.:
up (2,3) , 1 the bracket indicates no time lapse and comma is time lapse
down 1 , (2,3)
left 3,1,2
right 2,1,3

I have no idea how to count these events for the purpose of programming them !!

Are we not having fun?

Okay look, 3 events can take on 1 of 8 possible states and can occur sequentially in 1 of 6 possible orders.

Event 1 2 3

State 0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
Which is your basic 3-bit binary. So the state at any given time can be represented by 3 bits of a byte.

Create a struct with bit-fields;

struct
{
uint8_t state: 3;
uint8_t unused: 5;
} my_events;

So now, my_events.state can hold the current state of any possible combination of the three events.

The events can occur in 6 different orders:
1-2-3
1-3-2
2-1-3
2-3-1
3-1-2
3-2-1

The fact that 2 and 3 might occur at (seemingly) the same time just means that 1-2-3 an 1-3-2 get treated the same way (i.e. they fall through the switch statement together).
So I eluded earlier to think about weighting. When we assign weights to events, it's useful to remember a bit about prime numbers in that they (and 1) are their only factors and they can only ever factor into another number once (the way we use them). So pick three prime numbers, and since we've only got 5 bits left in our struct, keep them small. Oh, and to ensure some uniqueness, see the no three are equidistant (in other words, 1, 3 and 5 don't work as 1 and 3 are 2 apart as are 3 and 5). So how about 1, 3 and 7? Good choice.

arishy:
To be more specific let us say we arrange the three sensors in a triangle shape.

The pins are Pup Pleft, and Pright

IF I detect Pleft and Pright fire at the same time FOLLOWED by Pup this means motion is UP and so on

I can see where @DKWatson is going but it seems to me he is overlooking the time element.

I think I would record the times at which each pin is triggered so, let's say I have Utime, Ltime and Rtime

Then if Ltime and Rtime are nearly the same and Utime is a little later I would know it is an upward movement.

However I can see a complication - how do you know when a move starts and ends? I reckon you need to provide details of the physical system and the type of sensor.

...R

So, now we have three events and three weights.
If we assign each of these events a value and weight it according to the order of it's occurrance:

1-2-3 becomes 11 + 23 + 37 = 28
1-3-2 becomes 1
1 + 33 + 27 = 24
2-1-3 becomes 21 + 13 + 37 = 26
2-3-1 becomes 2
1 + 33 + 17 = 18
3-1-2 becomes 31 + 13 + 27 = 20
3-2-1 becomes 3
1 + 23 + 17 = 16

So each weighted possibility results in a unique value, and as each is less than 32 they will fit into the remaining 5 bits of the struct. Let's modify the struct;

struct
{
uint8_t state: 3;
uint8_t order: 5;
} my_events;

Now, as the events occur, assign their respective weight and store in my_event.order

Maybe we'll deal with details if the OP ever decides to share.

Just to finish off, take the struct that we've just created and nestle it inside a union;

union
{
uint8_t sw_state;
struct
{
uint8_t state: 3;
uint8_t order: 5;
};
} my_events;

Now the byte my_event.sw_state holds a unique identifier that contains in its 5 msb the order of events and in the 3 lsb, the current state.

my_event.sw_state (you can actually give it any name you want) can now be used in a switch/case state machine directed to function pertinent to each unique value.

As the state variable holds the order in which the events occurred, that would take care of the time element. As Robin pointed out however, everything hinges on being able to clearly identify when your events do in fact happen.

DKWatson:
Maybe we'll deal with details if the OP ever decides to share.

The one thing I wanted to avoid is giving details that will apply to specific hardware. I am still looking for IR solution, Ultrasound solution or may be laser solution.

All the above will address 3 pins attached to a triangle shape layout. ( I hope I am right in thinking this way)

So, I addressed the core of the problem, once I solve this hurdle with your help I will share whatever I decided to build this contraption; with you.

Now let us go "back" to the core problem.
I need to correct myself regarding the time lapse... There no such thing as zero time lapse, but we have small and big time lapses.

You addressed this very intelligently by given them weights. I love it.

arishy:
The one thing I wanted to avoid is giving details that will apply to specific hardware. I am still looking for IR solution, Ultrasound solution or may be laser solution.

I don't think the choice as between those technologies matters.

But you have provided no information abut how, in practice, your 3 sensors get triggered. For example

  • how often are they triggered
  • how much time is there between (say) the bottom row being triggered and the top sensor of the triangle?
  • when they are triggered does the object remain in front of the sensor
  • what starts a new set of sensor readings?

...R

Robin2:
But you have provided no information abut how, in practice, your 3 sensors get triggered.

Very good questions that need to be considered.

The aim is to control My TV:

  1. Up and Down for volume Left and right for Channels.
  2. The box containing the 3 sensors will be located in front of the TV. The triangle 3 center points are one inch apart. Can be modified based on testing.
  3. The functions triggered by my arm action will transmit the proper TV IR codes.

I am sure after knowing the project objectives, you will have a new set of questions, which I hope I can answer.

My feeling is this type of project is very experimental and requires a great deal of fine tuning. But it is doable.

arishy:

  1. Up and Down for volume Left and right for Channels.
  2. The box containing the 3 sensors will be located in front of the TV. The triangle 3 center points are one inch apart. Can be modified based on testing.
  3. The functions triggered by my arm action will transmit the proper TV IR codes.

That leaves me with the impression of three "windows" in a triangular arrangement facing me and I have a "wand" in my hand. The wand is wide enough to block one window (but not two) and long enough to block two windows. If I hold the wand horizontally and move it upwards first the bottom two windows are blocked and then they are uncovered and the top window is blocked and uncovered.

As I think more about it, maybe it is not necessary for the wand to uncover the bottom two windows when it covers the top one. But I think it is necessary that the action is completed by uncovering all the windows - not necessarily at the same instant.

Then there will be a relatively long pause before any of the windows is blocked again.

Does that make sense? if not, maybe you could post a diagram of the system. (It's easier at this stage to think of a wand rather than a human arm which is less easy to define).

If that makes sense then I would use the approach I suggested in Reply #7

As an entirely separate comment, I can see problems arising if the "wand" is not close enough to the "windows" as then the wrong window might "see" it. The spacing of the "windows" and the distance to the "wand" may affect one another.

For example I use QRE1113 reflective optical detectors which require the reflecting surface to be about 1mm from the device - hardly practical in your case, but it may provide food for thought.

...R

why dont use a "coded signal teqnique" like telecontrols do? Since your info is covered w 3 bits, send a sequense of x bits for time sync and then your 3 bit info and perhaps some bits after that, for confirmation.

Hey guys...God just send me a message ...I mean Google

So here is the code that goes with that video. The video uses short-distance IR reflective proximity detectors so you have to wave a hand directly over the sensors.

#define sIRA 10
#define sIRB 8
#define sIRC 9


#define LED1 3
#define LED2 4
#define LED3 5
char orders[3] = {'0', '0', '0'};
int indexOrder = 0;
//speed of detection Ms
int Captspeed = 1;


long tA;
long tB;
long tC;


void setup()
{
  Serial.begin (9600);
  for (int i = 8; i <= 10; i++)
    pinMode(i, INPUT);
  for (int i = 3; i <= 5; i++)
    pinMode(i, OUTPUT);
}


void loop()
{
  //Reset Command after 800 Msecond
  if (millis() % 1000 > 800)
    ResetCommand();
  //If we have 3 signals , Calculate Command
  if (tA > 0 && tB > 0 && tC > 0)
  {
    int command =  CalculateCommand();
    if (command <= 0)
      DoCommand(command);
  }
  //check for sensors
  if (indexOrder > 2)
    indexOrder = 0;


  int vA =  digitalRead(sIRA);
  if (tA == 0 && vA == 0) tA = millis();


  int vB =  digitalRead(sIRB);
  if (tB == 0 && vB == 0) tB = millis();


  int vC =  digitalRead(sIRC);
  if (tC == 0 && vC == 0) tC = millis();
  //Stop Command
  if (vA == 0 && vB == 0 && vC == 0 )
  {
    // DoCommand(0);
  }
  delay(Captspeed);
}


int CalculateCommand(void)
{
  Serial.print("tA = ");
  Serial.println(tA);
  Serial.print("tB = ");
  Serial.println(tB);
  Serial.print("tC = ");
  Serial.println(tC);
  delay(1);


  if ((tA <= tB) && tA <= tC)
    return -3 ;// FORWRD
  if ((tB <= tC) && tB <= tA)
    return -2 ;// LEFT
  if ((tC <= tB) && tC <= tA)
    return -1 ;//RIGHT
  //Etc
  return 1;


}


void  DoCommand(int command)
{
  switch (command)
  {
    case 0: Serial.println("Stopped"); delay(500); break;
    case -1: Serial.println("Turn RIGHT "); digitalWrite(LED1, HIGH); delay(1000); break;
    case -2: Serial.println("Turn LEFT "); digitalWrite(LED2, HIGH); delay(1000); break;
    case -3: Serial.println("GO FORWARD "); digitalWrite(LED3, HIGH); delay(1000); break;
    case -4: Serial.println(" GO BACK "); delay(1000); break;
    default : Serial.println("NO Command detected"); break;
  }
  ResetCommand();
}


void    ResetCommand()
{
  for (int i = 3; i <= 5; i++)
  {
    digitalWrite(i, LOW); //ALL LEDs
  }
  tA = 0;//Reset time A
  tB = 0;//Reset time B
  tC = 0;//Reset time C
}