Detecting occupied space using gridded motion sensors

This tutorial will show how to identify the coordinates of the space encompassed by objects within a grid. By using two axes with evenly spaced PIR motion detectors, multiple moving objects can be identified. In addition, when multiple objects are close together in the space, the coordinates will include any area covered on two sides by the objects themselves.

Note: Although this tutorial will use 3 total PIR detectors, the number of sensors can be expanded for larger grids with minimal changes to the code.


Figure A: Gridded PIR Sensor System



The gridded PIR sensors should be set up as shown in Figure A. In the next few diagrams, the circles represent objects in the grid, and the X’s represent the squares whose coordinates will be returned by Arduino via the serial cable. The red lines show which PIR sensors are set off by the objects.

Figure B: One Object Detected


If one object is present in the grid, it will set off  PIR sensors attached to the closest column and the closest row.

Figure C: Two objects detected in a line


If two objects in a straight horizontal/vertical line are detected, each object will be detected and the coordinates returned will only be those where the objects are located.

Figure D: Three objects detected (not in a line)


If the objects encompass a certain area on two sides (e.g. if a group of people is walking through a gridded area), the space that they enclose will also be returned as a coordinate value.

This will allow for the response to change when a group enters the space. If the group is neatly ordered in a straight line, the returned coordinates will similarly reflect a straight line. However, if the group is disorderly and spread out in the space, the returned coordinates will reflect the total area encompassed by the group.

Figure E: Objects Along a Diagonal Line


If the objects are placed along the entire diagonal, then all possible coordinates will be returned. According to the initial behavior, each returned value should be encompassed on two sides. In the diagonal case with all coordinate pairs returned, this is technically true, but some of the squares will be two squares or more removed from the actual object, which may encompass more space than desired. In order to fix this problem, additional sensors, such as force sensors on squares outside the diagonal, will provide enough input to double check the presence of objects in those areas.

This is an optional addition, but for our purposes, we will be focusing only on the PIR motion sensors in this tutorial.

Parts Required:

1x Arduino Uno

1x Breadboard

PIR Motion Sensors (one per mark on either axis forming the grid; for example, if the x-axis has 3 marks and the y-axis has 2 marks, then 5 total sensors are needed)

Assorted wires with headers (2x to bring power to the breadboard, 3x for the ground, 5V, and output on each PIR sensor)

Circuit Diagram :

Note: These are examples from a situation with 3 PIR Motion Sensors (1 row and 2 column); if adding more sensors, the wiring will be the same except additional sensors would connect into the digital inputs and the power (5V and Ground) rails on the breadboard.

Figure F: Breadboard diagram


Figure G: PCB diagram


Figure H: Constructed Circuit


Figure F is most helpful in seeing what the wiring looks like when connecting the different sensors to the Arduino, while Figure G shows the simplified connections from each sensor to the individual pins on the board. Figure H is provided as an example of what an assembled circuit would look like (here, the alligator clips are used to connect wires to increase length–these are optional).

The exact pin that the output of the sensor goes to is unimportant, as long as the arrays storing pin values in the Arduino code are also changed to match the locations of the row and column pins.

Note: In Figures A and C, the sensors are shown pointed in the correct direction, although the spacing would be much further apart in a finished project (Remember, the sensors can detect motion up to 20 feet away!).

Arduino Code:


Here the variables initialized are used to keep track of the pins in each row and column, the number of pins in rows and columns, and the value read from each pin. Arrays are used to keep track of pins and their values so that the value of each sensor can be iterated through using a for loop later on in the code. The rowInputPinCount and columnInputPinCount help this for loop count up to the total number of pins. As an example, row number 0 would correspond to pin number 13.

Change PinCount variables  and the values in the array to accommodate for more sensors added in. For example, if you added in a row sensor at pin 5, the rowInputPin would need a 5 at the end, the rowInputPinCount would be raised to 2, and the rowVal array would need another 0 at the end.


Each for loop is used to declare all the pins that measure movement in the rows or columns into INPUT pins. In addition, the setup initializes the serial monitor to begin communication–this can later be hooked up into Processing or read on a screen for human input.



The loop starts off with two for statements that take in the readings from each PIR sensor and store them in either the array for row sensors or column sensors depending on the PIR location.

This enables later code to use one index number to find both the PIR sensor’s pin and the value from that pin.

This part of the code looks daunting at first, but it’s essentially nested for loops that check every coordinate in the grid. If both the column and the row pin detected motion, then the coordinate corresponding to that row number and that grid number are printed out.

In the code itself, you can uncomment certain lines to make the output easier to read in the serial monitor. Alternatively, leaving the code as is will make it easier to send to an outside program such as Processing.

The first for loop runs through a check of each of the column pins and then runs them through an if statement to check if any of them detected motion. If so, then the next for loop runs through every row pin to see if it detected motion. If at any point, a row sensor and a column sensor both detect motion, then the coordinate of that point is then printed to the serial monitor.

Variables rowInputPinCount and columnInputPinCount ensure that the for loops do not exceed the number of entries in the arrays that store the pin values for the row and column pins.

Note: If the coordinates outputted don’t match the ones that you have assigned to the rows/columns, then check to make sure the pins are entered in the correct order on the rowInputPin and columnInputPin arrays. If the order of sensors is switched, then the coordinates will be incorrect.


Figure I: Serial Monitor Output


When the PIR sensors in the row alone detect movement,  no motion is registered (in the first line, each of the column sensor values are 0, indicating lack of change).

As soon as motion is detected in the columns as well as the row, then the serial output changes. Since the system has confirmation that multiple sensors are seeing a change, motion is registered and the coordinates that it covers are outputted to the monitor.

Currently, the PIR sensor is set to retriggering mode–it will output a constant value as long as the obstruction is present. The sensitivity can be adjusted by turning the orange knob at the back counterclockwise (to reduce sensitivity), as well as by changing the position of the jumper (which will make it non-retriggering–registering motion only once, as opposed to continuously for the duration of its presence in front of the sensor). A guide on how to adjust these two aspects is found here (

Full Arduino Code:




Leave a Reply

Your email address will not be published. Required fields are marked *