Raspberry Pi 400, SparkFun pHAT extension, Qwiic cable, and SparkFun 20x4 SerLCD not working

Hi,

I am trying to create a digital clock using a Raspberry Pi 400, SparkFun pHat extension (https://www.sparkfun.com/products/17512), an Adafruit JST SH 4-Pin Qwiic compatible cable (10cm), and SparkFun 20x4 SerLCD (https://www.sparkfun.com/products/16398).

The SerLCD is directly connected via the Qwiic cable to the pHAT extension. And the pHAT extension is plugged into the Raspberry Pi 400. There are no other cables or extensions between the components.

I2C is enabled on my system, and I can see the SerLCD with

$ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- 72 -- -- -- -- --

But writing to SerLCD fails after a few seconds/writes with:

OSError: [Errno 121] Remote I/O error

I tried different libraries (including your Qwiic Raspberry Pi Python library), but I always get this error.

Similar code runs fine on my Raspberry Pi Pico. Also, other I2C devices work like Sense HAT 1.0 mounted on the Qwiic pHAT.

Also, I connected the SerLCD with short jumper cables directly to the GPIO pins 2,3, GND and +3.3V without any luck.

The only way to make it work was using software I2C by adding

dtoverlay=i2c-gpio,bus=3,i2c_gpio_sda=5,i2c_gpio_scl=6

to /boot/config.txt

And using the GPIO pins 5 and 6. Then it works flawless.

This is the shortest piece of code that always fails with the Qwiic connection:

import smbus
i2c = smbus.SMBus(1)

i2c.write_byte(114, 0x7C)
i2c.write_byte(114, 0x2D)
i2c.write_byte(114, 0x7C)
i2c.write_byte(114, 0x18)
i2c.write_byte(114, 150)

The code fails randomly on the second, third, or fourth write.

Is there a way to make the SerLCD work using the Qwiic connectors?

System details:

SerLCD 20x4:

OpenLCD 1.4

Raspberry Pi 400:

Linux raspberrypi 5.10.17-v7l+ #1403 SMP Mon Feb 22 11:33:35 GMT 2021 armv7l GNU/Linux

config.txt:

dtparam=i2c_arm=on

dtparam=spi=on

software I2C bus

dtoverlay=i2c-gpio,bus=3,i2c_gpio_sda=5,i2c_gpio_scl=6

Thank you very much and best regards,

Josef

Thanks for reaching out to us on this.

The fact that they work with the Pi Pico lets us know that problem is likely some setting in the Pi 400 - please go through the entire hookup guide here https://learn.sparkfun.com/tutorials/qw … okup-guide (there is a section about enabling i2c on boot)

After that, if you still have issues it might be a good idea to try manually changing the i2c address(es)

Hope this helps, and happy sparking!

Thank you for your quick reply.

Yes, I did follow the hookup guide at https://learn.sparkfun.com/tutorials/qw … okup-guide:

  • Enabled i2c through raspi-config
  • Rebooted
  • Checked that dev files are there:
    $ ls /dev/*i2c*
    /dev/i2c-1  /dev/i2c-3
    
  • Installed i2c-tools
  • Checked if SerLCD is there:
    $ i2cdetect -y 1
         0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
    00:          -- -- -- -- -- -- -- -- -- -- -- -- --
    10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    70: -- -- 72 -- -- -- -- --
    

    Still does not work on I2C bus 1 (pins 2 + 3 or Qwiic cable).

    So, as suggested I changed the I2C address. Used the software I2C bus 3 just to be sure that nothing goes wrong while changing the address:

    import smbus
    i2c = smbus.SMBus(3)
    i2c.write_byte(114, 0x7C)
    i2c.write_byte(114, 0x2D)
    i2c.write_byte(114, 0x7C)
    i2c.write_byte(114, 0x19)
    i2c.write_byte(114, 0x50)
    

    Change is successful:

    $ i2cdetect -y 3
         0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
    00:          -- -- -- -- -- -- -- -- -- -- -- -- --
    10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    50: 50 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    70: -- -- -- -- -- -- -- --
    

    Code works fine with software I2C bus 3 (pins 5+6).

    Connecting it again via Qwiic cable (hardware I2C bus 1):

    $ i2cdetect -y 1
         0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
    00:          -- -- -- -- -- -- -- -- -- -- -- -- --
    10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    50: 50 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    70: -- -- -- -- -- -- -- --
    

    Again error 121 after a few writes:

    Traceback (most recent call last):
      File "/home/pi/Projects/mu_code/clock_lcd_pi.py", line 14, in <module>
        i2c.write_byte(0x50, 0x2D)
    OSError: [Errno 121] Remote I/O error
    
  • Just to clarify, other I2C devices do work on the Qwiic connector. I hooked up a SSD 1306 OLED display, and it works fine. But the SerLCD does not.

    Please see the attached picture:

    Can you confirm what baud rate is being used? SerLCD prefers 9600

    Sure, the baud rate is 9600.

    Okay, I used the weekend to run some additional tests:

    Raspberry Pi Pico with MicroPython 1.14:

    Works stable without any sleeps.

    Raspberry Pi Pico with CircuitPython 6.2.0:

    Needs additional sleeps (50ms) after commands/writes to run stable.

    Raspberry Pi 400 with Python 3.7.3 (Hardware I2C - SMBus, SMBus2, busio, Qwiic Python library,
    Sparkfun_CircuitPython_SerLCD)

    Does not work even with excessive sleeps after each command/write. Seems to work fine at first, but crashes within one minute.

    Raspberry Pi 400 with Python 3.7.3 (Software I2C - SMBus, SMBus2)

    Works fine without any sleeps.

    Any updates on this issue? I tested multiple I2C devices (HD44780 1602 LCD with PCF8574 expander, SSD1306 128x32 OLED, SSD1306 128x64 OLED), and they all work fine.

    So, is your SerLCD supposed to work with a Pi 400?

    It’s never been tested on the Pi400 as far as I can tell. It could be a software problem or possibly an issue with I2C on the Pi400 that causes the display to not work.

    You might try switching to TTL serial rather than Qwiic, that shouldn’t have any issues with the Pi400.

    Thank you for confirming that the combination is untested.

    Sure, I can make it work using SPI or TTL serial, but it is a bit disappointing that the QWIIC connection is not working.

    I did some tests with my oscilloscope, and I think this is the infamous clock stretching bug of the BCM2835/36/37 (https://www.advamation.com/knowhow/rasp … c-bug.html). Like in the pictures on the webpage, I see a clock pulse that is just a tiny spike after sending the device’s address (0x50) and before sending the data byte (0x2D). And this is the exact moment where the code fails.

    Okay, I managed to create a screen shot of the failing I2C write:

    The pink line is SCL, yellow is SDA. In this shot you can see a short yellow peak right after the acknowledge. Not sure if this is an additional issue or not. More serious is the missing clock signal after the ack. The oscilloskope was not able to decode the second byte, too.

    It sounds like there may be some incompatibility between the Pi400 and our SerLCD Python library. You might want to [file an issue in the libraries Git repo so that the author can take a look and see if there’s some sort of workaround that can be implemented.](Issues · sparkfun/Qwiic_SerLCD_Py · GitHub)

    Thank you for the suggestion, but this will not help. I can reproduce the issue also in C using the SMBus or BCM2835 low level APIs. The only way to work around this issue would be to improve the speed of the AVR on the SerLCD. If it fast enough and does not need to strech the clock then it should work fine with all APIs and libraries on the Pi. Not sure if this is possible, so I would add this issue to the troubleshoot section of the SerLCD documentation (https://learn.sparkfun.com/tutorials/av … leshooting).