DDS238-1-esp8266
Introduction
The [DDS328-1] is an inexpensive Single-phase power-meter with an LCD readout, a pulse-led and an 'S0' bus (also known as IEC62053-21). It's essentially the 'phototransistor' side of an optocoupler, together with an internal resistor to limit current.
Be aware that there seem to both be different MODELS of the device with extra features, as well as different VARIANTS with altered pinouts.
The device I purchased has the following pinout:
___________ | * * | | 6 3 | 1 : L IN ----------- 3 : L OUT | * * | 4 : N IN | 21 20 | 6 : N OUT ----------- 20: S0- |DDS238-1 | 21: S0+ | ____ | | | | | |K| | | |W| | | |H| | | | | | | | ------ | | O LED | ----------- | 5 2 | | * * | ----------- | 4 1 | | * * | ---------
It's useful to note that it shouldnt really matter which side you use as 'IN' or 'OUT'. The N-side is essentially a solid metal bar between 4 and 6. The L-side is made up of two copper segments with a current-sensing resistor in between. Both the N and L rails are tapped to an internal PSU to provide power to the logic.
The S0 connection
As said, the S0 connection is essentially an opto-coupler. Normally, they are designed to work with voltages of 5V-30V or so. This particular one lists that it wants a maximum of 27V (DC!) Even more important is the current-limit that it lists: 27mA
From a discussion on [a raspberry PI forum] I was able to find an example of just how some people hook up an S0 bus to a raspberry PI. My version looks much like this:
3.3V | ---- | 1 | | 0 | | K | ----- PIN 20 | _________ -----\ /-----------------| 1KOhm |------ PIN D4 | |--/ --------- (GPIO2) ------ | \ / ---> | \/ ---> | ------ |--\ | v _______/ \____________ PIN 21 | ----- --- GND
To power the device, you can use a USB-wallwart and a micro-USB cable, or feed 5V directly to Vin/GND.
MQTT code
I wanted it to report stuff via MQTT. A quick-and-dirty arduino sketch can accomplish quite a lot. Here's an initial attempt. Note that the Mqtt-subscription to 'cmd' is not handled yet; but is designed to force the device to report itself. This is to query whether the device is online at all, as well as to force an update if no pulses have been counted for a while.
The 'incr' variable should be set to whatever the Wh/imp value is of the device. The DDS238-1 has 0.5Wh/Imp.
The larger device in the power-box of the space lists '100Imp/KwH', which makes its 'inc' to be set to '10'
Another improvement would be to also have a timeout-counter running that forces the device to report it's current state every now and then; resetting to zero whenever a pulse is detected.
If you are on the space wifi, you should be able to see the messages come by with 'mosquitto_sub -v -h mqtt.ti -t "space/power/#"'
#include <Arduino.h> #include <ESP8266WiFi.h> #include <Ticker.h> #include <AsyncMqttClient.h> const int led = 5; const int in = 2; int temp = 0; int laststate = HIGH; int count=0; float incr=0.5; float wh=0; char tempStr[20]; #define WIFI_SSID "TechInc" #define WIFI_PASSWORD "itoldyoualready" #define MQTT_HOST IPAddress(10, 209, 10, 8) #define MQTT_PORT 1883 AsyncMqttClient mqttClient; Ticker mqttReconnectTimer; WiFiEventHandler wifiConnectHandler; WiFiEventHandler wifiDisconnectHandler; Ticker wifiReconnectTimer; void connectToWifi(); void onWifiConnect(const WiFiEventStationModeGotIP& event); void onWifiDisconnect(const WiFiEventStationModeDisconnected& event); void connectToMqtt(); void onMqttConnect(bool sessionPresent); void onMqttDisconnect(AsyncMqttClientDisconnectReason reason); void onMqttSubscribe (uint16_t packetId, uint8_t qos); void onMqttUnsubscribe(uint16_t packetId); void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total); void onMqttPublish(uint16_t packetId); void connectToWifi() { Serial.println("Connecting to Wi-Fi..."); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); } void onWifiConnect(const WiFiEventStationModeGotIP& event) { Serial.println("Connected to Wi-Fi."); connectToMqtt(); } void onWifiDisconnect(const WiFiEventStationModeDisconnected& event) { Serial.println("Disconnected from Wi-Fi."); mqttReconnectTimer.detach(); wifiReconnectTimer.once(2,connectToWifi); } void connectToMqtt() { Serial.println("Connecting to MQTT..."); mqttClient.connect(); } void onMqttConnect(bool sessionPresent) { Serial.println("Connected to MQTT."); Serial.print("Session present: "); Serial.println(sessionPresent); uint16_t packetIdSub = mqttClient.subscribe("space/power/cmd", 2); Serial.print("Subscribing at QoS 2, packetId: "); Serial.println(packetIdSub); mqttClient.publish("space/power/status",0,true,"joined"); } void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) { Serial.println("Disconnected from MQTT."); if (WiFi.isConnected()) { mqttReconnectTimer.once(2, connectToMqtt); } } void onMqttSubscribe(uint16_t packetId, uint8_t qos) { Serial.println("Subscribe acknowledged."); Serial.print(" packetId: "); Serial.println(packetId); Serial.print(" qos: "); Serial.println(qos); } void onMqttUnsubscribe(uint16_t packetId) { Serial.println("Unsubscribe acknowledged."); Serial.print(" packetId: "); Serial.println(packetId); } void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) { Serial.println("Publish received."); Serial.print(" topic: "); Serial.println(topic); Serial.print(" qos: "); Serial.println(properties.qos); Serial.print(" dup: "); Serial.println(properties.dup); Serial.print(" retain: "); Serial.println(properties.retain); Serial.print(" len: "); Serial.println(len); Serial.print(" index: "); Serial.println(index); Serial.print(" total: "); Serial.println(total); Serial.println(payload); } void onMqttPublish(uint16_t packetId) { Serial.println("Publish acknowledged."); Serial.print(" packetId: "); Serial.println(packetId); } void setup() { Serial.begin(115200); delay(500); Serial.println(); Serial.println(); wifiConnectHandler = WiFi.onStationModeGotIP(onWifiConnect); wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWifiDisconnect); mqttClient.onConnect(onMqttConnect); mqttClient.onDisconnect(onMqttDisconnect); mqttClient.onSubscribe(onMqttSubscribe); mqttClient.onUnsubscribe(onMqttUnsubscribe); mqttClient.onMessage(onMqttMessage); mqttClient.onPublish(onMqttPublish); mqttClient.setServer(MQTT_HOST, MQTT_PORT); connectToWifi(); pinMode(led, OUTPUT); pinMode(in, INPUT); } void loop() { temp = digitalRead(in); if (temp != laststate) { digitalWrite(led,temp); laststate=temp; if (temp == LOW) { count=count+1; Serial.print("Pulse: "); Serial.println(count); wh=count*incr; Serial.print("WH : "); Serial.println(wh); sprintf(tempStr, "%.1f", wh); mqttClient.publish("space/power/wh",0,true, tempStr); sprintf(tempStr, "%d",count); mqttClient.publish("space/power/pulse",0,true,tempStr); sprintf(tempStr, "Uptime: %d", millis()); mqttClient.publish("space/power/status",0,true,tempStr); } } }