Getting started with I2C on up4000

KrissNC
KrissNC New Member Posts: 31

Hello guys.

I have an I2C Display, I would like to write onto it from my up4000 (linux)
What should I use for that ? I can't seem to have mraa working (any help ? is mraa supported on up4000? )

I have been able to use sysfs IO, and a C program to detect rising edges on some HAT pin (437).

Now my only problem left is writing on an I2C peripheral. I think 3 and 5 are the right pins, I think this is I2C controller 2 on the up4000. But then not sure what to do now.

Will I2c work with 3.3 or 5v ?

SOS

Answers

  • Wilbert
    Wilbert New Member Posts: 168 ✭✭✭

    Hi Sir,

    I2C work with 3.3V.

    Best Regards,
    Wilbert Lee

  • garyw
    garyw New Member, Moderator, AAEON Posts: 82 admin
    edited February 2023

    @KrissNC
    The mraa is supported on up4000.
    There are a lot of sample for I2C display in Linux, especially RPi peripheral, the only different is i2c bus number.

  • KrissNC
    KrissNC New Member Posts: 31

    I can't have mraa working on my boards... what versions should I use ?

    Should I compile it from a github source ? is there a special kernel to have ? is the Hat driver necessary ? (pinctrl-upboard_1.0.1_all.deb) ?
    Should I go for mraa working first, then use mraa samples to have I2C work ?

  • KrissNC
    KrissNC New Member Posts: 31

    Ok another try...
    My project begins with 700x up4000 boards (7 hundreds), up to thousands (for a NATO army).
    My last problem is writing something on an i2c display.
    Mraa is not working atm.
    And i2cdetect doesn't detect anything but : the i2c display is probably 5v(2004LCD, classic i2c), since it works with an arduino, and the sda/scl pins are supposedly 3.3v on an up4000. Do I need a level shifter ?
    (should I plug VCC as pin 2 (5v) or pin 1 (3.3v))
    I don't think working with i2c is "that difficult" but I need someone who has done it to tell me what he did. Same for mraa, I can't have it working... (using

  • Wilbert
    Wilbert New Member Posts: 168 ✭✭✭

    Hi Sir,

    Due to purchased modules, you need to read the module specifications you purchased for detailed electrical characteristics.
    If you buy 5V I2C, you need to add level shift to convert the level, otherwise I2C cannot communicate normally. (Mainly because the module uses 5V, it may not be able to recognize 3.3V signals.)

    Although it is a very common module, there are many kinds of I2C adapters. I can't know the detailed specifications of the module you use.
    In this regard, you need to ask the module supplier for relevant information.
    If it is 3.3V I2C, you need to confirm the overall environment. It would be better if you have tools to help with measurement.

    Best Regards,
    Wilbert Lee.

  • garyw
    garyw New Member, Moderator, AAEON Posts: 82 admin

    @KrissNC
    if you want to use the new pinctrl driver(pinctrl-upboard_1.0.1_all.deb) in Linux, the mraa is not ready for new pinctrl driver, we'll share mraa for new pinctrl driver to you next week.

    The new pinctrl driver is mapping all up boards GPIOs into RPi GPIO number, like UP-BOARD's mapping and supported DKMS and native kernel, you don't need using our customization kernel (UP 5.4) when you use new pinctrl driver.

  • KrissNC
    KrissNC New Member Posts: 31

    @garyw I don't "want" to use pinctrl(I don't care, depending if my project needs it or not), I'm asking if it is mandatory or not. since it kinda has no documentation. My "Need" is I2C to work on a typical 2004 5v I2c screen, I wired an i2c level shifter, but i2cdetect doesn't detect anything on any i2c adatper from 0 to 7. Using or not this software or this one is not a question of wish but a question of "do I need it for my projet to work".
    I cant have I2C working and I'm stuck , I'm almost losing my job now, because I can't have that up4000 i2c to work. I'm simply asking what is needed to have i2c working on that up4000. a special kernel ? some kernel driver(pinctrl driver)/software ? mraa ? what can I do to "see" i2c work ? everything I tried failed. So from people who actually made some I2C work on up4000 I'm asking what they had to do. I don't want to be rude, but look at how many posts I made in the forum to have that i2c work. and I'm still stuck. I'm actually wiring my stiff on a rasberry PI to try validate the wiring (do I need pull up reistors ? I put 2 10k to +5v on sda and scl)

  • Wilbert
    Wilbert New Member Posts: 168 ✭✭✭

    Hi Kriss,

    I set up two sets of the same UP-4000 here, measured the signal with an oscilloscope, and confirmed that the I2C two groups have signal output, and the data of the EEPROM can be read normally.
    The test tool is the i2c-tool on the Internet, not a specially tool.
    On our mainboard, I2C already have pull-high resistor 2.2K ohm to 3.3V.
    OS : Ubuntu 22.04, Kernel 5.19.0-32.
    BIOS Version R1.1.
    Attach the oscilloscope diagram and test circuit.

    I need to make sure that I2C can be used normally. (our I2C is 7bit)
    Please connect the customer to logic anylizer or an oscilloscope, connect the I2C, and confirm whether the data/waveform change has been captured when command is input?
    I have encountered other customers who reported that our I2C has not been able to recognize their devices, and finally found that the customer did not add the last bit of R/W, resulting in the output command being unable to be recognized by the device, so it cannot be recognized.



    Best Regards,
    Wilbert Lee.

  • garyw
    garyw New Member, Moderator, AAEON Posts: 82 admin

    @KrissNC
    I2C is used native kernel driver, it's simple to make it work in ubuntu OS and kernel 5.0+,

    please detect your i2c device by i2c-tools, please use the command as following
    $sudo i2cdetect -y -r 1
    $sudo i2cdetect -y -r 2

    bus 2 is pin 3/5, bus 1 is pin 27/28, or try another I2C bus because the bus number is dynamic by different kernel version.

    you should see the I2C slave address detected, I cannected 0x48 device as below screenshot.

  • KrissNC
    KrissNC New Member Posts: 31

    yep, I know I2cdetect should detect it, but it doesnt ... on any bus I try, my I2c screen address is 0x27 (it works on this adress with an arduino) but i2cdetect does not "see" my I2c device.

  • KrissNC
    KrissNC New Member Posts: 31


    This is what I did with the level shifter.
    Kernel is "up" 5.4 on a ubuntu.
    Is there a speed to setup in the bios ? an option to set ? should I2C ports in bios be configured as PCI or ACPI mode (I'm ACPI atm). I'll try to find a 3.3 simple I2c peripheral an retry without level shifter.
    I2Cdetect (from I2ctools) does not detect anything
    Btw I'm not sure to understand the 7bits I2c you are takling about. My device is at 0x27. Would the address change on an up4000 ? What adresses would I then expect ?

  • garyw
    garyw New Member, Moderator, AAEON Posts: 82 admin

    @KrissNC
    i2cdetect will scan 0x3~0x77 salve address, if there are any ACK from this adrress you will see it on the screen.
    if there are no device detected, you can check is it the up4000 hardware issue, you can enter BIOS and setup pin3/5 as output and set it high/low you need save setting and reboot to take effect.

    if you can't control high/low in BIOS the hardware pins should be corrupt.

  • KrissNC
    KrissNC New Member Posts: 31

    OK. I ported this exact schematic on a rasberry PI, same pins.
    I enabled I2C.
    the VERY FIRST TRY, i2cdetect detected my LCD screen at the right address. (0x27)
    I installed a few python stuff, and 10 min after that I had my display working.
    So I'm asking again : is there a special config/bios/kernel, anything that could justify that i2c won't work on my up4000s, when I made it work in 30 min on a Raspberry PI.
    There is obviously a software problem, since the hardware/schematic is now validated on a PI.
    Can you point me to a kernel you would advise. I will try to reinstall. But frankly I have been trying to have the I2C work for weeks, and after 30 min it worked on a PI. Should I use a standard ubuntu kernel (fresh ubuntu install), the 5.4 one from up ? Why would something that works on a Pi on the exact same pins, not work on an up4000 if not so software.

  • KrissNC
    KrissNC New Member Posts: 31

    @Wilbert "I have encountered other customers who reported that our I2C has not been able to recognize their devices, and finally found that the customer did not add the last bit of R/W, resulting in the output command being unable to be recognized by the device, so it cannot be recognized."

    What do you mean by "add the R/W bit ?" (how can I check that ?) I'm simply using I2cdetect atm. It works on a PI. The same thing doesn't work on my up4000s (I have 2). Same schematic.(posted up there). This, (or the speed maybe ? ) coud be the problem, but I have no control on what I2cdetect does. (unless there' an option to set/unset that rw bit ?)

  • KrissNC
    KrissNC New Member Posts: 31

    Digging with the "r/w" bit enigma, I tried i2cdetect -y -r 2 instead of i2cdetect -y 2

    root@up4k002:/home/adrem# i2cdetect -y -r 2
    0 1 2 3 4 5 6 7 8 9 a b c d e f
    00: -- -- -- -- -- -- -- -- -- -- -- -- --
    10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    20: -- -- -- -- -- -- -- 27 -- -- -- -- -- -- -- --
    30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    70: -- -- -- -- -- -- -- --
    And the display now is detected...
    Not completly sure how to continue right now, (to write something on the display), but I can now assert that I2c works. (Not sure how to put the -r option in a C/python program)

  • KrissNC
    KrissNC New Member Posts: 31

    an i2C one, which has and i2c interface, plugged onto the back of think kind of LCD. I found some C and python code that made it work after I validated the I2cdetect was the problem. (the -r option), I'll post the urls

  • KrissNC
    KrissNC New Member Posts: 31


    I managed to have I2C work, with and without a level shifter. This is without, displaying IP address (python)

  • Wilbert
    Wilbert New Member Posts: 168 ✭✭✭

    Hi Sir,

    Glad your problem was solved.
    At that time, I wanted to add level shift because according to the specifications, the I2C LCD requires a signal of 2.8~5.5V, and the typical signal is 5V. It is recommended to ensure that it can be used at 5V just in case.
    In theory, 3.3V is also feasible.
    Reply on 2/24, in fact, if Address 0x27 is detected, it means that the overall problem is fine, only some details need to be adjusted. If the location is recognized, it means that the I2C BUS has been enable, the wiring has been connected, and the device has been recognized.

    Best Regards,
    Wilbert Lee

  • loonix
    loonix New Member Posts: 8
    edited March 2023

    @KrissNC said:

    I managed to have I2C work, with and without a level shifter. This is without, displaying IP address (python)

    Are you able to share how you got this working? I am still not able to get this working. I have followed the instructions from the forum with the installation of the PPA kernel on Ubuntu 20.04. installed libmraa and pincrtl but my python script is still failing with "ValueError: Invalid GPIO pin specified".

    Your help is much appreciated.

    Thanks

    Alex

  • KrissNC
    KrissNC New Member Posts: 31

    @Ioonix
    wiring is direct : sda to sda(pin3) scl to scl (pin5), vcc to vcc (5v pin2), and ground to ground (pin6)
    (i2cdetect from i2c-tools, detected my screen using "i2cdetect -y -r 2" (as posted up there))

    I started with this, in C.
    https://github.com/albertherd/LCD1602
    in main.c I had to change init to rc = lcd1602Init(2, 0x27); to open i2c bus 2, (on a PI this is almost always bus 1)
    this works.

    for python3 : I used
    https://www.raspberrypi-spy.co.uk/2015/05/using-an-i2c-enabled-lcd-screen-with-the-raspberry-pi/
    same thing I had to modify the opening of the bus from
    bus = smbus.SMBus(1) to bus = smbus.SMBus(2)
    I also installed python3-smb (most tutorials are using an old version python-smbus) using
    apt install python3-smbus

    both examples do work on my 2 up4000s.

    don't forget to use this hardware stuff with root privileges (sudo)

    (I can't remember where I found this IP address python example, but the important is writing on the screen)

    (did you get mraa working ? I never did. I would be interested in this... what versions ? what mraa, any special lib ?)

  • KrissNC
    KrissNC New Member Posts: 31
    edited March 2023

    this is the IP address stuff I used.
    Interresting python lib/source in my opinion
    https://www.circuitbasics.com/raspberry-pi-i2c-lcd-set-up-and-programming/
    I had to change interface name to enp2s0 (not eth0) (to get the IP address stuff on up4000)
    mylcd.lcd_display_string(get_ip_address('enp2s0'), 2)
    (I might have also used the bus 2 somewhere, [edit, yes bus=2 in the driver])
    also the getip addresse was not working I found another one on github...

  • loonix
    loonix New Member Posts: 8

    @KrissNC - thank you so much for pointing me in the right direction - I am still struggling a bit as I am trying to get a different OLED (https://bit.ly/3rjHarP) going and not an LCD like yours. I will keep at it and report back here.

    Thanks

    Alex

  • KrissNC
    KrissNC New Member Posts: 31

    I'm tyring to have and oled too but I wanted to ensure I2C was working. I had it work on arduino, then PI then up4000. Now that' Im sure about I2c working, I can work on that oled stuff. (thow my boss poped with a "ho I have this new screen it's cheap !", which is an SPI one, (I've been wroking on I2C for weeks)

  • loonix
    loonix New Member Posts: 8
    edited March 2023

    So, after what feels like an eternity, I finally was able to make some progress and display some system stats on an I2C OLED.

    By fluke I came across the oled-i2c-bus node.js library and had some initial success displaying system stats on the OLED.

    Since I am a python guy (I created a python based installation package to display system information on an 128x32 OLED), I asked chatGPT to convert the node.js script to python. Believe it or not, chatGPT came through, and spat out a python script that basically worked (needed some customization to do what I wanted it to do).

    The key to success was the chatGPT suggested to use the luma.oled library. This python library finally allowed me to control and display the info I wanted on the OLED. It is still no 100% perfect but definitely a step in the right direction. I will keep you posted.

    Picture of system stats on OLED

    Here is the code I used (btw on stock Ubuntu 22.04 with python3 and the respective libraries installed via pip):

    `

    !/usr/bin/python3

    from smbus2 import SMBus
    from luma.oled.device import ssd1306
    from luma.core.render import canvas
    from luma.core.interface.serial import i2c
    import subprocess
    from PIL import Image, ImageDraw, ImageFont

    width = 128
    height = 32

    serial = i2c(port=1, address=0x3C)
    device = ssd1306(serial, width=width, height=height)

    Make sure to create image with mode '1' for 1-bit color.

    image = Image.new("1", (width, height))

    Get drawing object to draw on image.

    draw = ImageDraw.Draw(image)

    Draw a black filled box to clear the image.

    draw.rectangle((0, 0, width, height), outline=0, fill=0)

    Draw some shapes.

    First define some constants to allow easy resizing of shapes.

    padding = -2
    top = padding
    bottom = height - padding

    Move left to right keeping track of the current x position for drawing shapes.

    x = 0

    Load font.

    font = ImageFont.truetype("/usr/share/fonts/truetype/msttcorefonts/arial.ttf", 10)

    cmd = "hostname -I | cut -d' ' -f1"
    IP = subprocess.check_output(cmd, shell=True).decode("utf-8")
    cmd = 'cut -f 1 -d " " /proc/loadavg'
    CPU = subprocess.check_output(cmd, shell=True).decode("utf-8")
    cmd = "free -m | awk 'NR==2{printf \"Mem: %.2f%% of \" ,$3*100/$2}' && free -hm | awk 'NR==2{printf \"%s\", $2}'"
    MemUsage = subprocess.check_output(cmd, shell=True).decode("utf-8")
    cmd = 'df -h | awk \'$NF=="/"{printf "Disk: %d/%d GB %s", $3,$2,$5}\''
    Disk = subprocess.check_output(cmd, shell=True).decode("utf-8")

    while True:
    with canvas(device) as draw:
    draw.text((x, top + 0), "IP: " + IP, font=font, fill=255)
    draw.text((x, top + 8), "CPU load: " + CPU, font=font, fill=255)
    draw.text((x, top + 16), MemUsage, font=font, fill=255)
    draw.text((x, top + 24), Disk, font=font, fill=255)
    `

    I keep at it. Let me know if you have any feedback or suggestions to this method.

    Thanks

    Alex aka. loonix

  • loonix
    loonix New Member Posts: 8

    @loonix said:
    So, after what feels like an eternity, I finally was able to make some progress and display some system stats on an I2C OLED.

    Looks like the formatting in the above post is screwed up and I can not edit it anymore for some reason. Here is a link to a clean and updated version of this post on my blog.

    Thanks

    Alex aka. loonix

  • loonix
    loonix New Member Posts: 8

    So, here is the latest update.

    I was able to use the python smbus2 module to make it work. Now my stats python3 script is compatible across several hardware platforms - Raspberry Pi, Banana Pi, Upboard Up 4000. I posted it on github: https://oleddisplaystats.loonix.ca/

    Here is the script running on the up4000 board:

    stats running on up4000

    Thanks for all the support.

    Alex aka. loonix

  • loonix
    loonix New Member Posts: 8

    Me again

    I was also able to convert this OLED monitoring python script to run on the Up 4000 with the smbus2 module.

    Adapted python script attached.

    Thanks

    Alex aka. loonix

  • loonix
    loonix New Member Posts: 8
    edited April 2023

    So, I noticed that when you reboot the i2c bus flips between 1 and 2. Not sure why this is happening but it doesn't stay static for some reason. This is on Ubuntu 22.04.

    This behaviour breaks the python3 script I wrote as you have to define the i2c bus as '1' or '2' to control the attached OLED.

    To overcome this and to allow to start the script automatically on reboot, I added the following 'if' statement to my script to check which bus i2c is assigned to:

    def check_i2c_bus(bus_number):
        cmd = f"i2cdetect -y -r {bus_number} | grep 3c"
        output = os.popen(cmd).read()
        return True if output else False
    
    bus_number = 1 if check_i2c_bus(1) else 2
    
    

    So far it seems to be working.

    Thought this could be helpful as I can't be the only one having run into this.

    Thanks

    Alex aka. loonix