I have wanted to build a people counter sensor for a while now an after seeing People counter demo on youtube I ordered a couple of VL53L1X sensors.
I managed to find the code that ST Microelectronics uses in the demo but it is created for some other kind of board that ST sells. Here is a git repo which should get access to all of the sensors functions as I understand github repo. I am a novice so I gave up after just looking at the original code.
But how difficult would it be for someone that is a advanced arduino user to understand and convert the code to be able to use in the same way on an arduino. If necessary I could pay that person to have the code converted as I really want that function when trying to create my own "smart" home.
Thanks for the answer, but it is a different sensor. Also the ST-code uses more advanced functions like zones if I understand correctly. I have not seen that in any arduino code.
Also the ST-code uses more advanced functions like zones if I understand correctly
I don’t think you have. You get a single number from the sensor. The zones they talk of in the video are simply ranges of distance. The distance will be smaller as you are under the sensor, if the distance is less than the normal floor reading but greater than the directly under reading it is considered to be an outer zone. It is a bit of a trick as that demo would not work with children nor with people below a specific height.
If you take continuous readings from the sensor and plot them to the serial plotter then you should see a curve and it might be easer to spot where you have to set your height thresholds.
To count as a person in, you will get an outer zone followed by an inner zone and then followed by an outer zone. If you get this and immediately get an inner zone distance followed by an outer zone then this is counted as a partial entry.
Ok, but I still think that my theory about the zones is a little more complicated. I found some more code from sparkfun where you can specify different Areas (Regions of Interest):
void setROI(uint16_t x, uint16_t y); --- Set the height and width of the ROI in SPADs, lowest possible option is 4. ROI is always centered.
uint16_t getROIX(); --- Returns the width of the ROI in SPADs
uint16_t getROIY(); --- Returns the height of the ROI in SPADs
as the sensor is using a 16x16 arrray of detectors. But I don't understand how to specify a custom region when you only get a single x and y.
If necessary I could pay that person to have the code converted
Consider posting on the Gigs and Collaborations forum section.
My reading of the people counter code suggests that there are both ranging zones and regions of interest (in the field of view) zones. If the range is below a certain distance, a person is detected. Then, there is a state change algorithm that decides whether someone has entered or is in the left or right regions of interest, and is moving from one region to the other or exiting either. That is all generic C/C++, so the main task would be to convert any processor specific code to Arduino.
This is the heart of the algorithm and looks to be pretty well designed. It should compile and run on Arduino with no problems.
int ProcessPeopleCountingData(int16_t Distance, uint8_t zone) {
static char PeopleCountString[4];
static int PathTrack[] = {0,0,0,0};
static int PathTrackFillingSize = 1; // init this to 1 as we start from state where nobody is any of the zones
static int LeftPreviousStatus = NOBODY;
static int RightPreviousStatus = NOBODY;
static int PeopleCount = 0;
int CurrentZoneStatus = NOBODY;
int AllZonesCurrentStatus = 0;
int AnEventHasOccured = 0;
if (Distance < DIST_THRESHOLD_MAX) {
// Someone is in !
CurrentZoneStatus = SOMEONE;
}
// left zone
if (zone == LEFT) {
if (CurrentZoneStatus != LeftPreviousStatus) {
// event in left zone has occured
AnEventHasOccured = 1;
if (CurrentZoneStatus == SOMEONE) {
AllZonesCurrentStatus += 1;
}
// need to check right zone as well ...
if (RightPreviousStatus == SOMEONE) {
// event in left zone has occured
AllZonesCurrentStatus += 2;
}
// remember for next time
LeftPreviousStatus = CurrentZoneStatus;
}
}
// right zone
else {
if (CurrentZoneStatus != RightPreviousStatus) {
// event in left zone has occured
AnEventHasOccured = 1;
if (CurrentZoneStatus == SOMEONE) {
AllZonesCurrentStatus += 2;
}
// need to left right zone as well ...
if (LeftPreviousStatus == SOMEONE) {
// event in left zone has occured
AllZonesCurrentStatus += 1;
}
// remember for next time
RightPreviousStatus = CurrentZoneStatus;
}
}
// if an event has occured
if (AnEventHasOccured) {
if (PathTrackFillingSize < 4) {
PathTrackFillingSize ++;
}
// if nobody anywhere lets check if an exit or entry has happened
if ((LeftPreviousStatus == NOBODY) && (RightPreviousStatus == NOBODY)) {
// check exit or entry only if PathTrackFillingSize is 4 (for example 0 1 3 2) and last event is 0 (nobobdy anywhere)
if (PathTrackFillingSize == 4) {
// check exit or entry. no need to check PathTrack[0] == 0 , it is always the case
if ((PathTrack[1] == 1) && (PathTrack[2] == 3) && (PathTrack[3] == 2)) {
// This an entry
PeopleCount ++;
sprintf(PeopleCountString, "%d", PeopleCount);
XNUCLEO53L1A1_SetDisplayString(PeopleCountString);
} else if ((PathTrack[1] == 2) && (PathTrack[2] == 3) && (PathTrack[3] == 1)) {
// This an exit
PeopleCount --;
sprintf(PeopleCountString, "%d", PeopleCount);
XNUCLEO53L1A1_SetDisplayString(PeopleCountString);
}
}
PathTrackFillingSize = 1;
}
else {
// update PathTrack
// example of PathTrack update
// 0
// 0 1
// 0 1 3
// 0 1 3 1
// 0 1 3 3
// 0 1 3 2 ==> if next is 0 : check if exit
PathTrack[PathTrackFillingSize-1] = AllZonesCurrentStatus;
}
}
// output debug data to main host machine
return(PeopleCount);
}
That's not the paper that explains the actual people counting. That one is linked by the comment above me from @JoerideMan.
Thus far, i haven't been able to find code to use in the ESP8266 for this but i assume it's not "that" difficult to get it working on there anymore as all code is just there (CodePile | Easily Share Piles of Code).
Got the people detection using VL53L1X working using the codes found from above, and install on the top of the door frame (aiming downward).
But not very accurate...sometimes not able to detect people in 1 direction... .at the end, the in and out do not match (if it works well, then the out = in).
Anyone got any idea what needs to be tweaked to get it to work?
"2.2 Timing considerations" - "The minimum inter-measurement period must be longer than the timing budget + 4 ms." This is not in the example code, or in Rev 1.
"2.5.3 Distance mode" - 'short' mode ("Up to 1.3m" in dark) has "Better ambient immunity"
Threshold-based interrupts probably better than continuous distance reading for low power home automation.
There is also a ST VL53L3CX, which does some kind of processing of the histogram, returning an array of distances for "multi-target detection" (VL53LX_GetMultiRangingData(Dev, pMultiRangingData)). Different purpose?
Very useful links Cretep thank you. I have implemented the code from your link Here. I have found however, that the code is unreliable in detecting direction. Left -> Right movement is sometimes recorded as Right -> Left and vice versa. I was able to make it slightly more reliable by reducing SPAD array zone size, however it still fails ~25% of the time.
Edit: I managed to get much better results with these ROI(Region of Interest)/zone settings: Width=8, Height=8, opticalCentre[] = {167, 223}