kdschlosser / lvgl_micropython

LVGL module for MicroPython
MIT License
42 stars 11 forks source link

can't import espidf module #61

Open arunkm490 opened 1 week ago

arunkm490 commented 1 week ago

i built a firmware for ESP32 GENERIC S3 (ESP32-S3-WROOM-1) python3 make.py esp32 submodules clean mpy_cross BOARD=ESP32_GENERIC_S3 DISPLAY=ili9488 INDEV=xpt2046 by using this command. binary file created successfully. but i can not import the required modules.

import time import espidf as esp import math import lvgl as lv from xpt2046 import xpt2046 from ili9XXX import ili9488 import ili9XXX import machine import struct from machine import UART,I2C,Pin uart2 = UART(2, 19200) uart2.init(19200, bits=8, parity=None, stop=1) disp = ili9488(miso=19, mosi=23, clk=18, cs=4, dc=15, rst=2, spihost=esp.VSPI_HOST, mhz=40, factor=64, hybrid=True, width=480, height=320, invert=False, double_buffer=True, half_duplex=False,rot=-2) touch = xpt2046(cs=5, spihost=esp.VSPI_HOST, transpose=True)

module error in this (import espidf as esp)(from xpt2046 import xpt2046) (from ili9XXX import ili9488)

ImportError: no module named 'espidf'

zelogik commented 1 week ago

import esp should be enough ? but the constructor is not the same as the official lv_micropython, so esp.VSPI_HOST will not work here

Even give you some ram free, and don´t import it if you don't use it :D

And working example for a CYS (cheap yellow Screen)

from micropython import const  # NOQA
from machine import Pin, SPI # NOQA
import lcd_bus

# Display settings
_WIDTH = const(320)
_HEIGHT = const(240)

# Display SPI bus settings
_LCD_HOST = const(1)
_LCD_FREQ = const(20000000)
_LCD_MISO = const(16)
_LCD_MOSI = const(13)
_LCD_SCK = const(14)
_LCD_CS = const(15)

# display additional pins
_LCD_RST = const(12)
_LCD_DC = const(2)
_LCD_BKL = const(21)
_LCD_PWR = None

# touch panel SPI settings
_TP_HOST = const(2)
_TP_FREQ = const(10000000)
_TP_MISO = const(39)
_TP_MOSI = const(32)
_TP_SCK = const(25)
_TP_CS = const(33)

# create the SPI bus for the display
lcd_spi_bus = SPI(
    _LCD_HOST,
    _LCD_FREQ,
    mosi=_LCD_MOSI,
    miso=_LCD_MISO,
    sck=_LCD_SCK
)

# create the SPI device on the bus for the display
display_bus = lcd_bus.SPIBus(
    spi_bus=lcd_spi_bus,
    dc=_LCD_DC,
    freq=_LCD_FREQ,
    cs=_LCD_CS
)

import ili9341  # NOQA
import lvgl as lv  # NOQA

# create the display driver
display = ili9341.ILI9341(
    data_bus=display_bus,
    display_width=_WIDTH,
    display_height=_HEIGHT,
    reset_pin=_LCD_RST,
    power_pin=_LCD_PWR,
    backlight_pin=_LCD_BKL,
    color_space=lv.COLOR_FORMAT.RGB565,
    # color_byte_order=ili9341.BYTE_ORDER_BGR,
    rgb565_byte_swap=False
)

# start the display driver
display.set_power(True)
display.init()
display.set_backlight(100)

import xpt2046  # NOQA

# create the SPI bus for the touch panel
touch_bus = SPI(
    _TP_HOST,
    _TP_FREQ,
    mosi=_TP_MOSI,
    miso=_TP_MISO,
    sck=_TP_SCK,
    cs=_TP_CS
)

# create the touch driver
touch = xpt2046.XPT2046(touch_bus, startup_rotation=lv.DISPLAY_ROTATION._90)
display.set_rotation(lv.DISPLAY_ROTATION._0)  # NOQA

other solution: repl the MCU, import e\<tab> will five to you errno, esp, esp32 for example

ikkesia commented 1 week ago

@zelogik can you provide an example that uses new ESP32 SPI drivers with display and touch panel (ili9341 and xpt2046) sharing the same SPI bus ?

kdschlosser commented 1 week ago

have you read the readme?

ikkesia commented 1 week ago

Yes of course, I read it. And this is the test script I wrote.

from micropython import const
from machine import SPI
import sys
import lcd_bus

#Display settings
_WIDTH = const(320)
_HEIGHT = const(240)

# Display SPI bus settings
_LCD_SPI_HOST = const(1)
_LCD_SPI_FREQ = const(40_000_000)
_LCD_MOSI_PIN = const(23)
_LCD_MISO_PIN = const(25)
_LCD_SCLK_PIN = const(19)
_LCD_CS_PIN = const(22)
# display additional pins
_LCD_RST_PIN = const(18)
_LCD_DC_PIN = const(21)
_LCD_BKL_PIN = const(5)
_LCD_PWR_PIN = None

# touch panel SPI settings
_TP_SPI_HOST = const(1)
_TP_SPI_FREQ = const(1_000_000)
_TP_CS_PIN = const(32)
_TP_INT_PIN = const(-1)

# create the SPI bus for the display
spi_bus = SPI(
    _LCD_SPI_HOST,
    _LCD_SPI_FREQ,
    miso=_LCD_MISO_PIN,
    mosi=_LCD_MOSI_PIN,
    sck=_LCD_SCLK_PIN,
    cs=_LCD_CS_PIN
)

display_bus = lcd_bus.SPIBus(
    spi_bus=spi_bus,
    dc=_LCD_DC_PIN,
    freq=_LCD_SPI_FREQ
)

import ili9341
import lvgl as lv

display = ili9341.ILI9341(
    data_bus=display_bus,
    display_width=_WIDTH,
    display_height=_HEIGHT,
    reset_pin=_LCD_RST_PIN,
    power_pin=_LCD_PWR_PIN,
    backlight_pin=_LCD_BKL_PIN,
    backlight_on_state=ili9341.STATE_HIGH,
    color_space=lv.COLOR_FORMAT.RGB565,
#    color_byte_order=ili9341.BYTE_ORDER_BGR,
    rgb565_byte_swap=False
)

# start the display driver
display.init()
#display.set_rotation(lv.DISPLAY_ROTATION._90)

import xpt2046 

# create the SPI bus for touch panel
touch_bus = SPI(
    _LCD_SPI_HOST,
    _TP_SPI_FREQ,
    miso=_LCD_MISO_PIN,
    mosi=_LCD_MOSI_PIN,
    sck=_LCD_SCLK_PIN,
    cs=_TP_CS_PIN
)
#indev = xpt2046.XPT2046(spi_bus, _TP_CS, _TP_INT)

try:
    indev = xpt2046.XPT2046(touch_bus, touch_cal=None, debug=True)
    print('is_calibrate is', indev.is_calibrated)
except Exception as ex:
    sys.print_exception(ex)

scrn = lv.screen_active()
slider = lv.slider(scrn)
slider.set_size(_WIDTH - 50, 50)
slider.center() 

import task_handler
th = task_handler.TaskHandler()

Running the script the touch panel works fine, I can see it from the debug printouts, but nothing appears on the display. Display that has always worked well in the period that I followed your development of the new drivers.

kdschlosser commented 1 week ago

I am going to make a change to the code and remove the last thing I added. I believe it is causing some issues. I am going to make it optional to use for the time being so I will still be able to test it.

kdschlosser commented 1 week ago

do me a favor and run it without the touch screen and see if it displays. I want to make sure the SPI drivers are working properly and not bumping heads with each other.

ikkesia commented 1 week ago

With or without touch screen no display.

I used the latest commit #6fffcda.

ikkesia commented 1 week ago

I made some measurements on the signals with an oscilloscope. I see that the _LCD_CS_PIN pin is fixed low while _TP_CS_PIN switches on/off as expected.

Running with only the LCD (without touch screen) _LCD_CS_PIN is still always low.

kdschlosser commented 1 week ago

You are passing the LCD CS pin to the wrong constructor. You need to be passing it to the lcd_bus.SPIBus constructor and not the machine.SPI constructor.

Here use this code..

from micropython import const
from machine import SPI
import sys
import lcd_bus

#Display settings
_WIDTH = const(320)
_HEIGHT = const(240)

# Display SPI bus settings
_LCD_SPI_HOST = const(1)
_LCD_SPI_FREQ = const(40_000_000)
_LCD_MOSI_PIN = const(23)
_LCD_MISO_PIN = const(25)
_LCD_SCLK_PIN = const(19)
_LCD_CS_PIN = const(22)
# display additional pins
_LCD_RST_PIN = const(18)
_LCD_DC_PIN = const(21)
_LCD_BKL_PIN = const(5)
_LCD_PWR_PIN = None

# touch panel SPI settings
_TP_SPI_HOST = const(1)
_TP_SPI_FREQ = const(1_000_000)
_TP_CS_PIN = const(32)
_TP_INT_PIN = const(-1)

# create the SPI bus for the display
spi_bus = SPI(
    _LCD_SPI_HOST,
    _TP_SPI_FREQ,
    miso=_LCD_MISO_PIN,
    mosi=_LCD_MOSI_PIN,
    sck=_LCD_SCLK_PIN,
    cs=_TP_CS_PIN
)

display_bus = lcd_bus.SPIBus(
    spi_bus=spi_bus,
    dc=_LCD_DC_PIN,
    freq=_LCD_SPI_FREQ,
    cs=_LCD_CS_PIN
)

import ili9341
import lvgl as lv

display = ili9341.ILI9341(
    data_bus=display_bus,
    display_width=_WIDTH,
    display_height=_HEIGHT,
    reset_pin=_LCD_RST_PIN,
    power_pin=_LCD_PWR_PIN,
    backlight_pin=_LCD_BKL_PIN,
    backlight_on_state=ili9341.STATE_HIGH,
    color_space=lv.COLOR_FORMAT.RGB565,
#    color_byte_order=ili9341.BYTE_ORDER_BGR,
    rgb565_byte_swap=False
)

# start the display driver
display.init()
display.set_brightness(100)  # have to turn on the backlight
#display.set_rotation(lv.DISPLAY_ROTATION._90)

import xpt2046 

try:
    indev = xpt2046.XPT2046(spi_bus, touch_cal=None, debug=True)
    print('is_calibrate is', indev.is_calibrated)
except Exception as ex:
    sys.print_exception(ex)

scrn = lv.screen_active()
slider = lv.slider(scrn)
slider.set_size(_WIDTH - 50, 50)
slider.center() 

import task_handler
th = task_handler.TaskHandler()
kdschlosser commented 1 week ago

I didn't want to change how the machine.SPI class works too much. I wanted to make sure it was going to remain consistant with how it worked prior to adding LVGL to MicroPython.

with just vanilla MicroPython you could not easily have more than one device attached to the SPI bus. There was some goofy coding that would need to be done if you had more than one. It was rather cumbersome to deal with. You then ran into the issue of having to handle the CS line state change yourself and if that is not done properly you could end up with a device getting data that it shouldn't be getting. This became even more of an issue when dealing with DMA memory transfers where the program is able to continue to run while the transfer is taking place. You are not able to handle the CS pin state changes when this is happening.

So what I did was I extended the micropython.SPI class to allow the CS line to be passed but I also allow it to be created more than a single time passing the same host and pins. There is a check that is done to see if the bus has been initialized and if it has been it doesn't error out which is what used to happen. Now it continues on to add a new device to the bus. The CS line needs to be passed with the device that is being added. In this case the display is the device we want to add to the bus so the CS line gets passed to the lcd_bus.SPIBus constructor. The passing of the machine.SPI instance is for convenience and also to show that you have more than one thing attached to the same bus. You can see this is being done in the code above. Since you are sharing the bus between the display and the touch we pass the touch CS when initilizing the bus and then pass the bus to the lcd_bus.SPIBus constructor.

The actual structure of everything in the esp-idf is done wrong.

for example,

to attach and SPI display in order to get thing running I have to create the bus and then pass that bus to the constructor to create the display. The display in this case would be considered to be a device. The same thing has to happen in MicroPython's SPI as well. This is done for you as a single step when it should be separated.

Where we run into an issue tho is with the I8080 displays. While I am able to have more than a single I8080 device connected to the same wires there is no separation in the IDF code to allow for this to take place. And with the RGB displays it ends up being a whole different way it is done. There is no separate "device" and "bus" either.

It would make things a whole lot easier if it was separated and I will probably end up writing custom drivers to handle this properly.

ikkesia commented 1 week ago

Even with this code there is no display. With or without touch screen.

ikkesia commented 1 week ago

Thanks for the explanation. And thank you very much also for the commitment and time you spend on this project.

ikkesia commented 1 week ago

It seems that the cause of the problem is the default polarity of the signal driving the LCD reset input.

If I add reset_state=ili9341.STATE_LOW,

slider appears !

kdschlosser commented 1 week ago

well that's awesome. Some displays have a high reset state and some have a low reset state. That part is up to you to figure out.

ikkesia commented 1 week ago

Yes of course, I should have realized this sooner and I'm sorry for wasting your time on this.

Il giorno 21 giu 2024, alle ore 02:38, Kevin Schlosser @.***> ha scritto:

well that's awesome. Some displays have a high reset state and some have a low reset state. That part is up to you to figure out.

— Reply to this email directly, view it on GitHub https://github.com/kdschlosser/lvgl_micropython/issues/61#issuecomment-2181781412, or unsubscribe https://github.com/notifications/unsubscribe-auth/ASI4WC26JERWP5HJ6YGUOPTZINYZXAVCNFSM6AAAAABJROP3IOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCOBRG44DCNBRGI. You are receiving this because you commented.

kdschlosser commented 1 week ago

Oh your fine. Not a big deal it happens. I am fighting with a problem that is exactly the same as yours but using a different bus driver. So I had thought the problem was more systemic at that point. Now I know it is actually a problem with that specific bus driver.