CrawlSpaceSensor: Difference between revisions

From RevSpace
Jump to navigation Jump to search
No edit summary
 
(27 intermediate revisions by the same user not shown)
Line 1: Line 1:
   {{Project
   {{Project
   |Name=CrawlSpaceSensor
   |Name=CrawlSpaceSensor
   |Picture=whyunoimage.png
   |Picture=CrawlSpaceSensor.jpg
   |Omschrijving=Sensor inside crawl space
   |Omschrijving=Water level sensor inside crawl space
   |Status=Initializing
   |Status=Completed
   |Contact=bertrik
   |Contact=bertrik
   }}
   }}
Line 17: Line 17:
Measurement data is uploaded once an hour over WiFi to an MQTT server.
Measurement data is uploaded once an hour over WiFi to an MQTT server.


Since there is likely no mains power easily available in a crawl space, it is battery operated.
See [http://graphana.vanheusden.com/dashboard/db/fvh-shared the bottom graph on this page] for live data from a water level meter in the crawl space.
 
Status:
we tried it, didn't work really well on raw water surface, probably we need to bounce the laser of something that floats in the water.
 
== Theory ==
=== Reflection ===
The range measurement of the VL53L0X module is based on time-of-flight of the laser signal reflecting off a surface.
 
Wikipedia shows [https://en.wikipedia.org/wiki/Fresnel_equations#Normal_incidence the formula] for the reflection off an interface between two materials with different refractive index at normal incidence, examples:
* for air-glass, we have n1=1.00 and n2=1.50, the reflection coefficient is 4%.
* for air-water, we have n1=1.00 and n2=1.33, the reflection coefficient is 2%.
 
A reflection coefficient of 2% is quite low, and indeed experimentation showed difficulties determining range towards the fluid level in a glass of water.
Perhaps a practical way is to measure distance to some floating object instead, like a piece of white polystyrene foam, or a white ping-pong ball.
 
=== Calibration ===
We're considering only a ranging offset error in the measurement system.
 
Assume:
* L is the water level (mm)
* R is the distance measured by the lidar between the module and the water
 
The water level L can be calculated from the range R as follows:
  level L (mm) = Constant C (mm) - range R (mm)
 
So, once we know the actual water level L (as measured using some external means) and range R (as measured by the lidar module), we can calculate the constant C as:
  C = L + R


== Design ==
== Design ==
The plan is to use an ESP8266 to read the sensors, connect to the house WiFi and upload the measurement data once an hour.
The plan is to use an ESP8266 to read the sensors, connect to the house WiFi and upload the measurement data once an hour.
When not measuring, the ESP8266 is in deep-sleep mode (something like 80 uA current).
When not measuring, the ESP8266 is put in deep-sleep mode.
Time-of-day is retrieved using (S)NTP.
Time-of-day is retrieved using (S)NTP.


Line 28: Line 55:
* LiFePO4 battery, because they have about the right voltage for direct drive and are safe to use
* LiFePO4 battery, because they have about the right voltage for direct drive and are safe to use
* [http://www.st.com/en/imaging-and-photonics-solutions/vl53l0x.html VL53L0X] LIDAR module to accurately measure the water level
* [http://www.st.com/en/imaging-and-photonics-solutions/vl53l0x.html VL53L0X] LIDAR module to accurately measure the water level
* DHT11 or DHT22 to measure humidity and temperature
* DHT11, DHT22 or AM2302 to measure humidity and temperature
 
Pin connections
{| class="wikitable"
! ESP8266 pin
! Connect to
! Remark
|-
| D0 || ESP8266 RESET || Loopback wire to allow the ESP to wake itself from deep sleep
|-
| D1 || VL53L0X SCL || I2C clock
|-
| D2 || VL53L0X SDA || I2C data
|-
| D3 || VL53L0X SHDN || Shutdown pin
|-
| D5 || DHT11 GND || GND from GPIO
|-
| D6 || DHT11 DATA || DHT11 DATA pin
|-
| D7 || DHT11 VIN || Power supply from GPIO
|-
| 3V3 || VL53L0X VIN || Power supply
|-
| GND || VL53L0X GND || Ground
|}


==== VL53L0X LIDAR ====
==== VL53L0X LIDAR ====
Line 46: Line 98:
I plan to use the high accuracy mode since measurement time is not very important (doing only one measurement per hour and the run-time is already dominated by other tasks).
I plan to use the high accuracy mode since measurement time is not very important (doing only one measurement per hour and the run-time is already dominated by other tasks).


The documentation appears to be very careful in avoiding claims about accuracy of the ranging measurement.
This could be because there are a lot of factors involved, like temperature, cover glass, calibration, target characteristics, etc.
The API user manual indicates the following settings for high accuracy mode:
The API user manual indicates the following settings for high accuracy mode:
* a "signal rate" of 0.25 (I guess this is a measure for the amplitude of the laser return signal)
* a "signal rate" of 0.25 (I guess this is a measure for the amplitude of the laser return signal)
Line 53: Line 103:
* a measurement timing budget of 200 ms
* a measurement timing budget of 200 ms


I think the accuracy can be further improved, e.g. by increasing the measurement time.
I think the accuracy can be further improved, e.g. by increasing the measurement time and reducing the sigma limit.
According to the remark mentioned earlier, I expect that doubling the accuracy requires four times the measurement time
According to the remark mentioned earlier, I expect that doubling the accuracy requires four times the measurement time.
So for example, I think it should be possible to spend 3200 ms instead of 200 ms on the measurement, which theoretically should give 4 times the accuracy.


Using a cover glass on top of the sensor makes things more complicated, so I plan to not use a cover glass.
Using a cover glass on top of the sensor makes things more complicated, so I plan to not use a cover glass.
=== Materials ===
* A ping-pong ball, used as a target to reflect the laser off of, typically has a diameter of 40 mm.
* PVC tube 50mm, with the thickness of the tube about 3mm, should have 44 mm inside diameter, e.g. https://www.gamma.nl/assortiment/martens-rio-buis-grijs-50-mm-1-meter/p/B258777
* PVC end cap 50mm, to mount the electronics on, e.g. https://www.gamma.nl/assortiment/martens-eindstop-grijs-met-schroefdeksel-50-mm/p/B019216


=== Software ===
=== Software ===


==== Measurement cycle ====
==== Source code ====
The source code for the measurement application is [https://github.com/bertrik/crawlspace available on github].
 
I'm using the pololu library for communication with the VL53L0X.
As I understand this is not simply a wrapper around the code from ST, but is a kind of reverse engineered code.
 
==== Measurement cycle timing ====
Software tasks in one measurement cycle are: (estimated run-time)
Software tasks in one measurement cycle are: (estimated run-time)
* wake up from deep sleep (1.0s)
* wake up from deep sleep (0.3s)
* connect and authenticate to the WiFi (3.0s)
* connect and authenticate to the WiFi (4.8s)
* perform an SNTP request to get the current date/time (1.0s)
* perform an SNTP request to get the current date/time (0.1s)
* perform a distance measurement using the LIDAR (3.0s)
* perform a distance measurement using the LIDAR (0.2s)
* perform temperature/humidity measurement (1.0s)
* perform temperature/humidity measurement (0.1s)
* publish measurements to MQTT (1.0s)
* publish measurements to MQTT (0.1s)
* calculate sleep time until next wakeup and enter deep-sleep (0.0s)
* calculate sleep time until next wakeup and enter deep-sleep (0.0s)


Total about 10 seconds per measurement cycle.
Total about 5.6 seconds per measurement cycle.


Initially, when no WiFi network is known, the sensor starts its own access point presenting a captive portal allowing a WiFi network to be selected.
Initially, when no WiFi network is known, the sensor starts its own access point presenting a captive portal allowing a WiFi network to be selected.
==== Data format ====
The plan is to encode the measurement data in JSON and post it as text on a MQTT topic.
Example of proposed data format:
<pre>
{
    "id": "12AABB",
    "time": 123456789,
    "humidity": 87,
    "temperature": 21.4,
    "range": 78
}
</pre>
Where id is the ESP8266 unique id (in hex), time is in seconds since 1970/1/1 (UTC), humidity in percent, temperature in degrees Celcius and range in millimeters.
The "range" value represents the distance between the sensor and the fluid.
A higher range means a lower fluid level.
==== Libraries ====
The plan is to use the following libraries:
* WifiManager to handle WiFi authentication and presenting a captive portal if it cannot authenticate
* [https://github.com/pololu/vl53l0x-arduino pololu VL53L0X] library


=== Battery Life ===
=== Battery Life ===
Line 78: Line 164:
An 18650 type battery has approximately double capacity compared to a 14500 battery, about 1500 mAh.
An 18650 type battery has approximately double capacity compared to a 14500 battery, about 1500 mAh.


Sleep current is estimated to be about 0.10 mA total (about 80 uA for the ESP8266 in deep-sleep, about 5 uA for the VL53L0X in HW standby mode).
Sleep current is estimated to be about 0.15 mA total (about 80 uA for the ESP8266 in deep-sleep, about 50 uA for the DHT11/22, about 5 uA for the VL53L0X in HW standby mode).


When awake, current consumption is estimated to take 100 mA on average for 10 seconds.
When awake, current consumption is estimated to take 70 mA on average for 5.6 seconds.
This means each measurement takes about 0.28 mAh.
This means each measurement takes about 0.11 mAh.


So, over one measurement cycle of one hour, we consume about 0.10 mAh in sleep-current and about 0.28 mAh in run-current, for a total of about 0.38 mAh.
So, over one measurement cycle of one hour, total charge consumed sums up to a total of about 0.26 mAh.
With a 700 mAh battery this would allow about 1800 measurements, making the battery last about 76 days.
With a 700 mAh battery this would allow about 2500 measurements, making the battery last about 100 days.


== Interesting links ==
== Interesting links ==
* The [http://www.st.com/content/st_com/en/products/embedded-software/proximity-sensors-software/stsw-img005.html STSW-IMG005] library from ST
* The [http://www.st.com/content/st_com/en/products/embedded-software/proximity-sensors-software/stsw-img005.html STSW-IMG005] library from ST
* [https://www.youtube.com/watch?v=EgPu58bh1r4 Video] showing this module being used to measure fluid level
* [https://www.youtube.com/watch?v=EgPu58bh1r4 Video] showing this module being used to measure fluid level
* [http://www.davidpilling.net/wiki/index.php/TOF Liquid level sensor using a laser time of flight sensor] by David Pilling

Latest revision as of 16:03, 4 April 2022

Project CrawlSpaceSensor
CrawlSpaceSensor.jpg
Water level sensor inside crawl space
Status Completed
Contact bertrik
Last Update 2022-04-04

Introduction

This is a project idea for monitoring the crawl space under a house for water ingress. Basically looking for a nice use case to try out these miniature LIDAR sensors that are now available cheaply (about E8,-).

This things monitors the crawl space for the following properties:

  • water level (in case it is flooded), using a VL53L0X lidar sensor
  • humidity and temperature using a DHT11 or DHT22

Measurement data is uploaded once an hour over WiFi to an MQTT server.

See the bottom graph on this page for live data from a water level meter in the crawl space.

Status: we tried it, didn't work really well on raw water surface, probably we need to bounce the laser of something that floats in the water.

Theory

Reflection

The range measurement of the VL53L0X module is based on time-of-flight of the laser signal reflecting off a surface.

Wikipedia shows the formula for the reflection off an interface between two materials with different refractive index at normal incidence, examples:

  • for air-glass, we have n1=1.00 and n2=1.50, the reflection coefficient is 4%.
  • for air-water, we have n1=1.00 and n2=1.33, the reflection coefficient is 2%.

A reflection coefficient of 2% is quite low, and indeed experimentation showed difficulties determining range towards the fluid level in a glass of water. Perhaps a practical way is to measure distance to some floating object instead, like a piece of white polystyrene foam, or a white ping-pong ball.

Calibration

We're considering only a ranging offset error in the measurement system.

Assume:

  • L is the water level (mm)
  • R is the distance measured by the lidar between the module and the water

The water level L can be calculated from the range R as follows:

 level L (mm) = Constant C (mm) - range R (mm)

So, once we know the actual water level L (as measured using some external means) and range R (as measured by the lidar module), we can calculate the constant C as:

 C = L + R

Design

The plan is to use an ESP8266 to read the sensors, connect to the house WiFi and upload the measurement data once an hour. When not measuring, the ESP8266 is put in deep-sleep mode. Time-of-day is retrieved using (S)NTP.

Hardware

  • ESP8266 in a Wemos D1 mini board, because they're so easy to use
  • LiFePO4 battery, because they have about the right voltage for direct drive and are safe to use
  • VL53L0X LIDAR module to accurately measure the water level
  • DHT11, DHT22 or AM2302 to measure humidity and temperature

Pin connections

ESP8266 pin Connect to Remark
D0 ESP8266 RESET Loopback wire to allow the ESP to wake itself from deep sleep
D1 VL53L0X SCL I2C clock
D2 VL53L0X SDA I2C data
D3 VL53L0X SHDN Shutdown pin
D5 DHT11 GND GND from GPIO
D6 DHT11 DATA DHT11 DATA pin
D7 DHT11 VIN Power supply from GPIO
3V3 VL53L0X VIN Power supply
GND VL53L0X GND Ground

VL53L0X LIDAR

This module integrates a VCSEL laser, a photo diode, probably some analog circuitry and a small microcontroller to do digital processing. It has an I2C interface, but it seems you need a library from ST to get an actual meaningful distance out of it.

I'm not actually sure how it works exactly, it measures the time-of-flight between light sent out by the laser and received back through the photo diode. Apparently it involves averaging a lot of individual measurements, since the API manual mentions:

 "Increasing the timing budget increases the range measurement accuracy. That is: x N on timing budget => standard deviation / square root of N. For example is the timing budget is increased by a factor of x 2, then the range measurement standard deviation decreases by square root of 2."

Taking a measurement after reset requires a couple of initialisation/calibration steps, I need to figure out which ones are actually relevant for my use case.

The API describes basically three ranging profiles with impact on the time required to do one measurement:

  • high accuracy
  • high speed
  • long range.

I plan to use the high accuracy mode since measurement time is not very important (doing only one measurement per hour and the run-time is already dominated by other tasks).

The API user manual indicates the following settings for high accuracy mode:

  • a "signal rate" of 0.25 (I guess this is a measure for the amplitude of the laser return signal)
  • a "sigma" of 18 mm
  • a measurement timing budget of 200 ms

I think the accuracy can be further improved, e.g. by increasing the measurement time and reducing the sigma limit. According to the remark mentioned earlier, I expect that doubling the accuracy requires four times the measurement time. So for example, I think it should be possible to spend 3200 ms instead of 200 ms on the measurement, which theoretically should give 4 times the accuracy.

Using a cover glass on top of the sensor makes things more complicated, so I plan to not use a cover glass.

Materials

Software

Source code

The source code for the measurement application is available on github.

I'm using the pololu library for communication with the VL53L0X. As I understand this is not simply a wrapper around the code from ST, but is a kind of reverse engineered code.

Measurement cycle timing

Software tasks in one measurement cycle are: (estimated run-time)

  • wake up from deep sleep (0.3s)
  • connect and authenticate to the WiFi (4.8s)
  • perform an SNTP request to get the current date/time (0.1s)
  • perform a distance measurement using the LIDAR (0.2s)
  • perform temperature/humidity measurement (0.1s)
  • publish measurements to MQTT (0.1s)
  • calculate sleep time until next wakeup and enter deep-sleep (0.0s)

Total about 5.6 seconds per measurement cycle.

Initially, when no WiFi network is known, the sensor starts its own access point presenting a captive portal allowing a WiFi network to be selected.

Data format

The plan is to encode the measurement data in JSON and post it as text on a MQTT topic.

Example of proposed data format:

{
    "id": "12AABB",
    "time": 123456789,
    "humidity": 87,
    "temperature": 21.4,
    "range": 78
}

Where id is the ESP8266 unique id (in hex), time is in seconds since 1970/1/1 (UTC), humidity in percent, temperature in degrees Celcius and range in millimeters.

The "range" value represents the distance between the sensor and the fluid. A higher range means a lower fluid level.

Libraries

The plan is to use the following libraries:

  • WifiManager to handle WiFi authentication and presenting a captive portal if it cannot authenticate
  • pololu VL53L0X library

Battery Life

A typical LiFePO4 "AA" (14500) type battery has 700 mAh capacity. An 18650 type battery has approximately double capacity compared to a 14500 battery, about 1500 mAh.

Sleep current is estimated to be about 0.15 mA total (about 80 uA for the ESP8266 in deep-sleep, about 50 uA for the DHT11/22, about 5 uA for the VL53L0X in HW standby mode).

When awake, current consumption is estimated to take 70 mA on average for 5.6 seconds. This means each measurement takes about 0.11 mAh.

So, over one measurement cycle of one hour, total charge consumed sums up to a total of about 0.26 mAh. With a 700 mAh battery this would allow about 2500 measurements, making the battery last about 100 days.

Interesting links