Ultrasonic Distance Sensor "Oscar" (LoRaWAN)
Target Measurement / Purpose
Distance measurements via ultrasound.
Features
- 30 cm to 3 m detection range
- Up to 8 detected objects
Technical Description
The device is based on the PGA460 from Texas Instruments (http://www.ti.com/product/PGA460).
The PGA460 enables tuning of the ultrasonic sensor for all kinds of environments. The default firmware supports parameters tested in underground waste bins.
Lobaro offers customized tuning and consulting for environments where the default configuration does not match.
The sensor can detect multiple "objects", but the LoRaWAN payload only contains the first one.
Open-Top vs. Closed-Top
The sensor is shipped with an open-top membrane. This has advantages in sensitivity and range, but is more prone to environmental impacts.
Closed-top sensors (e.g. as used in automotive applications) need more energy to send out a clear signal, but are resistant against environmental impacts.
Configuration
LoRaWAN Parameters
For the configuration of the LoRaWAN connection parameters (OTAA/ABP, DevEUI,
AppEUI, AppKey, SF, ADR, …), refer to the
LoRaWAN configuration article.
Ultrasonic Parameters
Parameters specific to the sensor.
| Name | Type | Description |
|---|---|---|
ReadDistCron | String | Cron expression that starts the distance readout, blank = disabled (see Introduction to CRON expressions). |
UsonicPreset | Int | Preset for the ultrasonic sensor used by custom firmwares (keep the default!). |
UsonicTest | Bool | Enables test mode: a measurement is executed and logged permanently. |
LogDump | Bool | Also log the raw data dump of the ultrasonic sensor. |
Available firmware versions and release notes are listed on the Firmware & Changelog page.
Payload
The following structures are derived from the parser below. All multi-byte values are little-endian.
Status Packet (Port 1)
| Name | Pos | Len | Type | Description |
|---|---|---|---|---|
| firmware version | 0 | 3 | byte[3] | Firmware version as major.minor.patch. |
| vBat | 4 | 2 | uint16 LE | Battery voltage in mV. |
| temperature | 6 | 2 | int16 LE | Temperature in 1/10 °C. |
Payload (Port 2)
| Name | Pos | Len | Type | Description |
|---|---|---|---|---|
| vBat | 0 | 2 | uint16 LE | Battery voltage in mV. |
| temperature | 2 | 2 | int16 LE | Temperature in 1/10 °C. |
| numResults | 4 | 1 | uint8 | Number of detected objects in this payload. |
| results | 5 | 8 × N | see below | One 8-byte block per detected object. |
Each result block is structured as follows:
| Name | Pos | Len | Type | Description |
|---|---|---|---|---|
| distance | 0 | 4 | uint32 LE | Distance to the object in mm. |
| tof | 4 | 2 | uint16 LE | Time of flight in µs. |
| width | 6 | 1 | uint8 | Signal width in µs. |
| amplitude | 7 | 1 | uint8 | Signal amplitude (0–255). |
Currently only the first detected object is uploaded via LoRaWAN.
Parser
The Things Network (TTN)
This is a decoder written in JavaScript that can be used to parse the device's LoRaWAN messages. It can be used as is in The Things Network.
function decodeUInt16(byte1, byte2) {
var decoded = byte1 | byte2 << 8;
if ((decoded & 1 << 15) > 0) { // value is negative (16bit 2's complement)
decoded = ((~decoded) & 0xffff) + 1; // invert 16bits & add 1 => now positive value
decoded = decoded * -1;
}
return decoded;
}
function Decoder(bytes, port) {
// Decode an uplink message from a buffer
// (array) of bytes to an object of fields.
var decoded = {};
if (port === 2) { // Payload
decoded.vBat = (bytes[0] | bytes[1] << 8) / 1000.0; // byte 6-7 (originally in mV)
decoded.temp = decodeUInt16(bytes[2], bytes[3]) / 10.0;
decoded.numResults = bytes[4];
var idx = 5;
decoded.results = [];
for (var i = 0; i < decoded.numResults; i++) {
var result = {};
result.distance_mm = bytes[idx] | bytes[idx + 1] << 8 | bytes[idx + 2] << 16 | bytes[idx + 3] << 24;
result.distance_m = result.distance_mm / 1000;
result.tof_us = bytes[idx + 4] | bytes[idx + 5] << 8;
result.width = bytes[idx + 6];
result.amplitude = bytes[idx + 7];
decoded.results[i] = result;
idx += 8;
}
}
// example decoder for status packet by lobaro
if (port === 1) { // status packet
decoded.firmwareVersion = bytes[0] + "." + bytes[1] + "." + bytes[2]; // byte 0-3
decoded.vBat = (bytes[4] | bytes[5] << 8) / 1000.0; // byte 6-7 (originally in mV)
decoded.temp = decodeUInt16(bytes[6], bytes[7]) / 10.0; // byte 8-9 (originally in 10th degree C)
decoded.msg = "Firmware Version: v" + decoded.firmwareVersion + " Battery: " + decoded.vBat + "V Temperature: " + decoded.temp + "°C";
}
return decoded;
}
Example Parser Result
{
"numResults": 1,
"results": [
{
"amplitude": 215,
"distance_m": 0.761,
"distance_mm": 761,
"tof_us": 4539,
"width": 122
}
],
"temp": 21.8,
"vBat": 2.779
}
You can think of the ultrasonic signal as a strength of signal or volume over time:
- Amplitude ranges from 0–255 and has no unit. It is highly influenced by the internal amplification parameter. An amplitude of 100 or above is interpreted as a reflected signal. Values below 100 are dismissed as background noise.
- ToF is the time of flight measured in µs. Together with the speed of sound, the distance to a detected object is calculated from it.
- Width indicates how "wide" a detected signal is in time. That is the time in µs before the amplitude drops back below the threshold.
Encoder
Used to update the configuration on the device.
function Encoder(object, port) {
// Encode downlink messages sent as
// object to an array or buffer of bytes.
var bytes = [];
string = object["string"] || "";
for (var i = 0; i < string.length; ++i) {
bytes.push(string.charCodeAt(i));
}
return bytes;
}