Everything about Internet of Things and more

Arduino Snow Depth Remote Sensing with Ultrasonic sensor and ESP8266

Gearbest  promotion

Wouldn’t be great to know in the morning how much snow has fallen over the night just by looking at you smartphone? Either you need to go to work or you want to know the snow depth at your vacancy house in the mountains, there is a simply way to do that by setting up a remote snow depth measuring unit and tracking it with Internet of Things on your mobile devices. In this article I will tell you everything you need to know about this IoT project, in order to do it yourself.

Probably the best books to learn Arduino

How to measure the Snow Depth with Arduino and Internet of Things

While I’m writing, in Romania continuously snows since 2 days ago and the temperature in my city is -13 °C. I can proudly tell you that, without looking at TV weather programs, the snow depth is about 38 cm, just by looking at my smartphone. In order to achieve this I’ve made a little project which costed my under 15$, but depending on which data transmission method you choose to use, it may vary.

I live in Bucharest (Romania), in a building with 10 floors in the middle of the city, and because of that, I felt that the best place to measure the snow depth is on the rooftop. Measuring the snow depth at the ground level would have been a challenge because of the very small distance between the buildings and trees and also allot of cars. My building rooftop is perfectly flat has no barriers to stop the snow to settle evenly.

Arduino Snow Depth Remote Sensing with Ultrasonic sensor and ESP8266

Project design and working principle

I spent some time thinking the how to design this project in order to have good results, accurate measuring and also to fit my electronics into it. While there are many methods out there, my approach is based on an ultrasonic Arduino compatible sensor, a ordinary HC-SR04 that typically can be bought with less than 6$. See how it looks in the image below:

HC-SR04 Ultrasnoic sensor technical specifications

Before explaining the way I used this sensor to measure the snow depth, you first need to understand how an ultrasonic sensor works. As you can see in the image above, this little board has a symmetrical look and feel, where the two round components which looks like miniature speakers, are in fact the ultrasonic transceiver and receiver modules. As the manual says:

The HC-SR04 ultrasonic sensor uses sonar to determine distance to an object like bats or dolphins do. It offers excellent non-contact range detection with high accuracy and stable readings in an easy-to-use package. From 2cm to 400 cm or 1” to 13 feet. It operation is not affected by sunlight or black material like Sharp rangefinders are (although acoustically soft materials like cloth can be difficult to detect).

To start measurement, Trig of SR04 must receive a pulse of high (5V) for at least 10us, this will initiate the sensor will transmit out 8 cycle of ultrasonic burst at 40kHz and wait for the reflected ultrasonic burst. When the sensor detected ultrasonic from receiver, it will set the Echo pin to high (5V) and delay for a period (width) which proportion to distance. To obtain the distance, measure the width (Ton) of Echo pin.

Extras from manual offered by cytron.com.my.

A more simple (less technical) explanation: 

Arduino Snow Depth Remote Sensing with Ultrasonic sensor and ESP8266

The transceiver sends a sound wave with the speed of sound (343.2 m/s) and the receiver waits for the signal to come back while counting the time. A basic sound echo phenomenon. Basic physics tells that if we know the speed and time we can easily calculate the distance by applying formula D = VT/2, where:

D = distance, V = Sound speed, T = measured time for trigger signal to perform the round trip

But working with ultrasonic sensors can be tricky sometimes if you don’t know the entire picture. In a perfect setup, having a proper environment they should do a good job, but you can encounter problems if you do not respect the working conditions, especially the angle alignment, and also the ambient temperature.

Regarding the perfect setup:

The speed of sound is the distance traveled per unit time by a sound wave as it propagates through an elastic medium. In dry air at 20 °C, the speed of sound is 343.2 meters per second, or a kilometer in 2.914 s or a mile in 4.689 s. Wikipedia

Ultrasonic Temperature compensation

Well, at least in my country, it doesn’t snow at 20 °C, as I told you the temperature at this moment is somewhere between -5 °C and -15 °C so adjustments needs to be done in order to get relevant data. There are many factors that can influence the speed of sound but in this case the temperature and humidity is the most critical. To reduce the impact over the result we need to apply the practical formula for dry air which says:

The approximate speed of sound in dry (0% humidity) air, in meters per second, at temperatures near 0 °C, can be calculated from

C air = (331.3 + 0.606 * T) m/s

where T is the temperature in degrees Celsius (°C). So at -13 °C we should have the speed of sound = (331.3 + 0.606 * (-13)) = 318.9  m/s. Therefore, because the temperature is not constant, a temperature sensor was needed, and I choosed to use a DS18B20 1-Wire Temperature sensor from Dallas. Read this DS18B20 Arduino Tutorial if you never used this sensor before.

Now that we covered this part, you should know that another limitation of this HC-SR04 ultrasonic sensor is the angle. The emitted sound is a longitudinal wave. Therefore when the obstacle is not perfectly in front of the module, sounds can be deflected and echo signal may not reach back the sensor or reach it very attenuated and hence not being detected. Bad and good examples in the images below:

Arduino Snow Depth Remote Sensing with Ultrasonic sensor and ESP8266

Arduino Snow Depth Remote Sensing with Ultrasonic sensor and ESP8266

More examples about how to NOT use HC-SR04:

Arduino Snow Depth Remote Sensing with Ultrasonic sensor and ESP8266

You can see in the bottom left corner a warning when “Object is too soft”, and you may thing that the snow is soft too and the sound waves may not be reflected. I thought that too, until I made some research and after reading this article about snow reflecting sounds, I decided that I should give it a try.

So I mounted the ultrasonic sensor at a precise distance of 104 cm from the ground (measured with a real ruler), facing down (to the rooftop) like in the picture below.

Arduino Snow Depth Remote Sensing with Ultrasonic sensor and ESP8266

The plan was that while the snow settles, the distance between the ultrasonic sensor and the rooftop (as the closest front object) will gradually drop. Therefore I could easily find the snow depth by subtracting the current measured distance from the base distance. So let’s say our sensor is currently measuring a distance equal with 85 cm, that means that by simply doing 104 – 85 = 19. This means that the snow depth right under the sensor is about 19cm.

Arduino Snow Depth Remote Sensing with Ultrasonic sensor and ESP8266

Hardware parts and materials

Note that I my advantage is that living at the last floor (10th), I have a pretty good WiFi signal on the rooftop from my apartment router, and this simplified allot the project by using the ESP8266-12F as a controller and also as a WiFi solution. As many of you probably don’t have a WiFi coverage in the spot you want to measure the snow depth, the same results can be achieved with an Arduino Pro Mini and a 3G GSM Arduino compatible module (I will describe that later). Read this ESP8266 Arduino tutorial if you never used this board.

In the image bellow I tried to reproduce a sketch of the actual project to have a better overview about my design idea. Off course in reality the space inside is a little smaller, but I found a way to fit all inside and to squeeze some cotton wool for protection.

Arduino Snow Depth Remote Sensing with Ultrasonic sensor and ESP8266

Hookup and schematics

The hookup is not so complicated, the only thing you should really be careful at is the Echo channel of the SR04, which sends 5V signal and needs to be step down to 3.3V, as the ESP8266 GPIO input is rated. A simple 3.3V divider with two resistors should do the job. Also the data pin from the DS18B20 should be pulled up with a 4.7K Ohm resistor as described in the datasheet. Nevertheless, because the ESP8266 sends RF bursts, I always use a tiny capacitor (10-100nF) as close as possible to the ESP8266 power terminals to cut down the peeks, and ensure a stable operation.

Arduino Snow Depth Remote Sensing with Ultrasonic sensor and ESP8266

A Panasonic 18650 Li-Ion battery nominal voltage is 3.7V. Take a look at the discharge capacity test of the NCR18650B (green model):

Arduino Snow Depth Remote Sensing with Ultrasonic sensor and ESP8266

You can see from this graphic that this battery can ensure over 3.1V almost all the discharge phase while consuming under 0.5A. After reading some forums I’ve decided to try powering all modules using 4×18650 in parallel, meaning with 3.7V. That didn’t work for the HC-SR04, the echo response was useless. Here is a comparison between 3V3 and 5V:

Arduino Snow Depth Remote Sensing with Ultrasonic sensor and ESP8266

Arduino Snow Depth Remote Sensing with Ultrasonic sensor and ESP8266

After this “fail”, I decided to regroup the batteries like this: 2xParallel (~6000mAh@3.7V) for the ESP Module + DS18B20 and 2xSeries(~3300mAh@7V) for the HC-SR04, while connected in the circuit with a common ground. A resistor was needed before the HC-SR04 Vcc, to drop a bit the voltage up to near 5V. The moral is that the HC-SR04 can be triggered with 3.3V but if you want to get any results it should be powered with 5V. This is the new hookup schematic:
Arduino Snow Depth Remote Sensing with Ultrasonic sensor and ESP8266

The software – Arduino code example

Because I use the ESP8266 DEEP_SLEEP mode, the business process is done entirely in the setup method while the loop method is empty. In order to get more relevant results, considering that this ultrasonic sensor is not very accurate and the probability to get two identical measurements in a row is low, I tried to reduce the peeks by making an average on three measurements series. Same with the temperature too. Also, in the sketch above you will see that I’ve connected the GPIO 16 with the REST pin in order give the ESP module possibility to wake-up from the DEEP_SLEEP mode.

  ESP8266 Arduino Tutorial - Snow Depth with Temperature Compensation
  Arduino code example

  - replace the dots with your Wi-fi credentials and
  - your Channel API key from Thingspeak account
  - replace the DS18B20 Address with yours
#include <OneWire.h>
#include <DallasTemperature.h>
#include <ESP8266WiFi.h>

// DS18B20 data GPIO
#define ONE_WIRE_BUS 4
// Turn OFF temperature compensation if FIXEDSPEED == 1
#define FIXEDSPEED 0

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
// DS18B20 address needs to be discovered with OneWireSearch example
DeviceAddress insideThermometer = {0x28, 0xC0, 0xFA, 0x79, 0x06, 0x00, 0x00, 0x70};

// Thingspeak API key and API service
String apiKey = "************";
const char* logServer = "api.thingspeak.com";

// Home WiFi Internet router credentials
const char* ssid = "************";
const char* password = "***************";

// HC-SR04 GPIO mapping
int pingPin = 12;
int inPin = 14;

// ESP8266 DEEP_SLEEP interval = 5m
int sleepInterval = 300;

// Distance from the HC-SR04 to the ground
int baseDistance = 104;

float t1, t2, t3;
float d1, d2, d3;

float temp, dist, snowDepth;

void setup() {
  if (!oneWire.search(insideThermometer)) {
    Serial.println("Unable to find address for insideThermometer");
  sensors.setResolution(insideThermometer, 9);


     Working process management
     Main functions calling
  // Get the average temperature
  temp = getTemperature(insideThermometer);
  // Get the average distance
  dist = getAverageDistance(temp);
  // Calculate the Snow Depth
  snowDepth = calculateSnowDepth(dist);
  // Send data to Thingspeak
  sendSnowDepth(temp, snowDepth);
  // Go to DEEP_SLEEP 5 minutes

  This function returns an average of
  three measurements at a 200ms
  distance to have more accuracy
float getTemperature(DeviceAddress deviceAddress) {
  t1 = sensors.getTempC(deviceAddress);
  t2 = sensors.getTempC(deviceAddress);
  t3 = sensors.getTempC(deviceAddress);

  return (t1 + t2 + t3) / 3;

  This function returns the distance to the object
  in front of the HC-SR04 sensor with Temperature
  compensation depending of FIXEDSPEED setting
float getDistance(float pi_temp) {
  long duration;
  float c; // speed of sound

  // The sensor is triggered by a HIGH pulse of 10 or more microseconds.
  // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  digitalWrite(pingPin, HIGH);
  digitalWrite(pingPin, LOW);

  // Read the signal from the sensor: a HIGH pulse whose
  // duration is the time (in microseconds) from the sending
  // of the ping to the reception of its echo off of an object.
  pinMode(inPin, INPUT);
  duration = pulseIn(inPin, HIGH);

  // estimate speed of sound from temperature:

  if (FIXEDSPEED == 1)  {
    c = 10000.0 / 29; // Original value for c in code
  }  else {
    c = 331.3 + 0.606 * pi_temp / 100;
  return microsecondsToCentimeters(duration, c);

  This function gets an average distance from
  three measurements done at 200ms interval
float getAverageDistance(float pi_temp) {
  d1 = getDistance(pi_temp);
  d2 = getDistance(pi_temp);
  d3 = getDistance(pi_temp);
  return (d1 + d2 + d3) / 3;

float calculateSnowDepth(float pi_dist) {
  return baseDistance - pi_dist;

float microsecondsToCentimeters(long microseconds, float c) {
  // The speed of sound is 340 m/s or 29 microseconds per centimeter.
  // actually 29 microsec/cm = 10000/29 = 344.8 m/s, ie 22.3 deg C
  // The ping travels out and back, so to find the distance of the
  // object we take half of the distance travelled.
  return microseconds * c / 20000;

void connectToWiFiRouter() {
  Serial.println("- connecting to Home Router SID: " + String(ssid));
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
  Serial.println("- succesfully connected");

void sendSnowDepth(float pi_temp, float pi_dist) {

  Serial.println("- starting client");
  WiFiClient client;

  Serial.println("- connecting to IoT server: " + String(logServer));
  if (client.connect(logServer, 80)) {
    Serial.println("- succesfully connected");
    String postStr = apiKey;
    postStr += "&field1=";
    postStr += String(pi_temp);
    postStr += "&field2=";
    postStr += String(pi_dist);
    postStr += "\r\n\r\n";
    Serial.println("- sending data...");
    client.print("POST /update HTTP/1.1\n");
    client.print("Host: api.thingspeak.com\n");
    client.print("Connection: close\n");
    client.print("X-THINGSPEAKAPIKEY: " + apiKey + "\n");
    client.print("Content-Type: application/x-www-form-urlencoded\n");
    client.print("Content-Length: ");
  Serial.println("- stopping the client");

void goToSleep() {
  ESP.deepSleep(1000000 * sleepInterval);

void loop() {}

The results over the night – snow depth and temperature graphics

After struggling to fix them on the rooftop, the snowfall has started late in the night, and after couple of hours here are the results:

Arduino Snow Depth Remote Sensing with Ultrasonic sensor and ESP8266

This charts are snapshots from the Thingspeak.com, the IoT platform used in the Arduino code example. Although there are not the prettiest, you can clearly see that while in the left the temperature drops pretty fast, in the right the snow depth is growing linear and stable. That means that the idea seems to work at first glance, but off course many improvements can be done.

How to display Thingspeak on Android (Thingkspeak widget)

At the beginning of the article we were talking about seeing the snow depth on the smartphone and now is the time to do that. This is very simple. In order to achieve that, you need to go to Android Google Play (Marketplace) and download this application. After installing the IoT Thingspeak Monitor Widget, you need to go to your widgets and drag this one to one of your desktops. Then immediately the settings screen will popup and ask you to fill with Thingspeak channel Id and Read API Key like in the following images:
Arduino Snow Depth Remote Sensing with Ultrasonic sensor and ESP8266

Project downsides

The biggest downside of my idea is obviously the power management. Although I used a micro-controller which offer various lower power consumption modes (DEEP_SLEEP), batteries are not the happiest solution because of the high power consumption during the measurement and RF transmissions. While the DS18B20 temperature sensor has a very low current consumption, the ESP and the HC-SR04 are eating the battery pretty quickly. My design won’t last more than 3-5 days from my calculations, for a more solid project I recommend a fixed power supply, or batteries with a bigger capacity.

Another downside is the accuracy of the HC-SR04, this sensor is not the best choice if you want very relevant results, but it does the job. While searching over the market, I was able to find dedicated ultrasonic sensors for snow measurement, but the price is so high that I couldn’t consider them. If you are interested in more specific ultrasonic sensors, check this website.

Final thoughts

Looking at the overall price for this winter IoT project, I think that it definitely worth the effort to make it. You can use the same idea in industrial or agriculture to measure the filling level of boilers or calculate the volume of cereals enclosures, or whatever your imagination can generate, but don’t forget that usually the quality comes with the price.

For those situations when you need to do measurements from very remote locations, very soon, I will update the article with how to replace the WiFi solution with a GPRS GSM 3G Module in order to be able to send data from any place. The HTTP request management is almost the same once you established a connection, and the communication between the Arduino and the GSM module can be easily done with SoftwareSerial Library.

Hoping that this article inspired you, I kindly invite you share this articlesubscribe my YouTube channel and join the communities on social networks. Feel free to comment or send suggestions / remarks so i can improve the content quality.




Gearbest  promotion

Share on: Facebook Twitter Google+

11 Replies to “Arduino Snow Depth Remote Sensing with Ultrasonic sensor and ESP8266”

  1. Mohan raj says:

    Dear ,
    I need to measure cement level in silo
    And the hight of the silo is 10 to 15m
    Please suggest suitable one for my project and thank you

    • GeeksTips says:

      Hello! Thank you for interest! The cement is liquid or solid? It is very important. Thanks.

  2. Anonymous says:

    Cool project!

    Have you considered posting a link to this project on http://community.thingspeak.com/forum

    • GeeksTips says:

      Hello, thank you for your suggestion, I really don’t have the time to post it everywhere, but you can share it with people if you think that can help others!

  3. Benjamin Sjavik says:

    Great article! I have been doing a very similar thing with a raspberry pi and an HC-SR04. We had power at the well, so I was able to connect it using a powerline networking kit.

    Unfortunately, the cheap powerline networking kit I was using failed, and they cost about $80 to get a proper one. I have been looking for a lower power solution I could run on batteries, and using a HC-12 long range radio (discussed here: https://youtu.be/DGRPqeacJns) to send the data down to the house to a second paired unit, which would then display the data in a webserver on the local network.

    I have some commentary and some questions for you. Firstly, it looks like you don’t need to bother stepping down the output of the HC-SR04 for the esp8266. While the esp8266 is not 5v tolerant for power, it is tolerant up to 6v for reading high on one of the pins. Discussion here: https://hackaday.io/page/2024-esp8266-is-5v-tolerant-after-all

    That’s not to say you should change your design (if it works, don’t break it right?). But for future builds, you can take that into consideration.

    In both cases, using either the onboard wifi antenna or the HC-12 consumes a lot of power. If you were to run this for months at a time, you wouldn’t want to be sending data when there is no snow, right? Putting in logic so that it only sends if the reading is above a certain threshold would go a long way, as in your case, even if it is below freezing there isn’t necessarily snow. For my well tank, this would be pretty straightforward- as long as the tank is more than 85% full, don’t send any data. Maybe you could store all the data that is going to be sent as an array, then send the array when the latest reading is above or below your threshold. Lots of ways to do this.

    I guess my only question is “how can we improve battery life further?”. In my situation, I could use anything from a couple of D batteries (I don’t know if they have the same names in Romania- they are the largest easily-available alkaline batteries in the US) to even a 12v car battery. Do you have any recommendations for how to power this? Ideally, the well tank sensor wouldn’t have to be bothered more than once a year (or more).

    • GeeksTips says:

      Hello! From what I knew, the Tensilica Xtensa LX106 used from Espressif didn’t had 3v3 limitation, and the rudimentary ESP doesn’t have power regulators, but I will take a look over your materials. Regarding the battery matter, my directions now goes in saving readings in the internal clock memory of the ESP8266 and send data only three times a day. This will probably increase the battery life by using less the radio modules. I think the RTC Memory can offer something like ~400Kbytes where you can write readings from sensor, and this space will not be deleted after DEEP_SLEEP wake up. I am thinking at building an energy bank using 20-30 cells from dead notebooks as they can be bought very cheap and have it charged once on few months.

      • Anonymous says:

        Good call on transmitting more data less frequently. Unfortunately my use case doesn’t really work for that approach, but it’s a good idea.

  4. ed says:

    Great project. I have done something similar to measure the water level in my pond. Too bad indeed that the sensor needs 5 Volt. I like the design of your container, might be an idea for mine, although I dont have to cram the batteries in there (powersupply line in the garden)

    • GeeksTips says:

      That’s beautiful to have an external powersupply line. I had to improvise from old laptops cells, but hopefully I will find something more stable.

  5. ed says:

    Looking at how cold it gets at your place….. how are yr batteries holding up? I have used LiPo cells outside and I already saw a significant drop just around zero degrees, cant imagine how it would be at minus 20

    • GeeksTips says:

      Hello, Panasonic 18650 do well under zero. In the datasheet they say that the discharge can be done safely in between -20 and +60 Celsius. Having already used cells from old laptops, I cannot realize if the behavior is affected. But before choosing any type of batteries you should check the manufacturer datasheet. For Panasonic 18650 you can see it here:

Leave a Reply

Your email address will not be published.