At TowerUp we are keen to create apps around wind. Our WindFinder predicts extreme wind speeds for any location around the globe based on historical weather station data, most of the cases from an airport or heliport. The app is using reliable wind speed data fetched from the weather stations and we do our maths to deliver extreme wind speeds to our user. This is great, but I thought that if we build our small, home weather station to measure wind speed, we can understand better how these instruments work and how we can deliver better products to our users.

This post will show the steps how I built-up my own "weather station" and measuring wind speeds with different averaging time. The equipments used during the installation are not the latest products in the market, but you may arrive to similar solution with the latest Raspberry or Davis anemometer.

Step 1: Installation of the devices and wiring

I want to setup my Raspberry Pi 3 headless, as I have no access to an extra monitor, etc. and I want to use my wi-fi connection to connect to it. With a headless setup we are also more flexible for future setups and it creates less electronic devices in the house ;)

First things first, we can download an appropriate Raspberry Pi OS (earlier Raspbian) from here. Since I will not use the Pi as as desktop and lot of programs which the base image provides, I will go with the Lite version.

Step 2: Format the SD memory card for the Raspberry Pi

Once we have the image downloaded we can burn it into the SD card. I use the balenaEtcher utility from Balena.

balenaEtcher to burn the image to the SD card

The steps are straightforward: choose the downloaded and un-zipped image, select your memory card as target, click flash. Some times the flashing gives an error and in most of my cases I just needed to repeat the process. Another issue can be if you do not see your memory card, then just remove it safely and insert it again.

Step 3: Remote connection to the Raspberry Pi

As in the description of the post, I want to connect to the device headless, so without a monitor and keyboard. We can then work through a terminal window with just nano to the file, but I found it more convenient using a remote connection within Visual Studio (VS). I am a fun of Atom but unfortunately it does not offer remote development and as per their statement, they will not plan to do so. It's a pity.  (I will not detail here the SSH setup for VS, that I leave outside the scope of this article)

a.) Enable SSH connection

By default the SSH connection is not enabled to the Pi. To enable it you need to place an empty file named ssh (no extension) in the root of the boot disk. From a Mac terminal window we can do this easily by the following command once the SD card is mounted to the card reader. With the second command I just add a whitespace to the file:

~ % touch /Volumes/boot/ssh
~ % echo " " > /Volumes/boot/ssh

b.) Add network info

Create a file in the root of boot called: wpa_supplicant.conf (instructions below). Then paste the following into it (adjusting for your ISO 3166 alpha-2 country code, network name and network password):

~ % touch /Volumes/boot/wpa_supplicant.conf

Then nano to the file and paste the below code.

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev


c.) Boot the Raspberry Pi

Now we are ready with our setup on the SD card, so we can start to boots the device. Eject the SD card, insert it into the Pi and power up. It can take about 1-2 minutes to boot, so be patient.

d.) Login to the Pi

This part assumes that ssh is enabled for your image and that the default user is pi with a password of raspberry.

NOTE: Your machine must be on the same WiFi network that you configured the Pi for.

Open up the terminal and type the following commands.

ssh-keygen -R raspberrypi.local
ssh pi@raspberrypi.local
  • Don’t worry if you get a host not found error for the first command - the idea is to clear out any previous references to raspberrypi.local
  • If the pi won’t respond, press Ctrl-C and try the last command again
  • If prompted with a warning just hit enter to accept the default (Yes)
  • Type in the password – by default this is raspberry

Because your pi is now on the network, it is advisable to change the hostname and password. At the Pi command line type: sudo raspi-config and follow the instructions.

Step 4: First code on the remote Pi

Ok, we have established a secure connection to our Pi. Now it's time to write some code in it. As a first step I do to print out some core temperature from the Pi, so we do not need any wiring at this stage. Anyhow, since the Raspberry will be used outdoor, it is important to monitor the temperature. Here in Norway, we do not need to worry so much about heat, so I am not expecting to reach 80 or 82 degree celsius where the Pi should start to suffer. Let's paste the below code to our terminal in the remotely connected Pi to see the core temperature in Celsius degree.

pi@raspberrypi:~ $ vcgencmd measure_temp

Ok, cool, today is a nice day and the core temperature of the Pi is ideal for through some more code in it. But let's move these command into a Python file, so we can use it later to log the core temperature of the Pi along other data, like the wind speed. This will be specially useful during the wintertime where the ambient temperature can go below -20 Celsius in my area. We can achieve this to create a new file called and paste the below code into it.

import os
import time

def measure_temp():
        temp = os.popen("vcgencmd measure_temp | egrep -o '[0-9]*\.[0-9]*'").read()
        return temp

while True:

To make sure our Pi is up-to-date, run the follwing commands:

pi@raspberrypi:~/sandbox $ sudo apt-get update
pi@raspberrypi:~/sandbox $ sudo apt-get upgrade

Now our package list is updated, but w also need some other packages for later use. I will use Python 3, so lets install those as well.

sudo apt-get install python3-dev python3-pip

After running these commands, heading to our /sandbox folder, typing python3 we can see the temperature logged to the terminal window as below. You may notice that I used some regular expression to extract only the values, so we can use it later for logging. I also created a folder to place these files, so I named in sandbox.

pi@raspberrypi:~/sandbox $ python



Now we can see that we can communicate with Pi remotely and run some basic command in its terminal, and also run small Python scripts, let's move on to eventually measure the wind speed.

Step 5: Connect the anemometer to the Raspberry

To make sure what we are doing, we can print the pins to the command line with pinout command from the terminal. In my case the result looks like this:

| oooooooooooooooooooo J8     +====
| 1ooooooooooooooooooo        | USB
|                             +====
|      Pi Model 3B  V1.2         |
|      +----+                 +====
| |D|  |SoC |                 | USB
| |S|  |    |                 +====
| |I|  +----+                    |
|                   |C|     +======
|                   |S|     |   Net
| pwr        |HDMI| |I||A|  +======
`-| |--------|    |----|V|-------'

Revision           : a22082
SoC                : BCM2837
RAM                : 1024Mb
Storage            : MicroSD
USB ports          : 4 (excluding power)
Ethernet ports     : 1
Wi-fi              : True
Bluetooth          : True
Camera ports (CSI) : 1
Display ports (DSI): 1

   3V3  (1) (2)  5V    
 GPIO2  (3) (4)  5V    
 GPIO3  (5) (6)  GND   
 GPIO4  (7) (8)  GPIO14
   GND  (9) (10) GPIO15
GPIO17 (11) (12) GPIO18
GPIO27 (13) (14) GND   
GPIO22 (15) (16) GPIO23
   3V3 (17) (18) GPIO24
GPIO10 (19) (20) GND   
 GPIO9 (21) (22) GPIO25
GPIO11 (23) (24) GPIO8 
   GND (25) (26) GPIO7 
 GPIO0 (27) (28) GPIO1 
 GPIO5 (29) (30) GND   
 GPIO6 (31) (32) GPIO12
GPIO13 (33) (34) GND   
GPIO19 (35) (36) GPIO16
GPIO26 (37) (38) GPIO20
   GND (39) (40) GPIO21

Now, as I am sure which pin is which I can connect the anemometer safely. We have four wires on our Davis anemometer. These are as follows:

wires function Raspberry Pi pin
BLACK wind speed PIN29 (GPIO05)
RED ground PIN39
GREEN wind direction PIN31 (GPIO06)

The Davis anemometer has a reed switch for the wind speed, so we can count how many times it turns. The reed switch is similar to a button when it's pressed. According to Davis anemometer technical document 1600 revolution per hour equals to 1mph wind speed. I want to eliminate the conversion of wind speed at different averaging time, so I can establish here any kind of intervals I wish. This is great as my anemometer is located close to the wall at the ground level of a 4-stories building, so it would be extremely difficult to figure out proper conversion factors for different wind speeds. Anyhow, my measurements will not be fully compliant to international standards as the anemometer is not at the right location (i.e 10m above ground, open terrain ,etc.) But at least for the averaging time I will establish the followings:

  • Interval: 3 sec
  • Interval: 1 min
  • Interval: 2 min
  • Interval: 10 min

I also want to report wind speeds in meter per seconds, so the maths will look like in the table below. All intervals refer to 1mph or 0.447 m/s wind speed:

Intervals revolution wind speed
3 sec 1.33 1mph
1 min 26.67 1mph
2 min 53.33 1mph
10 min 266.67 1mph

Step 6: Write the code for the telemetry

import time
from gpiozero import Button
from signal import pause
import statistics
import pyrebase
import Adafruit_DHT as dht

wind_speed_sensor = Button(5)
wind_count = 0

interval = 3

def spin():
    global wind_count
    wind_count = wind_count + 1
    #print("spin" + str(wind_count))

#time shall be in seconds
def calc_speed(spins, interval):
    #based on Davis tech document
    # V = P*(2.25/T) the speed is in MPh
    # P = no. of pulses per sample period
    # T = sample period in seconds
    wind_speed_mph = spins * (2.25 / interval) 
    return wind_speed_mph

def reset_wind():
    global wind_count
    wind_count = 0

store_speeds = []

wind_speed_sensor.when_pressed = spin

while True:
    start_time = time.time()
    print('##### 10-min started #####')
    while time.time() - start_time <= 600:    
        print('Start 3 second')
        humidity, temperature = dht.read_retry(dht.AM2302, DHT_PIN)
        if humidity is not None and temperature is not None:
            print("Temp={0:0.1f}*C  Humidity={1:0.1f}%".format(temperature, humidity))
        count_start = wind_count
        count_end = wind_count
        spins = count_end - count_start
        bws_3_sec = calc_speed(spins, 3)
        data_3sec = {
            "bws-3-sec": bws_3_sec,
            "temperature": temperature,
            "humidity": humidity,
            "timestamp": time.time()
        print('Number of spins: ', spins)
        print('Wind speed (mph): ', bws_3_sec)
        print('Global count: ', wind_count)
    #Measure for 10-min
    bws_10_min = calc_speed(wind_count, 600)
    data_10_min = {
        "bws_10_min": bws_10_min,
        "temperature": temperature,
        "humidity": humidity,
        "timestamp": time.time()
    print('###### 10-min data #####')
    print('Global count: ', wind_count)
    print('10-min BWS: ', bws_10_min)
    print('##### 10-min END #####')


Now, I can read my wind speed, temperature and humidity data. But what if I want to make a more robust system and connect my device to the internet with a more industrial way. The current solution is lacking any scalability and even not stable. If, for instance, I shut down my notebook, the SSH connection will be dropped to the Pi and then data will not be sent anymore without rerun the Python script.

There are certainly many providers out there for IoT device management but I prefer to choose a system which can scale, has open source library with an active community and flexible enough to attach other systems to it. I have made my research and tested out several options, namely:

My choice was Mender as their published solution works well, the dashboard is not overwhelming, and scales well and promises a real industrial experience for software updates. I will show you in my next article how to:

  • setup the IoT system
  • create service scripts to run codes upon network failures
  • push some software updates
  • create a Firebase real-time database connection
  • create a simple front-end to consume data
Home IoT system for wind measurements

So stay tuned, and check back soon.


[1] [2] [3]

  1. ↩︎

  2. ↩︎

  3. ↩︎

  4. ↩︎