3-wire 9-bit SPI ST7789 TFT with FT6236 capacitive touch on ESP32-S3-Zero/CircuitPython
This video show
Waveshare ESP32-S3-Zero
running
CircuitPython 9.0.0-beta.0, display on
1.54" 240x240 3-wire 9-bit SPI ST7789 TFT with capacitive touch driver
FT6236G.
About 9-bit SPI:
The display module use ST7789 driver with 3-wire SPI, no DC pin.
On CircuitPython (9.0.0-beta.0 in this exercise), if the command (DC) pin is not specified, a 9-bit SPI mode will be SIMULATED by adding a data/command bit to every bit being transmitted, and splitting the resulting data back into 8-bit bytes for transmission. The extra bits that this creates at the end are ignored by the receiving device.
ref: https://docs.circuitpython.org/en/latest/shared-bindings/fourwire/index.html#fourwire.FourWire
About fourwire library:
Start from CircuitPython 9.0.0 Alpha 2:
Split off parts of displayio into multiple modules: busdisplay, fourwire, epaperdisplay, i2cdisplaybus, paralleldisplaybus. The existing displayio hierarchy will still be available 9.x.x, but is deprecated, and will be removed in 10.0.0.
About FocalTech capacitive touch driver for CircuitPython:
In the official CircuitPython library for FT6236 capacitive touch, adafruit_focaltouch.mpy, it check vend_id (should be vendor ID). But my module is not in the list, and RuntimeError of "Did not find FT chip" raised. My solution is to download the source code of adafruit_focaltouch.py, modified to skip vend_id checking, the video show how.
Libraries needed:
All the libraries used in the exercises:
- adafruit_cursorcontrol folder
- adafruit_display_shapes folder
- adafruit_display_text folder
- my_focaltouch (modified from adafruit_focaltouch.mpy)
- adafruit_simplemath.mpy
- adafruit_st7789.mpy
If you don't know how to download libraries and upload to device, read the video https://youtu.be/mdyNBVjnC2c?t=33
Connection:
ST7789 ESP32-S3-Zero
=============================
(3 wire 9bit SPI)
GND GND
VCC 3V3
SCL GP12
SDA GP11
RES GP13
DATA1 (NC)
CS GP10
BL GP7
FT6236 cap. touch
(I2C)
CTP-SCL GP9
CTP-SDA GP8
CTP-INT GP6 (option)
CTP-RST GP5 (option)
Exercise Code:
cpyS3_st7789_9bitSPI_FT6236_dummy.py, just a dummy code to make sure the libraries loaded and run correctly.
"""
CircuitPython exercise run on Waveshare ESP32-S3-Zero,
with 1.54" 240x240 3-wire 9-bit SPIST7789 TFT
and capacitive touch FT6236G, WLK1501SPI-8P.
Dummy setup libraries for 3-wire 9-bit SPIST7789/FT6236G.
Test on:
dev. board: Waveshare ESP32-S3-Zero
CircuitPython: 9.0.0-beta.0
Libraries needed, for this and following exercises:
- adafruit_cursorcontrol folder
- adafruit_display_shapes folder
- adafruit_display_text folder
- my_focaltouch (adafruit_focaltouch.mpy)
- adafruit_simplemath.mpy
- adafruit_st7789.mpy
If you don't know how to download libraries and upload to device, read:
https://youtu.be/mdyNBVjnC2c?t=33
"""
import os, sys
import board
import busio
import terminalio
import displayio
import fourwire
from adafruit_display_text import label
from adafruit_display_shapes.rect import Rect
import adafruit_st7789
import adafruit_focaltouch
import my_focaltouch
from digitalio import DigitalInOut, Direction
import adafruit_cursorcontrol.cursorcontrol
from adafruit_simplemath import map_range
import time
# Release any resources currently in use for the displays
displayio.release_displays()
#===init display ======================
#Connection to ST7789
DISP_SCL = board.IO12
DISP_SDA = board.IO11
DISP_RES = board.IO13
DISP_DC = None
DISP_CS = board.IO10
DISP_BL = board.IO7
#Connection to FT6236G
TOUCH_SCL = board.IO9
TOUCH_SDA = board.IO8
TOUCH_INT = board.IO6 #optional
TOUCH_RST = board.IO5 #optional
touch_irq = DigitalInOut(TOUCH_INT)
touch_irq.direction = Direction.INPUT
touch_res = DigitalInOut(TOUCH_RST)
touch_res.direction = Direction.OUTPUT
touch_res.value = True
time.sleep(0.1)
touch_res.value = False
time.sleep(0.1)
touch_res.value = True
time.sleep(0.1)
disp_spi = busio.SPI(clock=DISP_SCL,
MOSI=DISP_SDA)
touch_i2c = busio.I2C(TOUCH_SCL, TOUCH_SDA)
ft = my_focaltouch.My_FocalTouch(touch_i2c, debug=False, irq_pin=touch_irq)
"""
On CircuitPython 9
FutureWarning: FourWire moved from displayio to fourwire
If the command pin is not specified, a 9-bit SPI mode will be SIMULATED.
ref: https://docs.circuitpython.org/en/latest/shared-bindings/fourwire/index.html#fourwire.FourWire
"""
#display_bus = displayio.FourWire(disp_spi, command=DISP_DC, chip_select=DISP_CS, reset=DISP_RES)
display_bus = fourwire.FourWire(disp_spi, command=DISP_DC, chip_select=DISP_CS, reset=DISP_RES)
#--- Setup display ---
# for 1.54" 240x240 3-wire 9-bit SPI ST7789 TFT
disp_width = 240
disp_height = 240
display = adafruit_st7789.ST7789(display_bus,
width=disp_width,
height=disp_height,
rowstart=40,
backlight_pin=DISP_BL)
# Once a Display is setup, before switche to display any given group of layers,
# the default CircuitPython terminal will be shown; work as REPL display terminal.
#=======================================
info = os.uname()[4] + "\n" + \
sys.implementation[0] + " " + os.uname()[3] + "\n" + \
adafruit_st7789.__name__ + " " + adafruit_st7789.__version__ + "\n" + \
str(display.width) + "x" + str(display.height) + "\n" + \
adafruit_focaltouch.__name__ + " " + adafruit_focaltouch.__version__ + "\n" + \
my_focaltouch.__name__ + " " + my_focaltouch.__version__
print("=======================================")
print(info)
print("ft.chip:", ft.chip)
print("=======================================")
time.sleep(2)
while True:
pass
print("~ bye ~")
cpyS3_st7789_9bitSPI_color.py, for color testing of the display.
"""
CircuitPython exercise run on Waveshare ESP32-S3-Zero,
to display on IPS with ST7789 3-wire 9-bit SPI driver
and capacitive touch FT6236G, WLK1501SPI-8P.
Color test
Test on:
dev. board: Waveshare ESP32-S3-Zero
CircuitPython: 9.0.0-beta.0
Libraries needed:
- adafruit_st7789.mpy
- my_focaltouch.py (adafruit_focaltouch.mpy)
- adafruit_cursorcontrol folder
- adafruit_display_text folder
"""
import os, sys
import board
import busio
import terminalio
import displayio
import fourwire
from adafruit_display_text import label
import adafruit_st7789
from digitalio import DigitalInOut, Direction
import adafruit_cursorcontrol.cursorcontrol
import time
# Release any resources currently in use for the displays
displayio.release_displays()
#===init display ======================
#Connection to ST7789
DISP_SCL = board.IO12
DISP_SDA = board.IO11
DISP_RES = board.IO13
DISP_DC = None
DISP_CS = board.IO10
DISP_BL = board.IO7
#Connection to FT6236G
TOUCH_SCL = board.IO9
TOUCH_SDA = board.IO8
TOUCH_INT = board.IO6 #optional
TOUCH_RST = board.IO5 #optional
touch_irq = DigitalInOut(TOUCH_INT)
touch_irq.direction = Direction.INPUT
touch_res = DigitalInOut(TOUCH_RST)
touch_res.direction = Direction.OUTPUT
touch_res.value = True
time.sleep(0.1)
touch_res.value = False
time.sleep(0.1)
touch_res.value = True
time.sleep(0.1)
disp_spi = busio.SPI(clock=DISP_SCL,
MOSI=DISP_SDA)
"""
On CircuitPython 9
FutureWarning: FourWire moved from displayio to fourwire
If the command pin is not specified, a 9-bit SPI mode will be SIMULATED.
ref: https://docs.circuitpython.org/en/latest/shared-bindings/fourwire/index.html#fourwire.FourWire
"""
#display_bus = displayio.FourWire(disp_spi, command=DISP_DC, chip_select=DISP_CS, reset=DISP_RES)
display_bus = fourwire.FourWire(disp_spi, command=DISP_DC, chip_select=DISP_CS, reset=DISP_RES)
#--- Setup display ---
# for 1.54" 240x240 3-wire 9-bit SPI ST7789 TFT
disp_width = 240
disp_height = 240
display = adafruit_st7789.ST7789(display_bus,
width=disp_width,
height=disp_height,
rowstart=40,
backlight_pin=DISP_BL)
print("=======================================")
print("coXXect.blogspot.com")
print("=======================================")
time.sleep(1)
# Make the display context
bgGroup = displayio.Group()
"""
show() is deprecated and will be removed in CircuitPython 9.0.0. Use .root_group = group instead.
https://docs.circuitpython.org/en/8.2.x/shared-bindings/displayio/index.html#displayio.Display.show
"""
#display.show(bgGroup)
display.root_group = bgGroup
bg_bitmap = displayio.Bitmap(display.width, display.height, 1) # with one color
bg_palette = displayio.Palette(1)
bg_palette[0] = 0xFFFFFF # White
bg_sprite = displayio.TileGrid(bg_bitmap, pixel_shader=bg_palette, x=0, y=0)
bgGroup.append(bg_sprite)
colorSet = ((0xFF0000, "RED"),
(0x00FF00, "GREEN"),
(0x0000FF, "BLUE"),
(0xFFFFFF, "WHITE"),
(0x000000, "BLACK"))
color_bitmap = displayio.Bitmap(display.width-2, display.height-2, 1) # with one color
color_palette = displayio.Palette(1)
color_palette[0] = 0x000000 # BLACK
color_sprite = displayio.TileGrid(color_bitmap, pixel_shader=color_palette, x=1, y=1)
bgGroup.append(color_sprite)
# Draw label
text_group = displayio.Group(scale=2, x=2, y=120)
text = "coXXect.blogspot.com"
text_area = label.Label(terminalio.FONT, text=text, color=0xFFFFFF)
text_group.append(text_area) # Subgroup for text scaling
bgGroup.append(text_group)
time.sleep(1)
text_group.x = 15
text_area.text = "coXXect"
text_area.color = 0xFFFF00 #yellow
text_group.scale = 5
for i in colorSet:
time.sleep(0.5)
color_palette[0] = i[0]
text_area.text = i[1]
text_area.color = i[0] ^ 0xFFFFFF
while True:
pass
print("~ bye ~")
cpyS3_st7789_9bitSPI_FT6236.py, read Focal Touch and display a cursor on screen following the touch. Actually, the display can detect more than one touch point, but I handle one only.
"""
CircuitPython exercise run on Waveshare ESP32-S3-Zero,
to display on IPS with ST7789 3-wire 9-bit SPI driver
and capacitive touch FT6236G, WLK1501SPI-8P.
Read touch to move cursor
Test on:
dev. board: Waveshare ESP32-S3-Zero
CircuitPython: 9.0.0-beta.0
Libraries needed:
- adafruit_st7789.mpy
- my_focaltouch.py (adafruit_focaltouch.mpy)
- adafruit_cursorcontrol folder
- adafruit_display_text folder
"""
import os, sys
import board
import busio
import terminalio
import displayio
import fourwire
from adafruit_display_text import label
import adafruit_st7789
import my_focaltouch
from digitalio import DigitalInOut, Direction
import adafruit_cursorcontrol.cursorcontrol
import time
# Release any resources currently in use for the displays
displayio.release_displays()
#===init display ======================
#Connection to ST7789
DISP_SCL = board.IO12
DISP_SDA = board.IO11
DISP_RES = board.IO13
DISP_DC = None
DISP_CS = board.IO10
DISP_BL = board.IO7
#Connection to FT6236G
TOUCH_SCL = board.IO9
TOUCH_SDA = board.IO8
TOUCH_INT = board.IO6 #optional
TOUCH_RST = board.IO5 #optional
touch_irq = DigitalInOut(TOUCH_INT)
touch_irq.direction = Direction.INPUT
touch_res = DigitalInOut(TOUCH_RST)
touch_res.direction = Direction.OUTPUT
touch_res.value = True
time.sleep(0.1)
touch_res.value = False
time.sleep(0.1)
touch_res.value = True
time.sleep(0.1)
disp_spi = busio.SPI(clock=DISP_SCL,
MOSI=DISP_SDA)
touch_i2c = busio.I2C(TOUCH_SCL, TOUCH_SDA)
ft = my_focaltouch.My_FocalTouch(touch_i2c, debug=False, irq_pin=touch_irq)
"""
On CircuitPython 9
FutureWarning: FourWire moved from displayio to fourwire
If the command pin is not specified, a 9-bit SPI mode will be SIMULATED.
ref: https://docs.circuitpython.org/en/latest/shared-bindings/fourwire/index.html#fourwire.FourWire
"""
#display_bus = displayio.FourWire(disp_spi, command=DISP_DC, chip_select=DISP_CS, reset=DISP_RES)
display_bus = fourwire.FourWire(disp_spi, command=DISP_DC, chip_select=DISP_CS, reset=DISP_RES)
#--- Setup display ---
# for 1.54" 240x240 3-wire 9-bit SPI ST7789 TFT
disp_width = 240
disp_height = 240
display = adafruit_st7789.ST7789(display_bus,
width=disp_width,
height=disp_height,
rowstart=40,
backlight_pin=DISP_BL)
print("=======================================")
print("coXXect.blogspot.com")
print("=======================================")
time.sleep(1)
# Make the display context
bgGroup = displayio.Group()
"""
show() is deprecated and will be removed in CircuitPython 9.0.0. Use .root_group = group instead.
https://docs.circuitpython.org/en/8.2.x/shared-bindings/displayio/index.html#displayio.Display.show
"""
#display.show(bgGroup)
display.root_group = bgGroup
bg_bitmap = displayio.Bitmap(display.width, display.height, 1) # with one color
bg_palette = displayio.Palette(1)
bg_palette[0] = 0xFFFFFF # White
bg_sprite = displayio.TileGrid(bg_bitmap, pixel_shader=bg_palette, x=0, y=0)
bgGroup.append(bg_sprite)
color_bitmap = displayio.Bitmap(display.width-2, display.height-2, 1) # with one color
color_palette = displayio.Palette(1)
color_palette[0] = 0x000000 # BLACK
color_sprite = displayio.TileGrid(color_bitmap, pixel_shader=color_palette, x=1, y=1)
bgGroup.append(color_sprite)
# Draw label
text_group = displayio.Group(scale=2, x=2, y=120)
text = "coXXect.blogspot.com"
text_area = label.Label(terminalio.FONT, text=text, color=0xFFFFFF)
text_group.append(text_area) # Subgroup for text scaling
bgGroup.append(text_group)
# Draw labels to display touch x/y
x_group = displayio.Group(scale=2, x=0, y=20)
x_text = "---"
x_area = label.Label(terminalio.FONT, text=x_text, color=0xFFFFFF)
x_group.append(x_area)
bgGroup.append(x_group)
y_group = displayio.Group(scale=2, x=0, y=40)
y_text = "---"
y_area = label.Label(terminalio.FONT, text=y_text, color=0xFFFFFF)
y_group.append(y_area)
bgGroup.append(y_group)
time.sleep(1)
text_group.x = 15
text_area.text = "coXXect"
text_area.color = 0xFFFF00 #yellow
text_group.scale = 5
# initialize the mouse cursor object
# place over all others
mouse_cursor = adafruit_cursorcontrol.cursorcontrol.Cursor(
display, display_group=bgGroup)
mouse_cursor.x = int(display.width/2)
mouse_cursor.y = int(display.height/2)
while True:
# if the screen is being touched print the touches
if ft.touched:
touches = ft.touches
#sometimes ft.touches is [], empty!
#so I check len to prevent IndexError: index out of range
if len(touches)>0:
#print(touches)
x = touches[0]['x']
y = touches[0]['y']
mouse_cursor.x = x
mouse_cursor.y = y
x_area.text = str(x)
y_area.text = str(y)
else:
print('no touch')
time.sleep(.3)
cpyS3_st7789_9bitSPI_FT6236_visualSquare.py, a exercise of Visual Illusion.
"""
CircuitPython exercise run on Waveshare ESP32-S3-Zero,
to display on IPS with ST7789 3-wire 9-bit SPI driver
and capacitive touch FT6236G, WLK1501SPI-8P.
Visual illusion:
Both square have the same gray level, but visually changed.
Test on:
dev. board: Waveshare ESP32-S3-Zero
CircuitPython: 9.0.0-beta.0
Libraries needed:
- adafruit_st7789.mpy
- my_focaltouch.py (adafruit_focaltouch.mpy)
- adafruit_cursorcontrol folder
- adafruit_display_text folder
"""
import os, sys
import board
import busio
import terminalio
import displayio
import fourwire
from adafruit_display_shapes.rect import Rect
import adafruit_st7789
import my_focaltouch
from digitalio import DigitalInOut, Direction
from adafruit_simplemath import map_range
import time
# Release any resources currently in use for the displays
displayio.release_displays()
#===init display ======================
#Connection to ST7789
DISP_SCL = board.IO12
DISP_SDA = board.IO11
DISP_RES = board.IO13
DISP_DC = None
DISP_CS = board.IO10
DISP_BL = board.IO7
#Connection to FT6236G
TOUCH_SCL = board.IO9
TOUCH_SDA = board.IO8
TOUCH_INT = board.IO6 #optional
TOUCH_RST = board.IO5 #optional
touch_irq = DigitalInOut(TOUCH_INT)
touch_irq.direction = Direction.INPUT
touch_res = DigitalInOut(TOUCH_RST)
touch_res.direction = Direction.OUTPUT
touch_res.value = True
time.sleep(0.1)
touch_res.value = False
time.sleep(0.1)
touch_res.value = True
time.sleep(0.1)
disp_spi = busio.SPI(clock=DISP_SCL,
MOSI=DISP_SDA)
touch_i2c = busio.I2C(TOUCH_SCL, TOUCH_SDA)
ft = my_focaltouch.My_FocalTouch(touch_i2c, debug=False, irq_pin=touch_irq)
"""
On CircuitPython 9
FutureWarning: FourWire moved from displayio to fourwire
If the command pin is not specified, a 9-bit SPI mode will be SIMULATED.
ref: https://docs.circuitpython.org/en/latest/shared-bindings/fourwire/index.html#fourwire.FourWire
"""
#display_bus = displayio.FourWire(disp_spi, command=DISP_DC, chip_select=DISP_CS, reset=DISP_RES)
display_bus = fourwire.FourWire(disp_spi, command=DISP_DC, chip_select=DISP_CS, reset=DISP_RES)
#--- Setup display ---
# for 1.54" 240x240 3-wire 9-bit SPI ST7789 TFT
disp_width = 240
disp_height = 240
display = adafruit_st7789.ST7789(display_bus,
width=disp_width,
height=disp_height,
rowstart=40,
backlight_pin=DISP_BL)
# Make the display context
bgGroup = displayio.Group()
"""
show() is deprecated and will be removed in CircuitPython 9.0.0. Use .root_group = group instead.
https://docs.circuitpython.org/en/8.2.x/shared-bindings/displayio/index.html#displayio.Display.show
"""
#display.show(bgGroup)
display.root_group = bgGroup
# background
no_of_color = display.height
bg_bitmap = displayio.Bitmap(display.width, display.height, no_of_color)
bg_palette = displayio.Palette(no_of_color)
bg_sprite = displayio.TileGrid(bg_bitmap, pixel_shader=bg_palette, x=0, y=0)
for i in range(no_of_color):
lv = int(map_range(i, 0, no_of_color, 0, 0xFF))
bg_palette[i] = lv*0x10000 + lv*0x100 + lv
for y in range(display.height):
for x in range(display.width):
bg_bitmap[x, y] = y
bgGroup.append(bg_sprite)
# end of background
sq = Rect(20, 20, 50, 50, fill=0xA0A0A0)
bgGroup.append(sq)
sq2 = Rect(80, 20, 50, 50, fill=0xA0A0A0)
bgGroup.append(sq2)
while True:
# if the screen is being touched print the touches
if ft.touched:
touches = ft.touches
#sometimes ft.touches is [], empty!
#so I check len to prevent IndexError: index out of range
if len(touches)>0:
#print(touches)
x = touches[0]['x']
y = touches[0]['y']
sq.y = y
else:
print('no touch')
time.sleep(.3)
Updated@2024-02-11
As stated above, starting in CircuitPython 9.x FourWire moved from displayio to fourwire. In order to make it work on both CircuitPython 8 and 9, the "import fourwire" statement can be modified as:
try:
from fourwire import FourWire
except ImportError:
from displayio import FourWire
And the "display_bus = fourwire.FourWire(disp_spi, ..." statement change to:
display_bus = FourWire(disp_spi, ...
Comments
Post a Comment