In this tutorial we will make a connected anemometer with a wind vane based on a ESP8266 WiFi module. If you have a 3D printer, you just need to print mechanical components of this projects with your printer. You can find all STL files on github.
For the anemometer, we will use a hall effect sensor. The hall effect sensor allow to count the turn of the anemometer propeller. To find to wind direction, we will make an optical encoder based on led and phototransistors. For the Arduino part, i used an ESP8266 module. I like the Wemos d1 mini because it is really small and cheap (about 5€).
BOM : what do you need for the project
All design are ready for the Wemos d1 mini module. If you choose the module, you probably need to update the design. Chose a ESP-12E or ESP-12F module.For this project, you will need :
- 1x ESP8266 WiFi Module.
- 1x hall effect sensor. I used a us1881, really cheap and easy to buy
- 2x neodymium magnets diam.6mm x 3mm
- 5x led. Yellow color is better, but you can use red, blue or green too
- 5x phototransistors. I used Vishay TEPT4400, cheap and easy to buy on internet
- 1x prototyping board (cuted 46mm x 42mm)
- Some 22AWG wire
- 4x ball bearing 5mm x 10mm x 5mm (or 4mm)
- Nuts and screws
- 10x M4 nuts
- 4x M5 nuts
- 1x M6 nut
- 1x M6x30 screw
- 3x M3*20 screws
- 3x M3 nuts
The cost of this project (with 3D printed parts) is about 30€.
Circuit
The circuit is composed by two functions:
- The first function is the angular encoder. We need 5 led and 5 phototransistors. The phototransistor is like a switch. Each time a phototransistor detect the light of the led, the state of the bit associated change (LOW or HIGH). We need a 10 kΩ resistor for each phototransistor between +5V and the smallest pin. Connect the longest pin to GND.
- The second function is the turn counter. The us1881 hall effect sensor is composed by 3 pins (angled corners in front of you).
- Left pin <=> +5V
- Middle pin <=> GND
- Right pin <=> signal
- Connect a 10 kΩ between right and left pins
Do not sold directly the Wemos d1 mini on the circuit to be able to remove it. Some time, it’s not possible to upload the Arduino program. You need to remove the Wemos before.
Follow the wiring diagram for making the circuit.
3D parts
I use Autodesk Fusion 360 to design this project. Fusion 360 is free for students and teachers (3 years). You will find Fusion 360 and STEP files on GitHub here.
Part | Design |
Anemometer propeller | |
Anemometer housing | |
Support of the us1881 hall effect sensor | |
Connecting plate (anemometer and wind vane housing) Connect the wind vane and anemometer housing Hall for phototransistors | |
Central ball bearing housing | |
Wind vane housing | |
Led support | |
Encoding disk (gray code) | |
Wind vane |
You will need about 62 meters of PLA and about 11 hours to produce all 3D parts.
Arduino code compatible ESP8266
Download and open the Arduino code into your IDE. Modify the following variables before downloading the program. If you don’t publish data on a MQTT broker, comment all pubsub lines. Modify the pins adresses of the phototransistors if needed.
#define wifi_ssid “SSID”
#define wifi_password “PASSWORD”
#define mqtt_server “IP_MQTT_BROKER”
#define mqtt_user “guest”
#define mqtt_password “guest”
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#define wifi_ssid "enter_our_ssid"
#define wifi_password "enter_your_password"
#define mqtt_server "IP_MQTT"
#define mqtt_user "guest"
#define mqtt_password "guest"
long lastMsg = 0;
long lastRecu = 0;
#define vitessems_topic "anemometre/vitesseVentMS" // Wind speed in m/s
#define vitessekmh_topic "anemometre/vitesseVentKMH" // Wind speed in km/h
#define direction_topic "anemometre/directionVent" // Wind Direction
WiFiClient espClient;
PubSubClient client(espClient);
volatile int rpmcount = 0;
volatile float vitVentMS = 0;
volatile float vitVentKMH = 0;
int rpm = 0;
unsigned long lastmillis = 0;
bool debug = false;
int pinBit0 = D7;
int pinBit1 = D6;
int pinBit2 = D5;
int pinBit3 = D4;
int pinBit4 = D3;
int pinHall = D2;
int bit0 = 0;
int bit1 = 0;
int bit2 = 0;
int bit3 = 0;
int bit4 = 0;
int dureeMesVitVent = 5000; // en ms, durée de mesure de la vitesse du vent. Choisir un multiple de 1000 pour le calcul de la vitesse du vent
byte girouette = 0;
String dirVent = "N";
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
attachInterrupt(pinHall, rpm_vent, FALLING);
pinMode(pinBit0, INPUT);
pinMode(pinBit1, INPUT);
pinMode(pinBit2, INPUT);
pinMode(pinBit3, INPUT);
pinMode(pinBit4, INPUT);
//attachInterrupt(D7, bit0, FALLING);
setup_wifi();
client.setServer(mqtt_server, 1883); // Connect to MQTT broker
client.setCallback(callback);
Serial.print("GO");
}
void setup_wifi() {
delay(10);
Serial.println();
Serial.print("Connexion to ");
Serial.println(wifi_ssid);
WiFi.begin(wifi_ssid, wifi_password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected with IP ");
Serial.println(WiFi.localIP());
}
void reconnect() {
while (!client.connected()) {
Serial.print("Connexion to MQTT...");
if (client.connect("ESP8266Client", mqtt_user, mqtt_password)) {
Serial.println("OK");
} else {
Serial.print("KO, erreur : ");
Serial.print(client.state());
Serial.println(" Wait 5 secondes before restart");
delay(5000);
}
}
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
getVitesseVent();
getDirVent();
client.publish(vitessems_topic, String(vitVentMS).c_str(), true); // Publie la vitesse du vent en m/s
client.publish(vitessekmh_topic, String(vitVentKMH).c_str(), true); // La vitesse du vent en km/h
client.publish(direction_topic, String(dirVent).c_str(), true); // La direction du vent
//ESP.deepSleep(1000000 * 10, WAKE_NO_RFCAL); //Pour la prochaine version futur
//delay(500); //attente activation du deep sleep
delay(2000);
}
void getVitesseVent() {
if (millis() - lastmillis >= dureeMesVitVent ){
detachInterrupt(pinHall);
rpm = rpmcount * ( 60 / ( dureeMesVitVent / 1000 ) );
if ( rpm > 0 ) {
vitVentKMH = ( rpm + 6.174 ) / 8.367;
vitVentMS = ( ( ( rpm + 6.174 ) / 8.367 ) * 1000 ) / 3600;
} else {
vitVentKMH = 0;
vitVentMS = 0;
}
Serial.println(vitVentKMH);
rpmcount = 0;
lastmillis = millis();
attachInterrupt(pinHall, rpm_vent, FALLING);
}
}
void getDirVent(){
bit0 = not(digitalRead(pinBit0));
bit1 = not(digitalRead(pinBit1));
bit2 = not(digitalRead(pinBit2));
bit3 = not(digitalRead(pinBit3));
bit4 = not(digitalRead(pinBit4));
girouette = (bit4 * 16) + (bit3 * 8) + (bit2 * 4) + (bit1 * 2) + bit0;
Serial.print(bit0); Serial.print(bit1); Serial.print(bit2); Serial.print(bit3); Serial.print(bit4);
Serial.print(" => ");
Serial.print(girouette);
Serial.print(" Orientation");
switch (girouette) {
case 24: dirVent="N"; break;
case 10: dirVent="NE"; break;
case 18: dirVent="E"; break;
//case 18: dirVent="SE"; break;
case 16: dirVent="S"; break;
case 2: dirVent="SW"; break;
case 26: dirVent="O"; break;
case 8: dirVent="NO"; break;
default: dirVent="N"; break;
}
Serial.println(dirVent);
}
void rpm_vent(){
//Serial.println("Tour"),
rpmcount++;
}
void callback(char* topic, byte* payload, unsigned int length) {
}
Assembling
Step | Picture |
Assembling subsets
| |
Wind vane assembly | |
Wind vane encoder assembly | |
Insert the us1881 sensor | |
ESP8266 assembly into anemometer housing | Top vue |
All finish |
Anemometer calibration
If like me you don’t have a laboratory wind tunnel, you need to use your care to make the calibration of the anemometer. Make several records at different speeds to find the relation between car speed and number of turns of the propeller.
If you don’t modify 3D parts of the propeller, you don’t need to calibrate the anemometer. be careful if you use your car for calibration like me !
This anemometer can :
- Measure wind speed from 8km/h (about 2m/s)
- Up to 100 km/h
- Use this relation to calculate wind speed. WindSpeed = (NumberOfTurns + 6,174 ) / 8,367
Wind vane calibration
In this version, i don’t develop any calibration code for the wind vane. Simply use your smartphone to find the index of the wind direction and update the program.
Conclusion
I hope you enjoyed this tutorial. This is the first version we can improve :
- Firstly, the design to make it weather resistant.
- Replace the optical encoder by a magnetic sensor uses less power than LED and easier to program and possible to use with a battery.
Feel free to leave me your comments or questions in the comments.
Amazing ! its a pity that i don’t own a 3d printer . i really like to make a small weather station with windspeeds/direction and temp/bar/uv/light to be readable in the home automation software domoticz. Would be great if it is using mqtt then it will be widely usable with many devices/programs. Great build !
For those of us who don’t own a 3D printer or know someone with one, does anyone sell the plastic parts? Or how about a non 3D print alternative?
3dhubs.com
perfect, thanks for the share.. sick simple design 🙂
ESP-12F variant improved the wifi signal strength or reduced noise.
How does the sensor handle rain, freezing temperatures etc ?