0
\$\begingroup\$

I have a ST7567S 128 x 64 LCD display connected via I2C to an Adafruit Feather M0. After a random amount of time (seconds to minutes), the processor gets stuck in the sendBuffer() routine. Then, if I unplug the module, the controller resumes like nothing had happend. It seems to wait for some response from the display that never comes. This happens also with another display (same type) and another microcontroller (Arduino Nano). After a lot of investigation with the help of the guy who wrote the I2C library (discussion is here: https://github.com/olikraus/u8g2/issues/2182) I found out it is an issue with the I2C bus.

The master transmits lots of data to the slave, everything is fine. But then, a transmitted byte gets pre-maturely acknowledged by the slave with the 8th clock, but it should be with the 9th clock.

Then, there is no more clock cycle and the clock line remains high. The data line is driven low by the display (slave). The levels of data and clock line remain in their last state forever. The problem is, the microcontroller waits forever for a proper acknowledge and no program is executed any more.

So here is my in-depth-analysis of everything:

Scope Setup:

  • Ch1: SDA, 0.5V/div, offset 0 div
  • Ch2: SCL, 1V/div, offset -3 div

Complete transmission, time scale 50µs/div: Complete transmission, time scale 50µs/div Address, command, then 20 successful data bytes, then one more which is acknowledged prematurely. Clock stops and data line remains low. Acknowlege level from the display is 0.6V, low level from the microcontroller is 0.0V.

Detail: Start of transmission, time scale 5µs/div: Detail: Start of transmission, time scale 5µs/div

  • First byte: 01111110:
    • address = 0x3F
    • RW = 0
  • Second byte: 01000000:
    • Co = 0 → Last control byte. Only a stream of data bytes is allowed to follow. This stream may only be terminated by a STOP or RE-START condition.
    • A0 = 1 → display data bytes will be stored
  • Third byte and following are data bytes.

Detail: Last, unsuccessful byte, time scale 2µs/div: Transmitted byte gets pre-maturely acknowledged with the 8th clock, but it should be with the 9th clock. Then, there is no more clock cycle and the clock line remains high. The data line is driven low by the display (slave). The levels of data and clock line remain in their last state forever: Detail: Last, unsuccessful byte, time scale 2µs/div

So I am wondering why this is happening? And what can I do to stop this problem from happening.

EDIT: Most posts hint at the less-than-optimal waveforms. An analysis of the board attached to the LCD revealed a lot of protection curcuitry that gets in the way: There is 470 Ohm series resistor, which I already replaced with a 100 Ohm. Both I replaced with a direct jumper wire. Additionally, there is a Zener to ground (hence the series resistor), clamping voltage levels at 2.2V. This I also removed. The 3.3V-LDO I already shorted for the above measurements. Here is my reverse-engineered circuit diagram, modifications are in green: LCD schematic

The LCD is this one on Aliexpress. The display's controller datasheet is on buydisplay.com

With those modifications it seems to work! It's running now for an hour. Thank you everybody for your valuable hints!

\$\endgroup\$
8
  • 3
    \$\begingroup\$ Please provide schematics and links data sheets of the chips involved. Frankly, those bus waveforms look terrible and no wonder there is problems. Schematics won't tell with what kind of cabling and how long the cabling is between devices, so please add any relevant info. Also why is the signal about 4.2V? Why isn't it 5V or 3.3V? \$\endgroup\$
    – Justme
    May 31 at 21:22
  • 3
    \$\begingroup\$ What’s the value of the pull-up? Are there any pull-ups in either if the devices? Are the values of the interface mode configuration pins stable? Does the fault always happen after a specific data exchange, at a specific point, or is it random? Are there any other devices in the I2C bus? \$\endgroup\$
    – jcaron
    May 31 at 21:56
  • \$\begingroup\$ @Justme: You are right, I made a mistake when reporting the scaling: It is not 1V/div for Ch1 and 2V/div for Ch2 but 0.5V/div for Ch1 and 1V/div for Ch2. \$\endgroup\$
    – Heideachim
    Jun 1 at 7:13
  • 1
    \$\begingroup\$ Looking at your circuit diagram, it seems you've removed both 5.1k pull-up resistors (they're crossed out). If that's the case, you need to replace them. \$\endgroup\$
    – Velvet
    Jun 1 at 10:26
  • 1
    \$\begingroup\$ I find it weird that you had to modify the screen’s controller board to make it work, but good thing they it does. It may be interesting for you to show what it looks like on the scope now. \$\endgroup\$
    – jcaron
    Jun 1 at 21:13

1 Answer 1

1
\$\begingroup\$

Without an annotated schematic I will take a SWAG as I have seen this before. What value of pull up resistors did you use? The waveform indicates to me they are too weak, delaying the logic 1. Look at the slower rise times vs the fall times. This can also be caused by excess capacitance on the I2C wiring because of long wires, etc. Try something around 3 kΩ.

\$\endgroup\$
1
  • \$\begingroup\$ They might also be too strong if the chips can't pull the wire very low. The voltage can be incorrect as it's higher than display controller accepts. Wiring can be incorrect due to crosstalk and ringing, although ringing can be due to poor probing technique too. \$\endgroup\$
    – Justme
    May 31 at 22:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.