rotation counter

I am trying to write a program using two IR sensors to measure number of rotations and direction of rotation of a shaft.
I have two IR sensors which are placed as it's shown in the attached picture.
I need to make a counter to show the numbers of rotations of the shaft. if it rotates clockwise, the number increases and if it rotates counterclockwise the number decreases.

I wrote the below code but it has two problems:

  1. it uses one of the sensors for increasing the number and the another for decreasing which is totally wrong!!!
  2. it is unreliable and sometimes it increase or decrease the number two steps!

I need a help to modify my code or rewrite it again. thank you!

const int sensor1 = 2; //sensor 1
const int sensor2 = 3;// sensor 2

int cw = 0;  // counts clock wise
int ccw = 0; // count counter clock wise

int sensor1_state = 0;      //current state
int sensor1_laststate = 0;  //last state
int sensor2_state = 0;      //current state
int sensor2_laststate = 0;  //last state

int counter = 0;
int lastcounter = 0;


void setup() {

  pinMode(sensor1, INPUT);
  pinMode(sensor2, INPUT);


  Serial.begin(9600);
}

void loop() {

  // read sensors

  sensor1_state = digitalRead(sensor1);
  sensor2_state = digitalRead(sensor2);

  if (sensor1_laststate != sensor1_state) { // if sensor 1 status is changed

    if (sensor1_state > sensor2_state) {  // if sensor 2 status is changed

      cw++;
    }
  }

  if (sensor2_laststate != sensor2_state) { // if sensor 1 status is changed

    if (sensor2_state > sensor1_state) {  // if sensor 2 status is changed

      ccw++;
    }
  }

  // updating status
  sensor1_laststate = sensor1_state;
  sensor2_laststate = sensor2_state;


  counter = cw + ccw;

  if (lastcounter != counter) {  // if the count has changed we print the new count

    Serial.print("number:  ");
    Serial.println(cw-ccw);

    lastcounter = counter;
  }
}

const int sensor1 = 2; //sensor 1
const int sensor2 = 3;// sensor 2

You don't have a generic sensor. You have a very specific kind of sensor. The names shouldn't pretend that any old sensor will do.

int cw = 0;  // counts clock wise
int ccw = 0; // count counter clock wise

Rubbish. There is a number of rotations, that is increasing when the motor is rotating in one direction, and decreasing when it is rotating the other way.

    if (sensor1_state > sensor2_state) {  // if sensor 2 status is changed

What?

The only way to tell the direction of rotation is to know which sensor was triggered first. Nowhere in your code do you record when the sensors were triggered, so you have no way of knowing the direction. The direction is NOT based on which pin is in a higher state RIGHT AT THIS MOMENT.

With two sensors positioned 180 degrees apart, there is no way you will be able to determine which direction the shaft is turning. If the sensors are adjacent to each other, you can determine direction by which sensor triggers first, but you will have to take into consideration how fast the shaft turns.

PaulS:
The only way to tell the direction of rotation is to know which sensor was triggered first. Nowhere in your code do you record when the sensors were triggered, so you have no way of knowing the direction. The direction is NOT based on which pin is in a higher state RIGHT AT THIS MOMENT.

Thank you for your reply.

for detecting which sensor is triggered first, I should use millis(), right?
is this correct?

  timer = millis();

  // read sensors

  sensor1_state = digitalRead(sensor1);
  sensor2_state = digitalRead(sensor2);

  if (sensor1_laststate != sensor1_state) { // if sensor 1 status is changed
    timer1 = timer;
  }
  if (sensor2_state != sensor2_state) {  // if sensor 2 status is changed

    timer2 = timer;
  }

  if (timer2 > timer1) {
    cw++;
  }

  else {
    ccw++;
  }

Unfortunately this code didn't work either.

david_2018:
With two sensors positioned 180 degrees apart, there is no way you will be able to determine which direction the shaft is turning. If the sensors are adjacent to each other, you can determine direction by which sensor triggers first, but you will have to take into consideration how fast the shaft turns.

Thank you David. you are right. I can put sensors adjacent to each other. but now I am struggling with codes.

Use search term 'quadrature encoder'.

The value returned by millis() is NOT a timer. It is a time.

dougp:
Use search term 'quadrature encoder'.

+1 for that.

This is the most bullet-proof technique that I've seen: Buxtronix: Rotary encoders, done properly

If interested, here's an interrupt-driven implementation: GitHub - gfvalvo/NewEncoder: Rotary Encoder Library

gfvalvo:
+1 for that.

This is the most bullet-proof technique that I've seen: Buxtronix: Rotary encoders, done properly

If interested, here's an interrupt-driven implementation: GitHub - gfvalvo/NewEncoder: Rotary Encoder Library

Thanks gfvalvo,

The second link was helpful.