-
Notifications
You must be signed in to change notification settings - Fork 636
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Multiple PZEM004T #1051
Comments
Not sure but I would first try to use the current PZEM004TSensor class to handle it. Currently, it has a hardcoded address of 192.168.1.1. So you will first need to be able to pass a certain value and also a way to set the addresses individually. Not sure how this is done... |
Here is a preliminary version, not fully tested yet, I'll test tonight with 4 PZEM004T. See if it is in the right direction, I'll finalize it then I'll create a PR. This implementation has no side effects for current users. It will work the same as before but will accept more addresses and work accordingly. I'm also considering adding support for direction detection, see here: Measure direction hack. Do you believe we have space for this kind of modification or should this live in a private version? diff --git a/code/espurna/config/sensors.h b/code/espurna/config/sensors.h
index 4df614e4..aa17e0ba 100644
--- a/code/espurna/config/sensors.h
+++ b/code/espurna/config/sensors.h
@@ -537,6 +537,10 @@
#define PZEM004T_HW_PORT Serial // Hardware serial port (if PZEM004T_USE_SOFT == 0)
#endif
+#ifndef PZEM004T_ADDRESSES
+#define PZEM004T_ADDRESSES "192.168.1.1" // Multiple addresses can be provided, separated by space("192.168.1.1 192.168.1.2 192.168.1.3")
+#endif
+
//------------------------------------------------------------------------------
// SHT3X I2C (Wemos) temperature & humidity sensor
// Enable support by passing SHT3X_SUPPORT=1 build flag
diff --git a/code/espurna/sensor.ino b/code/espurna/sensor.ino
index 06e40e7a..35c45b11 100644
--- a/code/espurna/sensor.ino
+++ b/code/espurna/sensor.ino
@@ -544,6 +544,7 @@ void _sensorLoad() {
#else
sensor->setSerial(& PZEM004T_HW_PORT);
#endif
+ sensor->setAddresses(PZEM004T_ADDRESSES);
_sensors.push_back(sensor);
}
#endif
diff --git a/code/espurna/sensors/PZEM004TSensor.h b/code/espurna/sensors/PZEM004TSensor.h
index 2d2f8037..a125e860 100644
--- a/code/espurna/sensors/PZEM004TSensor.h
+++ b/code/espurna/sensors/PZEM004TSensor.h
@@ -9,9 +9,13 @@
#include "Arduino.h"
#include "BaseSensor.h"
+#include <string.h>
#include <PZEM004T.h>
+#define MAGNITUDE_COUNT 4
+#define MAX_DEVICES 5
+
class PZEM004TSensor : public BaseSensor {
public:
@@ -21,13 +25,15 @@ class PZEM004TSensor : public BaseSensor {
// ---------------------------------------------------------------------
PZEM004TSensor(): BaseSensor() {
- _count = 4;
_sensor_id = SENSOR_PZEM004T_ID;
- _ip = IPAddress(192,168,1,1);
}
~PZEM004TSensor() {
if (_pzem) delete _pzem;
+ for(int i = 0; i < _addresses.size() ; i++) {
+ delete _addresses[i];
+ }
+ _addresses.clear();
}
// ---------------------------------------------------------------------
@@ -49,6 +55,25 @@ class PZEM004TSensor : public BaseSensor {
_dirty = true;
}
+ void setAddresses(char const *addresses) {
+ char const * sep = " ";
+ char tokens[strlen(addresses) + 1];
+ strlcpy(tokens, addresses, sizeof(tokens));
+ char *address = tokens;
+
+ int i = 0;
+ address = strtok(address, sep);
+ while (address != 0 && i++ < MAX_DEVICES) {
+ IPAddress * addr = new IPAddress();
+ if (addr->fromString(address)) {
+ _addresses.push_back(addr);
+ }
+ address = strtok(0, sep);
+ }
+ _count = _addresses.size() * 4;
+ _dirty = true;
+ }
+
// ---------------------------------------------------------------------
unsigned char getRX() {
@@ -74,7 +99,9 @@ class PZEM004TSensor : public BaseSensor {
} else {
_pzem = new PZEM004T(_pin_rx, _pin_tx);
}
- _pzem->setAddress(_ip);
+ if(_addresses.size() == 1) {
+ _pzem->setAddress(*(_addresses[0]));
+ }
_ready = true;
_dirty = false;
@@ -83,7 +110,7 @@ class PZEM004TSensor : public BaseSensor {
// Descriptive name of the sensor
String description() {
- char buffer[28];
+ char buffer[27];
if (_serial) {
snprintf(buffer, sizeof(buffer), "PZEM004T @ HwSerial");
} else {
@@ -99,11 +126,14 @@ class PZEM004TSensor : public BaseSensor {
// Address of the sensor (it could be the GPIO or I2C address)
String address(unsigned char index) {
- return _ip.toString();
+ int i = index / MAGNITUDE_COUNT;
+ return _addresses[i]->toString();
}
// Type for slot # index
unsigned char type(unsigned char index) {
+ int i = index / MAGNITUDE_COUNT;
+ index = index - (i * MAGNITUDE_COUNT);
if (index == 0) return MAGNITUDE_CURRENT;
if (index == 1) return MAGNITUDE_VOLTAGE;
if (index == 2) return MAGNITUDE_POWER_ACTIVE;
@@ -113,11 +143,13 @@ class PZEM004TSensor : public BaseSensor {
// Current value for slot # index
double value(unsigned char index) {
+ int i = index / MAGNITUDE_COUNT;
+ IPAddress ip = *(_addresses[i]);
double response = 0;
- if (index == 0) response = _pzem->current(_ip);
- if (index == 1) response = _pzem->voltage(_ip);
- if (index == 2) response = _pzem->power(_ip);
- if (index == 3) response = _pzem->energy(_ip) * 3600;
+ if (index == 0) response = _pzem->current(ip);
+ if (index == 1) response = _pzem->voltage(ip);
+ if (index == 2) response = _pzem->power(ip);
+ if (index == 3) response = _pzem->energy(ip) * 3600;
if (response < 0) response = 0;
return response;
}
@@ -130,7 +162,7 @@ class PZEM004TSensor : public BaseSensor {
unsigned int _pin_rx = PZEM004T_RX_PIN;
unsigned int _pin_tx = PZEM004T_TX_PIN;
- IPAddress _ip;
+ std::vector<IPAddress *> _addresses;
HardwareSerial * _serial = NULL;
PZEM004T * _pzem = NULL; |
Looks like it is working, just some small changes to the diff I sent. I also added a command Unfortunately, I have only 2 PZEMs to test, but others in the mail. |
I'll finish some tests and submit a PR. |
Well, after some digging, looks like the ESP can't handle 3 or more devices, it hangs, probably too busy to handle all magnitudes of all devices. I made it work for 3 devices, but too much unreliable, some readings fail, sometimes the device panic, doesn't worth the PR. I'll work on a version using an Atmega Pro Mini handling the PZEM reading and forwarding to an ESP-01 module with Espurna, probably will create a new sensor that can handle all readings in the same request. I'll close this bug. |
I'm reopening this issue because I could figure out a way to handle multiple PZEM004T devices. The concept is the same, multidrop UART TX. I also added 3 commands:
I just need to confirm that the set address in the PZEM004T is persistent across reboots, otherwise, I'll need to add more changes, I'll submit the PR to start the discussion. |
Hi!
I'm working on a project that has 3 PZEM004T sensors connected to the same UART. They have addresses and only respond when the message is directed to them.
My schematics is like this:
![1e1675e4-147b-4ebd-82ef-92ea8a1bca27](https://user-images.githubusercontent.com/289289/42666879-20e80928-861e-11e8-97ca-35f0992f9b1b.png)
What is the way you think is right to implement on ESPurna? Create a new "sensor" , or retrofit the actual
PZEM004TSensor.h
?The text was updated successfully, but these errors were encountered: