reaper7 / SDM_Energy_Meter

reading SDM72 SDM120 SDM220 SDM230 SDM630 modbus energy meters from arduino (esp8266, esp32, avr)
247 stars 97 forks source link

Odd numbers are read correctly, even numbers not #7

Closed sjfaustino closed 6 years ago

sjfaustino commented 7 years ago

When using the code below with a SDM120C: `#include //import SDM template library

SDM<2400, D1, D2> sdm; //SDM120C baud, rx pin, tx pin

void setup() { Serial.begin(115200); //initialize serial sdm.begin(); //initalize SDM220 communication baudrate }

void loop() {

Serial.print("Frequency: "); Serial.print(sdm.readVal(SDM120C_FREQUENCY), 2); //display frequency Serial.println("Hz");

Serial.print("Voltage: "); Serial.print(sdm.readVal(SDM120C_VOLTAGE), 2); //display voltage Serial.println("V");

delay(1000); //wait a while before next loop }` I get:

Frequency: 50.00Hz Voltage: 228.70V Frequency: 50.00Hz Voltage: nanV Frequency: 50.00Hz Voltage: nanV Frequency: 50.00Hz Voltage: nanV Frequency: 50.00Hz Voltage: nanV Frequency: 50.04Hz Voltage: nanV Frequency: 50.00Hz Voltage: nanV

If I swap the read order as on the code below: `#include //import SDM template library

SDM<2400, D1, D2> sdm; //SDM120C baud, rx pin, tx pin

void setup() { Serial.begin(115200); //initialize serial sdm.begin(); //initalize SDM220 communication baudrate }

void loop() {

Serial.print("Voltage: "); Serial.print(sdm.readVal(SDM120C_VOLTAGE), 2); //display voltage Serial.println("V");

Serial.print("Frequency: "); Serial.print(sdm.readVal(SDM120C_FREQUENCY), 2); //display frequency Serial.println("Hz");

delay(1000); //wait a while before next loop }` I get:

Voltage: 231.20V Frequency: 50.00Hz Voltage: 230.80V Frequency: nanHz Voltage: 230.80V Frequency: nanHz Voltage: 230.80V Frequency: nanHz Voltage: 230.80V Frequency: nanHz Voltage: 231.30V Frequency: nanHz

beireken commented 7 years ago

Please try a delay(50); between each sdm.readVal. It never works without here.

sjfaustino commented 7 years ago

A delay(1) between reading each value seems to be sufficient. Since 1ms is such a small delay, would it not be wise to add it on the library so that the user doesn't have to worry?

      delay(1);
      if (_dere_pin != NOT_A_PIN)                                               //transmit to SDM  -> DE Enable, /RE Disable (for control MAX485)
reaper7 commented 7 years ago

I can add this, but I never had such a problems I read all values one-by-one without any delay:

    sdmval.voltage = sdm.readVal(SDM220T_VOLTAGE);
    sdmval.current = sdm.readVal(SDM220T_CURRENT);
    sdmval.power = sdm.readVal(SDM220T_POWER);
    sdmval.frequency = sdm.readVal(SDM220T_FREQUENCY);
    sdmval.energy = sdm.readVal(SDM220T_TOTAL_ACTIVE_ENERGY);

my config: SDM220 at 4800 baud

maybe baudrate affected this?

If I find some free time, then I insert some debug code with count wrong/nan reading

beireken commented 7 years ago

Not sure it's Baud related. I have 120c and 630 with 2400 and 9600 baud rate. They both show this behaviour.

reaper7 commented 7 years ago

After 1 hour of tests with error counter, I don't have any wrong readings.

this is my code (sorry but not usable as is because it uses my priv helper lib for wifi connection/ota/oled) as You see, I reading all values one-by-one without any delay between. I add errors counter variable (errorscnt), incremented every 1000ms loop, if any of reading values are NAN, but all readings from last hour (every 1000ms) are good!

#include <ESP8266WiFi.h>

#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <AsyncJson.h>

#include <ThingSpeak.h>

#include "ESP8266r7Helper.h"
#include "SDM.h"

AsyncWebServer server(80);

WiFiClient  client;

unsigned long myChannelNumber = xxxxxx;
const char * myWriteAPIKey = "XxXxXxXxXxXxXxXxXx";

unsigned long lastsdmreadtime = 0;                //store time of last smd read

bool dtardy = false;

uint16_t errorscnt = 0;                           //error counter for debug

//------------------------------------------------------------------------------
SDM<> sdm;

struct sdm_values {
  float voltage;
  float current;
  float power;
  float frequency;
  float energy;
} sdmval;
//------------------------------------------------------------------------------
void jsonrequest(AsyncWebServerRequest *request) {
  if (dtardy) {
    AsyncJsonResponse * response = new AsyncJsonResponse();
    JsonObject& root = response->getRoot();
    root["rp"] = String(sdmval.power,1);
    root["kw"] = String(sdmval.energy,2);
    root["rv"] = String(sdmval.voltage,1);
    root["rc"] = String(sdmval.current,2);
    root["rf"] = String(sdmval.frequency,2);
    root["er"] = String(errorscnt);

    response->setLength();
    request->send(response);
    request->client()->close();
  } else {
    request->send(404);  
  }
}
//------------------------------------------------------------------------------
void outrequest(AsyncWebServerRequest *request) {
  int params = request->params();
  for(int i=0;i<params;i++){
    AsyncWebParameter* p = request->getParam(i);
    Serial.printf("GET[%s]: %s\n", p->name().c_str(), p->value().c_str());
  }
  request->send(200, "text/plain", "OK");
}
//------------------------------------------------------------------------------
void setup() {
  devicename = "PWRMETER";

  sdmval.voltage = NAN;
  sdmval.current = NAN;
  sdmval.power = NAN;
  sdmval.frequency = NAN;
  sdmval.energy = NAN;

  Serial.begin(115200);

  oledinit();
  wifiinit();
  otainit();  

  sdm.begin();

  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain", String(ESP.getFreeHeap()));
  });  
  server.on("/data.json", HTTP_GET, jsonrequest);
  server.on("/out", HTTP_GET, outrequest);
  server.onNotFound([](AsyncWebServerRequest *request){
    Serial.println("404: not found");
    request->send(404);
  });
  server.begin();  

  Serial.println(ESP.getFreeHeap());
  oledprintline((String)ESP.getFreeHeap());

  delay(2000);
}
//------------------------------------------------------------------------------
void loop() {
  static unsigned long tsupload = 0;
  static float lastenergy = -1.00;
  static float sumpower = 0.00;
  static float measurecnt = 0.00;
  static uint16_t minutes = 0;

  float tmpvoltage = NAN;
  float tmpcurrent = NAN;
  float tmppower = NAN;
  float tmpfrequency = NAN;
  float tmpenergy = NAN;

  if ((!otalock) && (millis() >= (lastsdmreadtime + SDM_READ_EVERY))) {
    lastsdmreadtime = millis();

    tmpvoltage = sdm.readVal(SDM220T_VOLTAGE);
    tmpcurrent = sdm.readVal(SDM220T_CURRENT);
    tmppower = sdm.readVal(SDM220T_POWER);
    tmpfrequency = sdm.readVal(SDM220T_FREQUENCY);
    tmpenergy = sdm.readVal(SDM220T_TOTAL_ACTIVE_ENERGY);

    if ((isnan(tmpvoltage)) || (isnan(tmpcurrent)) || (isnan(tmppower)) || (isnan(tmpfrequency)) || (isnan(tmpenergy))) {   // if one of reading values is a NAN then set "dataready flag to false

      dtardy = false;
      errorscnt++;                                                                                                          // increment errorscnt for debug

      sdmval.voltage = 0.00;
      sdmval.current = 0.00;
      sdmval.power = 0.00;
      sdmval.frequency = 0.00;
      sdmval.energy = 0.00;

    } else {                                                                                                                // else -> every values != NAN

      sdmval.voltage = tmpvoltage;
      sdmval.current = tmpcurrent;
      sdmval.power = tmppower;
      sdmval.frequency = tmpfrequency;
      sdmval.energy = tmpenergy;

      dtardy = true;

      if (lastenergy == -1.00) {
        lastenergy = sdmval.energy;
      }

      sumpower += sdmval.power;
      measurecnt = measurecnt + 1.00;

      char buff[48] = {};
      sprintf(buff, "V:%7.2f\nA:%7.2f\nP:%7.2f\nF:%7.2f\0", sdmval.voltage, sdmval.current, sdmval.power, sdmval.frequency);

      oledprintline(buff, 0, true, Cousine_Bold_10, TEXT_ALIGN_CENTER);

      if (lastsdmreadtime >= (tsupload + 60000)) {
        char floatchr[12];

        minutes++;

        tsupload = lastsdmreadtime;

        ThingSpeak.begin(client);
        ThingSpeak.setField(1,dtostrf(sdmval.voltage,0,2,floatchr));
        ThingSpeak.setField(2,dtostrf(sdmval.current,0,2,floatchr));
        ThingSpeak.setField(3,dtostrf(float(sumpower / measurecnt),0,2,floatchr));
        ThingSpeak.setField(4,dtostrf(sdmval.frequency,0,2,floatchr));
        if (minutes == 59) {
          ThingSpeak.setField(5,dtostrf((sdmval.energy - lastenergy),0,2,floatchr));
          minutes = 0;
          lastenergy = sdmval.energy;
          ThingSpeak.setField(6,errorscnt);                                                                                         // every hour send errorscnt value to thingspeak for debug
          errorscnt = 0;                                                                                                            // errorscnt uploaded, set to 0
        }    
        ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);

        measurecnt = 0.00;
        sumpower = 0.00;
      }
    }
  }
  ArduinoOTA.handle() ;                           // Check for OTA
}

this is a prototype code but works ~129days without a problems

reaper7 commented 7 years ago

one more thing... how is Your connection between SDM and converter? two wire (A&B) or three wire (A&B&GND) I have 3 wire...

sjfaustino commented 7 years ago

I'm using a Wemos D1 mini (esp8266) connected to this ttl2rs485: https://www.aliexpress.com/item/TTL-turn-RS485-module-485-to-serial-UART-level-mutual-conversion-hardware-automatic-flow-control/32709226383.html

Wemos mini to TTL2RS485: Wemos D1 to TX TTL2RS485 Wemos D2 to RX TTL2RS485 Wemos GND to GND TTL2S485 Wemos 3.3V to VCC TTL2RS485

TTL2RS485 to SDM120C B to pin9 A to pin10 GND not connected (don't know what is the gnd pin on the sdm120c, maybe 8?)

So, 2 wire. Also, no 120 ohm resistor in use ( I believe it is only necessary on long cable runs).

I sugest adding a ifdefine add_sdm_delay to the library and let the user do a #define add_sdm_delay if he wants.

reaper7 commented 7 years ago

I can't reproduce this error. On my hardware configuration, example from this lib and my other project works without problem, so...at this moment please add delays to Your main program or clone this lib and do this on Your copy.

GND...maybe 8: http://techfreak.pl/miernik-zuzycia-energii-elektrycznej-sdm120/sdm120-connection/ http://eastron.inf.ua/SDM120.html

reaper7 commented 7 years ago

after 14 hours still no errors

reaper7 commented 7 years ago

@beireken - do You check if this problem also exists when converter is connected via hardware serial?

I checked this problem whole weekend, code read all fourteen SDM220 registers at once in loop every 2sec and after 2 days I have only 37 errors where number of all reading = 48h 60m (60s/2) = 86400 readings

I must check if problem is a timeout/bad checksum/not enough bytes read

beireken commented 7 years ago

@reaper7 Do you mean changing the library to function with hardware serial and not softserial? Or just using the pins of tx and rx and not random other.?

reaper7 commented 7 years ago

no no, this lib is ready for use with hardware serial, user must set at top of sketch:

#define USE_HARDWARESERIAL

before:

#include <SDM.h> 

If You not tested yet hardware serial functionality of this lib then no question :D

Today I added a few fix, maybe some reading errors disappear...

beireken commented 7 years ago

Hmm I did not know that. I will test this when I get the chance and report back.

reaper7 commented 7 years ago

ok, tnx. You can test software serial too, without any delay between each sdm read

mariusz84pl commented 7 years ago

Im trying to use your code from above but im missing this library ESP8266r7Helper.h Where can i find it?

reaper7 commented 7 years ago

@mariusz84pl - this is my private lib, only for connect to wifi, configure ota and print lines on oled display. You can replace my functions:

  oledinit();
  wifiinit();
  otainit(); 
  oledprintline("some text");

with Your own solution. I do not publish this lib because it contains many private data like passwords etc.

mariusz84pl commented 7 years ago

I'm trying to use hardwareserial cut can't get to work with it. TX working but no RX.

in sketch added #define USE_HARDWARESERIAL on top. I'm using nodemcu dev Lolin, connecting to TX, RX in it. Is there something else to be added or removed?

#define USE_HARDWARESERIAL
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <AsyncJson.h>
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>
#define USE_SERIAL Serial
ESP8266WiFiMulti WiFiMulti;
#include "SDM2.h"
reaper7 commented 7 years ago

added or removed? I don't know what is needed in Your application.

What kind of converter you are using, with or without DE/RE pins ? Maybe You swap tx / rx lines?

mariusz84pl commented 7 years ago

I have this one https://www.aliexpress.com/item/TTL-turn-RS485-module-485-to-serial-UART-level-mutual-conversion-hardware-automatic-flow-control/32709226383.html

Tryed every combination of connection TX/RX and can't get any values

reaper7 commented 7 years ago

I use the same :)

so, I just tested this simple sketch with hw serial (my sdm is set to 9600b!!!):

#define USE_HARDWARESERIAL

#include <SDM.h>

SDM<9600> sdm;

void setup() {
  pinMode(BUILTIN_LED, OUTPUT);
  digitalWrite(BUILTIN_LED, HIGH);
  sdm.begin();
}

void loop() {
  float tmpval = NAN;

  tmpval = sdm.readVal(SDM220T_VOLTAGE);

  if (!isnan(tmpval)) {
    digitalWrite(BUILTIN_LED, LOW);
  }

  delay(1000);
  digitalWrite(BUILTIN_LED, HIGH);
}

led blinks, it's mean reading ok

this is my "hardware" ;)

sdm2

mali-x commented 6 years ago

I have WEMOS d1 mini. What does the error ets Jan 8 2013,rst cause:4, boot mode:(1,7)

wdt reset

reaper7 commented 6 years ago

watchdog timer reset

https://github.com/esp8266/Arduino/blob/4897e0006b5b0123a2fa31f67b14a3fff65ce561/doc/faq/a02-my-esp-crashes.md https://techtutorialsx.com/2017/01/21/esp8266-watchdog-functions/

I have to guess for what reason?

mali-x commented 6 years ago

This happens to me when I want to test Sdm_live_page.

reaper7 commented 6 years ago

at start or whether during operation? example modified in some way? it connects to the access point?

mali-x commented 6 years ago

Error appears at the beginning. With programming i do not have problem. It is, when the program start on esp. I used your DEMO Sdm_live_page

reaper7 commented 6 years ago

example sdm_simple works for You?

mali-x commented 6 years ago

sorry, yes sdm_simple works. on esp works others examples with wifi

reaper7 commented 6 years ago

I removed some external libs(for display the time) from example, please download again and try.

You are using hardware or software serial? If softwareserial, then on which pins?

Try debuging code yourself by inserting Serial.print("something"); in different places, to detect the error location.

mali-x commented 6 years ago

reinstall arduino and libraries SDM120 pin 13/15 or 12/14

ets Jan 8 2013,rst cause:4, boot mode:(3,7)

wdt reset load 0x4010f000, len 1384, room 16 tail 8 chksum 0x2d csum 0x2d v614f7c32 ~ld something

reaper7 commented 6 years ago

sorry but I cant duplicate this issue, with core debug enabled I got on hardware serial console:

10f000, len 1384, room 16 
tail 8
chksum 0x2d
csum 0x2d
v00000000
~ld

SDK:2.2.1(cfd48f3)/Core:win-2.5.0-dev/lwIP:2.0.3(STABLE-2_0_3_RELEASE/glue:arduino-2.4.1)
sta config unchangedscandone
scandone
state: 0 -> 2 (b0)
state: 2 -> 3 (0)
state: 3 -> 5 (10)
add 0
aid 3
cnt 

connected with TP-LINK_XXXXXX, channel 11
dhcp client start...
ip:192.168.6.37,mask:255.255.255.0,gw:192.168.6.1
pm open,type:2 0
:urn 41
:urd 12, 41, 13
:urd 4, 41, 26
:urd 5, 41, 31

web page works

this is my code:

//sdm live page example by reaper7

//#define USE_HARDWARESERIAL
#define READSDMEVERY  2000                                                      //read sdm every 2000ms
#define NBREG   6                                                               //number of sdm registers to read
//#define USE_STATIC_IP

/*  WEMOS D1 Mini                            
                     ______________________________                
                    |   L T L T L T L T L T L T    |
                    |                              |
                 RST|                             1|TX
                  A0|                             3|RX
                  D0|16                           5|D1
                  D5|14                           4|D2
                  D6|12                    10kPUP_0|D3
RX SSer/HSer swap D7|13                LED_10kPUP_2|D4
TX_SSer/HSer swap D8|15                            |GND
                 3V3|__                            |5V
                       |                           |
                       |___________________________|
*/

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <ESP8266mDNS.h>
#include <ArduinoOTA.h>

#include <ESPAsyncTCP.h>                                                        // https://github.com/me-no-dev/ESPAsyncTCP
#include <ESPAsyncWebServer.h>                                                  // https://github.com/me-no-dev/ESPAsyncWebServer

#include <SDM.h>                                                                // https://github.com/reaper7/SDM_Energy_Meter

#include "index_page.h"
//------------------------------------------------------------------------------
AsyncWebServer server(80);

#if !defined ( USE_HARDWARESERIAL )                                             // SOFTWARE SERIAL
SDM<4800, 13, 15, NOT_A_PIN> sdm;                                               // baud, rx_pin, tx_pin, de/re_pin(not used in this example)
#else                                                                           // HARDWARE SERIAL
SDM<4800, NOT_A_PIN, false> sdm;                                                // baud, de/re_pin(not used in this example), uart0 pins 3/1(false) or 13/15(true)
#endif
//------------------------------------------------------------------------------
String devicename = "PWRMETER";

#if defined ( USE_STATIC_IP )
IPAddress ip(192, 168, 0, 130);
IPAddress gateway(192, 168, 0, 1);
IPAddress subnet(255, 255, 255, 0);
#endif

const char* wifi_ssid = "TP-LINK_XXXXXX";
const char* wifi_password = "12345678";

String lastresetreason = "";

unsigned long readtime;
volatile bool otalock = false;
//------------------------------------------------------------------------------
typedef volatile struct {
  volatile float regvalarr;
  const uint16_t regarr;
} sdm_struct;

volatile sdm_struct sdmarr[NBREG] = {
  {0.00, SDM220T_VOLTAGE},                                                      //V
  {0.00, SDM220T_CURRENT},                                                      //A
  {0.00, SDM220T_POWER},                                                        //W
  {0.00, SDM220T_POWER_FACTOR},                                                 //PF
  {0.00, SDM220T_PHASE_ANGLE},                                                  //DEGREE
  {0.00, SDM220T_FREQUENCY},                                                    //Hz
};
//------------------------------------------------------------------------------
void xmlrequest(AsyncWebServerRequest *request) {
  String XML = F("<?xml version='1.0'?><xml>");
  if(!otalock) {
    for (int i = 0; i < NBREG; i++) { 
      XML += "<response" + (String)i + ">";
      XML += String(sdmarr[i].regvalarr,2);
      XML += "</response" + (String)i + ">";
    }
  }
  XML += F("<freeh>");
  XML += String(ESP.getFreeHeap());
  XML += F("</freeh>");
  XML += F("<rst>");
  XML += lastresetreason;
  XML += F("</rst>");
  XML += F("</xml>");
  request->send(200, "text/xml", XML);
}
//------------------------------------------------------------------------------
void indexrequest(AsyncWebServerRequest *request) {
  request->send_P(200, "text/html", index_page); 
}
//------------------------------------------------------------------------------
void ledOn() {
  digitalWrite(LED_BUILTIN, LOW);
}
//------------------------------------------------------------------------------
void ledOff() {
  digitalWrite(LED_BUILTIN, HIGH);
}
//------------------------------------------------------------------------------
void ledSwap() {
  digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
//------------------------------------------------------------------------------
void otaInit() {
  ArduinoOTA.setHostname(devicename.c_str());

  ArduinoOTA.onStart([]() {
    otalock = true;
    ledOn();
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    ledSwap();
  });
  ArduinoOTA.onEnd([]() {
    ledOff();
    otalock = false;
  });
  ArduinoOTA.onError([](ota_error_t error) {
    ledOff();
    otalock = false;
  });
  ArduinoOTA.begin();
}
//------------------------------------------------------------------------------
void serverInit() {
  server.on("/", HTTP_GET, indexrequest);
  server.on("/xml", HTTP_PUT, xmlrequest);
  server.onNotFound([](AsyncWebServerRequest *request){
    request->send(404);
  });
  server.begin();
}
//------------------------------------------------------------------------------
static void wifiInit() {
  WiFi.persistent(false);                                                       // Do not write new connections to FLASH
  WiFi.mode(WIFI_STA);
#if defined ( USE_STATIC_IP )
  WiFi.config(ip, gateway, subnet);                                             // Set fixed IP Address
#endif
  WiFi.begin(wifi_ssid, wifi_password);

  while( WiFi.status() != WL_CONNECTED ) {                                      //  Wait for WiFi connection
    ledSwap();
    delay(100);
  }
}
//------------------------------------------------------------------------------
void sdmRead() {
  float tmpval = NAN;

  for (uint8_t i = 0; i < NBREG; i++) {
    tmpval = sdm.readVal(sdmarr[i].regarr);

    if (isnan(tmpval))
      sdmarr[i].regvalarr = 0.00;
    else
      sdmarr[i].regvalarr = tmpval;

    yield();
  }
}
//------------------------------------------------------------------------------
void setup() {
#ifndef USE_HARDWARESERIAL
  Serial.begin(115200);
#endif
  pinMode(LED_BUILTIN, OUTPUT);
  ledOn();

  lastresetreason = ESP.getResetReason();

  wifiInit();
  otaInit();
  serverInit();
  sdm.begin();

  readtime = millis();

  ledOff();
}
//------------------------------------------------------------------------------
void loop() {
  ArduinoOTA.handle();

  if ((!otalock) && (millis() - readtime >= READSDMEVERY)) {
    sdmRead();
    readtime = millis();
  }

  yield();
}
mali-x commented 6 years ago

Hello.

Thank you very much for all your help and informations. I did my web. But now i have another problem. :) In Simple Program is between datas NAN. I changed pin and changed delay and all other things. By every measure is ther one NAN. What i did wrong and where is the problem?

Best Regards, M. Rotovnik

reaper7 commented 6 years ago

all measurements in one loop run are NAN? or one incorrect reading in each loop (random, sometimes voltage, sometimes frequency etc...)?

what you changed? 7 days ago you wrote (https://github.com/reaper7/SDM_Energy_Meter/issues/7#issuecomment-375027078):

sorry, yes sdm_simple works. on esp works others examples with wifi

mali-x commented 6 years ago

I have SDM120 and https://www.aliexpress.com/store/product/10PCS-LOT-TTL-turn-RS485-module-485-to-serial-UART-level-mutual-conversion-hardware-automatic-flow/403088_32709166081.html

Example :sdm_simple change serial PIN SDM<2400, 4, 5> sdm;
or SDM<2400, 14, 16> sdm;
or SDM<2400, 13, 15> sdm;

Change delay time: if (_dere_pin != NOT_A_PIN) digitalWrite(_dere_pin, HIGH); delay(2);

Change delay : ..... Serial.print(sdm.readVal(SDM220T_VOLTAGE), 2); delay(50); Serial.print(sdm.readVal(SDM220T_CURRENT), 2); delay(50); ......

Change SDM120 - SDM220 sdm.readVal(SDM120C_CURRENT sdm.readVal(SDM220T_CURRENT

............................ Random NAN Voltage: 236.10V Current: 0.00A Power: 0.00W Frequency: 50.04Hz Voltage: nanV Current: 0.00A Power: 0.00W Frequency: 50.09Hz Voltage: 236.10V Current: 0.00A Power: nanW Frequency: 50.09Hz Voltage: 236.10V Current: 0.00A Power: 0.00W Frequency: 50.09Hz Voltage: 236.10V Current: 0.00A Power: 0.00W Frequency: 50.04Hz Voltage: 236.10V Current: 0.00A Power: 0.00W Frequency: 50.09Hz Voltage: 236.10V Current: nanA Power: 0.00W Frequency: nanHz Voltage: 236.10V Current: 0.00A Power: 0.00W Frequency: nanHz

reaper7 commented 6 years ago

try to check which error causes a bad reading, add after every reading (before delay):

Serial.print("Last ERROR: ");
Serial.println(sdm.getErrCode(true));

Have you tried other speeds? 4800?

I still suggest switching to HardwareSerial which I personally use. I read all 14 SDM220 registers in loop every 3sec with only yeld() between every register(without any delay), what it takes ~470ms and after last 15hours I have only two errors. 14registers 20readings every minute 60min * 15h = 252000readings and only 2 errors...

mali-x commented 6 years ago

Error 4. Speed 4800 to SDM120 does not work

Voltage: 230.50V Last ERROR: 0 Current: nanA Last ERROR: 4 Power: 0.00W Last ERROR: 0 Frequency: 50.00Hz Last ERROR: 0 Voltage: 230.40V Last ERROR: 0 Current: 0.00A Last ERROR: 0 Power: 0.00W Last ERROR: 0 Frequency: nanHz Last ERROR: 4 Voltage: nanV Last ERROR: 4 Current: 0.00A Last ERROR: 0 Power: 0.00W Last ERROR: 0 Frequency: 50.00Hz Last ERROR: 0

reaper7 commented 6 years ago

error 4 -> SDM_ERR_TIMEOUT this means that at the declared time (in this case 500ms) esp serial did not get full reply frame (9 bytes) from sdm.

Try to increase MAX_MILLIS_TO_WAIT in line 18 https://github.com/reaper7/SDM_Energy_Meter/blob/master/SDM.h#L18 from 500 to e.g. 1000 maybe 500ms is too low for Your baud rate 2400

mali-x commented 6 years ago

Thank you for all informations. I change all times, but nothing helps.

How can I change the speed from 2400 to 4800?

I would not yous Tx in Rx pin, because I allready use them for Serial.print.

janbro1 commented 5 years ago

Thank you for all informations. I change all times, but nothing helps.

How can I change the speed from 2400 to 4800?

I would not yous Tx in Rx pin, because I allready use them for Serial.print.

I have the very same setup as descibed here. I also changed the MAX_MILLIS_TO_WAIT to 1500 to be on the safe side. But I continue to receive the error code 4 as well. If possible I would like to stay with 2400 baud. Simply because I don't have the software to change it.