People counting has a long history which I won't repeat here. There are several available solutions that can be purchased including those using IR emit/detect (so two devices required), cameras and AI (not cheap and cameras present a privacy concern), and even radar (also not cheap). The problem with these solutions is that they don't meet some or all of the (OK, my) criteria for a ubiquitous IoT people counter. Reiterating my ideal design specifications:

1) small and unobtrusive (say, 50 cc or less)

2) ultra low power so it can run on two AAA batteries for 2 years or more

3) inexpensive, say $40 or less BOM cost

4) connected via LPWAN (low-power wide-area network), either LoRaWAN or BLE 5.0

5) utterly reliable, meaning 100% no false positives or negatives

6) no cameras or imagers that might compromise people's demand for privacy (added to the list, but no camera-based technology can meet 2) and 3) anyway).

 I am restricting the people counting I have in mind to a device that counts the number of ingresses and egresses at a portal. Some of the devices mentioned above might do other things as well and could be worth the cost, size, and otherwise be perfectly good products that deserve your attention for whatever use case you have in mind. But for the specific task of counting individual human ingress and egress events at a portal and sending the data via LPWAN to a smart device there are currently no solutions that meet the six criteria above.

This project's goal is to design and test such a device.

In order to reach the goal, the right choice of sensor(s) is going to be critical, so let's start there and consider some of the options.

First, in order to reach acceptably low power operation it is necessary that any sensors have an interrupt. This is because the optimal way to run a low power device is to put the MCU to sleep in an ultra-low power (~2 uA) state until woken up by an interrupt, either a timer interrupt or a sensor data ready or threshold crossing interrupt. So any MCU that lacks a state-preserving low-power mode (like the nRF52 and ESP32) can't be a candidate for this people counter. Any sensor that requires continuous monitoring by a host MCU must also be discarded.  This rules out most analog sensors. And while there are a spectrum of remaining options, I seriously considered only four:

The AMG8833 is an attractive option since although it is technically a camera, it is simply not possible to identify anyone from their 8 x 8 pixel AMG8833 thermal image. So this allays privacy concerns. It has a range from 0 to 5 meters, so can easily detect people passing a portal. The fastest frame rate is 10 Hz, a bit on the slow side for people counting. The AMG8833 has the rather unique ability to generate an interrupt when a pixel exceeds a temperature threshold. Yes, that's right, this device has a pixel-specific interrupt. Once the user specifies a temperature threshold, the user can query after interrupt reception which specific pixel or set of pixels caused the interrupt condition. This is extremely useful for people counting, since typically the set of pixels on one side of the device will reach the threshold condition before the set of pixels on the opposite side of the device providing the directional information required for proper egress and ingress discrimination. We successfully developed a prototype using this sensor (which is an uber-kool sensor to play with in any case) but the Achilles Heel here is power consumption. Normal (continuous 10 Hz) mode uses 4.5 mA, standby mode (0.1 Hz, measure every 10 s and too slow for this application) uses 0.8 mA, and while there is a sleep mode for the sensor the lowest current draw is 200 uA. Ouch! Just in case 200 uA sounds low to you, let's do the math: 0.2 mA x 24 hours/day =  4.8 mAH/day, 1200 mAH (2 x  AAA batteries)/4.8  mAH/day = 250 days. This is not taking into account the rest of the components' power usage nor the fact that the AMG8833 has to be awake some of the time to actually detect egress and ingress! This might work with a bigger battery but in the end there are better solutions out there...

The VL53L1 is a time-of-flight ranging sensor that offers superbly accurate distance estimation from 0.4 - 4 meters. The feature especially useful for people counting is that the 16 x 16 SPAD detector array can be segregated into up to four user-defined regions of interest as small as 4 x 4, and these can be used to discriminate between egress and ingress similar to the way we used the AMG8833. This means that as a person approaches, first one region will detect the distance change and then the second, and the time difference can be used as a way to discriminate direction of motion. Just watch! I tried Kabron's example for how to make this work and while I did see a small difference between rise times for the two ROIs defined the discrimination was poor. Maybe with more work or help from ST I could make this work like in the video. The VL53L1 runs at up to 50 Hz, has adequate range (for this application we selected the highest accuracy, short --1.4 meter-- range configuration), is low cost (~$4) and only one would be required. Another option is to use two VL53L1 separated by ~20 mm and this should work very well. I am tempted to try two (haven't yet) but again power consumption has given me pause. The ranging measurement uses 16 mA but the standby current is only 20 uA. So in the mode where only occasional ranging measurements are being performed this is an ultra-low-power sensor. But when ranging at 10 Hz with a 33 ms timing budget (see data sheet) the power draw is ~6 mA, about a third of the 16 mA as expected. The user can set distance thresholds and the VL53L1 can generate interrupts when these are crossed so this might be a way to minimize power. But still the device would have to be on in order to detect distance threshold crossings and even at 10 Hz (which is a bit too slow) the VL53L1 blows the power budget. Two would be worse still...

The AK9753AE is a four channel IR sensor running at up to 8.8 Hz with interrupt that measures temperature of an object in its field of view. Since the four channels are arrayed at four (N-E-S-W) positions on the sensor (like four pre-defined regions of interest) it is possible to discriminate direction by comparing the relative timing of the temperature excursion. Sparkfun has made a good start on this by taking the derivative of the temperature measurement for one of the sensors and looking for the zero crossing in order to detect the temperature peak. I modified this method to look at two of the sensor's signals, compare the times of the temperature peak maxima and thereby determine direction of motion. This kind of sort of works but there are a lot of false positives (reporting activity when there is none) and negatives (not reporting activity when there is). Even if this method were to work reliably, two of the four channels are basically being wasted for this application. Although in addition to the data ready interrupt there is a threshold interrupt for the differential function (IR1 - IR3)/(IR2 - IR4), so numerator and denominator are pairs of sensor elements 180 degrees apart.  I was using IR1 and IR3 for ingress and egress detection, and  while I am not sure what use could be made of setting a threshold for this function, it is interesting that one can set the threshold in the embedded EEPROM and the device will send interrupts to the MCU even when no I2C bus is active. I continue to be somewhat baffled by this (Switch) mode of operation and its intent. And while the continuous power usage is close to meeting the design specs (100 uA), it is still a bit too large. But the real killer here is the range. The sensor needs a lens in order to get out to the one or two meter range required for this application. And while Seeed Technology has had a lens designed for this sensor, they won't share the design nor sell me any of the lenses. And I don't want to pay the company that designed the lens for Seeed to design  a custom lens for me. I am cheap that way, and besides, this would violate design criterion 3)! The better way to use the AK9753AE sensor would to define a temperature threshold and get an interrupt when this is crossed by any of the four sensor elements with information on which element caused the interrupt. Unfortunately, this sensor doesn't support this mode of operation. But there is a similar sensor that does.

This brings us to the Excelitas Calipile TPiS 1385  presence and motion detector. It is a single-channel IR sensor that measures ambient and object temperature. The sensor samples data at a rate up to 166 Hz, at which rate it uses no more than 15 uA. The data sheet claims that the range without lens or other modification is 1 - 2 meters. So far so good. It also has various low pass and other processing filters embedded in its ASIC for the purpose of detecting human presence and human motion. I spent quite a bit of time playing with these filters trying to detect directional motion with a single sensor and it is basically impossible no matter how fancy the processing, as a few seconds of quiet thought should convince you. But it occured to me (embarrassingly late I admit) that I could just use two of these sensors spaced ~3 cm apart and even at a briskly-paced 10 miles per hour (~450 cm/second) walking speed I could expect to get a minimum sensor-to-sensor transit time difference (~7 ms) well matched to the data rate of the sensor. In practice, two or three times this transit time is the minimum time discrimination needed for a typical walker. One problem with this solution is that the field of view of the sensor is a fairly wide 120 degrees. So even at 3 cm sensor separation, the range at which 7 ms time discrimination is possible drops rapidly; at far enough range the sensors see almost the same motion. The solution to this problem is a constriction in the view, using either aluminum tubes as in the evaluation kit user's guide or simply a hole in the device container to narrow the field of view a bit, and increase the effective separation of the sensors. The scheme to discriminate ingress from egress here is simpler than Sparkfun's derivative and zero crossing approach. The idea is to set a threshold for interrupt  for each of the two sensors for an object temperature about 5% above the long term average of the object temperature, which in the absence of humans in the field of view is simply the ambient temperature. I suppose one could also just use the ambient temperature to set the threshold. The threshold needs to change with changes in the ambient temperature. Then, when the threshold interrupt is triggered, the time is recorded for that sensor. When both sensors have received an interrupt, and the interrupt times are correlated (a detail we will discuss later), then a simple subtraction gives the direction of motion and either a new egress or ingress is recorded and the update sent via LPWAN. Preliminary testing with hand waving on a benchtop shows 100% reliability of this detection scheme. This solution has the potential to fulfill all of the six design criteria, but it remains to design a pcb with the solution (first and second cuts submitted to OSH Park), assemble and test the design, and then package the pcb into a suitable container and verify function and power consumption estimates in the intended use mode. I have chosen LoRaWAN for this first test of the People Counter. Initial assembly and testing results will be the subject of the first log sometime in the first half of March.