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

compile errors with MKR 1010 #39

Closed nmsneves closed 2 years ago

nmsneves commented 3 years ago

hi, i've been using the library very well on an arduino uno, but today i decided to compile it for an arduino MKR1010, without sucess. is this board compatible? i tried to use both hardware and software serial. the errors are the following:

`In file included from C:\Users\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.8.8\cores\arduino/delay.h:23:0, from C:\Users\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.8.8\cores\arduino/Arduino.h:81, from C:\Users\MEOCloud\Arduino\libraries\PZEM-004T-v30-master\PZEM004Tv30.h:41, from C:\Users\MEOCloud\Arduino\libraries\PZEM-004T-v30-master\PZEM004Tv30.cpp:23: C:\Users\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.8.8\variants\mkrwifi1010/variant.h:222:37:

error: conflicting declaration 'HardwareSerial SerialUSB'

define Serial SerialUSB

                                 ^

C:\Users\\Arduino\libraries\PZEM-004T-v30-master\PZEM004Tv30.cpp:54:23: note: in expansion of macro 'Serial' extern HardwareSerial Serial; ^~ In file included from C:\Users\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.8.8\cores\arduino/Arduino.h:139:0, from C:\Users\MEOCloud\Arduino\libraries\PZEM-004T-v30-master\PZEM004Tv30.h:41, from C:\Users\MEOCloud\Arduino\libraries\PZEM-004T-v30-master\PZEM004Tv30.cpp:23: C:\Users\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.8.8\cores\arduino/USB/CDC.h:158:16: note: previous declaration as 'Serial SerialUSB' extern Serial SerialUSB; ^~~~~ C:\Users\\Arduino\libraries\PZEM-004T-v30-master\PZEM004Tv30.cpp: In destructor 'PZEM004Tv30::~PZEM004Tv30()': C:\Users\MEOCloud\Arduino\libraries\PZEM-004T-v30-master\PZEM004Tv30.cpp:119:22: warning: deleting object of abstract class type 'Stream' which has non-virtual destructor will cause undefined behavior [-Wdelete-non-virtual-dtor] delete this->_serial; ^~~ exit status 1 Erro ao compilar para a placa Arduino MKR WiFi 1010. `

mandulaj commented 3 years ago

Hey @nmsneves! I am sorry, I don't have an Arduino MKR 1010 so I have never tested the library with it. It looks like there might be and issue with the Hardware serial declaration.... Seems like the API is not 100% compatible between the various Arduino boards. I don't know if I will have time to look into this but I will mark it as something that should be fixed so that at least the common Arduino boards are supported.

Thanks.

nmsneves commented 3 years ago

hi @mandulaj , thanks for marking this to be fixed. And like you say, it really should be a problem with the hardware serial definition. I could make it compile and run today, just by replacing every call involving the serial port, by a call to "Serial1", and modifying the constructor

mandulaj commented 3 years ago

@nmsneves could you perhaps create a pull request with your changes? I would need more other people to test it since as I said, I don't have the Arduino at hand... Thanks 😊

nmsneves commented 3 years ago

@nmsneves could you perhaps create a pull request with your changes? I would need more other people to test it since as I said, I don't have the Arduino at hand... Thanks 😊

... i would, but i'm not familiar with github. give me a while to look how to do it

seramonte commented 3 years ago

I have same problem with DUE. The following changes allow program to compile. But still no output.

@PZEM004Tv30.h:67 //PZEM004Tv30(HardwareSerial* port, uint8_t addr=PZEM_DEFAULT_ADDR); PZEM004Tv30(USARTClass* port, uint8_t addr=PZEM_DEFAULT_ADDR); // added for DUE

@PZEM004Tv30.cpp:55 //extern HardwareSerial Serial; // commented out for DUE

@PZEM004Tv30.cpp:102 //PZEM004Tv30::PZEM004Tv30(HardwareSerial* port, uint8_t addr) PZEM004Tv30::PZEM004Tv30(USARTClass* port, uint8_t addr) // for DUE


EDIT: 2021-03-20 -- Solution for no output (apparent failed initialization). In addition to above. Class creation/initialization is divided in two.

@PZEM004Tv30.cpp: ~101, comment out:

// PZEM004Tv30::PZEM004Tv30(HardwareSerial* port, uint8_t addr)
// {
//    port->begin(PZEM_BAUD_RATE);
//    this->_serial = port;
//    this->_isSoft = false;
//    init(addr);
//}

Replace with:

/*
 * Changed PZEM004Tv30::PZEM004Tv30 -- needed for DUE board
 * 
 * This change separates class creation before setup() from 
 * serial port begin in setup().
 */
PZEM004Tv30::PZEM004Tv30(void)
{
}

/*
 * NEW PZEM004Tv30::begin
 * 
 * Called in setup().
 */
void PZEM004Tv30::begin(uint8_t addr, Stream &serial)
{
  _serial = &serial;
  init(addr);
}

@PZEM004Tv30.h: ~46

// Uncomment
#define PZEM004_NO_SWSERIAL  //  for Arduino Due

@PZEM004Tv30.h: ~59, comment 2 lines; add one line; then add new method

class PZEM004Tv30
{
public:
#if defined(PZEM004_SOFTSERIAL)
    PZEM004Tv30(uint8_t receivePin, uint8_t transmitPin, uint8_t addr=PZEM_DEFAULT_ADDR);
#endif
   // PZEM004Tv30(HardwareSerial* port, uint8_t addr=PZEM_DEFAULT_ADDR);
   // ~PZEM004Tv30();
    PZEM004Tv30(void);  // new

...

    // Add new begin()
    void begin(uint8_t slave, Stream &serial);  // added

Then, in your sketch:

#include "PZEM004Tv30.h"
//PZEM004Tv30 pzem(11, 12); //RX, TX  software serial
PZEM004Tv30 pzem004t; // uses new pzem.begin() in setup()

setup()
{
  Serial2.begin(9600, SERIAL_8N1);
  pzem004t.begin(0x0F8, Serial2);  // Using pzem004tv30 library
}
nmsneves commented 3 years ago

u

Hi @seramonte , the changes I did to have the library to compile and run on my MKR1010 were these:

like you, I comment this line: //extern HardwareSerial Serial; modified the hardware serial constructor:

//PZEM004Tv30::PZEM004Tv30(HardwareSerial* port, uint8_t addr)
PZEM004Tv30::PZEM004Tv30(uint8_t addr)
{
    /*
    port->begin(PZEM_BAUD_RATE);
    this->_serial = port;
    this->_isSoft = false;
   */
    init(addr);
}

and every occurrence of _serial-> was replaced by Serial1.

in the examples code, the only change I did to have it running was this:

#define PZEM_DEFAULT_ADDR    0xF8

PZEM004Tv30 pzem(PZEM_DEFAULT_ADDR);
Fox2829 commented 3 years ago

@nmsneves, could you clarify.

You changed in the file PZEM004Tv30.cpp:

  1. //extern HardwareSerial Serial;

  2. //PZEM004Tv30::PZEM004Tv30(HardwareSerial* port, uint8_t addr) PZEM004Tv30::PZEM004Tv30(uint8_t addr) { /* port->begin(PZEM_BAUD_RATE); this->_serial = port; this->_isSoft = false; */ init(addr); }

  3. In four places // _serial->write(sendBuffer, 8); // send frame Serial1.write(sendBuffer, 8); // send frame or _Serial1->write(sendBuffer, 8); // send frame or somehow differently?

  4. And You changed in the file PZEMHardSerial.ino: //PZEM004Tv30 pzem(&Serial3); #define PZEM_DEFAULT_ADDR 0xF8 PZEM004Tv30 pzem(PZEM_DEFAULT_ADDR);

Because I can't:

" PZEMHardSerial:9:35: error: invalid conversion from 'int' to 'HardwareSerial' [-fpermissive] PZEM004Tv30 pzem(PZEM_DEFAULT_ADDR); ^ In file included from C:\Users\CD86~1\AppData\Local\Temp\arduino_modified_sketch_27982\PZEMHardSerial.ino:1:0: D:\���������\Arduino\libraries\PZEM-004T-v30-master/PZEM004Tv30.h:65:5: note: initializing argument 1 of 'PZEM004Tv30::PZEM004Tv30(HardwareSerial, uint8_t)' PZEM004Tv30(HardwareSerial port, uint8_t addr=PZEM_DEFAULT_ADDR); ^~~ exit status 1 invalid conversion from 'int' to 'HardwareSerial' [-fpermissive] "

MikeHales1 commented 3 years ago

Hi,

I'm getting similar problems trying to use the library on an Arduino UNO Wifi Rev 2 board. Errors reported are: O:\Documents\Arduino\libraries\PZEM004Tv30\PZEM004Tv30.cpp:54:23: error: conflicting declaration 'arduino::HardwareSerial Serial' extern HardwareSerial Serial; ^~ In file included from C:\Users\Mike\AppData\Local\Arduino15\packages\arduino\hardware\megaavr\1.8.7\cores\arduino/Arduino.h:140:0, from O:\Documents\Arduino\libraries\PZEM004Tv30\PZEM004Tv30.h:41, from O:\Documents\Arduino\libraries\PZEM004Tv30\PZEM004Tv30.cpp:23: C:\Users\Mike\AppData\Local\Arduino15\packages\arduino\hardware\megaavr\1.8.7\cores\arduino/UART.h:182:20: note: previous declaration as 'UartClass Serial' extern UartClass Serial; ^~ exit status 1 Error compiling for board Arduino Uno WiFi Rev2.

As the error suggests, it is something to do with the line 'extern HardwareSerial Serial;' but I haven't tracked down what. I will try the comments above.

Just as a further note, I have used the library on the Arduino MEGA without any problems, so I don't understand why the UNO Wifi is causing problems. The only difference is the UNO uses Serial1 not Serial3; I will go back and see if it works on the MEGA on Serial1, although I doubt this is the cause due to the code line the error is reporting.

Any help on fixing this would be great.

Thanks.

MikeHales1 commented 3 years ago

As I suspected, it runs fine on Arduino MEGA on Serial1. Might need to delve a bit deeper into why the MEGA and UNO Wifi compile differently as they both use Arduino.h which in turn uses HardSerial.h. Interestingly the MRK 1010 is also a Wifi board.

zygisjas commented 3 years ago

Serial1

Could you please clarify your changes? I have same problem on Arduino Nano 33 IoT. I've tried suggested changes, but getting this error:

Arduino\libraries\PZEM-004T-v30\PZEM004Tv30.cpp:109:1: error: prototype for 'PZEM004Tv30::PZEM004Tv30(uint8_t)' does not match any in class 'PZEM004Tv30'

PZEM004Tv30::PZEM004Tv30(uint8_t addr)

MikeHales1 commented 3 years ago

Hi,

I tried to work out what was wrong with the library but gave up.

I'm currently writing a function to read the values without using the library. In essence you simply send a number of bytes and then interpret the bytes received. Not too difficult.

Regards,

Mike

On Tue, 16 Mar 2021, 21:17 Žygimantas Jasiūnas, @.***> wrote:

Serial1

Could you please clarify your changes? I have same problem on Arduino Nano 33 IoT

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/mandulaj/PZEM-004T-v30/issues/39#issuecomment-800611925, or unsubscribe https://github.com/notifications/unsubscribe-auth/ATB5QMHYEX3SBODB2JIKLJ3TD7DFTANCNFSM4TKXJNPA .

zygisjas commented 3 years ago

Hi, I tried to work out what was wrong with the library but gave up. I'm currently writing a function to read the values without using the library. In essence you simply send a number of bytes and then interpret the bytes received. Not too difficult. Regards, Mike On Tue, 16 Mar 2021, 21:17 Žygimantas Jasiūnas, @.***> wrote: Serial1 Could you please clarify your changes? I have same problem on Arduino Nano 33 IoT — You are receiving this because you commented. Reply to this email directly, view it on GitHub <#39 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/ATB5QMHYEX3SBODB2JIKLJ3TD7DFTANCNFSM4TKXJNPA .

What board do you use?

mandulaj commented 2 years ago

I will close this as stale. In case you still face problems even with the new version, feel free to reopen the issue.

Neorx commented 2 years ago

Hi Guys,

I've read the topic but unfortunately no opportunity to find a proper solution. I've exactly the same issue with the PXEM-004T V3 and Arduino MKR 1010 WiFi. Everything is working perfectly on the Nano, but the MKR with the impossibility to use neither the SoftwareSerial or HardwareSerial solutions makes impossible to use the library...

Is there someone that found a solution to use it?

MikeHales1 commented 2 years ago

Hi @Neorx. I never figured out why the library doesn't work with the Uno Wifi. However the PZEM modules work fine with the Uno Wifi. I touch the parts of the library I needed and put the code into my code. Some minor changes and it worked great. I actually think this worked better as I only have the code I need and it's simple to understand.

Neorx commented 2 years ago

Hi @Neorx. I never figured out why the library doesn't work with the Uno Wifi. However the PZEM modules work fine with the Uno Wifi. I touch the parts of the library I needed and put the code into my code. Some minor changes and it worked great. I actually think this worked better as I only have the code I need and it's simple to understand.

Thank you @MikeHales1 for your reply, I'm definetly not an expert but I think this is an issue with the SAMD based boards and related serial ports management. your approach seem definetly to be a good solution.

could you share the code? I can think to use the same approach.

This is a great device but an improvement over the library for the SAMD boards would be great PS : in any case, for my curiosity I've ordered an ESP8266 board to check if that one is easier.

MikeHales1 commented 2 years ago

This is a shortened file I used. It might not compile. However, it shows how to initiate Serial1 to use with 3 PZEM modules on the same serial port. The routine to read the PZEMs is setup to use addresses 10, 11 and 12. To work out the correct codes to send I used the CRC calculator in the PZEM library, as they are constants you only need to do this once. Then it is really simple to read the modules. As I only pole them at a maximum rate of every 2 seconds, I don't need to check if new data is available. Good luck.

include

include

/* PZEM variables, constants, etc

void setup() {

//PZEM comms is 9600 baud, 8 bits, 1 stop bit, no parity Serial1.begin (9600, SERIAL_8N1);

CurrentSecond = second(); //Initialise the current second FileNames (MonthFile, MonthFileW, YearFile); //Initialise the monthly and annual filename

}

void loop() {

//Routines to run every second if (CurrentSecond != second()) { //Read the PZEMs every second if ((second() % SDFreq) == 0) { ReadPZEM (PZEM10H, House); //Read the house values ReadPZEM (PZEM11S, Solar); //Read the solar values ReadPZEM (PZEM12I, Immer); //Read the immersion heater values } CurrentSecond = second(); } }

//Start of subroutines

void PZEMtoSD (float PZEMData[7], char Line[40]) { char Part[10]; //Format float array into char array for output to SD card dtostrf (PZEMData[0],5,1, Part); //Convert volts strcpy (Line,Part); strcat (Line,","); dtostrf (PZEMData[1],6,3, Part); //Convert amps strcat (Line,Part); strcat (Line,","); dtostrf (PZEMData[2],8,1, Part); //Convert watts strcat (Line,Part); strcat (Line,","); dtostrf (PZEMData[3],8,0, Part); //Convert Wh strcat (Line,Part); strcat (Line,","); dtostrf (PZEMData[4],4,1, Part); //Convert Hz strcat (Line,Part); strcat (Line,","); dtostrf (PZEMData[5],4,2, Part); //Convert pf strcat (Line,Part); // strcpy (Line,","); // dtostrf (PZEMData[6],4,0, Part); //I don't want to store the alarm status // strcat (Line,Part); }

void ReadPZEM (float ReadData [7], int BoardAddr) { //These messages were determined from the library functions //Message to read 10 registers from PZEM-004T Rev 3 module at address 10 '0x0A' const byte Read10[8] = {0x0A, 0x04, 0x00, 0x00, 0x00, 0x0A, 0x71, 0x76}; //Message to read 10 registers from PZEM-004T Rev 3 module at address 11 '0x0B const byte Read11[8] = {0x0B, 0x04, 0x00, 0x00, 0x00, 0x0A, 0x70, 0xA7}; //Message to read 10 registers from PZEM-004T Rev 3 module at address 12 '0x0C' const byte Read12[8] = {0x0C, 0x04, 0x00, 0x00, 0x00, 0x0A, 0x71, 0x10}; const int TimeOut = 100; //Takes about 60msec to read 25 bytes long int StartRead; //Millis at start of read cycle int inByte; //Count of incoming bytes //Buffer to store the response from the read command uint32_t Buff12[25]; //Buffer is converted to floating point array: //[0] - Volts //[1] - Amps //[2] - Watts //[3] - Wh //[4] - Hz //[5] - pf //[6] - Alarm

//Send read results command to Serial1 //Checking which board address is required if (BoardAddr == 10) { Serial1.write (Read10, sizeof (Read10)); } else if (BoardAddr == 11) { Serial1.write (Read11, sizeof (Read11)); } else if (BoardAddr == 12) { Serial1.write (Read12, sizeof (Read12)); } else return; //Only the above addresses are coded inByte = 0; StartRead = millis(); //If required response is not returned in 'TimeOut' exit loop while (inByte < 25 && (millis() - StartRead < TimeOut)) { //Read serial data and store in buffer if (Serial1.available() > 0) { Buff12 [inByte] = Serial1.read(); inByte = inByte + 1; } if (millis() < StartRead) StartRead = millis(); //Compensate for millis going back to 0 every 50 days or so } //Check the reply is the correct length and the correct slave address and responding to the read instruction //Could also check CRC but doesn't seem worth the effort if the above is correct if ((inByte == 25) && (Buff12[0] == BoardAddr) && (Buff12[1] == 0x04)) { //Convert read buffer to floaing point numbers ReadData[0] = (Buff12[3] << 8 | // Raw voltage in 0.1V Buff12[4])/10.0; ReadData[1] = (Buff12[5] << 8 | // Raw current in 0.001A Buff12[6] | Buff12[7] << 24 | Buff12[8] << 16) / 1000.0; ReadData[2] = (Buff12[9] << 8 | // Raw power in 0.1W Buff12[10] | Buff12[11] << 24 | Buff12[12] <<16) / 10.0; ReadData[3] = (Buff12[13] << 8 | //Raw energy in 1Wh Buff12[14] | Buff12[15] << 24 | Buff12[16] << 16) / 1000.0; ReadData[4] = (Buff12[17] << 8 | // Raw frequency in 0.1Hz Buff12[18]) / 10.0; ReadData[5] = (Buff12[19] << 8 | // Raw pf in 0.01 Buff12[20] ) / 100.0; ReadData[6] = (Buff12[21] << 8 | // Raw alarm value Buff12[22]); } else { //If error then set to NAN - 'Not a Number' ReadData[0] = NAN; ReadData[1] = NAN; ReadData[2] = NAN; ReadData[3] = NAN; ReadData[4] = NAN; ReadData[5] = NAN; ReadData[6] = NAN; } }