In this article we will resume the topic started with in “Detecting obstacle with IR Sensor and Arduino”. More in details, we are going to use the IR sensor like an objects counter.
The counter application is often used for:
- counting people traversing a certain passage or entrance. For example, in commercial buildings there are gates which control user access or presence often used to optimize energy consumption;
- counting objects or merchandise in industrial sector;
A counter can be made not only with IR technology but also with thermal imaging systems that use an array of sensors which detect heat sources or using machine vision which usually requires complex image processing algorithms.
Introducing the application: a counter with IR technology
The distance from the object is very important and in some cases the IR sensor is not suitable for these applications. If the distance from the object is greater than 20-30cm, the ultrasonic sensor can be a better choice.
We need to know when the IR sensor changes its state from HIGH to LOW and count how many times this transition happens: this is called state change detection. For more information on operation principle of the IR sensor we suggest to read the main article.
A bidirectional counter
High end counters use sophisticated hardware for counting process. Our project is a simple objects counter based on Arduino and two IR sensors. More in details, it is a 0 to 9 counter in which the first sensor is used to count ingoing people, the second those outgoing. The difference (IN – OUT) is shown on a 7-segments display.
Hardware description: a 7-segments display
Focusing on the 7-segments display SMA42056, this is an electronic component designed to for display numbers and often used in digital clocks, electronic meters and other kind of numeric displays.
The SMA42056 model is a common cathode 7-segments display with eventually an additional segment called decimal point or simply dot, represented by the P letter (See Fig.2), which is used for displaying non-integer numbers. Each segment is just a simple LED, and is often represented by the letters from A to G. The 7-segment display doesn’t embed a series resistor for each LED and driving them with a constant DC voltage can permanently damage junctions: to avoid this we will use a series resistor of 220Ω for each LED.
Demo Explained: A bidirectional counter
What it has to do and what is the necessary
This proposed demo counts non-transparent objects which are traversing two IR gate: the first gate produce an increment on a total counter, the second produce a decrement. Since our simple demo uses a one digit display our application checks that two things have occurred:
- The counting must not be represented by a negative number;
- The counting must not be represented by a number greater than 9;
Our BOM (Bill of Materials) is:
- Arduino UNO board;
- 2 x IR sensor fc-51;
- 1 x 7-segments display SMA42056;
- 8 x R = 220Ω.
From schematic to code
To drive the 7 segment display we need for 7 digital output PINs as shown in Fig.4. We also need to read information from our two IR sensors. This requires to use 9 digital pins.
In our case we have used the pin from D2 to D10 of our Arduino. To make code much more clear we have defined PIN numbers assigning them a proper name. Note that, parameters which are constant at run time and, consequently, defined at compile time, we are using preprocessor directives.
Using the “define” directive we are not only reducing memory occupation, but also optimizing the program execution.
We are defined the digital pins (from D2 to D8) we are going to use to drive our display as DISP_PIN_x (x from 0 to 6). The two output pins of the IR sensors (D9 and D10) has been defined as IR1 and IR2.
We have also defined some additional constants:
- NUMB_OF_PRESET, that is number of pre-set stored in our look up table (i.e. 10 since we are going to use digits from 0 to 9);
- NUMB_OF_SEGMENTS, that is the display segments we are using;
- MAX_NUMB, that is the high counting range limit.
There are some other constant value declared in our code, anyway for ease of use we preferred to store them into an bidimensional array called displaySEG is a look up table: in other words it is an collection of PIN preset required to show a certain digit on the display.
While the rows indicate the digit, the columns represent each segment (LED) of the display. For example, to display the number 0, all the segment except G must be set as HIGH (see Fig.2). The first element of our array stores the configuration required by each DISP_PIN to display a 0. So we can use the array displaySEG in a loop to set each DISP_PIN according to our preset and obtain our 0.
We need for additional variables which are the status of the IR sensors named as IRx_out (with x 1 or 2), a variable to store the counting value and a generic i used in loops.
This function writes a number from 0 to 9 on the display. More in details, the parameter n represent the number to show on our display. Note that n%10 is required to avoid eventual buffer overflow.
This is not a function but a macro which ridefine setDisplayValue passing 0 as argument. This macro is used to reset display on start-up. Note that using the preprocessor directives we are still optimizing memories and performances avoiding to create an additional activation record.
This function increases the counter and updates the display. Note that, if the counter becomes greater than MAX_NUMB it wraps to 1.
This function decreases the counter and updates the display. Note that, if the counter is equal to 0 it does nothing: in this way we are avoiding negative numbers.
The setup() sets pin modes: IRx as inputs and DISP_PIN_x as output. Than it call initDisplay() showing a zero on our SMA42056.
The loop reads IR statuses saving in them into IRx_out. When an non-transparent object is detected by an IR its value is LOW. If the “entrance” IR detects an object loop calls increaseAndDisplay(), if the other IR detects an object the loops calls decreaseAndDisplay(). Note that a delay is required to avoid false detections.
Download for Arduino IDE
This demo has been tested under Arduino IDE 1.6.7:
- A bidirectional counter
- Demo Explained: A bidirectional counter
- Download for Arduino IDE