Hi, need help. I am using Arduino Mega 2560 to monitor power line voltage using PZEM004T power sensors. I am trying to use internet interrupt from Arduino, just to make sure that I can read the sensor reliably. Here is my code:
#include <SPI.h>
#include <PZEM004Tv30.h>
PZEM004Tv30 pzem1(&Serial2);
volatile int i=0;
volatile float lineVolt = 0;
void setup() {
Serial.begin(9600);
Serial.println("Testing interrupt");
//==== this part for setting interrupt!
cli();//stop interrupts
//set timer4 interrupt at 1Hz
TCCR4A = 0;// set entire TCCR1A register to 0
TCCR4B = 0;// same for TCCR1B
TCNT4 = 0;//initialize counter value to 0
// set compare match register for 1hz increments
OCR4A = 15624/1;// = (16*10^6) / (1*1024) - 1 (must be <65536)
// turn on CTC mode
TCCR4B |= (1 << WGM12);
// Set CS12 and CS10 bits for 1024 prescaler
TCCR4B |= (1 << CS12) | (1 << CS10);
// enable timer compare interrupt
TIMSK4 |= (1 << OCIE4A);
sei();
}
ISR(TIMER4_COMPA_vect) {
// this function will be executed very 1hz (or 1 second)
Serial.println(i++);
ineVolt = pzem1.voltage();
Serial.println(lineVolt);
}
void loop() {
}
The line that accessing the pzem object is the culprit. I don't know how and why it can't work using the interrupt. Any idea?
Library can be downloaded here:
I am using hardware serial connection. Thank you in advance.
There are multiple problems using an interrupt to read this device. The primary problem is that you are communicating with the device using a serial port which needs interrupts and interrupts are disabled when you are in an ISR!!! Also, if you look in the library for this device, it only updates the values every 200ms.
The bottom line is, it makes no sense to use interrupts for this device.
sorry for all the typos. not internet interrupt, but internal interrupt (not triggered externally). The serial.print is for debugging purposes only, just to know what causes the trouble, I just simplify the code inside the ISR, and I found out the call to pzem caused the problem. Yes, I tried to check the code, but I failed to see whether it can / can't be called using the interrupt.
Thanks to you and jremington, I think this is the limitation.
Here is my situation: I have an on-grid solar panel system to be monitored. So, I use the Arduino and 2 pzem to monitor the power line from the inverter line and the grid line to calculate the import, export, load power, etc. I also use a touch panel LCD to display the data. And starting from that, I was thinking of putting a nice graphical chart on LCD, and so on. The problem is that this chart takes time to render. So, in order to guarantee that the Arduino gets the data from the pzem precisely every 60 seconds, then I decided to use the interrupt to simplify the coding.
Originally I use an RTC call to determine whether a minute has elapsed in the loop() (similar to using milis()). I just think using the interrupt will simplify everything and make sure it won't miss every minute it elapses and I could write a code to render a chart without thinking of putting a code to check the time and calling the pzem here and there.
So, I think, my options are:
a. putting a code to read the pzem inside chart rendering's code here and there.
b. or, sending the data to the cloud and rendering the chart from it.
c. or, using another Arduino to draw the chart, and any other Arduino just taking data from pzem.
Nothing can be further from the true, as you've discovered. Interrupts are a Catch 22 ... You shouldn't try to use them unless you know what you're doing. But .... you'll never learn their proper usage unless you try and get burned a few times. So, you're on your way.
Before doing any of those things, I endeavor to rewrite the code that renders the chart to be nonblocking. There's no reason it must all be done in one shot. Divide it into smaller chunks and do a little bit on every iteration through the loop() function.
Surely it won't take 60 seconds to render a chart. How precise is "precisely"? Because if "precisely" is less than +/-200ms then the pzem library doesn't support that anyhow (at least in it's unmodified form because it is hardcoded).
If you are worried about the rendering time then just use some contrived data and measure the time it takes to render. In any case you should avoid code that blocks.