LCD over I2C not working with Timer2

Hi,
I connected the LCD HD44780 (16x2) module over I2C module to Uno.
Then I configured Timer2 to count and to see it on LCD.
But when I enable interrupt TIMSK2 |= (1 << TOIE2); LCD does not works but Timer2 working.
And when disable interrupt TIMSK2 |= (1 << TOIE2); LCD working and Timer2 not works.
Why enabling interrupt Timer2 stops LCD? How to fix it?

#include <LiquidCrystal_I2C.h>

#define ledPin 13
LiquidCrystal_I2C lcd(0x3C,16,2); //A0 and A1 are shorted
int i;
void setup()
{
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);

  // initialize timer2 
  noInterrupts();           // disable all interrupts
  TCCR2A = 0;
  TCCR2B = 0;
  TCNT2 = 255;
  TCCR2B |= (1 << CS22, 1 << CS21, 1 << CS20);    // 1024 prescaler 
  //TIMSK2 |= (1 << TOIE2);   // enable timer overflow interrupt
  interrupts();             // enable all interrupts

  lcd.init(); // Initializing LCD  
  lcd.begin(16, 2);
  lcd.backlight(); //lcd backlight on
}

ISR(TIMER2_OVF_vect)        // interrupt service routine that wraps a user defined function supplied by attachInterrupt
{
  i++;
  if(i>=100)
  {
    digitalWrite(ledPin, digitalRead(ledPin) ^ 1); 
    i=0;
  }
  Serial.println(i);
}

void loop()
{
  lcd.setCursor(1, 0);
  lcd.print(i);
}

There are some things you cannot do within an interrupt service routine (ISR) and Serial.print() is one of them.

In general your ISR should do as little as possible, such as setting or clearing a flag, and it should then return control to the main program. The main program should be set up to periodically check the flag and decide what to do.

Don

floresta:
There are some things you cannot do within an interrupt service routine (ISR) and Serial.print() is one of them.

In general your ISR should do as little as possible, such as setting or clearing a flag, and it should then return control to the main program. The main program should be set up to periodically check the flag and decide what to do.

Actually for a while now there is code in HardwareSerial write() code that will revert back to polling the UART if it is called from ISR to allow printing from an ISR.

I'm assuming that since the OP didn't mention that the serial output is not working that serial output is working.

Deep_Sky,

I haven't done the math to see how often the ISR is called,
but if the ISR is triggered faster than the output time for the characters that are being printed.
The ISR prints 2 characters most of the time, so at 9600 baud if the ISR is called more than every 2ms there will be issues as the code will be continually calling the ISR with virtually no time for anything else.

But the main problem here looks like the variable being printed on the LCD "i" in this case, was not declared as volatile.

So more than likely LCD output is working but the value of i showing up on the LCD is not changing since the optimizer is calling lcd.write(i) with the same value over and over again instead of the actual value of i stored in memory.

You could see this if you declared another variable that you printed that you incremented in loop() instead of the ISR.
That variable would increment, but the value if i would not.

Change the declaration of i to include volatile and the "problem" with printing i should go away.

However, the next issue will likely be that the LCD isn't properly showing the value of i when it is less than 10 which is because the code in loop() doesn't clear out the character positions before it prints the value so when i wraps around back to a single digit, there will be left over '9' to the right of the single digit.
Just keep that in mind.

--- bill

bperrybap,

Yes, loop() does not return any variable from ISR. But even a lcd.print("Hello"); does not works when interrupt is enable.
I need this timer function to not use delay() and millis(). Purpose using the Timer2 is, modify the Timer2 frequency, complete the processes in it and return results to loop() to do further works and display on LCD.

You toggle the LED every 100 times into the ISR but you are printing 4 characters to the serial port at 9600 baud every single ISR.
You can not do what you are trying to do in your ISR because it takes too long.

You are generating interrupts every 10 to 20 us and in the ISR you are trying to print characters that takes longer than the time between interrupts. At 9600 baud to print 4 characters, which is what are doing most of the time as you print two digits and then CR and then LF, takes around 4ms.
That won't work as nothing else gets any time to run. The code will exit the ISR and immediately get pulled back in because the ISR code spent more time trying to output serial characters than the amount of time until the next interrupt.

So you have both problems, no volatile declaration on the i variable and you are taking WAY too long in your ISR.

You can get it work with the Serial printing if you move the Serial.println() inside the if that only happens every 100 ISR events where you toggle the LED.

--- bill