I have a ESP32 with an Arduino Nano pulsing voltage via a relay for 500 milliseconds every 10 seconds.
The ESP32 has an interrupt that should trigger on the rising edge. Note that the ESP32 uses reverse logic so that means it should trigger when the voltage pulse stops.
The interrupt is initialized like this:
Before setup
void LogSensorReading () {
if (inloop == true) { //when the board first boots up unfortuantly it runs the interrupt and resets all our credentials, so we need to ensure that we are in the loop before the option to reset the credentials comes available
/* GET THE CURRENT TIME */
DateTime now = rtc.now();
/* AND PUT THE CURRENT YEAR, MONTH, DAY, HOURS, MINUTES, SECONDS INTO ONE STRING */
int currentYear = now.year(); //put the current year into a variable
int currentMonth = now.month(); //put the current month into a variabl
int currentDay = now.day(); //put the current day into a variable
int currentHour = now.hour(); //put the current hours into a variable
int currentMinute = now.minute(); //put the current minutes into a variable
int currentSecond = now.second(); //put the current seconds into a variable
String receivedTimeDate = (String(currentYear) + "-" + toStringAddZero(currentMonth) + "-" + toStringAddZero(currentDay)) + ("T") + (toStringAddZero(currentHour) + ":" + toStringAddZero(currentMinute) + ":" + toStringAddZero(currentSecond)) + ("Z");
if (stringQueue.isFull()) {
Serial.println("Queue full removing item....");
Serial.println(stringQueue.dequeue());
Serial.println("======================================================");
}
stringQueue.enqueue(receivedTimeDate); //enqueue the date and time
Serial.println(receivedTimeDate);
}
}
I will post full code shortly, but can anyone see what I am doing wrong? Would you like me to create and upload a wiring diagram?
It appears that you are attempting an i2c read and serial printing from within the isr.
These two activities are both inappropriate for an isr, because they require interrupts to be enabled to function properly, and interrupts are disabled within the isr.
What's done as a result of an interrupt needs necessarily to be exceedingly brief.
Where's this "reverse logic" bit written?
Many of the ESP32 GPIOs aren't for casual use (like Arduino GPIO), they're pulled-up or
have states that cannot be violated at boot and so on.
cattledog:
It appears that you are attempting an i2c read and serial printing from within the isr.
These two activities are both inappropriate for an isr, because they require interrupts to be enabled to function properly, and interrupts are disabled within the isr.
it is possible to read an I2C from within an ISR by giving the I2C a higher interrupt priority than the ISR doing the read - never attempted this on an Arduino though
certainly never attempt console IO from within an ISR
You have an inappropriate isr where you are trying to do too much within the isr. Enabling interrupts to make it all happen is not the correct solution to whatever you are trying to do. Why do you need an interrupt to detect a 500ms pulse in order to log something to the nearest second?
I want to store the time and date each time a pulse comes in and then do a HTTPS post, but if the pulse comes while doing the HTTPS post it needs to store this and then post it later.
How could I get the interrupt to be simple?
I need it to:
Get the current time and date
Enqueue the time and date
@runaway_pancake I want it to trigger when the pulse ends so I say when it "RISES" (1 = LOW, 0 = HIGH)
In the ISR, record the time. Next in loop(), do something with it. When done, clear the recorded time to zero.
Or maybe better, also set a flag in the ISR that a new time was recorded and clear that once the time is processed in loop().
Note that it's advisable to disable interrupts in loop(), make a copy of the recorded time to work with and immediately enable the interrupts again. That way, a new interrupt will not corrupt the time that you're processing.
I don't think that the issue is to do with what is in the interrupt because I removed everything except for a Serial.println and it still triggered when the voltage "ROSE" and "FELL". Is that a correct conclusion?
@horace thank you for the link but I don't think that the link applies to me as I am using an ESP32. Is that correct?
ZebH:
horace thank you for the link but I don't think that the link applies to me as I am using an ESP32. Is that correct?
in #1 you stated the host micro was a Arduino Nano which is based on the ATmega328 processor - hence the comment about fixed interrupt priorities
I was thinking back to when I was using a PIC24FJ256GA705 which enables interrupt device priorities to be set, e.g. the I2C priority could be set higher than the timer eanbling the I2C functions to be called from a timer interrupt service routine
certainly do not call console IO functions such as Serial.println from interrupt service routines
What are you doing to debounce the input signal?
Also, it would be simpler to save the time in unix time format, then do the conversion to human readable date/time outside the interrupt.
I have removed the Serial.println from the interrupt and just have it toggling a variable and the same problem is occurring (triggering on RISING and FALLING of voltage)
I have tried the code in last minute engineers tutorial but still have the same problem.
could you be getting some switch bounce from the relay so even on a falling edge you get bounce which triggers rising edge interrupt?
if you do a web search removing switch bounce you will get plenty of links
First is the multiple interrupts likely do to "bounce" from the relay. Do you have a scope to look at the signal? Because of the interrupt context, you can only use a lockout period for software debounce. Hardware debounce can open up additional possibilities.
Second, you have the issue of the HTTP post blocking the recording of a time stamp without the interrupt. As has been previously suggested, using a unix format time stamp will simplify things.
I would not get the time stamp from an rtc, but rather use a time library which is periodically synched to an rtc or ntp call for accuracy. You can eliminate the i2c call and rtc reading from the interrupt.
Finally, you might wish to explore the using of the dual cores of the ESP 32 to split the time stamp logging from the HTTP sending. I don't know if this is actually possible, using the Arduino core, or how you would do it.
You can't be the first person to run into issues with real time tasks blocked by the HTTP. Certainly if the HTTP task can be stopped and restarted by an interrupt you can likely manage this with other techniques. There must be "non blocking" methods to send out small pieces.
ZebH:
I need it to:
Get the current time and date
Enqueue the time and date
I would recommend installing the 'Time' library by Michael Margolis. Then set your RTC as the time source so the Time library will synchronize with it periodically. Between synchronizations, it uses the system clock to keep track of time. That way you can get the current time in your ISR without trying to read it from the RTC. You can also get the time in the form of a single unsigned long value. You can easily make a queue for the timestamps. Your loop() function can take timestamps out of the queue, convert them to text, and send them out.