Code Monkey home page Code Monkey logo

Comments (13)

Alfonso-Lijo avatar Alfonso-Lijo commented on May 28, 2024 1

Success!
I was able to perform all the steps using Arduino Mega!
The reason is quite obvious! Arduino Uno has only one serial port and simulates other serials on digital pins!
But the arduino Mega has 5 independent serial ports!
But attention: I do not know if I made a mistake or is a failure in the library, but only managed from the HardSerial example!
Follow my code!
I use an RTC1307, an SD card reader and a 20x4 LCD on my Datalogger!

/* **************************************************************************************************
SD - Se comunica por SPI
MOSI -> pino 51
MISO -> pino 50
SCK -> pino 52
CS (SS) -> Pino 53

Relógio RTC DS1307 - Se comunica por I2C no endereço 0x68
SDA -> pino 20
SCL -> pino 21

LCD se comunica por IC2 no endereço 0x27
SDA -> pino 20
SCL -> pino 21

Coleta de dados do Pzem 004
Pinos de comunicação Pzem (módulo Max485 RS 232 para Modbus)
Pino 14 TX fio verde
Pino 15 RX fio branco

Liga Backligth do LCD
pino digital 3 aciona o backligth
*/
#include <LiquidCrystal_I2C.h> // Biblioteca de configuração do LCD
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Inicializa o display no endereco 0x27
#include <SdFat.h> //Uso a biblioteca SdFat no lugar da original do arduino pois é mais otimizada.
SdFat SD; //Linha necessária para compatibilizar o programa escrito para SD.h (biblioteca original)
const int CS_SD = 53; //Pino do cartão SD
#include <DS1307RTC.h> //Biblioteca para controle do RTC DS1307
#include <PZEM004Tv30.h> //Biblioteca do monitor de energia Pzem
PZEM004Tv30 pzem(&Serial3); // TX(Verde),RX(Branco) conectados para RX,TX do PZEM

// Constantes variadas

const unsigned long intervaloLeitura = 2000; //inervalo de leitura [milisegundos]
const unsigned long intervaloEscritaSD = 300; //intervalo de escrita de dados no SD [milisegundos]
boolean temSD = 0; // Variável para indicar presença de cartão SD
const int intervaloSincro = 300; //Intervalo de sincronismo do arduino com o RTC [Seg.]. Sincronismo do RTC
//----------------------------------------------------------------------------------------------------------------

void setup()
{
lcd.begin (20, 4); //definição do LCD 20 colunas e 4 linhas
Serial.begin(115200); //Inicia a comunicação em 9600 kbps

//Inicializa cartão SD
// verifica se o SD está presente e pode ser inicializado:
if (!SD.begin(CS_SD)) {
temSD = 0; //Cartão SD não detectado
Serial.print("Cartão SD não detectado");
Serial.println();
}
else {
temSD = 1; //Cartão SD encontrado
Serial.print("Cartão está presente");
Serial.println();
}
//Inicializa o RTC e contagem de tempo
setTime(RTC.get());
setSyncProvider(RTC.get); //Estabelecemos o RTC como provedor do tempo
setSyncInterval(intervaloSincro); // Atualizamos seguindo intervalo definido
}

void loop() {
//iniciamos com as leituras dos dados do PZEM
float voltage = pzem.voltage();
if (voltage != NAN) {
Serial.print("Voltage: "); Serial.print(voltage); Serial.println("V");
} else {
Serial.println("Error reading voltage");
}

float current = pzem.current();
if (current != NAN) {
Serial.print("Current: "); Serial.print(current); Serial.println("A");
} else {
Serial.println("Error reading current");
}

float power = pzem.power();
if (current != NAN) {
Serial.print("Power: "); Serial.print(power); Serial.println("W");
} else {
Serial.println("Error reading power");
}

float energy = pzem.energy();
if (current != NAN) {
Serial.print("Energy: "); Serial.print(energy, 3); Serial.println("kWh");
} else {
Serial.println("Error reading energy");
}

float frequency = pzem.frequency();
if (current != NAN) {
Serial.print("Frequency: "); Serial.print(frequency, 1); Serial.println("Hz");
} else {
Serial.println("Error reading frequency");
}

float pf = pzem.pf();
if (current != NAN) {
Serial.print("PF: "); Serial.println(pf);
} else {
Serial.println("Error reading power factor");
}

static unsigned long millisPrevio = intervaloLeitura;
static unsigned long millisPrevio2 = intervaloEscritaSD;
static String dados;
unsigned long millisActual = millis();

// Enviamos os dados de hora e leituras do Pzem para o LCD trocando a cada 5 segundos

lcd.clear();
lcd.setBacklight(HIGH);
lcd.setCursor(0, 0);
lcd.print("Usina AlfonsoLijo");
lcd.setCursor(0, 1);
lcd.print("Capacidade 2.9 kWp");
lcd.setCursor(0, 2);
lcd.print ("Data:");
lcd.setCursor(6, 2);
lcd.print(timeLabel1()); //funciona
lcd.setCursor(0, 3);
lcd.print("Hora:");
lcd.setCursor(6, 3);
lcd.print(timeLabel2());
delay(15000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(voltage);
lcd.setCursor(7, 0);
lcd.print("V");
lcd.setCursor(10, 0);
lcd.print(current);
lcd.setCursor(17, 0);
lcd.print("A");
lcd.setCursor(0, 1);
lcd.print(power);
lcd.setCursor(17, 1);
lcd.print("kW");
lcd.setCursor(0, 2);
lcd.print(energy);
lcd.setCursor(17, 2);
lcd.print("kWh");
lcd.setCursor(0, 3);
lcd.print(frequency);
lcd.setCursor(7, 3);
lcd.print("Hz");
lcd.setCursor(10, 3);
lcd.print(pf);
lcd.setCursor(17, 3);
lcd.print("PF");
delay(15000);

if (millisActual - millisPrevio >= intervaloLeitura) { //Executa as siguintes ações só se é cumprido o intervalo

dados = timeLabel();           // coloca a marca de tempo no String dados
dados = dados + ", " + String(voltage);  //vai adicionando os valores medidos na string
dados = dados + ", " + String(current);
dados = dados + ", " + String(power);
dados = dados + ", " + String(energy);
dados = dados + ", " + String(frequency);
dados = dados + ", " + String(pf);
Serial.println(dados);            //mostra resultado na porta serial para simples consulta

millisPrevio = millisActual;

}

if (millisActual - millisPrevio2 >= intervaloEscritaSD * 60UL) { //se cumprido o intervalo especificado, procede a gravação dos dados
if (gravardadosSD(dados)) { //grava os dados no SD - se houver erro, retorna 1
}
millisPrevio2 = millisActual;
}
}

//função que devolve um String com a Hora/data atual
//Adiciona um '0' na esquerda nos valores de uma casa decimal e formata a hora/data

String timeLabel() {
time_t t = now();
String tempoAtual = String();
tempoAtual = year(t);
if (month(t) < 10)
tempoAtual = String(tempoAtual + '-' + '0' + month(t));
else
tempoAtual = String(tempoAtual + '-' + month(t));
if (day(t) < 10)
tempoAtual = String(tempoAtual + '-' + '0' + day(t));
else
tempoAtual = String(tempoAtual + '-' + day(t));
tempoAtual = String(tempoAtual + ',');
if (hour(t) < 10)
tempoAtual = String(tempoAtual + '0' + hour(t));
else
tempoAtual = String(tempoAtual + hour(t));
tempoAtual = String(tempoAtual + ':');
if (minute(t) < 10)
tempoAtual = String(tempoAtual + '0' + minute(t) + ':');
else
tempoAtual = String(tempoAtual + minute(t) + ':');
if (second(t) < 10)
tempoAtual = String(tempoAtual + '0' + second(t));
else
tempoAtual = String(tempoAtual + second(t));
return tempoAtual;
}

String timeLabel1() {
time_t t = now();
String tempoAtual1 = String();
tempoAtual1 = String(tempoAtual1 + day(t) + '-');
tempoAtual1 = String(tempoAtual1 + month(t) + '-');
tempoAtual1 = String(tempoAtual1 + year(t));
return tempoAtual1;
}

String timeLabel2() {
time_t t = now();
String tempoAtual2 = String();
if (hour(t) < 10)
tempoAtual2 = String(tempoAtual2 + '0' + hour(t));
else
tempoAtual2 = String(tempoAtual2 + hour(t));
tempoAtual2 = String(tempoAtual2 + ':');
if (minute(t) < 10)
tempoAtual2 = String(tempoAtual2 + '0' + minute(t) + ':');
else
tempoAtual2 = String(tempoAtual2 + minute(t));
// if (second(t) < 10)
// tempoAtual2 = String(tempoAtual2 + '0' + second(t));
// else
// tempoAtual2 = String(tempoAtual2 + second(t));
return tempoAtual2;
}

// Função que registra as medições feitas em um arquivo "meulog.cvs"
// Se o arquivo existir, os dados serão adicionados e, se não forem criados, os mesmos
// Recebe uma String com o formato a ser gravado
// Retorna 0 se correu bem e 1 se houve um erro

boolean gravardadosSD(String data) {
time_t t = now();
String date = String(); //Geramos um string para usar de nome de arquivo com a data do dia.
date = year(t);
if (month(t) < 10)
date = String(date + '0' + month(t));
else
date = String(date + month(t));
if (day(t) < 10)
date = String(date + '0' + day(t));
else
date = String(date + day(t));
date = String(date + ".csv");
char fileName[13];
date.toCharArray(fileName, 13); //convertemos o string para uma array de caracteres (exigido pela biblioteca do SD)

if (!temSD) {
return 1; //termina a função se o SD não esta inicializado
}
if (SD.exists(fileName)) { //Se existe o arquivo "fileName" o abrimos e adicionamos os dados.
File meulog = SD.open(fileName, FILE_WRITE);
if (meulog) { //Se o arquivo se abre corretamente escrevemos nele ...
meulog.println(data);
meulog.close();
return 0;
}
else {
return 1; //Não se conseguiu abrir o arquivo ...
}
}
else { //se não existe o archivo "meulog.cvs" criamos um novo e gravamos os dados ...
File meulog = SD.open(fileName, FILE_WRITE);
if (meulog) { //Se o arquivo é aberto corretamente gravamos os dados ...
meulog.println(F("Data, Hora, Volt, Amp, Watt, kWh, Hz, FP"));
meulog.println(data);
meulog.close();
return 0;
}
else {
return 1;
}
}
}

from pzem-004t-v30.

Alfonso-Lijo avatar Alfonso-Lijo commented on May 28, 2024

I have a same problem! Now ! tri to put a external power supply.

from pzem-004t-v30.

Alfonso-Lijo avatar Alfonso-Lijo commented on May 28, 2024

I just change the PZEM004T.h line 34 (#define PZEM_DEFAULT_ADDR 0x0F to 0x001 and work now!

from pzem-004t-v30.

Alfonso-Lijo avatar Alfonso-Lijo commented on May 28, 2024

This library needs tweaking!
I've managed to keep up communication when I add the RTC and LCD control libraries, but sending anything to the LCD just ends communication!

from pzem-004t-v30.

Alfonso-Lijo avatar Alfonso-Lijo commented on May 28, 2024

Thank you so much mandulaj for the beautiful work!

from pzem-004t-v30.

pye222 avatar pye222 commented on May 28, 2024

I'm glad that it works well with mega.
I did software serial communication with two Arduinos. And one side
PZEM-004T v3.0 was installed and data was transferred to another Arduino. Other Arduinos were used by connecting Sd card, LCD, and RTC

from pzem-004t-v30.

Alfonso-Lijo avatar Alfonso-Lijo commented on May 28, 2024

I am a beginner in Arduino!
I am trying to improve my code so that the data sent to the LCD does not interfere with the data recording!
As it stands today, LCD display time directly interferes with the amount of recorded data!
Could someone help me sort this out so that I can record more data on the SD card while keeping the display time of the data on the LCD?
I would be very grateful!

from pzem-004t-v30.

Alfonso-Lijo avatar Alfonso-Lijo commented on May 28, 2024

from pzem-004t-v30.

mandulaj avatar mandulaj commented on May 28, 2024

@Alfonso-Lijo, thanks for using my library, I wasn't expecting many people to do so. I was having similar issues and honestly I have no idea how to make it work more elegantly on an UNO . If you have any suggestions, please feel free to open up a pull request!

from pzem-004t-v30.

RB3rg avatar RB3rg commented on May 28, 2024

@mandulaj I would not waste time with software serial, we all know it is a workaround for old devices.
Most of all new devices (esp32, stm32) have more than one HW Serial.
In the real-life, no one will (or should) put in production a device for monitoring power using software serial. It ends up most of the people using SW Serial it's bench test.

from pzem-004t-v30.

mandulaj avatar mandulaj commented on May 28, 2024

@pye222 Is this still something that needs work? Have you found a way to fix or some kind of work around?

from pzem-004t-v30.

Alfonso-Lijo avatar Alfonso-Lijo commented on May 28, 2024

It's working within my needs and I haven't made any more changes! Thanks!

from pzem-004t-v30.

mandulaj avatar mandulaj commented on May 28, 2024

Ok, in that case I will close this issue.

from pzem-004t-v30.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.