Arduino / ESP32¶
The WattWächter TTL is a pure IR reading head: it outputs your meter's data stream 1:1 as a TTL serial signal. On a microcontroller such as the ESP32 you only need to read this stream on a UART interface and decode it.
Most modern meters (eHZ, smart meter gateways) send their data in the SML format (Smart Message Language) at 9600 baud, 8N1. For this guide we use the ready-made SML-Parser library, which decodes the stream byte by byte and verifies the CRC checksum automatically.
How the communication works
Most meters send their telegram on their own at regular intervals (push) – for those, the receive line (green / RXD) is sufficient for read-out. The yellow TX line is only needed for the remaining meters that have to be requested to send.
Meter prerequisites
For the meter to send the full instantaneous values (power, phases), the PIN usually has to be disabled and the extended info mode (Inf → On) enabled. You obtain the PIN from your grid operator.
Wiring¶
The four wires of the WattWächter TTL connect 1:1 to the ESP32 (the RX/TX crossover is already done on the reading head's circuit board).
| Wire (TTL) | Function | ESP32 pin |
|---|---|---|
| Brown | VCC (3–5 V) | 3V3 |
| Green | RXD (data) | GPIO16 (RX2) |
| Yellow | TXD | GPIO17 (TX2) — optional |
| White | GND | GND |
The wire colors are shown in the diagram: brown → VCC, green → RXD, yellow → TXD (dashed = optional), white → GND.
ESP8266 / D1 Mini
The ESP8266 has only one full hardware UART, which is shared with the USB-to-serial converter. Read the meter data there via Serial (RX = GPIO3) and send debug output via Serial1 (TX = GPIO2). SoftwareSerial is usually too slow at 9600 baud and leads to reception errors.
Option A — Arduino sketch (SML-Parser)¶
This option reads the most important values directly within the Arduino framework – ideal as a building block for your own projects.
Install the library¶
Open Tools → Manage Libraries…, search for SML-Parser (by olliiiver) and install it.
In platformio.ini:
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200
lib_deps =
olliiiver/SML Parser@^0.29
Sketch¶
#include <Arduino.h>
#include "sml.h" // "SML-Parser" library by olliiiver
// --- UART to the WattWächter TTL -------------------------------------------
// ESP32 hardware UART2: RX2 = GPIO16, TX2 = GPIO17
#define TTL_RX_PIN 16 // -> green wire (RXD) of the WattWächter TTL
#define TTL_TX_PIN 17 // -> yellow wire (TXD), only needed for meters you must request
#define TTL_BAUD 9600
HardwareSerial MeterSerial(2); // UART2
// --- Values we want to read from every SML telegram ------------------------
double importWh = -1; // 1-0:1.8.0 energy drawn from grid (Wh)
double exportWh = -1; // 1-0:2.8.0 energy fed into grid (Wh)
double powerW = -1; // 1-0:16.7.0 current active power (W)
void handleImport() { smlOBISWh(importWh); }
void handleExport() { smlOBISWh(exportWh); }
void handlePower() { smlOBISW(powerW); }
// OBIS code (6 bytes) -> matching handler function
typedef struct {
const unsigned char OBIS[6];
void (*Handler)();
} OBISHandler;
OBISHandler handlers[] = {
{{ 0x01, 0x00, 0x01, 0x08, 0x00, 0xff }, &handleImport}, // 1-0:1.8.0 import (Wh)
{{ 0x01, 0x00, 0x02, 0x08, 0x00, 0xff }, &handleExport}, // 1-0:2.8.0 export (Wh)
{{ 0x01, 0x00, 0x10, 0x07, 0x00, 0xff }, &handlePower}, // 1-0:16.7.0 active power (W, signed)
{{ 0x01, 0x00, 0x0f, 0x07, 0x00, 0xff }, &handlePower}, // 1-0:15.7.0 active power (magnitude) – fallback
{{ 0, 0 }}
};
void setup() {
Serial.begin(115200);
MeterSerial.begin(TTL_BAUD, SERIAL_8N1, TTL_RX_PIN, TTL_TX_PIN);
Serial.println(F("WattWaechter TTL reader started"));
}
void loop() {
while (MeterSerial.available() > 0) {
unsigned char c = MeterSerial.read();
sml_states_t state = smlState(c);
// A list inside the telegram finished:
// check whether it carried one of the OBIS values we want.
if (state == SML_LISTEND) {
for (uint8_t i = 0; handlers[i].Handler != 0; i++) {
if (smlOBISCheck(handlers[i].OBIS)) {
handlers[i].Handler();
break;
}
}
}
// Full telegram received and CRC verified -> print the values.
if (state == SML_FINAL) {
Serial.printf("Import: %.3f kWh\n", importWh / 1000.0);
Serial.printf("Export: %.3f kWh\n", exportWh / 1000.0);
Serial.printf("Power: %.0f W\n\n", powerW);
}
}
}
Reading additional values
Simply extend the handlers table with more OBIS codes. The convenience functions smlOBISW() (watts), smlOBISVolt(), smlOBISAmpere() and smlOBISHertz() already return the value correctly scaled. Examples of common OBIS codes can be found under Additional OBIS codes.
Option B — ESPHome (recommended for Home Assistant)¶
If the ESP32 is going to be integrated into Home Assistant anyway, ESPHome is the fastest route: the SML decoding is already built in as a component, so you don't have to write any code.
uart:
id: uart_meter
rx_pin: GPIO16 # green wire (RXD) of the WattWächter TTL
baud_rate: 9600
data_bits: 8
parity: NONE
stop_bits: 1
sml:
id: meter_sml
uart_id: uart_meter
sensor:
- platform: sml
name: "Total import"
sml_id: meter_sml
obis_code: "1-0:1.8.0"
unit_of_measurement: kWh
accuracy_decimals: 3
device_class: energy
state_class: total_increasing
filters:
- multiply: 0.0001 # adjust scaling to your meter (see logs)
- platform: sml
name: "Total export"
sml_id: meter_sml
obis_code: "1-0:2.8.0"
unit_of_measurement: kWh
accuracy_decimals: 3
device_class: energy
state_class: total_increasing
filters:
- multiply: 0.0001
- platform: sml
name: "Current power"
sml_id: meter_sml
obis_code: "1-0:16.7.0"
unit_of_measurement: W
accuracy_decimals: 0
device_class: power
state_class: measurement
Check the scaling factor
The ESPHome sml component returns the raw telegram value. The required multiply factor depends on the meter. Temporarily enable logger: level: VERY_VERBOSE, compare the output value with the reading on the meter and adjust the factor.
Troubleshooting¶
| Problem | Possible cause / solution |
|---|---|
| No data received | Reading head not positioned correctly over the IR diode; green wire (RXD) not connected to the RX pin |
| Only energy counters, no power/phases | Disable the PIN and set Inf → On on the meter |
Checksum error / Unexpected byte |
Wrong baud rate/parity – check 9600 8N1; on the ESP8266 use the hardware UART instead of SoftwareSerial |
| Values off by a factor of 10/100 | Scaler not taken into account – adjust multiply in ESPHome |