Using I2C display and Pin interrupt crashes arduino

I have a Rotary Encoder and a I2C LCD 16x2 display.
The Rotary Encoder is using an LS7184 IC to output a pusle and direction signal.

It works for the most time but after about 10 - 20 secs it crashes.

here is the very basic code

#include <LiquidCrystal_I2C.h>
#include <PinChangeInt.h>
#include <Wire.h> 

#define ConfigStat    A15                                        // rotary encoder direction
#define Enc01C        A14                                       // rotary encoder pulses

LiquidCrystal_I2C lcd1(0x27, 16, 2);  

int RotaryEncoder01 = 0;

void Enc01Cint()                                                          // interrupt handler for falling edge on clock from LS7184
{
  if (analogRead(ConfigStat) > 720)                         // resistors determine this as a forward/reverse direction
    RotaryEncoder01++;
  else
    RotaryEncoder01--;
}
void setup()
{
  digitalWrite(Enc01C, HIGH);                                                         // setup the pulse sense pin
  PCintPort::attachInterrupt(Enc01C, &Enc01Cint, FALLING);   // set the interrupt handler
  digitalWrite(ConfigStat, HIGH);                                                  // rotary encoder direction

  lcd1.init();
  lcd1.begin(16, 2);
  lcd1.display(); 
  lcd1.backlight();
  lcd1.home();
  lcd1.print("RotEnc+LCD test");
  lcd1.setCursor(0, 1);
  lcd1.print("                ");
}

void loop()
{
  lcd1.setCursor(0, 1);
  lcd1.print(RotaryEncoder01);
}

Has anyone else experienced this? Is it something to do with the library I am using because it sure seems like a memory conflict or leak of some kind

Baz

Not sure, but I have a nasty suspicion "analogRead" is not the sort of thing you should use in an interrupt routine.

Of course, unless the rotary encoder is going very fast (more than a thousand impulses per second), I would not favour the use of interrupts anyway.

Just as an FYI, you need to be careful when using globals in ISRs and foreground. (You have not declared the variable as volatile) In this case, you can get away with it since there are function calls in loop() that forcing the compiler to re-fetch the variable. If you were to spin on it without a function call, the code would break without the variable being declared as volatile.

In terms of the problem, "crashes" is a pretty nebulous term. I'm assuming that the LCD stop updating and not something like the board resets and starts over? Please describe what you mean by "crashes".

It could be that something gets hung up in the Wire library from the interrupts as quite a bit of the I2C protocol is handled in s/w. I'd try replacing the LCD output with output to the Serial port using a high baud rate and see if the problem still exists to try to narrow it down.

You could also try strobing pins high then low in the ISR and loop() to see if the code is still running.

If you have a logic analyzer or logic probe you could look at the pins and see and see if the code is still running and taking interrupts or running in loop().

--- bill

The ‘crashes’ occur in the main loop. Its as though something gets stuck in a permanent ‘while’.
The interrupts are still functioning as per normal (I am flashing the LED in the interrupt handler).

The rotary encoder is just a hand turn panel knob so nothing high speed.

here is the new code.

#include <LiquidCrystal_I2C.h>
#include <PinChangeInt.h>
#include <Wire.h> 

#define ConfigStat    A15      // rotary encoder direction and button > 670 < 1000 cw dir, > 500 < 800 ccw, > 600 button, < 1000 not connected
#define Enc01C        A14                                       // rotary encoder pulses

LiquidCrystal_I2C lcd1(0x27, 16, 2);  // set the LCD address to 0x20 for a 16 chars and 2 line display

volatile byte RotaryEncoder01 = 0;
byte aaaa = 0;
byte flash = 0;
int led = 13;

void Enc01Cint()                // interrupt handler
{
  if (!flash)
    digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  else
    digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  flash ^= 1;
  if (analogRead(ConfigStat) > 720)
    RotaryEncoder01++;
  else
    RotaryEncoder01--;
}
void setup()
{
  pinMode(led, OUTPUT);     
  digitalWrite(Enc01C, HIGH);
  PCintPort::attachInterrupt(Enc01C, &Enc01Cint, RISING);
  digitalWrite(ConfigStat, HIGH);                                       // rotary encoder direction and button

  lcd1.init();
  lcd1.begin(16, 2);
  lcd1.display(); 
  lcd1.backlight();
  lcd1.home();
  lcd1.print("RotEnc+LCD test");
  lcd1.setCursor(0, 1);
  lcd1.print("                ");
}

void loop()
{
  lcd1.setCursor(0, 1);
  lcd1.print(RotaryEncoder01);
}

The faster i turn the knob the quicker the fault occurs.

I think there is something amiss in the Wire library .

If I can’t get it resolved I may have to write code in the interrupt handler to detect loss of looping but that is only as a last resort.

Baz

Try disabling the interrupts when you call the LCD call, add a bit of a delay to slow things down in the loop.

Bazinoz: The faster i turn the knob the quicker the fault occurs.

Does it occur if you don't turn the knob?

fungus:

Bazinoz: The faster i turn the knob the quicker the fault occurs.

Does it occur if you don't turn the knob?

no.

also ...

Grumpy_Mike: Try disabling the interrupts when you call the LCD call, add a bit of a delay to slow things down in the loop.

I had already tried that as well.

.... but I have solved the problem.

Interestingly enough I was trying the sketch on a multitude of Arduino Mega 2560's and they all had the problem. So I tried it on a Ethermega and it worked perfectly! Went back to an Arduino Mega 2560 and crash, boom bang! Same board, different format so what gives? I determined it must have had something to do with the Analog input I was using and stopped blaming the code. Then I placed a 0.01uF capacitor across the Rotary Encoders clock and voila! slowed down the clock edge enough to not do whatever it was doing. Now I am going back to the original BIG sketch and repatch it in and see whats happening; fingers crossed.

Thanks for the help guys.

What did you find out about this in the end? I am having the exact problem I believe. I am using an mpu6050 with an interrupt and an i2c lcd. My loop stops at random places and it is driving me crazy. The loop never dies if I send my output to the serial port.

as I mentioned above I placed a 0.01uF capacitor across the interrupting pin and it has been perfect ever since.

Bazinoz: as I mentioned above I placed a 0.01uF capacitor across the interrupting pin and it has been perfect ever since.

That really isn't an answer as to what the problem is. The problem just happened to stopped occurring. Those types of "solutions" are not a true solution and are truly scary since you have no idea what it was or why it stopped. It also means it could potentially come back again.

--- bill