Need to make bidirectional rotation counter

Bidirectional Counter Project

I was attempting to make a counter that can indicate total number of rotations that a motor driven spool makes. The spool can turn both clockwise and counter clockwise. The spool holds a cord and each rotation equals +/- one foot of cord that has been played out. I initially thought I could do it using a mechanical approach where two microswitches (facing each other) would be activated by flexible lever that is moved by a post on the spool in either the forward or reverse direction. I thought I could just send these momentary signals to a totalizer counter that could add or subtract from the count displayed on a digital display.

(https://www.amazon.com/-/he/Hilitandpb68xgfw9i/dp/B0BR8DBBR2)

But I realized this was a very rudimentary and restrictive approach when I stumbled onto "bidirectional people counter" Arduino projects.

So, I am going to get a basic Arduino book for beginners (recommendations appreciated). However, I thought I’d join this forum and see if I can get some preliminary input that may make my exploratory journey more efficient.

According to most of the “bidirectional people counters” that I reviewed, the basic plan involves two IR sensor modules, which input into an Arduino Uno and then outputs to a digital display. Renu Robotics is an example of a typical project.

The main components are the following:

  • Arduino Uno
  • 16/2 display
  • infrared sensors x 2
  • Breadboard Arduino Data Cable
  • 9 volt power supply

Source Code & Circuit Diagram : GitHub - Renukanand1308/Bi-Directional-Visitor-Counter

Details of My Project:

Each rotation will roughly equal one foot of line out or in and will be tabulated on the display. This unit is contained in limited confines so I need fairly small components. Mainly the two paired sensors need to be the smallest possible and would be fixed on the stationary hub and interact with a post on the rotating spool that will pass in front of them and register with each turn, clockwise or counter clockwise, thus indicating a total length of line out.

Because the space available is limiting, I am hoping that only the sensors themselves need to be mounted in the hub and the three wire leads can be brought outside the case to the sensor board connections. I would like to use the smallest sensors, perhaps these.
Miniature Reflective Infrared Optical Sensors

I would like to consider using a TFT display in place of the 16/2 display. The count will not exceed three digits.

The display will be near the actual Arduino Uno circuit board and the IR sensors would be on the spool’s hub, be about 12 feet away. I don’t know if the leads from the sensors could be extended using a three-lead wire to the sensor board which could then be located next to the Arduino Uno unit. Would the long wire create either a resistance factor or electrical interference that would degrade the data transfer? Alternatively, could the sensors be connected to the sensor board with short leads and have the data transmitted through a simple, small wireless transmitter to a receiver connected to the Arduino Uno unit, thereby obviating the need for a hardwire connection from the IR sensors and the Arduino Uno. Since I have no idea how the data is transferred, I don’t know what the transmission options are.

Main Questions Needing Answers:

  • Can the IR sensors be separated from the sensor board using a wired link?
  • Can the wired link extend 12-15 feet to the board situated next to the Arduino unit? If not possible, can the wired link from the sensor board to the Arduino be extended to cover the 12-15 feet distance?
  • Can the IR sensors on the board be replaced by the smaller sensor units I found?
  • Can the link from the Arduino to a TFT display be replaced by a wireless link to an android phone?
  • Is the use of the paired IR sensors the best way to design the system? Could the use of a rotary encoder be a better alternative? If so, how is this done? I saw this thread that described using a rotary counter rather than IR sensors to get a more accurate count. rotation counter - #7 by gfvalvo
  • I need example of the program I can use

Picture of project layout (I posted this because I couldn't upload a picture)

/*
  Hey Guys! Welcome to RENU ROBOTICS
  This is a Simple Project
  Bi - Directional Visitor Counter
  Hope you Like It!! 
*/

#include<LiquidCrystal.h>//Declaring the Library 

LiquidCrystal lcd(12,11,5,4,3,2);// Setting up lcd 

#define in 8  // Defining In Sensor
#define out 9 // Defining Out Sensor
#define bulb 10 //Defining Bulb(Relay)

int count = 0; // Declaring count Value

void setup()
{
  lcd.begin(16,2); // Beggining the lcd
  lcd.print("Visitor Counter"); // Printing "Visitor Counter" to the LCD
  delay(2000); // Delay of 2 seconds
  pinMode(in,INPUT); // Setting up In Sensor as INPUT 
  pinMode(out,INPUT); // Setting up Out Sensor as INPUT
  pinMode(bulb,OUTPUT); // Setting up Bulb(Relay) pin as OUTPUT  
  lcd.clear(); // Clearing/Erasing the String in LCD
  lcd.print("Person In Room:"); // Printing "Person in Room" to the LCD
  lcd.setCursor(0,1); // Setting Cursor to Print the Counting
  lcd.print(count); // Printing the Couting
}

void loop()
{  
  int in_value = digitalRead(in); // Setting Variables & Reading Values from In Sensor
  int out_value = digitalRead(out); // Setting Variables & Reading Values from Out Sensor
  
  if(in_value == LOW)
  {
    count++;
    lcd.clear();
    lcd.print("Person In Room:");
    lcd.setCursor(0,1);
    lcd.print(count);
    delay(1000);
  }                                                        // Conditions
  
  if(out_value == LOW)
  {
    count--;
    lcd.clear();
    lcd.print("Person In Room:");
    lcd.setCursor(0,1);
    lcd.print(count);
    delay(1000);
  }                                                        // Conditions
 
  
  if(count==0)
  {
    lcd.clear();
    digitalWrite(bulb,HIGH);
    lcd.clear();
    lcd.print("Nobody In Room");
    lcd.setCursor(0,1);
    lcd.print("Light is Off");
    delay(200);
  }                                                       // Conditions
  
  else
  {
    digitalWrite(bulb,LOW);    
  }                                                      // Conditions
}

That's project's code doesn't look good for detecting rotation direction. It looks like it counts based on levels rather than events, and uses delays. If someone blocked the in-sensor it would count up about 1/sec, and it would be prone to missing events.

How fast will your spool turn? It cant handle rotation speeds higher than 60 (30?) RPM.

For directional rotational counting, you could use your two IR sensors or mechanical sensors with a half-disk (or fin), in "Quadrature". For example, if you place your sensors/switches offset from each other and read one sensor (DIRECTION) when the other sensor (CLOCK) switches from ON, the DIRECTION line will tell you which direction the disk was turning. The trick is that one switch has to make contact before the other switch so you can detect which switch triggered first to get the direction information.

Building a direction/rotation counter like this is essentially a quadrature encoder.

You could read the CLOCK sensor with code as in the state change detection example:

https://docs.arduino.cc/built-in-examples/digital/StateChangeDetection/

...and instead of counting on each change to HIGH, read the other sensor and either count up for down.

Or you could use the Arduino Encoder library:

Mechanical switches would need some debouncing, which the StateChangeDetection example demonstrates.

2 Likes

One outer loop will be much longer than one inner loop. If you will count rotations to calculate length, you will first need to measure the length of cord for each rotation through the nth rotation and add the decreasing lengths of cord corresponding to the increasing number of rotations.

This is avoided if you use a state machine and some 0.1uF capacitors to ground on both signal lines (OK this is debouncing but it is not software)

On a Uno I would always use this library to do this as some Arduino libraries do not implement the state machine correctly.

Rotary Library
from Encoder Library, for Measuring Quadarature Encoded Position or Rotation Signals

1 Like

There is a very simple solution to this:

print 30 to 50 empty lines to the serial monitor to wipe away the previous text
and then print the actual text always at the bottom

void clearSerialMonitor() {
  for (int i = 0; i < 50; i++) { // print 50 empty lines to clear screen
    Serial.println();
  }
}

clearSerialMonitor() ;
Serial.println("This line appears always at the bottom");

In this tutorial in post #7

There is a demo-code that demonstrates this on an example how non-blocking timing can be coded

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.