I am using Arduino mega with 4 interrupts to find the rotation speed of 4 motors . For this I have used INT2, INT3, INT4, INT5 and the code for the same is given below
struct Pulse {
uint32_t last_toggle;
uint32_t width;
bool stateHigh;
uint32_t get_width() {
noInterrupts();
uint32_t width_copy = width;
interrupts();
return width_copy;
}
};
Pulse ch1, ch2, ch3, ch4;
void pin_initialization() {
// Four engine configuration
pinMode(19, INPUT_PULLUP);
pinMode(18, INPUT_PULLUP);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
}
volatile uint32_t ovfCount = 0;
ISR(TIMER3_OVF_vect) {
ovfCount++;
}
void timer3_initialization() {
TCCR3A = 0x00;
TCNT3 = 0x1FF; // from datasheet
TIFR3 = _BV(TOV3);
TIMSK3 = _BV(TOIE3); // overflow enable
TCCR3B = B00000011; // 64 prescaling
}
void pulseWidthCalculator(Pulse *channel){
unsigned char sreg;
sreg = SREG;
cli();
uint16_t tcnt3 = TCNT3;
SREG = sreg;
uint32_t ovf_count = ovfCount;
if (bit_is_set(TIFR3, TOV3) && tcnt3 < 32768) {
ovf_count++;
}
uint32_t time = ovf_count << 16 | tcnt3;
if (!channel->stateHigh) { // first high
channel->stateHigh = true;
} else if ( channel->stateHigh) { // second High
channel->width = time - channel->last_toggle;
channel->stateHigh = false;
}
channel->last_toggle = time;
}
ISR(INT2_vect) {
pulseWidthCalculator(&ch1);
}
ISR(INT3_vect) {
pulseWidthCalculator(&ch2);
}
ISR(INT4_vect) {
pulseWidthCalculator(&ch3);
}
ISR(INT5_vect) {
pulseWidthCalculator(&ch4);
}
void externalInterrputInitialization() {
EIFR = _BV(INTF2) | _BV(INTF3) | _BV(INTF4) | _BV(INTF5);
EICRA = 0; EICRB = 0;
EICRA = B10100000;
EICRB = B00001010;
EIMSK = B00111100;
}
void setup() {
Serial.begin(115200);
pin_initialization();
delayMicroseconds(10);
externalInterrputInitialization();
delayMicroseconds(10);
timer3_initialization();
delayMicroseconds(10);
}
void loop() {
String a = String(15e6/ch1.get_width());
a += " ";
a += String(15e6/ch2.get_width());
a += " ";
a += String(15e6/ch3.get_width());
a += " ";
a += String(15e6/ch4.get_width());
Serial.println(a);
}
The issue I am facing is , whenever I give a signal to INT2, INT3 is also getting triggered, same with INT4, INT5 also getting triggered without signal .
What I am I missing here, ?
Should I make my channels ch1, ch2 , ch3, ch4 to volatile or not.? like
volatile Pulse ch1, ch2, ch3, ch4
- Any thing wrong with
OUTPUT_PULLUP
1 Answer 1
You have the right idea to atomically obtain a copy of the data that is updated by the interrupt:
unsigned char sreg;
sreg = SREG;
cli();
uint16_t tcnt3 = TCNT3;
SREG = sreg;
uint32_t ovf_count = ovfCount;
...but the last two lines should be swapped to keep the copying operation within the non-interrupt section:
unsigned char sreg;
sreg = SREG; // Save interrupt state.
cli(); // Disable interrupts.
uint16_t tcnt3 = TCNT3; // Atomic operations.
uint32_t ovf_count = ovfCount;
SREG = sreg; // Restore interrupt state.
Though I notice you are calling that code from within an interrupt service routine so interrupts should already be disabled unless you are intending to use nested interrupts.
The false interrupt could be caused by crosstalk between INT2 and INT3. You could confirm this by using an oscilloscope. Keep the signal wires separate to avoid crosstalk.
You could also try stronger external pull-ups such as 10K or 1K. The Arduino internal pull-ups are weaker at about 20-50K Ohms.
-
Thanks Tim , from oscilloscope I understood its an issue of INPUT_PULLUP, I will do external PULLUPs.Lawliet– Lawliet08/10/2021 07:06:04Commented Aug 10, 2021 at 7:06
-
used 1K resistor and its working. Is there any issue with using external pull-up along with INPUT_PULLUP.?Lawliet– Lawliet08/11/2021 10:01:54Commented Aug 11, 2021 at 10:01
volatile
is necessary to be sure changes made are observable between the ISR and non-ISR contexts. That said, it doesn't seem like it would completely account for what you're seeing. You should make themvolatile
an let us know what the behaviour in that case is though.volatile
in your code and remove the part where ask about doing that, to remove the distraction from the primary question.Serial
stream concatenates things for you as a matter of course. All of your assignments and appends toString a
are an inefficient and bug-prone alternative to a series ofprint
/println
calls.