DDS238-1-esp8266

From Technologia Incognita
Revision as of 22:55, 25 April 2019 by Justa (talk | contribs) (MQTT code)
Jump to: navigation, search
DDS238-1-top.jpg

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

DDS238-1-side.jpg

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

Esp-power-mqtt.jpg

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 wether the device is online at all, as well as to force an update if no pulses have been counted for a while.

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=10;
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);
    }
  }
}