Wednesday, August 25, 2021

Bi-direction BLE communication between Raspberry Pi/Python (with PyQt5 GUI) and ESP32/Arduino Nano RP2040 Connect

Raspberry Pi/Python/bluepy + ESP32

With bluepy installed, this exercise implement BLE client side on Raspberry Pi using Python, connect to ESP32 BLE uart server, send and receive data in between.


Prepare ESP32 BLE_uart

ESP32 side (NodeMCU ESP-32S) is programmed in Arduino framework. 

In Arduino IDE
- Open Examples > ESP32 BLE Arduino > BLE_uart in Arduino IDE, and upload to ESP32 board.

It's a BLE setup as server, wait connection. Once connected, send data to client repeatedly and display received data to Serial Monitor.

Test with nRF Connect App 

To verify the function of ESP32 BLE_art on Android device, install nRF Connect for Mobile App by Nordic Semiconductor ASA.

Simple test Python code -

Automatically connect to BLE_uart, send and receive data repeatedly.

 ex_bluepy_uart.py

from bluepy import btle
import time

class MyDelegate(btle.DefaultDelegate):
    def __init__(self):
        btle.DefaultDelegate.__init__(self)
        # ... initialise here

    def handleNotification(self, cHandle, data):
        #print("\n- handleNotification -\n")
        print(data)
        # ... perhaps check cHandle
        # ... process 'data'

# Initialisation  -------

p = btle.Peripheral("3c:71:bf:0d:dd:6a")   #NodeMCU-32S
#p = btle.Peripheral("24:0a:c4:e8:0f:9a")   #ESP32-DevKitC V4

# Setup to turn notifications on, e.g.
svc = p.getServiceByUUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E")
ch_Tx = svc.getCharacteristics("6E400002-B5A3-F393-E0A9-E50E24DCCA9E")[0]
ch_Rx = svc.getCharacteristics("6E400003-B5A3-F393-E0A9-E50E24DCCA9E")[0]

p.setDelegate( MyDelegate())

setup_data = b"\x01\00"
p.writeCharacteristic(ch_Rx.valHandle+1, setup_data)

lasttime = time.localtime()

while True:
    """
    if p.waitForNotifications(1.0):
        pass  #continue

    print("Waiting...")
    """
    
    nowtime = time.localtime()
    if(nowtime > lasttime):
        lasttime = nowtime
        stringtime = time.strftime("%H:%M:%S", nowtime)
        btime = bytes(stringtime, 'utf-8')
        try:
            ch_Tx.write(btime, True)
        except btle.BTLEException:
            print("btle.BTLEException");
        #print(stringtime)
        #ch_Tx.write(b'wait...', True)
        
    # Perhaps do something else here
Python code with PyQt5 GUI -
- Click "Start BLE" button to connect to BLE_uart.
- Display received data on QPlainTextEdit, and send user entered data to BLE



pyqt5_bluepy_thread_.py
import sys
import time

import requests
from PyQt5.QtCore import QObject, QRunnable, QThreadPool, QTimer, pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import (
    QApplication, QLabel, QMainWindow,  QPlainTextEdit, QPushButton, QVBoxLayout, QWidget,
    )

from bluepy import btle

class WorkerSignals(QObject):
    signalMsg = pyqtSignal(str)
    signalRes = pyqtSignal(str)
    
class MyDelegate(btle.DefaultDelegate):
    
    def __init__(self, sgn):
        btle.DefaultDelegate.__init__(self)
        self.sgn = sgn

    def handleNotification(self, cHandle, data):
        
        try:
            dataDecoded = data.decode()
            self.sgn.signalRes.emit(dataDecoded)
        except UnicodeError:
            print("UnicodeError: ", data)

class WorkerBLE(QRunnable):
    
    def __init__(self):
        super().__init__()
        self.signals = WorkerSignals()
        self.rqsToSend = False
        
    @pyqtSlot()
    def run(self):
        self.signals.signalMsg.emit("WorkerBLE start")
        
        #---------------------------------------------
        p = btle.Peripheral("3c:71:bf:0d:dd:6a")
        p.setDelegate( MyDelegate(self.signals) )

        svc = p.getServiceByUUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E")
        self.ch_Tx = svc.getCharacteristics("6E400002-B5A3-F393-E0A9-E50E24DCCA9E")[0]
        ch_Rx = svc.getCharacteristics("6E400003-B5A3-F393-E0A9-E50E24DCCA9E")[0]

        setup_data = b"\x01\00"
        p.writeCharacteristic(ch_Rx.valHandle+1, setup_data)

        # BLE loop --------

        while True:
            """
            if p.waitForNotifications(1.0):
                # handleNotification() was called
                continue

            print("Waiting...")
            """
            
            p.waitForNotifications(1.0)
            
            if self.rqsToSend:
                self.rqsToSend = False

                try:
                    self.ch_Tx.write(self.bytestosend, True)
                except btle.BTLEException:
                    print("btle.BTLEException");
            
        #---------------------------------------------hellohello
        self.signals.signalMsg.emit("WorkerBLE end")
        
    def toSendBLE(self, tosend):
        self.bytestosend = bytes(tosend, 'utf-8')
        self.rqsToSend = True
        """
        try:
            self.ch_Tx.write(bytestosend, True)
        except BTLEException:
            print("BTLEException");
        """
            
class MainWindow(QMainWindow):
    
    def __init__(self):
        super().__init__()
        
        layout = QVBoxLayout()
        
        buttonStartBLE = QPushButton("Start BLE")
        buttonStartBLE.pressed.connect(self.startBLE)
        
        self.console = QPlainTextEdit()
        self.console.setReadOnly(True)
        
        self.outconsole = QPlainTextEdit()
        
        buttonSendBLE = QPushButton("Send message")
        buttonSendBLE.pressed.connect(self.sendBLE)

        layout.addWidget(buttonStartBLE)
        layout.addWidget(self.console)
        layout.addWidget(self.outconsole)
        layout.addWidget(buttonSendBLE)
        
        w = QWidget()
        w.setLayout(layout)
        
        self.setCentralWidget(w)
        
        self.show()
        self.threadpool = QThreadPool()
        print(
            "Multithreading with Maximum %d threads" % self.threadpool.maxThreadCount())
            
    def startBLE(self):
        self.workerBLE = WorkerBLE()
        self.workerBLE.signals.signalMsg.connect(self.slotMsg)
        self.workerBLE.signals.signalRes.connect(self.slotRes)
        self.threadpool.start(self.workerBLE)
        
    def sendBLE(self):
        strToSend = self.outconsole.toPlainText()
        self.workerBLE.toSendBLE(strToSend)
        
    def slotMsg(self, msg):
        print(msg)
        
    def slotRes(self, res):
        self.console.appendPlainText(res)
        
app = QApplication(sys.argv)
window = MainWindow()
app.exec()



Raspberry Pi/Python/bluepy + Arduino Nano RP2040 Connect

Now, replace ESP32 with Arduino Nano RP2040 Connect, running following code using ArduinoBLE library. Please  note that you have to modify Python code to match with Arduino Nano RP2040 Connect's MAC address.


BLE_peripheral_uart.ino
/*
 * BLE_peripheral_uart:
 * modifid from Examples > ArduinoBLE > Peripheral > CallbackLED
 * 
 * Bi-direction BLE communication between Raspberry Pi/Python (with PyQt5 GUI) 
 * and ESP32/Arduino Naon RP2040 Connect
 * http://helloraspberrypi.blogspot.com/2021/08/bi-direction-ble-communication-between.html
 * 
*/

#include <ArduinoBLE.h>

#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"

//BLEService ledService("19B10000-E8F2-537E-4F6C-D104768A1214"); // create service
BLEService uartService(SERVICE_UUID); // create service

// create switch characteristic and allow remote device to read and write
//BLEByteCharacteristic switchCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);

BLEStringCharacteristic rxCharacteristic(CHARACTERISTIC_UUID_RX, BLEWrite, 30);
BLEStringCharacteristic txCharacteristic(CHARACTERISTIC_UUID_TX, BLENotify, 30);

// const int ledPin = LED_BUILTIN; // pin to use for the LED

void setup() {
  Serial.begin(115200);
  while (!Serial);
  
  // pinMode(ledPin, OUTPUT); // use the LED pin as an output

  // begin initialization
  if (!BLE.begin()) {
    Serial.println("starting BLE failed!");

    while (1);
  }
  
  // set the local name peripheral advertises
  BLE.setLocalName("BLE_peripheral_uart");
  // set the UUID for the service this peripheral advertises
  BLE.setAdvertisedService(uartService);

  // add the characteristic to the service
  uartService.addCharacteristic(rxCharacteristic);
  uartService.addCharacteristic(txCharacteristic);

  // add service
  BLE.addService(uartService);

  // assign event handlers for connected, disconnected to peripheral
  BLE.setEventHandler(BLEConnected, blePeripheralConnectHandler);
  BLE.setEventHandler(BLEDisconnected, blePeripheralDisconnectHandler);

  // assign event handlers for characteristic
  rxCharacteristic.setEventHandler(BLEWritten, rxCharacteristicWritten);
  // set an initial value for the characteristic
  rxCharacteristic.setValue("BLE_peripheral_uart");

  // start advertising
  BLE.advertise();

  Serial.println(("Bluetooth device active, waiting for connections..."));
  Serial.println(BLE.address());
}

void loop() {
  // poll for BLE events
  BLE.poll();
}

void blePeripheralConnectHandler(BLEDevice central) {
  // central connected event handler
  Serial.print("Connected event, central: ");
  Serial.println(central.address());
}

void blePeripheralDisconnectHandler(BLEDevice central) {
  // central disconnected event handler
  Serial.print("Disconnected event, central: ");
  Serial.println(central.address());
}

void rxCharacteristicWritten(BLEDevice central, BLECharacteristic characteristic) {
  // central wrote new value to characteristic, update LED
  Serial.print("Characteristic event, written: ");

  Serial.println("len=" + 
                  String(rxCharacteristic.valueLength()));
  String valString = rxCharacteristic.value();
  Serial.println(valString);
  valString.toUpperCase();
  Serial.println(valString);
  txCharacteristic.setValue(valString);
}



Wednesday, August 18, 2021

ov7670/ov2640 + ST7789 (IPS Display) on Raspberry Pi Pico/CircuitPython 7.0.0 alpha 6

This post show how to connect OV7670/OV2640 0.3-Megapixel Camera Module to Raspberry Pi Pico (in CircuitPython 7.0.0 alpha 6), display on ST7789 SPI IPS screen; running example ov2640_jpeg_sd_pico_st7789_2in.py.

ov7670:


It's library named adafruit_ov7670.mpy and example named ov7670_displayio_pico_st7789_2in.py in CircuitPython Bundle Libraries. I tried to run it on Pico with current stable CircuitPython 6.3.0. But fail with error of:

ImportError: cannot import name Colorspace


Then I tried on CircuitPython 7.0.0 alpha 6.

The connection between Pico and ov7670 camera module and st7789 SPI IPS display follow the ov7670_displayio_pico_st7789_2in.py example. But I have to add reset pin for display.


Connection:
Connection between Pico and ov7670 cam module
=============================================
	+-----------+
3V3	|3V3	DGND|	GND
GP9	|SCL	SDA |	GP8
GP7	|VS	HS  |	GP21
GP11	|PLK	XLK |	GP20
GP19	|D7	D6  |	GP18
GP17	|D5	D4  |	GP16
GP15	|D3	D2  |	GP14
GP13	|D1	D0  |	GP12
GP10	|RET	PWDN|
	+-----------+
		
*SCL/SDA are I2C control pin, pull-up resistors are needed.
 I use 2K ohm resistor for it.
		
Connection between Pico and ST7789 SPI IPS
==========================================
3V3		BLK
GP1		CS
GP0		DC
GP4		RES
GP3		SDA
GP2		SCL
3V3		VCC
GND		GND

Makesure Raspberry Pi Pico is installed with CircuitPython 7.0.0 alpha 6, download the matched bundle libraries 7.x. Copy adafruit_st7789.mpy and adafruit_ov7670.mpy from lib folder to Pico CIRCUITPY lib folder. Modify ov7670_displayio_pico_st7789_2in.py from examples folder to add reset pin to GP4, as shown in above screenshot.

remark:
In my test, once the program ran and stopped, to re-run it, have to disconnect and reconnect USB to Pico.



ov2640:


My ov2640 module have same pin assignment in ov7670, aligned to top with D0/D1 opened.

Connection:
Connection between Pico and ov2640 cam module
=============================================
	+-----------+
3V3	|3V3	GND |	GND
GP9	|SIOC	SIOD|	GP8
GP7	|VSYNC	HREF|	GP21
GP11	|PCLK	XCLK|	GP20
GP19	|D9	D8  |	GP18
GP17	|D7	D6  |	GP16
GP15	|D5	D4  |	GP14
GP13	|D3	D2  |	GP12
GP10	|RESET	PWDN|
	|D1	D0  |
	+-----------+
		
Library:
Copy adafruit_ov2640.mpy and adafruit_st7789.mpy from CircuitPython bundle 7.x lib to CIRCUITPY lib folder.

Example:

Locate and edit ov2640_displayio_pico_st7789_2in.py from CircuitPython bundle 7.x examples, as shown in this video:


Wednesday, August 11, 2021

ST7789 SPI (2" 240x320/1.54" 240x240) IPS RGB Display, on Raspberry Pi Pico/CircuitPython

Test 2" 240x320 and 1.54" 240x240 ST7789 SPI IPS RGB Display, on Raspberry Pi Pico/CircuitPython.


Connection:

3V3  - BLK
GP11 - CS
GP12 - DC
GP13 - RES
GP15 - SDA
GP14 - SCL
3V3  - VCC
GND  - GND

Prepare Libraries:

Visit https://circuitpython.org/libraries, download the appropriate bundle for your version of CircuitPython.

Unzip the file, copy adafruit_st7789.mpy, adafruit_display_text and adafruit_display_shapes folder to the lib folder on your CIRCUITPY drive.


Examples code for 2" 240x320 ST7789 SPI IPS RGB Display :

cpyPico_spiST7789_320.py
"""
Example of CircuitPython/RaspberryPi Pico
to display on 2.0" IPS 240x320 (RGB) screen
with ST7789 driver via SPI interface.

Connection between Pico and
the IPS screen, with ST7789 SPI interface.
3V3  - BLK (backlight, always on)
GP11 - CS
GP12 - DC
GP13 - RES
GP15 - SDA
GP14 - SCL
3V3  - VCC
GND  - GND
"""

import os
import board
import time
import terminalio
import displayio
import busio
from adafruit_display_text import label
#from adafruit_st7789 import ST7789
import adafruit_st7789

print("==============================")
print(os.uname())
print("Hello Raspberry Pi Pico/CircuitPython ST7789 SPI IPS Display")
print(adafruit_st7789.__name__ + " version: " + adafruit_st7789.__version__)
print()

# Release any resources currently in use for the displays
displayio.release_displays()

tft_cs = board.GP11
tft_dc = board.GP12
tft_res = board.GP13
spi_mosi = board.GP15
spi_clk = board.GP14

"""
classbusio.SPI(clock: microcontroller.Pin,
                MOSI: Optional[microcontroller.Pin] = None,
                MISO: Optional[microcontroller.Pin] = None)
"""
spi = busio.SPI(spi_clk, MOSI=spi_mosi)

display_bus = displayio.FourWire(
    spi, command=tft_dc, chip_select=tft_cs, reset=tft_res
)

display = adafruit_st7789.ST7789(display_bus,
                    width=240, height=320)

# Make the display context
splash = displayio.Group(max_size=10)
display.show(splash)

color_bitmap = displayio.Bitmap(135, 240, 1)
color_palette = displayio.Palette(1)
color_palette[0] = 0x00FF00

bg_sprite = displayio.TileGrid(color_bitmap,
                               pixel_shader=color_palette, x=0, y=0)
splash.append(bg_sprite)

# Draw a smaller inner rectangle
inner_bitmap = displayio.Bitmap(133, 238, 1)
inner_palette = displayio.Palette(1)
inner_palette[0] = 0x0000FF
inner_sprite = displayio.TileGrid(inner_bitmap,
                                  pixel_shader=inner_palette, x=1, y=1)
splash.append(inner_sprite)

# Draw a label
text_group1 = displayio.Group(max_size=10, scale=2, x=20, y=40)
text1 = "RPi Pico"
text_area1 = label.Label(terminalio.FONT, text=text1, color=0xFF0000)
text_group1.append(text_area1)  # Subgroup for text scaling
# Draw a label
text_group2 = displayio.Group(max_size=10, scale=1, x=20, y=60)
text2 = "CircuitPython"
text_area2 = label.Label(terminalio.FONT, text=text2, color=0xFFFFFF)
text_group2.append(text_area2)  # Subgroup for text scaling

# Draw a label
text_group3 = displayio.Group(max_size=10, scale=1, x=20, y=100)
text3 = adafruit_st7789.__name__
text_area3 = label.Label(terminalio.FONT, text=text3, color=0x0000000)
text_group3.append(text_area3)  # Subgroup for text scaling
# Draw a label
text_group4 = displayio.Group(max_size=10, scale=2, x=20, y=120)
text4 = adafruit_st7789.__version__
text_area4 = label.Label(terminalio.FONT, text=text4, color=0x000000)
text_group4.append(text_area4)  # Subgroup for text scaling

splash.append(text_group1)
splash.append(text_group2)
splash.append(text_group3)
splash.append(text_group4)

time.sleep(3.0)

rot = 0
while True:
    time.sleep(5.0)
    rot = rot + 90
    if (rot>=360):
        rot =0
    display.rotation = rot

cpyPico_spiST7789_bitmap_320.py
"""
Example of CircuitPython/Raspberry Pi Pico
to display on 2.0" IPS 240x320 (RGB) screen
with ST7789 driver via SPI interface.

Connection between Pico and
the IPS screen, with ST7789 SPI interface.
3V3  - BLK (backlight, always on)
GP11 - CS
GP12 - DC
GP13 - RES
GP15 - SDA
GP14 - SCL
3V3  - VCC
GND  - GND
"""

import os
import board
import time
import terminalio
import displayio
import busio
from adafruit_display_text import label
import adafruit_st7789

print("==============================")
print(os.uname())
print("Hello Raspberry Pi Pico/CircuitPython ST7789 SPI IPS Display")
print(adafruit_st7789.__name__ + " version: " + adafruit_st7789.__version__)
print()

# Release any resources currently in use for the displays
displayio.release_displays()

tft_cs = board.GP11
tft_dc = board.GP12
tft_res = board.GP13
spi_mosi = board.GP15
spi_clk = board.GP14

"""
classbusio.SPI(clock: microcontroller.Pin,
                MOSI: Optional[microcontroller.Pin] = None,
                MISO: Optional[microcontroller.Pin] = None)
"""
spi = busio.SPI(spi_clk, MOSI=spi_mosi)

display_bus = displayio.FourWire(
    spi, command=tft_dc, chip_select=tft_cs, reset=tft_res
)

display = adafruit_st7789.ST7789(display_bus,
                    width=240, height=320)
display.rotation = 270

group = displayio.Group(max_size=10)
display.show(group)

bitmap_width = 320
bitmap_height = 240
bitmap = displayio.Bitmap(bitmap_width, bitmap_height, bitmap_height)

palette = displayio.Palette(bitmap_height)
for p in range(bitmap_height):
    palette[p] = (0x010000*p) + (0x0100*p) + p

for y in range(bitmap_height):
    for x in range(bitmap_width):
        bitmap[x,y] = y
        
tileGrid = displayio.TileGrid(bitmap, pixel_shader=palette, x=0, y=0)
group.append(tileGrid)

time.sleep(3.0)

while True:
    for p in range(bitmap_height):
        palette[p] = p
    time.sleep(3.0)

    for p in range(bitmap_height):
        palette[p] = 0x0100 * p
    time.sleep(3.0)

    for p in range(bitmap_height):
        palette[p] = 0x010000 * p
    time.sleep(3.0)

cpyPico_spiST7789_shape_320.py
"""
Example of CircuitPython/Raspberry Pi Pico
to display on 2.0" IPS 240x320 (RGB) screen
with ST7789 driver via SPI interface.

modify example from:
https://circuitpython.readthedocs.io/projects/display-shapes/en/latest/index.html

Connection between Pico and
the IPS screen, with ST7789 SPI interface.
3V3  - BLK (backlight, always on)
GP11 - CS
GP12 - DC
GP13 - RES
GP15 - SDA
GP14 - SCL
3V3  - VCC
GND  - GND
"""

import os
import board
import time
import terminalio
import displayio
import busio
import adafruit_st7789
from adafruit_display_shapes.rect import Rect
from adafruit_display_shapes.circle import Circle
from adafruit_display_shapes.roundrect import RoundRect
from adafruit_display_shapes.triangle import Triangle

print("==============================")
print(os.uname())
print("Hello Raspberry Pi Pico/CircuitPython ST7789 SPI IPS Display")
print(adafruit_st7789.__name__ + " version: " + adafruit_st7789.__version__)
print()

# Release any resources currently in use for the displays
displayio.release_displays()

tft_cs = board.GP11
tft_dc = board.GP12
tft_res = board.GP13
spi_mosi = board.GP15
spi_clk = board.GP14

"""
classbusio.SPI(clock: microcontroller.Pin,
                MOSI: Optional[microcontroller.Pin] = None,
                MISO: Optional[microcontroller.Pin] = None)
"""
spi = busio.SPI(spi_clk, MOSI=spi_mosi)

display_bus = displayio.FourWire(
    spi, command=tft_dc, chip_select=tft_cs, reset=tft_res
)

display = adafruit_st7789.ST7789(display_bus,
                    width=240, height=320)
display.rotation = 270

splash = displayio.Group()
display.show(splash)

color_bitmap = displayio.Bitmap(320, 240, 1)
color_palette = displayio.Palette(1)
color_palette[0] = 0xFFFFFF
bg_sprite = displayio.TileGrid(color_bitmap, pixel_shader=color_palette, x=0, y=0)
splash.append(bg_sprite)

triangle = Triangle(170, 50, 120, 140, 210, 160, fill=0x00FF00, outline=0xFF00FF)
splash.append(triangle)

rect = Rect(80, 20, 41, 41, fill=0x0)
splash.append(rect)

circle = Circle(100, 100, 20, fill=0x00FF00, outline=0xFF00FF)
splash.append(circle)

rect2 = Rect(50, 100, 61, 81, outline=0x0, stroke=3)
splash.append(rect2)

roundrect = RoundRect(10, 10, 61, 81, 10, fill=0x0, outline=0xFF00FF, stroke=6)
splash.append(roundrect)

while True:
    pass

Examples code for 1.54" 240x240 ST7789 SPI IPS RGB Display :


cpyPico_spiST7789_240.py
"""
Example of CircuitPython/RaspberryPi Pico
to display on 2.0" IPS 240x320 (RGB) screen
with ST7789 driver via SPI interface.

Connection between Pico and
the IPS screen, with ST7789 SPI interface.
3V3  - BLK (backlight, always on)
GP11 - CS
GP12 - DC
GP13 - RES
GP15 - SDA
GP14 - SCL
3V3  - VCC
GND  - GND
"""

import os
import board
import time
import terminalio
import displayio
import busio
from adafruit_display_text import label
#from adafruit_st7789 import ST7789
import adafruit_st7789

print("==============================")
print(os.uname())
print("Hello Raspberry Pi Pico/CircuitPython ST7789 SPI IPS Display")
print(adafruit_st7789.__name__ + " version: " + adafruit_st7789.__version__)
print()

# Release any resources currently in use for the displays
displayio.release_displays()

tft_cs = board.GP11
tft_dc = board.GP12
tft_res = board.GP13
spi_mosi = board.GP15
spi_clk = board.GP14

"""
classbusio.SPI(clock: microcontroller.Pin,
                MOSI: Optional[microcontroller.Pin] = None,
                MISO: Optional[microcontroller.Pin] = None)
"""
spi = busio.SPI(spi_clk, MOSI=spi_mosi)

display_bus = displayio.FourWire(
    spi, command=tft_dc, chip_select=tft_cs, reset=tft_res
)

display = adafruit_st7789.ST7789(display_bus,
                    width=240, height=240, rowstart=80)

# Make the display context
splash = displayio.Group(max_size=10)
display.show(splash)

color_bitmap = displayio.Bitmap(135, 240, 1)
color_palette = displayio.Palette(1)
color_palette[0] = 0x00FF00

bg_sprite = displayio.TileGrid(color_bitmap,
                               pixel_shader=color_palette, x=0, y=0)
splash.append(bg_sprite)

# Draw a smaller inner rectangle
inner_bitmap = displayio.Bitmap(133, 238, 1)
inner_palette = displayio.Palette(1)
inner_palette[0] = 0x0000FF
inner_sprite = displayio.TileGrid(inner_bitmap,
                                  pixel_shader=inner_palette, x=1, y=1)
splash.append(inner_sprite)

# Draw a label
text_group1 = displayio.Group(max_size=10, scale=2, x=20, y=40)
text1 = "RPi Pico"
text_area1 = label.Label(terminalio.FONT, text=text1, color=0xFF0000)
text_group1.append(text_area1)  # Subgroup for text scaling
# Draw a label
text_group2 = displayio.Group(max_size=10, scale=1, x=20, y=60)
text2 = "CircuitPython"
text_area2 = label.Label(terminalio.FONT, text=text2, color=0xFFFFFF)
text_group2.append(text_area2)  # Subgroup for text scaling

# Draw a label
text_group3 = displayio.Group(max_size=10, scale=1, x=20, y=100)
text3 = adafruit_st7789.__name__
text_area3 = label.Label(terminalio.FONT, text=text3, color=0x0000000)
text_group3.append(text_area3)  # Subgroup for text scaling
# Draw a label
text_group4 = displayio.Group(max_size=10, scale=2, x=20, y=120)
text4 = adafruit_st7789.__version__
text_area4 = label.Label(terminalio.FONT, text=text4, color=0x000000)
text_group4.append(text_area4)  # Subgroup for text scaling

splash.append(text_group1)
splash.append(text_group2)
splash.append(text_group3)
splash.append(text_group4)

time.sleep(3.0)

rot = 0
while True:
    time.sleep(5.0)
    rot = rot + 90
    if (rot>=360):
        rot =0
    display.rotation = rot

cpyPico_spiST7789_bitmap_240.py
"""
Example of CircuitPython/Raspberry Pi Pico
to display on 2.0" IPS 240x320 (RGB) screen
with ST7789 driver via SPI interface.

Connection between Pico and
the IPS screen, with ST7789 SPI interface.
3V3  - BLK (backlight, always on)
GP11 - CS
GP12 - DC
GP13 - RES
GP15 - SDA
GP14 - SCL
3V3  - VCC
GND  - GND
"""

import os
import board
import time
import terminalio
import displayio
import busio
from adafruit_display_text import label
import adafruit_st7789

print("==============================")
print(os.uname())
print("Hello Raspberry Pi Pico/CircuitPython ST7789 SPI IPS Display")
print(adafruit_st7789.__name__ + " version: " + adafruit_st7789.__version__)
print()

# Release any resources currently in use for the displays
displayio.release_displays()

tft_cs = board.GP11
tft_dc = board.GP12
tft_res = board.GP13
spi_mosi = board.GP15
spi_clk = board.GP14

"""
classbusio.SPI(clock: microcontroller.Pin,
                MOSI: Optional[microcontroller.Pin] = None,
                MISO: Optional[microcontroller.Pin] = None)
"""
spi = busio.SPI(spi_clk, MOSI=spi_mosi)

display_bus = displayio.FourWire(
    spi, command=tft_dc, chip_select=tft_cs, reset=tft_res
)

display = adafruit_st7789.ST7789(display_bus,
                    width=240, height=240, rowstart=80)
display.rotation = 270

group = displayio.Group(max_size=10)
display.show(group)

bitmap_width = 240
bitmap_height = 240
bitmap = displayio.Bitmap(bitmap_width, bitmap_height, bitmap_height)

palette = displayio.Palette(bitmap_height)
for p in range(bitmap_height):
    palette[p] = (0x010000*p) + (0x0100*p) + p

for y in range(bitmap_height):
    for x in range(bitmap_width):
        bitmap[x,y] = y
        
tileGrid = displayio.TileGrid(bitmap, pixel_shader=palette, x=0, y=0)
group.append(tileGrid)

time.sleep(3.0)

while True:
    for p in range(bitmap_height):
        palette[p] = p
    time.sleep(3.0)

    for p in range(bitmap_height):
        palette[p] = 0x0100 * p
    time.sleep(3.0)

    for p in range(bitmap_height):
        palette[p] = 0x010000 * p
    time.sleep(3.0)

cpyPico_spiST7789_shape_240.py
"""
Example of CircuitPython/Raspberry Pi Pico
to display on 2.0" IPS 240x320 (RGB) screen
with ST7789 driver via SPI interface.

modify example from:
https://circuitpython.readthedocs.io/projects/display-shapes/en/latest/index.html

Connection between Pico and
the IPS screen, with ST7789 SPI interface.
3V3  - BLK (backlight, always on)
GP11 - CS
GP12 - DC
GP13 - RES
GP15 - SDA
GP14 - SCL
3V3  - VCC
GND  - GND
"""

import os
import board
import time
import terminalio
import displayio
import busio
import adafruit_st7789
from adafruit_display_shapes.rect import Rect
from adafruit_display_shapes.circle import Circle
from adafruit_display_shapes.roundrect import RoundRect
from adafruit_display_shapes.triangle import Triangle

print("==============================")
print(os.uname())
print("Hello Raspberry Pi Pico/CircuitPython ST7789 SPI IPS Display")
print(adafruit_st7789.__name__ + " version: " + adafruit_st7789.__version__)
print()

# Release any resources currently in use for the displays
displayio.release_displays()

tft_cs = board.GP11
tft_dc = board.GP12
tft_res = board.GP13
spi_mosi = board.GP15
spi_clk = board.GP14

"""
classbusio.SPI(clock: microcontroller.Pin,
                MOSI: Optional[microcontroller.Pin] = None,
                MISO: Optional[microcontroller.Pin] = None)
"""
spi = busio.SPI(spi_clk, MOSI=spi_mosi)

display_bus = displayio.FourWire(
    spi, command=tft_dc, chip_select=tft_cs, reset=tft_res
)

display = adafruit_st7789.ST7789(display_bus,
                    width=240, height=240, rowstart=80)
display.rotation = 270

splash = displayio.Group()
display.show(splash)

color_bitmap = displayio.Bitmap(240, 240, 1)
color_palette = displayio.Palette(1)
color_palette[0] = 0xFFFFFF
bg_sprite = displayio.TileGrid(color_bitmap, pixel_shader=color_palette, x=0, y=0)
splash.append(bg_sprite)

triangle = Triangle(170, 50, 120, 140, 210, 160, fill=0x00FF00, outline=0xFF00FF)
splash.append(triangle)

rect = Rect(80, 20, 41, 41, fill=0x0)
splash.append(rect)

circle = Circle(100, 100, 20, fill=0x00FF00, outline=0xFF00FF)
splash.append(circle)

rect2 = Rect(50, 100, 61, 81, outline=0x0, stroke=3)
splash.append(rect2)

roundrect = RoundRect(10, 10, 61, 81, 10, fill=0x0, outline=0xFF00FF, stroke=6)
splash.append(roundrect)

while True:
    pass


Related:

Next: