Arduino People Counter for Rooms

by danielterletzkiy in Circuits > Arduino

1039 Views, 2 Favorites, 0 Comments

Arduino People Counter for Rooms

People Counter | Arduino demonstration

So basically I made a project that counts how many people are in the room and how much people have walked in and out of a room.

I have made this project because I had the APDS-9960 already on my table and didn't really knew what to do with it jet, because of my bigger project, that I originally bought the sensor for, failed (The sensor doesn't really work with the ESP-8266).

I am still working on the project but it works like it should, except....

...the sensor has a limited range so it only detect "gestures" that are like ~3cm to ~20cm, wich is kinda sad,

so when you have, for example, a door witch is 1m wide, you really need to be on the side of the sensor or kinda walk in the middle of it.

Supplies

Lets Get to the Fun Part

People Counter wiring diagram.png

First you need the right library's

  1. SparkFun APDS-9960 Sensor Arduino Library
  2. U8G lib
  3. Wire.h

When you are wiring everything up you need to define an Interrupt Pin only, for example pin 2 on the Arduino UNO.

You can read more about Interrupts here.

#define APDS9960_INT 2 // Needs to be an interrupt pin

I have made some Icons that are already in the code. If you want to make your own Icons for OLED displays, you can check out this great Website.

Then what you need to do is go to the Code section that is marked:

//Image for [thing]

and replace the bytes with the Arduino code you got from the website.

NOTE: i have already configured all images to be 20x20 pixels, all except the "ICON" image wich is full sized(128x64 pixel).

Here is the full Code:

/*=================================================================================
Original Sketch by SparkFun

HEAVILY Modified Sketch by Daniel Terletzkiy

//================================================================================= */

#include #include #include "U8glib.h"

#define APDS9960_INT 2 // Needs to be an interrupt pin

const uint8_t icon[] PROGMEM = { //Icon image for startup 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0x80, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe7, 0xff, 0x83, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc7, 0xff, 0xcf, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc7, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xcf, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xcf, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x8f, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x9f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x9f, 0xf9, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1f, 0xf8, 0xdc, 0x1c, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf8, 0x22, 0x22, 0x60, 0xb0, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf0, 0x40, 0x41, 0x00, 0x98, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf0, 0x00, 0x81, 0x00, 0xa4, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xf0, 0x80, 0x81, 0x00, 0xa6, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x7f, 0xf0, 0x40, 0x41, 0x20, 0xa2, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfc, 0x40, 0x43, 0x21, 0x21, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0x36, 0x36, 0x1a, 0x20, 0xc2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf0, 0x7f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xfc, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfc, 0xfe, 0x3f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x01, 0xff, 0x84, 0xf9, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x7f, 0x00, 0x81, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x7f, 0x00, 0x81, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x00, 0xfe, 0x00, 0xf1, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfc, 0x00, 0xfe, 0x00, 0x81, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf8, 0x01, 0xfc, 0x00, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf8, 0x01, 0xfc, 0x00, 0x81, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x03, 0xf8, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xe0, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xe0, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x80, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x80, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

const uint8_t left_arrow[] PROGMEM = { //Image for Left arrow 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x3f, 0xff, 0x80, 0x1e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

const uint8_t right_arrow[] PROGMEM = { //Image for Right arrow 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x80, 0x1f, 0xff, 0xc0, 0x00, 0x07, 0x80, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

const uint8_t cross[] PROGMEM = { //Image for the "X" 0xc0, 0x00, 0x30, 0xe0, 0x00, 0x70, 0x70, 0x00, 0xe0, 0x38, 0x01, 0xc0, 0x1c, 0x03, 0x80, 0x0e, 0x07, 0x00, 0x07, 0x0e, 0x00, 0x03, 0x9c, 0x00, 0x01, 0xf8, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xf0, 0x00, 0x01, 0xf8, 0x00, 0x03, 0x9c, 0x00, 0x07, 0x0e, 0x00, 0x0e, 0x07, 0x00, 0x1c, 0x03, 0x80, 0x38, 0x01, 0xc0, 0x70, 0x00, 0xe0, 0xe0, 0x00, 0x70, 0xc0, 0x00, 0x30};

// Global Variables U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NONE); //Search in the Internet for wich model you use! SparkFun_APDS9960 apds = SparkFun_APDS9960(); int isr_flag = 0;

int int_room; int out_room; int people_room = 1;

int in_or_out;

void interruptRoutine(); void handleGesture();

void startupdraw() //Draws the Startup Icon { u8g.drawBitmapP(0, 0, 16, 64, icon); }

void draw(void) //Draws the main Screen { u8g.setFont(u8g_font_fur14);

u8g.setPrintPos(0, 20); u8g.print("In: "); u8g.print(int_room); u8g.setPrintPos(0, 60); u8g.print("Out: "); u8g.print(out_room); u8g.setFont(u8g_font_fur17); u8g.setPrintPos(0, 40); u8g.print("People~ "); u8g.print(people_room);

if (in_or_out == 2) { u8g.drawBitmapP(70, 0, 3, 20, left_arrow); } else if (in_or_out == 1) { u8g.drawBitmapP(70, 40, 3, 20, right_arrow); } else if (in_or_out == 3) { u8g.drawBitmapP(70, 0, 3, 20, cross); u8g.drawBitmapP(70, 40, 3, 20, cross); } }

void draw2() //Drwas the "Clear" Screen { u8g.setFont(u8g_font_fur17);

u8g.setPrintPos(0, 30); u8g.print("Clearing"); u8g.setPrintPos(0, 60); u8g.print("Variables!"); u8g.drawBitmapP(100, 10, 3, 20, cross);

u8g.enableCursor(); }

void setup() {

pinMode(APDS9960_INT, INPUT);

Serial.begin(115200); Serial.println(); Serial.println(F("--------------------------------")); Serial.println(F("-----------Count ´em------------")); Serial.println(F("--------------------------------"));

attachInterrupt(0, interruptRoutine, FALLING);

if (apds.init()) { Serial.println(F("APDS-9960 initialization complete")); } else { Serial.println(F("Something went wrong during APDS-9960 init!")); }

if (apds.enableGestureSensor(true)) { Serial.println(F("Gesture sensor is now running")); } else { Serial.println(F("Something went wrong during gesture sensor init!")); }

apds.setGestureGain(1);

if (u8g.getMode() == U8G_MODE_R3G3B2) { u8g.setColorIndex(255); } else if (u8g.getMode() == U8G_MODE_GRAY2BIT) { u8g.setColorIndex(3); } else if (u8g.getMode() == U8G_MODE_BW) { u8g.setColorIndex(1); } else if (u8g.getMode() == U8G_MODE_HICOLOR) { u8g.setHiColorByRGB(255, 255, 255); }

u8g.firstPage(); do { startupdraw(); } while (u8g.nextPage()); delay(3000); u8g.firstPage(); do { draw(); } while (u8g.nextPage()); }

void loop() { if (isr_flag == 1) { detachInterrupt(0); handleGesture(); isr_flag = 0; attachInterrupt(0, interruptRoutine, FALLING); } }

void interruptRoutine() { isr_flag = 1; }

void handleGesture() { if (apds.isGestureAvailable()) { switch (apds.readGesture()) { case DIR_DOWN: //Depending on Orientation you can change this to the right ones people_room++; Serial.println("Adding" + String(people_room));

u8g.firstPage(); do { draw(); } while (u8g.nextPage());

break; case DIR_UP: //Depending on Orientation you can change this to the right ones people_room--; Serial.println("Subtracting " + String(people_room));

u8g.firstPage(); do { draw(); } while (u8g.nextPage());

break; case DIR_RIGHT: //Depending on Orientation you can change this to the right ones

int_room++; people_room++; Serial.println("IN " + String(people_room)); in_or_out = 2; u8g.firstPage(); do { draw(); } while (u8g.nextPage()); in_or_out = 0; delay(700); u8g.firstPage(); do { draw(); } while (u8g.nextPage()); break; case DIR_LEFT: //Depending on Orientation you can change this to the right ones

out_room++; people_room--; Serial.println("OUT " + String(people_room)); in_or_out = 1; if (people_room == -1) { people_room = 0; } u8g.firstPage(); do { draw(); } while (u8g.nextPage()); in_or_out = 0; delay(700); u8g.firstPage(); do { draw(); } while (u8g.nextPage()); break; case DIR_FAR: //Depending on Orientation you can change this to the right ones Serial.println("FAR"); u8g.firstPage(); do { draw(); } while (u8g.nextPage()); break; case DIR_NEAR: //Depending on Orientation you can change this to the right ones Serial.println("NEAR || RESET"); out_room = 0; int_room = 0; people_room = 1; in_or_out = 0; u8g.firstPage(); do { draw2(); } while (u8g.nextPage());

delay(3000);

u8g.firstPage(); do { draw(); } while (u8g.nextPage());

break; default: Serial.println("NONE");

in_or_out = 3;

u8g.firstPage(); do { draw(); } while (u8g.nextPage());

in_or_out = 0;

delay(700); u8g.firstPage(); do { draw(); } while (u8g.nextPage()); } } }

If you have any questions or problems, you can always message me :)