Rotating display


I would like to know how to rotate display from portrait to landscape.

I use ili9341 display with touch.

The portrait configuration work perfectly but I have no idea where to look to change the orientation.



Hi @jfng!

I assume you are using the ili9341 micropython driver.
Please try to change the rot keyword argument of ili9341 constructor. options are: MADCTL_MY, MADCTL_MX, MADCTL_ML, MADCTL_MH. It sets the ILI9341 rotation mode during initialization.


Hello amirgone,

I am not very sure I am using the correct driver…

When I try rot=MADCTL_MY, I got the following error:

MPY: soft reboot
Traceback (most recent call last):
File “”, line 266, in
File “”, line 251, in init_gui
File “”, line 226, in init_gui_esp32
NameError: name ‘MADCTL_MX’ isn’t defined
MicroPython v1.9.4-2071-g87854b53c-dirty on 2019-12-28; ESP32 module with ESP32
Type “help()” for more information.

I build micropython using lv_micropython.

I’m a little bit confuse… How to use the correct driver? I see there is a lv_binding_micropython but don’t know how to use it or integrate it properly…



Try rot=ili9341.MADCTL_MY

I try:
self.disp = ili9341(rot=ili9341.MADCTL_MY)

And got this:

Traceback (most recent call last):
File “”, line 266, in
File “”, line 251, in init_gui
File “”, line 226, in init_gui_esp32
AttributeError: type object ‘ili9341’ has no attribute ‘MADCTL_MY’

Ok, I try to put the constant directly.
It seem to do something.

It flip screen correctly but widget only draw on the same axe…

When I try to change width to 320 and height to 240, display draw garbage…


Maybe you are using an older version of lv_micropython?

@jfng the following works for me:

import lvgl as lv
import ili9341
disp = ili9341.ili9341(rot=0x20, width=320, height=240)

b = lv.btn(lv.scr_act())
l = lv.label(b)
l.set_text("Hello World!")

Please check if this works for you.

There are a few things to improve in the driver, though:

  • Add a missing constant MV=0x20 (Row / Column Exchange)
  • Move the MADCTL constants into ili9341 class so it would be easier to access them
  • I think the touch driver would need some fix to work on landscape mode. Are you using xpt2046?

I’ve updated lv_micropython_bindings to address these issues.
xpt2046 works well but requires setting transpose=False.

Here is a simple example that creates a draggable button on portrait layout (make sure you use the latest lv_micropython from today):

import lvgl as lv
from ili9341 import ili9341
from xpt2046 import xpt2046

disp = ili9341(rot=ili9341.LANDSCAPE, width=320, height=240)
touch = xpt2046(transpose=False, cal_x0=3780, cal_y0=252, cal_x1=393, cal_y1=3751)

b = lv.btn(lv.scr_act())
l = lv.label(b)
l.set_text("Hello World!")

The calibration values can be calculated by running tpcal, but it needs to be modified to landscape as well when initializing ili9341 and xp2046 in it)

Hello Amir,

I will update lv_micropython and try your example.

Thank you!


Ok, I re-compile lv_micropython with today version and .LANDSCAPE seem to work!

When I try to run, and try new calibration, it’s look like when I drag the point left to right, the point drag up an down and vice-versa.

What value should I change to get the calibration cooresponding to the landscape screen?

disp = ili9341(rot=ili9341.LANDSCAPE, width=320, height=240)

HRES = lv.disp_get_hor_res(lv.disp_t.cast(None))
VRES = lv.disp_get_ver_res(lv.disp_t.cast(None))

Register raw resistive touch driver

import rtch
touch = rtch.touch(xp = 32, yp = 33, xm = 25, ym = 26, touch_rail = 27, touch_sense = 33, cal_x0=0, cal_x1 = HRES, cal_y0=0, cal_y1 = VRES)
indev_drv = lv.indev_drv_t()
indev_drv.type = lv.INDEV_TYPE.POINTER;
indev_drv.read_cb =;

Register xpt touch driver

import xpt2046 as xpt2046
touch = xpt2046.xpt2046(cal_x0=0, cal_x1 = HRES, cal_y0=0, cal_y1 = VRES)


Ok! forget the last message!

I just read the comment about xpt2046!

Just add transpose and work perfectly!

Many thanks!


Great! You are welcome.