Ultrasonic rangefinders and infrared (IR) rangefinders used to be the only solution for detecting proximity of largish objects / bodies reasonably accurately. They are however plagued with many issues, such as:
Ultrasonic: It's not very accurate
Multiple ultrasonic sensors firing away confuse each other
They occasionally suffer from ‘false positive’ or spiky readings – not a good scenario when small changes in measurements are needed
Ultrasonic: If the sensor faces out to a space beyond 4m, the chances of erratic readings are higher
IR: no good for outdoor (i.e. sunlit) scenarios
These days, we also have ToF (time of flight) laser IR rangefinders! Originally designed for the mobile smartphone industry (think proximity sensors used to detect if you have the handset held to your ear), these tiny sensors can now be fitted into smaller setups and achieve similar, if not slightly better performance compared to ultrasonic rangefinders. Since these use the I2C digital protocol to communicate back to microcontrollers, it is a lot simpler to connect hardware-wise. Code libraries are available to get started with the basics quickly. Like any I2C sensor, you need to connect the SDA/SCL lines:
While these do work outdoors, their IR nature means that direct sunlight scenarios are still not recommended. They will work better than IR rangefinders (laser vs LED), but plenty of testing is needed.
Note: this links to the Adafruit version of this board, but you can easily swap it with the [Pololu variant](https://www.pololu.com/product/2490) so long as you match the pin labels accordingly.
// This #include statement was automatically added by the Particle IDE.
#include<Adafruit_VL53L0X.h>#define VL53L0X_LOG_ENABLE 0uint32_t _trace_level = TRACE_LEVEL_ALL;
#if defined(PARTICLE) && (SYSTEM_VERSION >= 0x00060000)SerialLogHandler logHandler(LOG_LEVEL_ALL);
#endif
Adafruit_VL53L0X lox = Adafruit_VL53L0X();
// how long between each log update? feel free to change this value,
// but this must not be anything less than 1000 milliseconds!
#define INTERVAL_BETWEEN_LOGS 5000// initialise the timer
Timer dataTimer(INTERVAL_BETWEEN_LOGS, doDataUpdate);
// You can have up to 4 on one i2c bus but one is enough for testing!
Adafruit_MPR121 cap = Adafruit_MPR121();
// Keeps track of the last pins touched
// so we know when buttons are 'released'
uint16_t lasttouched =0;
uint16_t currtouched =0;
// code in this setup function runs just once, when Photon is powered up or reset
voidsetup() {
Serial.begin(9600); // Open a connection via the Serial port / USB cable – useful for debugging
if (!lox.begin()) {
Serial.println("Failed to boot VL53L0X");
while(1);
}
Serial.println("VL53L0X API Simple Ranging example\n\n");
delay(5000); // Common practice to allow board to 'settle' after connecting online
dataTimer.start();
}
// code in this loop function runs forever, until you cut power!
// for the A/D blackbox, there is nothing to do in here because data updates are handled by our timer
voidloop() {
}
// doDataUpdate runs every interval set in INTERVAL_BETWEEN_LOGS
voiddoDataUpdate() {
// IMPORTANT: to prevent server overload, the Particle cloud can only accept
// update rates of once per second, with the option to 'burst' 4 updates in a
// second (but then you'll get blocked for the next 4 seconds). 'Ration' your
// INTERVAL_BETWEEN_LOGS and the number of readings you are publishing; in our
// default example, we are frugally using just 1 publish, by concatenating
// all the data we want into a single publish statement
// get ready to print out all states of the sensor
String output ="";
VL53L0X_RangingMeasurementData_t measure;
lox.rangingTest(&measure, true); // pass in 'true' to get debug data printout!
if (measure.RangeStatus !=4) { // phase failures have incorrect data
Serial.print("Distance (mm): ");
Serial.println(measure.RangeMilliMeter);
output = measure.RangeMilliMeter;
} else {
output ="e";
Serial.println(" out of range ");
}
// prints this out the Serial port (coolterm) for us humans to verify and debug; comment the next line if you don't want to see it in Coolterm
Serial.println(output);
// finally, send it out (and have your IFTTT recipe ready to use it):
Particle.publish("sensorData", output);
}