Hello,
I have been facing a struggle trying to read PWM o/p data from 2 sensors using 2 pairs of RISING and FALLING edge interrupts with micros(). Basically I am using the interrupts as a higher temporal resolution proxy for pulseIn() which has given me less stable data (stability is important for my project). I have a board (Nano 33 IOT) that supports external HW interrupts on specific pins (2,3,10... I'm using 2 and 3) and can read PWM duty cycle data in microseconds perfectly fine for each pin in isolation but once I try connecting 2 pins at once and adding 2 other ISRs for the second pin I get unstable data read. I believe there is interference between the 2 ISRs. My objective is to be able to read the 2 o/p PWM waveforms' 'on' dutycycle in microseconds, as cleanly as possible. I'm using an AD2 to simulate the waveforms at 2KHz (max value in serial read is thus 500us).
Error/results: I get strange values that fluctuate all over the place, some values that spike over 500, and sometimes the values for both sensors read the same number which is obviously wrong.
I have tried the following (all of which I haven't gotten to work):
*Setting flags inside the ISRs; flag1 for rising, flag2 for falling (pin 1), and same for pin 2 and made a condition that when each pair is true (in other words when an entire pulse from ONE pin has been detected) I print the microsecond 'on' dutycycle value for that pin.
*Making the interrupts 'sequential', i.e.:
void RisingISR_1() {
//flag1a = true;
pTime1 = micros();
attachInterrupt(digitalPinToInterrupt(pin1),FallingISR_1,FALLING);
}
void FallingISR_1() {
dur_pin1 = micros() - pTime1;
attachInterrupt(digitalPinToInterrupt(pin2),RisingISR_2,RISING);
}
void RisingISR_2() {
pTime2 = micros();
attachInterrupt(digitalPinToInterrupt(pin2),FallingISR_2,FALLING);
}
void FallingISR_2() {
dur_pin2 = micros() - pTime2;
attachInterrupt(digitalPinToInterrupt(pin1),RisingISR_1,RISING);
}
such that the interrupts are 'allowed' to activate in order. I only declare the first interrupt ISR in setup to avoid the others being declared at the beginning and interfering. This hasn't worked
*Just declaring all of the interrupts separately and putting the rising edge ISR of the 2 pins in setup; the code looks like so:
void RisingISR_1() {
pTime1 = micros();
attachInterrupt(digitalPinToInterrupt(pin1),FallingISR_1,FALLING);
}
void FallingISR_1() { //ISR that emulates functionality of pulseIn()
dur_pin1 = micros() - pTime1;
attachInterrupt(digitalPinToInterrupt(pin1),RisingISR_1,RISING);
}
void RisingISR_2() {
pTime2 = micros();
attachInterrupt(digitalPinToInterrupt(pin2),FallingISR_2,FALLING);
}
void FallingISR_2() {
dur_pin2 = micros() - pTime2;
attachInterrupt(digitalPinToInterrupt(pin2),RisingISR_2,RISING);
}
*Other things including using delay in the ISRs to stop the rest of the code from executing, using detachInterrupt() to detach interrupts from the 'other' pin so that the same pin can be 'locked in' once rising edge has been detected, using attachInterrupt for all the other pins on one ISR, etc.
Can someone please help me debug this and/or give me any tips? It has been giving me hell. Thank you!!
p.s. Please dm me for questions, clarifications, etc. Here is the code (along with some variants commented out. I cannot attach sorry).
#include <stdio.h>
//Interrupt Specific Parameters
volatile unsigned long dur_pin1;
volatile unsigned long pTime1;
volatile unsigned long dur_pin2;
volatile unsigned long pTime2;
volatile bool flag1a = false;
volatile bool flag1b = false;
volatile bool flag2a = false;
volatile bool flag2b = false;
//Other Variables
int pin1 = 2; //Declare pin you will use. 2,3,10 work on Nano 33 IOT without register change
int pin2 = 3;
unsigned long FS_threshold = 500; //for threshold cap (not implemented)
void RisingISR_1() { //ISR that emulates functionality of pulseIn()
//flag1a = true;
//detachInterrupt(digitalPinToInterrupt(pin2));
pTime1 = micros();
attachInterrupt(digitalPinToInterrupt(pin1),FallingISR_1,FALLING);
}
void FallingISR_1() { //ISR that emulates functionality of pulseIn()
//flag1b = true;
dur_pin1 = micros() - pTime1;
attachInterrupt(digitalPinToInterrupt(pin1),RisingISR_1,RISING);
}
void RisingISR_2() { //ISR that emulates functionality of pulseIn()
//flag2a = true;
//detachInterrupt(digitalPinToInterrupt(pin1));
pTime2 = micros();
attachInterrupt(digitalPinToInterrupt(pin2),FallingISR_2,FALLING);
}
void FallingISR_2() { //ISR that emulates functionality of pulseIn()
//flag2b = true;
dur_pin2 = micros() - pTime2;
attachInterrupt(digitalPinToInterrupt(pin2),RisingISR_2,RISING);
}
void setup() {
pinMode(pin1, INPUT);
pinMode(pin2, INPUT);
Serial.begin(9600);
attachInterrupt(digitalPinToInterrupt(pin1),RisingISR_1,RISING);
//attachInterrupt(digitalPinToInterrupt(pin2),RisingISR_2,RISING);
//attachInterrupt(digitalPinToInterrupt(pin1),FallingISR_1,FALLING);
//attachInterrupt(digitalPinToInterrupt(pin2),FallingISR_2,FALLING);
}
void loop() {
//if (flag1a && flag1b) {
Serial.print(micros()); //Timestamp in microsecnods to be printed with each PWM 'on' measurement
//noInterrupts();
Serial.print(","); //for CSV
Serial.print(dur_pin1); //HE1 value
//flag1a = flag1b = false;
//interrupts();
//}
//if (flag2a && flag2b) {
//noInterrupts();
Serial.print(","); //for CSV
Serial.println(dur_pin2); //HE2 Value
//flag2a = flag2b = false;
//interrupts();
//}
}