Skip to content

Instantly share code, notes, and snippets.

@micw
Last active January 4, 2022 16:58
Show Gist options
  • Save micw/098709efc83a9d9ebf16d14cea4ca38e to your computer and use it in GitHub Desktop.
Save micw/098709efc83a9d9ebf16d14cea4ca38e to your computer and use it in GitHub Desktop.
Ventus W132 decoder sketch
/**
* Ein ESP8622 NodeMCU Develompent Board, welches Sensorwerte via MQTT verschickt
* http://frightanic.com/iot/comparison-of-esp8266-nodemcu-development-boards/
*
* Umbau eines W132 Windsensors von ELV
*
* - Abtrennen des 433 MHZ-Senders, welcher mit 3 Leitungen (Schwarz, Rot, Blau) an der Logik-Platine angeschlossen ist
* - Anschließen des ESP-8266
* - Schwarz -> GND
* - Rot -> 3.3V
* - Blau -> D2
*
* Eine Beschreibung des Protokoll ist unter http://www.tfd.hu/tfdhu/files/wsprotocol/auriol_protocol_v20.pdf zu finden, hilfreich ist auch https://sourceforge.net/p/wmrx00/discussion/855158/thread/b3a47730/
* - Bits und Sync-Signale werden über die Abstände der fallenden Flanke codiert
* - diese Implementierung nutzt dazu einen Interrupt auf der fallenden Flanke
*/
#define MQTT_ALIVE_TOPIC "sensor/%s/alive"
#define MQTT_DATA_TOPIC "sensor/%s/%s"
#include <common_wifi.h>
#include <common_mqtt.h>
#include <esp_pins.h>
#define PIN_ANEMOMETER D2
volatile unsigned long lastTrigger;
byte mac[6];
char sensorId[7];
char topicBuffer[255];
char messageBuffer[255];
byte bitPos=-1;
byte messageNum=-1;
// there are always sent 6 messages. For temperature/humidity, the message is repeatet 6 times. For wind, 2 messages are repeatet 3 times each
int message1Bits[36];
int message2Bits[36];
bool verifyChecksum(int bits[]) {
int checksum=0xf;
for (int i=0;i<8;i++) {
checksum-=bits[i*4]|bits[i*4+1]<<1|bits[i*4+2]<<2|bits[i*4+3]<<3;
}
checksum&=0xf;
int expectedChecksum=bits[32]|bits[33]<<1|bits[34]<<2|bits[35]<<3;
return checksum==expectedChecksum;
}
void decodeMessages() {
if (!verifyChecksum(message1Bits)) {
Serial.println("Checksum mismatch in message #1");
return;
}
/*
Serial.println("---");
for (int i=0;i<36;i++) {
Serial.print(message1Bits[i]);
Serial.print(" ");
}
Serial.println();
for (int i=0;i<36;i++) {
Serial.print(message2Bits[i]);
Serial.print(" ");
}
Serial.println();
*/
if (message1Bits[9]==1 && message1Bits[10]==1) { // wind data (2 messages)
if (!verifyChecksum(message2Bits)) {
Serial.println("Checksum mismatch in message #1");
return;
}
float windSpeed=(message1Bits[24] | message1Bits[25]<<1 | message1Bits[26]<<2 | message1Bits[27]<<3 |
message1Bits[28]<<4 | message1Bits[29]<<5 | message1Bits[30]<<6 | message1Bits[31]<<7)*0.2f;
Serial.print("Average wind speed: ");
Serial.print(windSpeed);
Serial.println(" m/s");
sprintf(topicBuffer, MQTT_DATA_TOPIC, sensorId, "wind_speed");
String value = String(windSpeed,1);
value.toCharArray(messageBuffer,255);
mqttClient.publish(topicBuffer,(byte*)messageBuffer,strlen(messageBuffer));
float windGust=(message2Bits[24] | message2Bits[25]<<1 | message2Bits[26]<<2 | message2Bits[27]<<3 |
message2Bits[28]<<4 | message2Bits[29]<<5 | message2Bits[30]<<6 | message2Bits[31]<<7)*0.2f;
Serial.print("Max wind speed: ");
Serial.print(windGust);
Serial.println(" m/s");
sprintf(topicBuffer, MQTT_DATA_TOPIC, sensorId, "wind_gust");
value = String(windGust,1);
value.toCharArray(messageBuffer,255);
mqttClient.publish(topicBuffer,(byte*)messageBuffer,strlen(messageBuffer));
int windDirection=(message2Bits[15] | message2Bits[16]<<1 | message2Bits[17]<<2 | message2Bits[18]<<3 |
message2Bits[19]<<4 | message2Bits[20]<<5 | message2Bits[21]<<6 | message2Bits[22]<<7 |
message2Bits[23]<<8);
Serial.print("Wind direction: ");
Serial.print(windDirection);
Serial.println(" °");
sprintf(topicBuffer, MQTT_DATA_TOPIC, sensorId, "wind_direction");
value = String(windDirection);
value.toCharArray(messageBuffer,255);
mqttClient.publish(topicBuffer,(byte*)messageBuffer,strlen(messageBuffer));
} else { // temperature/humidity in both messages
int temperatureRaw=(message1Bits[12] | message1Bits[13]<<1 | message1Bits[14]<<2 | message1Bits[15]<<3 |
message1Bits[16]<<4 | message1Bits[17]<<5 | message1Bits[18]<<6 | message1Bits[19]<<7 |
message1Bits[20]<<8 | message1Bits[21]<<9 | message1Bits[22]<<10| message1Bits[23]<<11);
if (temperatureRaw& 0x800) temperatureRaw+=0xF000; // negative number, 12 to 16 bit
float temperature=temperatureRaw*0.1f;
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.println(" °C");
sprintf(topicBuffer, MQTT_DATA_TOPIC, sensorId, "temp");
String value = String(temperature,1);
value.toCharArray(messageBuffer,255);
mqttClient.publish(topicBuffer,(byte*)messageBuffer,strlen(messageBuffer));
int humidity=(message1Bits[24] | message1Bits[25]<<1 | message1Bits[26]<<2 | message1Bits[27]<<3 )+
(message1Bits[28] | message1Bits[29]<<1 | message1Bits[30]<<2 | message1Bits[31]<<3 )*10;
Serial.print("Humidity: ");
Serial.print(humidity);
Serial.println(" %");
sprintf(topicBuffer, MQTT_DATA_TOPIC, sensorId, "humi");
value = String(humidity);
value.toCharArray(messageBuffer,255);
mqttClient.publish(topicBuffer,(byte*)messageBuffer,strlen(messageBuffer));
}
}
void dataTrigger() {
unsigned long now=micros();
unsigned long duration=now-lastTrigger;
lastTrigger=now;
if (duration>30000) { // a news block of messages begins
messageNum=0;
}
if (duration>7000) { // ~9 ms = sync signal
if (bitPos==36) { // we got a full message
if (messageNum==0) { // 1st message completed
messageNum=1;
} else if (messageNum==1) { // 2nd message completed
decodeMessages();
messageNum=-1;
}
}
bitPos=0; // Nachricht begonnen
return;
}
if (messageNum<0) return; // ignore repeated messages
if (bitPos<0) return; // invalid message, ignored
if (messageNum==0) {
message1Bits[bitPos]=(duration>3300); // 2.2ms=LOW, 4.4ms = HIGH bits
} else {
message2Bits[bitPos]=(duration>3300); // 2.2ms=LOW, 4.4ms = HIGH bits
}
bitPos++;
if (bitPos>36) bitPos=-1; // message too long -> invalid
}
void setup() {
wdt_enable(WDTO_8S); // Watchdog muss alle 8 Sekunden resettet werden
Serial.begin(115200);
Serial.println("Initializing");
WiFi.macAddress(mac);
sprintf(sensorId, "%02X%02X%02X", mac[3], mac[4], mac[5]);
setup_wifi();
wdt_reset(); // Watchdog resetten
setup_mqtt();
wdt_reset(); // Watchdog resetten
pinMode(PIN_ANEMOMETER,INPUT);
attachInterrupt(digitalPinToInterrupt(PIN_ANEMOMETER), dataTrigger, FALLING);
wdt_reset(); // Watchdog resetten
Serial.println("Starting");
}
void loop() {
wdt_reset(); // Watchdog resetten
connect_mqtt(0);
wdt_reset(); // Watchdog resetten
mqttClient.loop();
}
@t1me2die
Copy link

Hi, habe aktuell ein Problem mit der ermittelten Temperatur.
Ich vermute, dass eine negative Temperatur (ca. -5,0°C) falsch umgesetzt wird (Zeile 114-118).
Aktuell bekomme ich nämlich eine Temperatur von ~6550°C angezeigt.

Gruß
Mathias

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment