element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Raspberry Pi
  • Products
  • More
Raspberry Pi
Raspberry Pi Forum RPI Pico & ST7789 Display
  • Blog
  • Forum
  • Documents
  • Quiz
  • Events
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Raspberry Pi to participate - click to join for free!
Featured Articles
Announcing Pi
Technical Specifications
Raspberry Pi FAQs
Win a Pi
Raspberry Pi Wishlist
Actions
  • Share
  • More
  • Cancel
Forum Thread Details
  • Replies 15 replies
  • Subscribers 661 subscribers
  • Views 16458 views
  • Users 0 members are here
  • st7789
  • rpi pico
Related

RPI Pico & ST7789 Display

scottiebabe
scottiebabe over 3 years ago

I purchased an off brand ST7789 1.3" Display a few months ago and recently decided it was time to try it out.

 

I did not realize it at the time but there isn't a consistent pinout between display boards. As it turns out the board I purchased did not pin out the chip-select (CS) line.

 

The ST7789 display driver will function without a CS line, however you need to configure the SPI mode (idle state, edge polarity) to communicate with the display. In most cases, I suppose that would be easy enough to change the display driver.

 

Now I wanted to make use of this display with a PI Pico and Micropython. Pimoroni provide a Micropython release with a small number additional libraries on top of MicroPython : https://github.com/pimoroni/pimoroni-pico (unlike CircuitPython which is significantly different from MicroPython).

 

I was trying to get their example code for one of their displays: https://shop.pimoroni.com/products/1-3-spi-colour-lcd-240x240-breakout to function with my off brand display. Unfortunately, I could not find a way to change the SPI operating mode of the display driver unless I wanted to compile their distribution from source (which I didn't want to do), the SPI initialization was all buried in C code.

 

An intsructables author provided a wonderful guide to breaking out the chip-select line: https://www.instructables.com/Adding-CS-Pin-to-13-LCD/  Many thanks. In the process of modify my display I learned a few things the hard way:

  • Rotated R1 90' to bypass the NPN switch
  • Tossed R2 away and used this as the CS pad
  • Be carful with getting the display too hot. The adhesive that held the display in place virtually no longer exists now image
  • Be carful cleaning! Or don't clean at all. I ended up relocating the flux residue with isopropyl from the PCB to inside the display housing and its now a little merky image

image

 

After the display modifications the display came to life!

 

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

 

I have never used one of these displays before, but I have to say I am impressed. I was able to get 35 FPS out of a 240x240 display running over SPI.

 

I still don't know what the best way to add graphics to the PICO is. The image I showed in the video was created with ffmpeg outputting a raw video frame:

 

ffmpeg -vcodec png -i img.png -vcodec rawvideo -f rawvideo -pix_fmt rgb565 img.raw

 

Of this random image cropped down to 240x240:

image

Loading the image from flash was very slow.

 

Update: Image Loading Speed

The framebuffer for the ST7789 is stored big-endian so when I was loading the Image I had endian swap in python which was really slow. I can endian swap the raw image file format using dd:

dd conv=swab if=img.raw of=img2.raw

Now loading the image is now significantly faster:

t1 = time.ticks_us()
with open('img2.raw', 'rb') as f:
    for j in range(0,240,24):
        display_buffer[480*j:(480*(j+24))] = f.read(240*48)

display.update() # only update display once now, remove those tabs!
print((time.ticks_us() - t1)/1000)

 

Which now runs in 232 ms 85 ms and appears more as a transition animation versus terribly slow code.

 

Update: Overclocking in MicroPython

One can adjust the system clock frequency in MicroPython by issuing the following command:

machine.freq(190_000_000) # set system clock in Hz

 

When MicroPython alters the system clock frequency, it also reconfigures the peripheral clock source from clk_sys to the external crystal oscillator.

image

 

So, if you want to maintain a high-speed SPI clock frequency, you need to set the clock mux back to clk_sys yourself by:

mem32[0x40008000+0x48] = 0x800

 

With the Pico running at 190 MHz I achieved the following:

     Rainbow Spinner: 53 FPS

     FFT Demo: 16 FPS

     Image Load + Draw: 56 ms (49ms letting the garbage collector run before the load)

 

Of course, there are no guarantees this will always work for every Pico and or display.

  • Sign in to reply
  • Cancel
Parents
  • scottiebabe
    scottiebabe over 3 years ago

    Lorenez Clock

    For how complicated the mathematics are describing this particular set of differential equations, the MicroPython code to numerically solve the ODE is quite simple.

     

    https://en.wikipedia.org/wiki/Lorenz_system

     

    You don't have permission to edit metadata of this video.
    Edit media
    x
    image
    Upload Preview
    image

     

    from machine import Pin, SPI, mem32
    import time
    import random
    import math
    from ulab import numpy as np
    from random import random as randf
    from breakout_colourlcd240x240 import BreakoutColourLCD240x240
    np.set_printoptions(threshold=1000)
    
    rst = Pin(13,Pin.OUT)
    rst.value(1)
    
    width = BreakoutColourLCD240x240.WIDTH
    height = BreakoutColourLCD240x240.HEIGHT
    
    display_buffer = bytearray(width * height * 2)  # 2-bytes per pixel (RGB565)
    display = BreakoutColourLCD240x240(display_buffer)
    display.set_pen(255, 255, 255)  # Set pen to white
    display.clear()           # Fill the screen with the colour
    mem32[0x4003c000] = 0x007 # Configure SPI0 CLKFREQ for Fsys/2
    
    # From CPython Lib/colorsys.py
    def hsv_to_rgb(h, s, v):
        if s == 0.0:
            return v, v, v
        i = int(h * 6.0)
        f = (h * 6.0) - i
        p = v * (1.0 - s)
        q = v * (1.0 - s * f)
        t = v * (1.0 - s * (1.0 - f))
        i = i % 6
        if i == 0:
            return v, t, p
        if i == 1:
            return q, v, p
        if i == 2:
            return p, v, t
        if i == 3:
            return p, q, v
        if i == 4:
            return t, p, v
        if i == 5:
            return v, p, q
    
    # Lorenz State Model from Wikipedia
    # https://en.wikipedia.org/wiki/Lorenz_system#Python_simulation
    rho = 28.0
    sigma = 10.0
    beta = 8.0 / 3.0
    
    def f(state, t):
        x, y, z = state  # Unpack the state vector
        return np.array([sigma * (y - x), x * (rho - z) - y, x * y - beta * z])  # Derivatives
    
    state0 = np.array([1.0, 1.0, 1.0])
    state = state0
    
    display.set_pen(0, 0, 0)  # Set pen to black
    display.clear()           # Fill the screen with the colour
    
    xo = 120
    yo = 40
    tscreen = time.time() # time of last screen clear
    h=0 # hue angle
    while True:
        h += 1
        r, g, b = [int(255 * c) for c in hsv_to_rgb(h / 360.0, 1.0, 1.0)] 
        display.set_pen(r, g, b)  # Set pen to a converted HSV value
        
        for i in range(10):
            state = state + f(state,0)/1e3
            
        display.circle(int(xo+4*state[0]),int(yo+4*state[2]),1)
            
        display.set_pen(0, 0, 0)
        display.rectangle(50,0,200,50)
        display.set_pen(255, 255, 255)
        tm = time.localtime()
        display.text("{:02d}:{:02d}:{:02d}".format(tm[3],tm[4],tm[5]), 35, 0, 240, 5)  # Display Time
        display.text('Scottie',160,225,240,2)
        display.update()          # Update the display
        
        # clear screen every 2 minutes
        if time.time() - tscreen > 120:
            tscreen = time.time()
            display.set_pen(0, 0, 0)
            display.clear()

     

    I might look into implementing an actual ODE solver, but for now the solution it creates appear quite elegant (regardless if they may not be accurate).

     

    Still kind of amazed how simple that was to implement when using the demo examples as a starting point.

     

    This might be a project that deserves a real enclosure.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • shabaz
    shabaz over 3 years ago in reply to scottiebabe

    Nice project, and actually an excellent example showing the power of Python versus (say) C. It's so much easier to do all the maths algorithms in Python. Sure it won't run as fast as optimised C code, but efficiency of personal time use getting projects out of the door, or the ability to rapidly modify algorithms, may be more important than raw performance during execution.

    I wonder, has anyone implemented a pocket calculator or pocket computer with Pi Pico yet? I'd have thought that was a project screaming out for someone to implement.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • scottiebabe
    scottiebabe over 3 years ago in reply to shabaz

    Thank you for the kind words. I'm not sure if anyone has but together a pico calculator yet, with python it would be easy to support complex expressions. I have considered playing around with with a making a keypad layout for technical individuals not accountants. I still use my pocket scientific calculator all the time. Recently with micropython I have found myself holding a scope probe in one hand (or multimeter probe) and trying type with the other. I wish my keyboard keypad was had some of the same keys as my scientific calculator.

     

    From what I gather making a USB HID device is supposed to be simple with the Pico. Though, I have yet to try it myself.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
Reply
  • scottiebabe
    scottiebabe over 3 years ago in reply to shabaz

    Thank you for the kind words. I'm not sure if anyone has but together a pico calculator yet, with python it would be easy to support complex expressions. I have considered playing around with with a making a keypad layout for technical individuals not accountants. I still use my pocket scientific calculator all the time. Recently with micropython I have found myself holding a scope probe in one hand (or multimeter probe) and trying type with the other. I wish my keyboard keypad was had some of the same keys as my scientific calculator.

     

    From what I gather making a USB HID device is supposed to be simple with the Pico. Though, I have yet to try it myself.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
Children
  • shabaz
    shabaz over 3 years ago in reply to scottiebabe

    I learned a major problem with CircuitPython today; it is single-precision! I was hitting all manner of problems trying to do PLL configurations, and eventually realized it was due to that : ( I've not found out about MicroPython, but if it supports double precision on the Pico then I'm swapping over immediately : ) I've already hit two bugs with CircuitPython, one each on two separate releases, so CircuitPython is not giving me stability confidence either : ( originally I thought a benefit of CircuitPython would have been the vast amount of libraries, but of the few I tried, they all had limitations so I had to write my own code in place of the libraries : (

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • fmilburn
    fmilburn over 3 years ago in reply to shabaz

    I ran into the single-precision issue with CircuitPython also.  MicroPython can do double-precision floating and multi-precision integer but I haven't tried it yet: Maximum and minimum int and float values? - MicroPython Forum.  It can also do interrupts of some sort if I remember correctly and has experimental threads that haven't been implemented.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • scottiebabe
    scottiebabe over 3 years ago in reply to shabaz

    I suppose it is still early days for embedded python. I would have hoped ulab may would have supported 64 bit soft floats, but does not appear that way just yet. For a small number of calculations would working with a numpy datatype would be okay. Hopefully this is something they will add.

     

    I have had other floating point woes on the PICO with regarding execution time. I wasn't getting anywhere near the avg cycle times stated in the datasheet:

    image

    But I made up the difference converting my ADC integer arrays to floating point arrays using a lookup table, there is lots of memory to spare. A floating point lookup table of 256 elements is only 1 KB.

     

    Though you do appear to get 64-bit integers:

    imageimage

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
  • shabaz
    shabaz over 3 years ago in reply to scottiebabe

    I'm finding it unacceptable to not have double precision hehe. I had some luck today compiling MicroPython, and put a couple of Pi Pico double-precision MicroPython binaries here.

    I'm just typing up the procedure, so anyone can build them at any time, however the ones at that location are up-to-date (one is version 1.17 release code, and the other is the latest code in GitHub).

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
  • scottiebabe
    scottiebabe over 3 years ago in reply to shabaz

    That is really helpful. I suppose that means there would no longer be singles? When I think about it, one probably wouldn't notice the performance difference compared to the python overhead.

     

    image

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
  • shabaz
    shabaz over 3 years ago in reply to scottiebabe

    Hi Scott,

     

    This is true, processing time for the rest of Python will be quite large anyway, so it may not be very noticeable as you say. I'm still a Python beginner so I may have missed it, but I've not found so far if the type can be forced to be single-precision like (say) C.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube