T3.5 LCD and RTC on I2C - lock up

Status
Not open for further replies.

MogaRaghu

Well-known member
The code below locks up when the RTC module is plugged in ...but boots with no issues and displays the Home Screen when the RTC is pulled out. But then then there is no valid time display. But if after booting i insert the RTC module the code runs fine and time is valid.. so what i am doing wrong ? This is on a Teensy3.5.
( Some functions not shown to keep the code small )

Code:
// The LCD is a 4L x 20Char type with a I2C backpack.
// Both the LCD and the RTC are connected to the SCL0 and SDA0 lines of Teensy3.5
// thorugh a 3.3V to 5V level shifter.

#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#define DS3231_I2C_ADDRESS 0x68             // 0x68 is the RTC address

// DEFINE LCD PINS AND INSTANTIATE
LiquidCrystal_I2C  lcd(0x27, 2, 1, 0, 4, 5, 6, 7);          // 0x27 is the I2C bus address

void setup()
{
  // START SERIAL FOR DEBUGGING

  SerialPort.begin(9600);

  // START THE I2C INTERFACE

  Wire.begin();
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0xE);                            // Address the Control Register
  Wire.write(0x00);                           // Write 0x0 to control Register
  Wire.endTransmission();
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0xF);                            // Address the Status register
  Wire.write(0x00);                           // Write 0x0 to Status Register
  Wire.endTransmission();

  // START THE LCD INTERFACE
  lcd.begin(20, 4);
  lcd.setBacklightPin(3, POSITIVE);
  lcd.setBacklight(HIGH);
  lcd.clear();
  lcd.print(F( "   WELCOME TO MAKS. "));
  lcd.print(F( "   Version : MK2.0  "));

}

void loop ()
{
  ReadTime();
  if ( second != prevSecond )
  {
    prevSecond = second;
    printLCD_RF( "MAK TPM MANAGEMENT.", 0);
    sprintf(clockStringNow, "   %02d-%02d %02d:%02d:%02d   ", dayOfMonth, month, hour, minute, second);
    printLCD_RF("                    ", 1);
    printLCD_RF("                    ", 2);
    printLCD_RF(clockStringNow, 3);
  }
}
 
Do you have 2 pull-up resistors installed, between each of the i2c pins (i.e. one resistor between pin 18 and 3.3v and another between pin 19 and 3.3v)? The RTC may have pull-up resistors on its board, so if you plug it in, the i2c bus would work normally. But if it is unplugged, then the i2c stuff typically hangs.

Note, the 3.5 has an internal RTC, so if you keep it powered with a 3v coin cell battery, you don't need the external RTC. Note however, the RTC does not have a temp. sensor so it might vary somewhat if the Teensy is exposed to extreme temps. If that is the case, you might want to use a DS3231 RTC any way:

Or add a GPS receiver to make sure you have accurate time.
 
The code below locks up when the RTC module is plugged in ...but boots with no issues and displays the Home Screen when the RTC is pulled out. But then then there is no valid time display. But if after booting i insert the RTC module the code runs fine and time is valid.. so what i am doing wrong ? This is on a Teensy3.5.

Things to try:
1) Try putting a delay on the startup code prior to the Wire commands. If RTC holds SDA/SCL low during powerup it could hang the Wire commands (I'm not sure how default Wire lib handles bus busy condition).
2) Reorder the LCD commands so they occur first in init. If they are blocked it implies RTC is holding one of the SDA/SCL lines low.
3) Check SDA/SCL voltages on scope (or logic analyzer) during startup. Since it is transient a DMM probably won't give anything useful. Set a GPIO signal high in setup so you know when Wire commands occur during startup.
 
Thanks for the responses.

Just after I posted I read the warning about the pull ups... that could be the problem. Let me try it and post back. So the new PCB needs a surgery ...sigh!!

I did try shifting the RTC init code AFTER the LCD Init. Did not help - at times it fires up and most times its dead.
 
Well the two resistors ( 5K Ohm) between SCL and SDA to 3.3V initially looked like they helped but then after I tried to Reset a few times the screen froze. Only removing the RTC module makes a reboot reliable any number of times.
Right now the RTC section INIT is after the LCD INIT.
So I guess I need to use the on-board RTC. But I am curious whats going wrong - this setup is working on a Mega 2560 the last two years.
 
You don't mention which RTC module. IIRC, there were some RTC modules in the past that were 5v only (the Mega 2560 is 5v).

Similarly, are you passing 3.3v to the RTC or 5v? Even if the RTC works with both 3.3v and 5v, I would imagine it works better on a Teensy with 3.3v than 5v. If you had a Teensy LC or 3.6, powering the RTC with 5v might be a way to kill your Teensy. The 3.5 is 5v tolerant, but I might suspect that i2c doesn't work too well when the device/host are at different voltages, and you don't use an explicit level shifter to convert the voltages.

As nox771 says, many devices need a longer timeout on Teensy, due to the faster processor speed.

Given the prices of the RTC ($4.50 for USA shipping), it may make sense to buy a new DS3231 RTC off of ebay/amazon/etc. I've had some RTC's that were just flakey.

I imagine it isn't an issue, but i2c has several bus speeds, but I believe both Wire.h and t3_i2c.h default to the lowest bus speeds. If you explicitly choose a higher speed, some things won't work.

IIRC, i2c prefers smaller wires. If you are using long wires, it might be causing electrical interference, that might be more of a factor at 3.3v than 5v.

Finally, assuming you are using a coin cell battery to keep the time in the RTC, have you changed batteries? Maybe the battery is flakey.
 
Last edited:
You don't mention which RTC module. IIRC, there were some RTC modules in the past that were 5v only (the Mega 2560 is 5v).

Similarly, are you passing 3.3v to the RTC or 5v? Even if the RTC works with both 3.3v and 5v, I would imagine it works better on a Teensy with 3.3v than 5v. If you had a Teensy LC or 3.6, powering the RTC with 5v might be a way to kill your Teensy. The 3.5 is 5v tolerant, but I might suspect that i2c doesn't work too well when the device/host are at different voltages, and you don't use an explicit level shifter to convert the voltages.

As nox771 says, many devices need a longer timeout on Teensy, due to the faster processor speed.

Given the prices of the RTC ($4.50 for USA shipping), it may make sense to buy a new DS3231 RTC off of ebay/amazon/etc. I've had some RTC's that were just flakey.

I imagine it isn't an issue, but i2c has several bus speeds, but I believe both Wire.h and t3_i2c.h default to the lowest bus speeds. If you explicitly choose a higher speed, some things won't work.

IIRC, i2c prefers smaller wires. If you are using long wires, it might be causing electrical interference, that might be more of a factor at 3.3v than 5v.

Finally, assuming you are using a coin cell battery to keep the time in the RTC, have you changed batteries? Maybe the battery is flakey.

1. The RTC module is a 5V type DS3231 with the Coin cell on its back. The module itself is functional as I just pulled it out of the Mega 2560 setup. It alongwith the LCD interface with the Teensy IIC via a active regular Level translator ( not the resistor type )

2. The module is wired to the Teensy PCB with a short length ( 40mm to be exact ) of cables that come with the 4 -way Relimate connector.

3. I have not chosen a higher speed for the IIC bus and left it default. Incidentally I simply don't want the blazing 120MHz speed of the Teensy. I am yet to come to grips with the implications of this kind of speed - like a loop() with no delay will run like crazy ? So most times I step down the speed via the IDE to 16MHz which is a known turf.
 
>> As nox771 says, many devices need a longer timeout on Teensy, due to the faster processor speed.

Not sure how to do this ... do I introduce delay like 5ms after every Read or Write function to the IIC bus ??
 
>> As nox771 says, many devices need a longer timeout on Teensy, due to the faster processor speed.

Not sure how to do this ... do I introduce delay like 5ms after every Read or Write function to the IIC bus ??

By delay, I meant in the startup function. Many devices have a small window where they are not functional after powering up. So, you need a delay during setup before you try to contact them. The AVR processors being slower, the RTC might be ready by the time the AVR finishes its processing, particularly for the AVR's that do an initial wait to see if they are being re-programmed. Sorry to be unclear.

In terms of waiting on the i2c bus for the appropriate amount of time between sending out signals, the Teensy takes care of this.
 
By delay, I meant in the startup function. Many devices have a small window where they are not functional after powering up. So, you need a delay during setup before you try to contact them. The AVR processors being slower, the RTC might be ready by the time the AVR finishes its processing, particularly for the AVR's that do an initial wait to see if they are being re-programmed. Sorry to be unclear.

In terms of waiting on the i2c bus for the appropriate amount of time between sending out signals, the Teensy takes care of this.

Oh...ok got it. Will implement and check if it resolves the lock up after Reset. Thanks.
 
If I were to try reproducing this problem, which LCD and RTC modules should I buy?

And where should I download LiquidCrystal_I2C to get exactly the same copy you're using?
 
If I were to try reproducing this problem, which LCD and RTC modules should I buy?

And where should I download LiquidCrystal_I2C to get exactly the same copy you're using?

The LCD with IIC Interface here : https://www.ebay.in/itm/Serial-2004...686775?hash=item2835770e77:g:SOMAAOSw3utY6JDi

The RTC Module like here : https://www.ebay.in/itm/DS3231-AT24...856309?hash=item3d49f5e335:g:cUEAAOSwGepZzKnm

As to the liquid crystal library I am using the <LiquidCrystal_I2C.h> . I am attaching the whole folder as a zip file as it has many files in it.

I have tried all methods of delays at various points but still the I2C does not fire up reliably when I have both the RTC and LCD on line ( 4.7K pull up resistors also there ) And the same setup with a ATMega2560 is working reliably.
 

Attachments

  • LiquidCrystal.zip
    458.3 KB · Views: 232
As to the liquid crystal library I am using the <LiquidCrystal_I2C.h> . I am attaching the whole folder as a zip file as it has many files in it.

I installed this library, but I still can not compile your program. I get many errors, like this one:

Code:
sketch_dec08a: In function 'void setup()':
sketch_dec08a:16: error: 'SerialPort' was not declared in this scope
   SerialPort.begin(9600);
   ^

Obviously "SerialPort" is not defined anywhere in your code. Perhaps this is not actually the full program needed to reproduce the error?

Please copy the code you provided into Arduino and click Verify. Does it compile without any errors?
 
Hi Paul..... I am so sorry. Should have checked before posting. My bad. This is a small segment of the original code . Anyway now the one below compiles OK for T3.5.

Code:
// The LCD is a 4L x 20Char type with a I2C backpack.
// Both the LCD and the RTC are connected to the SCL0 and SDA0 lines of Teensy3.5
// thorugh a 3.3V to 5V level shifter.

#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#define DS3231_I2C_ADDRESS 0x68             // 0x68 is the RTC address

// DEFINE LCD PINS AND INSTANTIATE
LiquidCrystal_I2C  lcd(0x27, 2, 1, 0, 4, 5, 6, 7);          // 0x27 is the I2C bus address

byte second, minute, hour, dayOfWeek, dayOfMonth, month, year, prevSecond;

//######################################################

void setup()
{
  // START SERIAL FOR DEBUGGING

  Serial.begin(9600);

  // START THE I2C INTERFACE

  Wire.begin();
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0xE);                            // Address the Control Register
  Wire.write(0x00);                           // Write 0x0 to control Register
  Wire.endTransmission();
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0xF);                            // Address the Status register
  Wire.write(0x00);                           // Write 0x0 to Status Register
  Wire.endTransmission();

  // START THE LCD INTERFACE
  lcd.begin(20, 4);
  lcd.setBacklightPin(3, POSITIVE);
  lcd.setBacklight(HIGH);
  lcd.clear();
  lcd.print(F( "   WELCOME TO MAKS. "));
}

//#########################################

void loop ()
{
  ReadTime();
  if ( second != prevSecond )
  {
    char clockStringNow[21]; 
    prevSecond = second;
    lcd.print( "MAK TPM MANAGEMENT.");
    sprintf(clockStringNow, "   %02d-%02d %02d:%02d:%02d   ", dayOfMonth, month, hour, minute, second);
    lcd.setCursor(0,1); 
    lcd.print("                    ");
    lcd.setCursor(0,2);
    lcd.print("                    ");
    lcd.setCursor(0,3); 
    lcd.print(clockStringNow);
  }
}

//####################################

// READ THE RTC AND LOAD IN VARIABLES
void ReadTime()
{
  //Retrieve data from DS3231
  readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
}

//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// SET THE RTC REGISTERS FOR THE REQUIRED TIME.( Call in Setup the first time for setting ) 
void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year)
{
  // sets time and date data to DS3231
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set next input to start at the seconds register
  Wire.write(decToBcd(second)); // set seconds
  Wire.write(decToBcd(minute)); // set minutes
  Wire.write(decToBcd(hour)); // set hours
  Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
  Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
  Wire.write(decToBcd(month)); // set month
  Wire.write(decToBcd(year)); // set year (0 to 99)
  Wire.endTransmission();
}

//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// READ COMPLETE DATE AND TIME INFO FROM RTC.
void readDS3231time(byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month, byte *year)
{
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set DS3231 register pointer to 00h
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}

//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//CONVERT ROUTINES

byte bcdToDec(byte val)
{
  return ( (val / 16 * 10) + (val % 16) );
}

byte decToBcd(byte val)
{
  return ( (val / 10 * 16) + (val % 10) );
}
 
I had an old DS3231 (chronodot) laying around, CR1632 coin-cell had gone dead. I ran the sketch in post #16 (without LCD stuff), printing to monitor. DS3231 would hang on a a reprogram after printing bogus date-time 165-165 45:165:85 once. Meter shows SDA being held LOW. I had to cycle power to get it to run again.

I switched to i2c_t3.h, and after Wire.begin() did a Wire.resetBus(); , and the sketch would then run correctly even with reprogram ?

maybe not relevant ...

(of course, with dead battery, cycling power, resets the time to 0)
T3.2, 3v3 to DS3231, 2.2kohm pullups on SDA and SCL

https://www.adafruit.com/product/255

Related? http://forum.arduino.cc/index.php?topic=288573.0
 
Last edited:
Have you actually tested this exact code with the LCD and RTC?

Are you sure this exact code really does reproduce the problem?

Thanks Paul for your consistent follow up.

Since I did not have a 4 line LCD , just modified the code for a 2 line LCD and is given below. The problem as I notice :

When both the LCD and RTC are plugged in ,
A. applying power 10 times , results in the program starting up 4-5 times . Rest of the time the LCD does not initialize..
B. Pressing Reset at any time freezes the code ( even if the clock is showing the time )

When the RTC is pulled out , the LCD works, and the Reset works as they should.

And another point ... not sure if it means anything .. the start up is more reliable when powering from the T3.5 from a battery instead of the PC USB port

Code:
// The LCD is a 4L x 20Char type with a I2C backpack.
// Both the LCD and the RTC are connected to the SCL0 and SDA0 lines of Teensy3.5
// thorugh a 3.3V to 5V level shifter.

#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#define DS3231_I2C_ADDRESS 0x68             // 0x68 is the RTC address

// DEFINE LCD PINS AND INSTANTIATE
LiquidCrystal_I2C  lcd(0x3F, 2, 1, 0, 4, 5, 6, 7);          

byte second, minute, hour, dayOfWeek, dayOfMonth, month, year, prevSecond;

//######################################################

void setup()
{
  // START SERIAL FOR DEBUGGING

  Serial.begin(9600);

  // START THE I2C INTERFACE

  Wire.begin();
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0xE);                            // Address the Control Register
  Wire.write(0x00);                           // Write 0x0 to control Register
  Wire.endTransmission();
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0xF);                            // Address the Status register
  Wire.write(0x00);                           // Write 0x0 to Status Register
  Wire.endTransmission();

  // START THE LCD INTERFACE
  lcd.begin(16, 2);
  lcd.setBacklightPin(3, POSITIVE);
  lcd.setBacklight(HIGH);
  lcd.clear();
  lcd.print(F( " IIC CHECK OUT. "));
  delay(2000); 

  //setDS3231time(00,30,12,7,9,12,17);       // Uncomment, enter right date &time , download once. 
}

//#########################################

void loop ()
{
  ReadTime();
  if ( second != prevSecond )
  {
    char clockStringNow[17]; 
    prevSecond = second;
    lcd.setCursor(0,0); 
    lcd.print( "THE TIME NOW IS:");
    sprintf(clockStringNow, " %02d-%02d %02d:%02d:%02d", dayOfMonth, month, hour, minute, second);
    lcd.setCursor(0,1); 
    lcd.print(clockStringNow);
  }
}

//####################################

// READ THE RTC AND LOAD IN VARIABLES
void ReadTime()
{
  //Retrieve data from DS3231
  readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
}

//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// SET THE RTC REGISTERS FOR THE REQUIRED TIME.( Call in Setup the first time for setting ) 
void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year)
{
  // sets time and date data to DS3231
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set next input to start at the seconds register
  Wire.write(decToBcd(second)); // set seconds
  Wire.write(decToBcd(minute)); // set minutes
  Wire.write(decToBcd(hour)); // set hours
  Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
  Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
  Wire.write(decToBcd(month)); // set month
  Wire.write(decToBcd(year)); // set year (0 to 99)
  Wire.endTransmission();
}

//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// READ COMPLETE DATE AND TIME INFO FROM RTC.
void readDS3231time(byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month, byte *year)
{
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set DS3231 register pointer to 00h
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}

//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//CONVERT ROUTINES

byte bcdToDec(byte val)
{
  return ( (val / 16 * 10) + (val % 16) );
}

byte decToBcd(byte val)
{
  return ( (val / 10 * 16) + (val % 10) );
}
 

Attachments

  • FrozenState.jpg
    FrozenState.jpg
    122 KB · Views: 185
  • OK State.jpg
    OK State.jpg
    110.5 KB · Views: 179
Last edited:
I purchased the 4 line LCD because you said that was the display you were using.

Sorry about that. But OK... it also goes to confirm that the problem is across the spectrum of 2 Line or 4 line LCDs.

And since all of them use the HD44870 chipset, the code that I sent will work as is - except that the last 4 columns , and two bottom rows will be blank. And since we are checking the functionality per se, this should not be an issue.

But going past all these ( which are kind of manageable with the built in RTC which is what I am doing now ) what concerns me is the board freezing on a hardware reset. When all else fails that is the last resort on all MCUs and in this case that freezes a working code. ????
 
But going past all these ( which are kind of manageable with the built in RTC which is what I am doing now ) what concerns me is the board freezing on a hardware reset. When all else fails that is the last resort on all MCUs and in this case that freezes a working code. ????

Seeking clarification: in post #19 you said "When the RTC is pulled out , the LCD works, and the Reset works as they should.". But now are you saying even without the DS3231, the board freezes on a hardware reset?

By "hardware reset", do you just mean pushing the button on the T3.5? that button just does a re-program.

curiously, your 2nd photo in post #19 has the same bogus time I was getting in my tests in post #18 when the DS3231 hung. From the arduino.cc URL in #18, it is evident the DS3231 has issues holding the I2C lines. The i2c_t3 lib Wire.resetBus() seems to fix hangs on the DS3231, but that may no longer matter if you are no longer using the DS3231.
 
Seeking clarification: in post #19 you said "When the RTC is pulled out , the LCD works, and the Reset works as they should.". But now are you saying even without the DS3231, the board freezes on a hardware reset?

By "hardware reset", do you just mean pushing the button on the T3.5? that button just does a re-program.

curiously, your 2nd photo in post #19 has the same bogus time I was getting in my tests in post #18 when the DS3231 hung. From the arduino.cc URL in #18, it is evident the DS3231 has issues holding the I2C lines. The i2c_t3 lib Wire.resetBus() seems to fix hangs on the DS3231, but that may no longer matter if you are no longer using the DS3231.

- Yes. Even without the RTC plugged in, the code freezes on hardware Reset.
- Yes. The one on the board is NOT the Reset button. Its for Program download.
- Bogus time. Yes again because the RTC is lying on the table unconnected.
 
...
And another point ... not sure if it means anything .. the start up is more reliable when powering from the T3.5 from a battery instead of the PC USB port
Aren't i2c devices among those tend to power up slower than the Teensy? And warm start versus power on shows that up - maybe why the battery power version acts better.

Perhaps make setup() start like this with added delay()?
Code:
void setup()
{
  // START SERIAL FOR DEBUGGING

  Serial.begin(9600);
[B]  delay(1000); // Less delay may work - if this is the issue it should be time in excess ...[/B]
// ...
 
Status
Not open for further replies.
Back
Top