@StefanL38 I am also new on this form and having issues with P1 port of my XT211 energy meter reading.
Before writing this message, I kept on reading as much as I could, to find a way to communicate with this unit. (I've re/started mid January, when my meter was changed from analog to Digital.)
I've read that the signal is inverted. So, purchased components suggested on web to correct that.
I've also read how to and to what pin to connect.
So, here is where I am / have:
- Arduino Uno R3.
- Energy meter XT211
Handleidingen digitale elektriciteitsmeters | Fluvius - P1 port is open based on the request from me.
- Inverting signal diagram. Components available. Used even the "Example connection diagram:" with 1 x 1K, 2 x 10K, and 1x BC547B. Also the " Alternative with a BC547" as mentioned on the page.
https://domoticx.com/p1-poort-slimme-meter-uitlezen-hardware/ - Implemented library " ArduinoIDE AltSoftSerial library"
- Used examples from library.
- Even found kind "lookalike good" libraries like
GitHub - matthijskooijman/arduino-dsmr at 43146719f55ab981daf28ff37cd4a11da140c895 - Osciloscope purcased to see the signal.
So far all examples I've found are talking how to export the data to a computer or mobile phone / cloud / etc. Not what I want.
To me, an automation shall work independent and not requiring my attention.
I just want to read specific strings from the meter (like consumed power 2 or 3 values) and returned values (also 1-2 values). Do some mathematic with them. Mainly adding these values.
In later stage to export some values to a DO and / or a PWM.
I have a bit of knowledge of programing. Just syntax of C++ its killing.
But, one step at a time.
Will you be able to go along with me and help me to read the data from the meter?
For instance, I've taken the code from DSMR-BE-NL / read.
/*
* Permission is hereby granted, free of charge, to anyone
* obtaining a copy of this document and accompanying files,
* to do whatever they want with them without any restriction,
* including, but not limited to, copying, modification and redistribution.
* NO WARRANTY OF ANY KIND IS PROVIDED.
*
* Example that shows how to periodically read a P1 message from a
* serial port and automatically print the result.
*/
#include "dsmr.h"
/**
* Define the data we're interested in, as well as the datastructure to
* hold the parsed data. This list shows all supported fields, remove
* any fields you are not using from the below list to make the parsing
* and printing code smaller.
* Each template argument below results in a field of the same name.
*/
using MyData = ParsedData<
/* String */ identification,
/* String */ p1_version,
/* String */ timestamp,
/* String */ equipment_id,
/* FixedValue */ energy_delivered_tariff1,
/* FixedValue */ energy_delivered_tariff2,
/* FixedValue */ energy_returned_tariff1,
/* FixedValue */ energy_returned_tariff2,
/* String */ electricity_tariff,
/* FixedValue */ power_delivered,
/* FixedValue */ power_returned,
/* FixedValue */ electricity_threshold,
/* uint8_t */ electricity_switch_position,
/* uint32_t */ electricity_failures,
/* uint32_t */ electricity_long_failures,
/* String */ electricity_failure_log,
/* uint32_t */ electricity_sags_l1,
/* uint32_t */ electricity_sags_l2,
/* uint32_t */ electricity_sags_l3,
/* uint32_t */ electricity_swells_l1,
/* uint32_t */ electricity_swells_l2,
/* uint32_t */ electricity_swells_l3,
/* String */ message_short,
/* String */ message_long,
/* FixedValue */ voltage_l1,
/* FixedValue */ voltage_l2,
/* FixedValue */ voltage_l3,
/* FixedValue */ current_l1,
/* FixedValue */ current_l2,
/* FixedValue */ current_l3,
/* FixedValue */ power_delivered_l1,
/* FixedValue */ power_delivered_l2,
/* FixedValue */ power_delivered_l3,
/* FixedValue */ power_returned_l1,
/* FixedValue */ power_returned_l2,
/* FixedValue */ power_returned_l3,
/* uint16_t */ gas_device_type,
/* String */ gas_equipment_id,
/* uint8_t */ gas_valve_position,
/* TimestampedFixedValue */ gas_delivered,
/* uint16_t */ thermal_device_type,
/* String */ thermal_equipment_id,
/* uint8_t */ thermal_valve_position,
/* TimestampedFixedValue */ thermal_delivered,
/* uint16_t */ water_device_type,
/* String */ water_equipment_id,
/* uint8_t */ water_valve_position,
/* TimestampedFixedValue */ water_delivered,
/* uint16_t */ slave_device_type,
/* String */ slave_equipment_id,
/* uint8_t */ slave_valve_position,
/* TimestampedFixedValue */ slave_delivered
>;
/**
* This illustrates looping over all parsed fields using the
* ParsedData::applyEach method.
*
* When passed an instance of this Printer object, applyEach will loop
* over each field and call Printer::apply, passing a reference to each
* field in turn. This passes the actual field object, not the field
* value, so each call to Printer::apply will have a differently typed
* parameter.
*
* For this reason, Printer::apply is a template, resulting in one
* distinct apply method for each field used. This allows looking up
* things like Item::name, which is different for every field type,
* without having to resort to virtual method calls (which result in
* extra storage usage). The tradeoff is here that there is more code
* generated (but due to compiler inlining, it's pretty much the same as
* if you just manually printed all field names and values (with no
* cost at all if you don't use the Printer).
*/
struct Printer {
template<typename Item>
void apply(Item &i) {
if (i.present()) {
Serial.print(Item::name);
Serial.print(F(": "));
Serial.print(i.val());
Serial.print(Item::unit());
Serial.println();
}
}
};
// Set up to read from the second serial port, and use D2 as the request
// pin. On boards with only one (USB) serial port, you can also use
// SoftwareSerial.
#ifdef ARDUINO_ARCH_ESP32
// Create Serial1 connected to UART 1
HardwareSerial Serial1(1);
#endif
P1Reader reader(&Serial1, 2);
unsigned long last;
void setup() {
Serial.begin(115200);
Serial1.begin(115200);
#ifdef VCC_ENABLE
// This is needed on Pinoccio Scout boards to enable the 3V3 pin.
pinMode(VCC_ENABLE, OUTPUT);
digitalWrite(VCC_ENABLE, HIGH);
#endif
// start a read right away
reader.enable(true);
last = millis();
}
void loop () {
// Allow the reader to check the serial buffer regularly
reader.loop();
// Every minute, fire off a one-off reading
unsigned long now = millis();
if (now - last > 60000) {
reader.enable(true);
last = now;
}
if (reader.available()) {
MyData data;
String err;
if (reader.parse(&data, &err)) {
// Parse succesful, print result
data.applyEach(Printer());
} else {
// Parser error, print error
Serial.println(err);
}
}
}
Expected output would look like below:
0-0:96.1.4(xxxxx)
0-0:96.1.1(xxxxxxxxxxxxxxxxxxxxxxxxxxxx)
0-0:1.0.0(210204163628W)
1-0:1.8.1(000439.094kWh)
1-0:1.8.2(000435.292kWh)
1-0:2.8.1(000035.805kWh)
1-0:2.8.2(000012.156kWh)
0-0:96.14.0(0001)
1-0:1.7.0(00.233kW)
1-0:2.7.0(00.000kW)
1-0:21.7.0(00.233kW)
1-0:22.7.0(00.000kW)
1-0:32.7.0(236.2V)
1-0:31.7.0(002.04A)
0-0:96.3.10(1)
0-0:17.0.0(999.9kW)
1-0:31.4.0(999A)
0-0:96.13.0()
0-1:24.1.0(003)
0-1:96.1.1(xxxxxxxxxxxxxxxxxxxxxxxxxxxx)
0-1:24.4.0(1)
0-1:24.2.3(210204163500W)(00343.925*m3)
!1374
If I run the code, I got an error like Serial1 is not used correct.
"read.ino:121:3: error: 'Serial1' was not declared in this scope"
And here ... I am stuck.
Thanks.
PS. If no time, I understand. I will not give up anyway....