mandulaj / PZEM-004T-v30

Arduino library for the Updated PZEM-004T v3.0 Power and Energy meter
MIT License
256 stars 108 forks source link

Problems with multiple sensors #78

Closed Monracloche closed 2 years ago

Monracloche commented 2 years ago

Hello, first of all thank you very much for the help. I am testing the @mandulaj code for multiple sensors (2) with arduino mega and serial2 hardware but I can't operate both sensors at the same time. This is de code:

#include <PZEM004Tv30.h>
#define PZEM_SERIAL Serial2
#define NUM_PZEMS 2

PZEM004Tv30 pzems[NUM_PZEMS];

void setup() {
    Serial.begin(115200);

    // For each PZEM, initialize it
    for(int i = 0; i < NUM_PZEMS; i++)
    {
        pzems[i] = PZEM004Tv30(PZEM_SERIAL, 0x10 + i);
    }
}

void loop() {
    // Print out the measured values from each PZEM module
    for(int i = 0; i < NUM_PZEMS; i++){
        // Print the Address of the PZEM
        Serial.print("PZEM ");
        Serial.print(i);
        Serial.print(" - Address:");
        Serial.println(pzems[i].getAddress(), HEX);
        Serial.println("===================");

        // Read the data from the sensor
        float voltage = pzems[i].voltage();
        float current = pzems[i].current();
        float power = pzems[i].power();
        float energy = pzems[i].energy();
        float frequency = pzems[i].frequency();
        float pf = pzems[i].pf();

        // Check if the data is valid
        if(isnan(voltage)){
            Serial.println("Error reading voltage");
        } else if (isnan(current)) {
            Serial.println("Error reading current");
        } else if (isnan(power)) {
            Serial.println("Error reading power");
        } else if (isnan(energy)) {
            Serial.println("Error reading energy");
        } else if (isnan(frequency)) {
            Serial.println("Error reading frequency");
        } else if (isnan(pf)) {
            Serial.println("Error reading power factor");
        } else {
            // Print the values to the Serial console
            Serial.print("Voltage: ");      Serial.print(voltage);      Serial.println("V");
            Serial.print("Current: ");      Serial.print(current);      Serial.println("A");
            Serial.print("Power: ");        Serial.print(power);        Serial.println("W");
            Serial.print("Energy: ");       Serial.print(energy,3);     Serial.println("kWh");
            Serial.print("Frequency: ");    Serial.print(frequency, 1); Serial.println("Hz");
            Serial.print("PF: ");           Serial.println(pf);
        }

        Serial.println("-------------------");
        Serial.println();
    }

    Serial.println();
    delay(2000);
}

This is the wiring:

1637491612986

And this is the results image

The Tx and Rx leds from the sensors are blinking and when I disconnect one of them, the one that stays connected works 1637491612979

image

I have also tried serial software code with the same result, does anyone know what the problem is? Thank you very much again

mandulaj commented 2 years ago

Did you give the sensors the address 0x10 and 0x11? You have to use the set address script on each sensor individually in order to configure their address.

Monracloche commented 2 years ago

Yes, with this instruction pzems[i] = PZEM004Tv30(PZEM_SERIAL, 0x10 + i); they didn't change their addresses, they both kept the same address, I thought that's why it didn't work and I changed them with this other instruction pzems[i].setAddress(addr+i); now they each have a different address but they still don't work

mandulaj commented 2 years ago

No, I haven't explained that well. You DON'T configure the address in your program! You have to use the PZEMChangeAddress example sketch to configure each of the PZEMs individually! The PZEMChangeAddress sketch will write the custom address into the EEPROM of the connected PZEM. This way even after a power off, it will remember the new address. The PZEMChangeAddress example sketch should be available form the example folder in Arduino IDE under the PZEM-004T-v30 library.

Here is what you have to do:

  1. Open this example program https://github.com/mandulaj/PZEM-004T-v30/tree/master/examples/PZEMChangeAddress

  2. Change this #define SET_ADDRESS to 0x10:

    #if !defined(SET_ADDRESS)
    #define SET_ADDRESS 0x10
    #endif

    Make sure #define INCREMENT is false!

  3. Flash the modified example program (PZEMChangeAddress) to your microcontroller

  4. Connect ONE of the PZEMs to the micro controller and run the sketch. This configures the address for that ONE PZEM to 0x10

  5. Disconnect the PZEM!

  6. Change the SET_ADDRESS to 0x11

    #if !defined(SET_ADDRESS)
    #define SET_ADDRESS 0x11
    #endif
  7. Reflash it to the microcontroller

  8. Connect the second PZEM to the microcontroller and run the sketch

  9. The second PZEM will now have the address of 0x11

  10. Disconnect it from the microcontroller

  11. Flash your program (Do not include the pzems[i].setAddress(addr+i); in your program) Just use the pzems[i] = PZEM004Tv30(PZEM_SERIAL, 0x10 + i); when initizalizing the PZEMs

  12. Now connect both of the PZEMs to the microcontroller and yoru sketch should work.

mandulaj commented 2 years ago

Basically, when you have only one PZEM connected you can use the default 0xF8 address which every PZEM will always listen to regardless of what its actually custom address is. But if there are multiple PZEMs connected to the bus, the address 0xF8 makes no sense since all PZEMs would be responding to the messages.

This is why you have to configure them individually. Once you write a separate 0x10 and 0x11 address to the two PZEMs, you can use those to differentiate which one to talk to.

The PZEMChangeAddress example sketch does exactly this. It uses the default address 0xF8 to talk to the connected PZEM and uses pzems.setAddress(SET_ADDRESS); to set its address to the value of SET_ADDRESS.

You only have to do this once. Then the PZEMs will remember their custom addresses and you can talk to them using those.

Monracloche commented 2 years ago

I just tested what you wrote and it worked at the first time. Thank you very much for the help ... I had been trying things without success for days