• sales

    +86-0755-88291180

Raspberry Pi 1.14inch 1.3inch LCD - Python Usage

  • If you have previously installed the Kernel Driver with the PiTFT Easy Setup, you will need to remove it first in order to run this example.

Now that you have everything setup, we're going to look over three different examples. For the first, we'll take a look at automatically scaling and cropping an image and then centering it on the display.

Turning on the Backlight

On some displays, the backlight is controlled by a separate pin such as the 1.3" TFT Bonnet with Joystick. On such displays, running the below code will likely result in the display remaining black. To turn on the backlight, you will need to add a small snippet of code. If your backlight pin number differs, be sure to change it in the code:

 Download: file
  1. # Turn on the Backlight
  2. backlight = DigitalInOut(board.D26)
  3. backlight.switch_to_output()
  4. backlight.value = True

Displaying an Image

Here's the full code to the example. We will go through it section by section to help you better understand what is going on. Let's start by downloading an image of Blinka. This image has enough border to allow resizing and cropping with a variety of display sizes and rations to still look good.

Make sure you save it as blinka.jpg and place it in the same folder as your script. Here's the code we'll be loading onto the Raspberry Pi. We'll go over the interesting parts.

  1. """
  2. Be sure to check the learn guides for more usage information.
  3.  
  4. This example is for use on (Linux) computers that are using CPython with
  5. Adafruit Blinka to support CircuitPython libraries. CircuitPython does
  6. not support PIL/pillow (python imaging library)!
  7.  
  8. Author(s): Melissa LeBlanc-Williams for Adafruit Industries
  9. """
  10.  
  11. import digitalio
  12. import board
  13. from PIL import Image, ImageDraw
  14. import adafruit_rgb_display.ili9341 as ili9341
  15. import adafruit_rgb_display.st7789 as st7789 # pylint: disable=unused-import
  16. import adafruit_rgb_display.hx8357 as hx8357 # pylint: disable=unused-import
  17. import adafruit_rgb_display.st7735 as st7735 # pylint: disable=unused-import
  18. import adafruit_rgb_display.ssd1351 as ssd1351 # pylint: disable=unused-import
  19. import adafruit_rgb_display.ssd1331 as ssd1331 # pylint: disable=unused-import
  20.  
  21. # Configuration for CS and DC pins (these are PiTFT defaults):
  22. cs_pin = digitalio.DigitalInOut(board.CE0)
  23. dc_pin = digitalio.DigitalInOut(board.D25)
  24. reset_pin = digitalio.DigitalInOut(board.D24)
  25.  
  26. # Config for display baudrate (default max is 24mhz):
  27. BAUDRATE = 24000000
  28.  
  29. # Setup SPI bus using hardware SPI:
  30. spi = board.SPI()
  31.  
  32. # pylint: disable=line-too-long
  33. # Create the display:
  34. # disp = st7789.ST7789(spi, rotation=90, # 2.0" ST7789
  35. # disp = st7789.ST7789(spi, height=240, y_offset=80, rotation=180, # 1.3", 1.54" ST7789
  36. # disp = st7789.ST7789(spi, rotation=90, width=135, height=240, x_offset=53, y_offset=40, # 1.14" ST7789
  37. # disp = hx8357.HX8357(spi, rotation=180, # 3.5" HX8357
  38. # disp = st7735.ST7735R(spi, rotation=90, # 1.8" ST7735R
  39. # disp = st7735.ST7735R(spi, rotation=270, height=128, x_offset=2, y_offset=3, # 1.44" ST7735R
  40. # disp = st7735.ST7735R(spi, rotation=90, bgr=True, # 0.96" MiniTFT ST7735R
  41. # disp = ssd1351.SSD1351(spi, rotation=180, # 1.5" SSD1351
  42. # disp = ssd1351.SSD1351(spi, height=96, y_offset=32, rotation=180, # 1.27" SSD1351
  43. # disp = ssd1331.SSD1331(spi, rotation=180, # 0.96" SSD1331
  44. disp = ili9341.ILI9341(
  45. spi,
  46. rotation=90, # 2.2", 2.4", 2.8", 3.2" ILI9341
  47. cs=cs_pin,
  48. dc=dc_pin,
  49. rst=reset_pin,
  50. baudrate=BAUDRATE,
  51. )
  52. # pylint: enable=line-too-long
  53.  
  54. # Create blank image for drawing.
  55. # Make sure to create image with mode 'RGB' for full color.
  56. if disp.rotation % 180 == 90:
  57. height = disp.width # we swap height/width to rotate it to landscape!
  58. width = disp.height
  59. else:
  60. width = disp.width # we swap height/width to rotate it to landscape!
  61. height = disp.height
  62. image = Image.new("RGB", (width, height))
  63.  
  64. # Get drawing object to draw on image.
  65. draw = ImageDraw.Draw(image)
  66.  
  67. # Draw a black filled box to clear the image.
  68. draw.rectangle((0, 0, width, height), outline=0, fill=(0, 0, 0))
  69. disp.image(image)
  70.  
  71. image = Image.open("blinka.jpg")
  72.  
  73. # Scale the image to the smaller screen dimension
  74. image_ratio = image.width / image.height
  75. screen_ratio = width / height
  76. if screen_ratio < image_ratio:
  77. scaled_width = image.width * height // image.height
  78. scaled_height = height
  79. else:
  80. scaled_width = width
  81. scaled_height = image.height * width // image.width
  82. image = image.resize((scaled_width, scaled_height), Image.BICUBIC)
  83.  
  84. # Crop and center the image
  85. x = scaled_width // 2 - width // 2
  86. y = scaled_height // 2 - height // 2
  87. image = image.crop((x, y, x + width, y + height))
  88.  
  89. # Display image.
  90. disp.image(image)

So we start with our usual imports including a couple of Pillow modules and the display drivers. That is followed by defining a few pins here. The reason we chose these is because they allow you to use the same code with the PiTFT if you chose to do so.

 Download: file
  1. import digitalio
  2. import board
  3. from PIL import Image, ImageDraw
  4. import adafruit_rgb_display.ili9341 as ili9341
  5. import adafruit_rgb_display.st7789 as st7789
  6. import adafruit_rgb_display.hx8357 as hx8357
  7. import adafruit_rgb_display.st7735 as st7735
  8. import adafruit_rgb_display.ssd1351 as ssd1351
  9. import adafruit_rgb_display.ssd1331 as ssd1331
  10.  
  11. # Configuration for CS and DC pins
  12. cs_pin = digitalio.DigitalInOut(board.CE0)
  13. dc_pin = digitalio.DigitalInOut(board.D25)
  14. reset_pin = digitalio.DigitalInOut(board.D24)

Next we'll set the baud rate from the default 24 MHz so that it works on a variety of displays. The exception to this is the SSD1351 driver, which will automatically limit it to 16MHz even if you pass 24MHz. We'll set up out SPI bus and then initialize the display.

We wanted to make these examples work on as many displays as possible with very few changes. The ILI9341 display is selected by default. For other displays, go ahead and comment out the line that starts with:

disp = ili9341.ILI9341(spi,

and uncomment the line appropriate for your display. The displays have a rotation property so that it can be set in just one place.

 Download: file
  1. # Config for display baudrate (default max is 24mhz):
  2. BAUDRATE = 24000000
  3.  
  4. # Setup SPI bus using hardware SPI:
  5. spi = board.SPI()
  6.  
  7. #disp = st7789.ST7789(spi, rotation=90, # 2.0" ST7789
  8. #disp = st7789.ST7789(spi, height=240, y_offset=80, rotation=180, # 1.3", 1.54" ST7789
  9. #disp = st7789.ST7789(spi, rotation=90, width=135, height=240, x_offset=53, y_offset=40, # 1.14" ST7789
  10. #disp = hx8357.HX8357(spi, rotation=180, # 3.5" HX8357
  11. #disp = st7735.ST7735R(spi, rotation=90, # 1.8" ST7735R
  12. #disp = st7735.ST7735R(spi, rotation=270, height=128, x_offset=2, y_offset=3, # 1.44" ST7735R
  13. #disp = st7735.ST7735R(spi, rotation=90, bgr=True, # 0.96" MiniTFT ST7735R
  14. #disp = ssd1351.SSD1351(spi, rotation=180, # 1.5" SSD1351
  15. #disp = ssd1351.SSD1351(spi, height=96, y_offset=32, rotation=180, # 1.27" SSD1351
  16. #disp = ssd1331.SSD1331(spi, rotation=180, # 0.96" SSD1331
  17. disp = ili9341.ILI9341(spi, rotation=90, # 2.2", 2.4", 2.8", 3.2" ILI9341
  18. cs=cs_pin, dc=dc_pin, rst=reset_pin, baudrate=BAUDRATE)

Next we read the current rotation setting of the display and if it is 90 or 270 degrees, we need to swap the width and height for our calculations, otherwise we just grab the width and height. We will create an image with our dimensions and use that to create a draw object. The draw object will have all of our drawing functions.

 Download: file
  1. # Create blank image for drawing.
  2. # Make sure to create image with mode 'RGB' for full color.
  3. if disp.rotation % 180 == 90:
  4. height = disp.width # we swap height/width to rotate it to landscape!
  5. width = disp.height
  6. else:
  7. width = disp.width # we swap height/width to rotate it to landscape!
  8. height = disp.height
  9. image = Image.new('RGB', (width, height))
  10. # Get drawing object to draw on image.
  11. draw = ImageDraw.Draw(image)

Next we clear whatever is on the screen by drawing a black rectangle. This isn't strictly necessary since it will be overwritten by the image, but it kind of sets the stage.

 Download: file
  1. # Draw a black filled box to clear the image.
  2. draw.rectangle((0, 0, width, height), outline=0, fill=(0, 0, 0))
  3. disp.image(image)

Next we open the Blinka image, which we've named blinka.jpg, which assumes it is in the same directory that you are running the script from. Feel free to change it if it doesn't match your configuration.

 Download: file
  1. image = Image.open("blinka.jpg")

Here's where it starts to get interesting. We want to scale the image so that it matches either the width or height of the display, depending on which is smaller, so that we have some of the image to chop off when we crop it. So we start by calculating the width to height ration of both the display and the image. If the height is the closer of the dimensions, we want to match the image height to the display height and let it be a bit wider than the display. Otherwise, we want to do the opposite.

Once we've figured out how we're going to scale it, we pass in the new dimensions and using a Bicubic rescaling method, we reassign the newly rescaled image back to image. Pillow has quite a few different methods to choose from, but Bicubic does a great job and is reasonably fast.

 Download: file
  1. # Scale the image to the smaller screen dimension
  2. image_ratio = image.width / image.height
  3. screen_ratio = width / height
  4. if screen_ratio < image_ratio:
  5. scaled_width = image.width * height // image.height
  6. scaled_height = height
  7. else:
  8. scaled_width = width
  9. scaled_height = image.height * width // image.width
  10. image = image.resize((scaled_width, scaled_height), Image.BICUBIC)

Next we want to figure the starting x and y points of the image where we want to begin cropping it so that it ends up centered. We do that by using a standard centering function, which is basically requesting the difference of the center of the display and the center of the image. Just like with scaling, we replace the image variable with the newly cropped image.

 Download: file
  1. # Crop and center the image
  2. x = scaled_width // 2 - width // 2
  3. y = scaled_height // 2 - height // 2
  4. image = image.crop((x, y, x + width, y + height))

Finally, we take our image and display it. At this point, the image should have the exact same dimensions at the display and fill it completely.

 Download: file
  1. disp.image(image)
arduino_compatibles_2.2_Breakout_Image.jpeg

Drawing Shapes and Text

In the next example, we'll take a look at drawing shapes and text. This is very similar to the displayio example, but it uses Pillow instead. Here's the code for that.

  1. """
  2. This demo will draw a few rectangles onto the screen along with some text
  3. on top of that.
  4.  
  5. This example is for use on (Linux) computers that are using CPython with
  6. Adafruit Blinka to support CircuitPython libraries. CircuitPython does
  7. not support PIL/pillow (python imaging library)!
  8.  
  9. Author(s): Melissa LeBlanc-Williams for Adafruit Industries
  10. """
  11.  
  12. import digitalio
  13. import board
  14. from PIL import Image, ImageDraw, ImageFont
  15. import adafruit_rgb_display.ili9341 as ili9341
  16. import adafruit_rgb_display.st7789 as st7789 # pylint: disable=unused-import
  17. import adafruit_rgb_display.hx8357 as hx8357 # pylint: disable=unused-import
  18. import adafruit_rgb_display.st7735 as st7735 # pylint: disable=unused-import
  19. import adafruit_rgb_display.ssd1351 as ssd1351 # pylint: disable=unused-import
  20. import adafruit_rgb_display.ssd1331 as ssd1331 # pylint: disable=unused-import
  21.  
  22. # First define some constants to allow easy resizing of shapes.
  23. BORDER = 20
  24. FONTSIZE = 24
  25.  
  26. # Configuration for CS and DC pins (these are PiTFT defaults):
  27. cs_pin = digitalio.DigitalInOut(board.CE0)
  28. dc_pin = digitalio.DigitalInOut(board.D25)
  29. reset_pin = digitalio.DigitalInOut(board.D24)
  30.  
  31. # Config for display baudrate (default max is 24mhz):
  32. BAUDRATE = 24000000
  33.  
  34. # Setup SPI bus using hardware SPI:
  35. spi = board.SPI()
  36.  
  37. # pylint: disable=line-too-long
  38. # Create the display:
  39. # disp = st7789.ST7789(spi, rotation=90, # 2.0" ST7789
  40. # disp = st7789.ST7789(spi, height=240, y_offset=80, rotation=180, # 1.3", 1.54" ST7789
  41. # disp = st7789.ST7789(spi, rotation=90, width=135, height=240, x_offset=53, y_offset=40, # 1.14" ST7789
  42. # disp = hx8357.HX8357(spi, rotation=180, # 3.5" HX8357
  43. # disp = st7735.ST7735R(spi, rotation=90, # 1.8" ST7735R
  44. # disp = st7735.ST7735R(spi, rotation=270, height=128, x_offset=2, y_offset=3, # 1.44" ST7735R
  45. # disp = st7735.ST7735R(spi, rotation=90, bgr=True, # 0.96" MiniTFT ST7735R
  46. # disp = ssd1351.SSD1351(spi, rotation=180, # 1.5" SSD1351
  47. # disp = ssd1351.SSD1351(spi, height=96, y_offset=32, rotation=180, # 1.27" SSD1351
  48. # disp = ssd1331.SSD1331(spi, rotation=180, # 0.96" SSD1331
  49. disp = ili9341.ILI9341(
  50. spi,
  51. rotation=90, # 2.2", 2.4", 2.8", 3.2" ILI9341
  52. cs=cs_pin,
  53. dc=dc_pin,
  54. rst=reset_pin,
  55. baudrate=BAUDRATE,
  56. )
  57. # pylint: enable=line-too-long
  58.  
  59. # Create blank image for drawing.
  60. # Make sure to create image with mode 'RGB' for full color.
  61. if disp.rotation % 180 == 90:
  62. height = disp.width # we swap height/width to rotate it to landscape!
  63. width = disp.height
  64. else:
  65. width = disp.width # we swap height/width to rotate it to landscape!
  66. height = disp.height
  67.  
  68. image = Image.new("RGB", (width, height))
  69.  
  70. # Get drawing object to draw on image.
  71. draw = ImageDraw.Draw(image)
  72.  
  73. # Draw a green filled box as the background
  74. draw.rectangle((0, 0, width, height), fill=(0, 255, 0))
  75. disp.image(image)
  76.  
  77. # Draw a smaller inner purple rectangle
  78. draw.rectangle(
  79. (BORDER, BORDER, width - BORDER - 1, height - BORDER - 1), fill=(170, 0, 136)
  80. )
  81.  
  82. # Load a TTF Font
  83. font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", FONTSIZE)
  84.  
  85. # Draw Some Text
  86. text = "Hello World!"
  87. (font_width, font_height) = font.getsize(text)
  88. draw.text(
  89. (width // 2 - font_width // 2, height // 2 - font_height // 2),
  90. text,
  91. font=font,
  92. fill=(255, 255, 0),
  93. )
  94.  
  95. # Display image.
  96. disp.image(image)

Just like in the last example, we'll do our imports, but this time we're including the ImageFont Pillow module because we'll be drawing some text this time.

 Download: file
  1. import digitalio
  2. import board
  3. from PIL import Image, ImageDraw, ImageFont
  4. import adafruit_rgb_display.ili9341 as ili9341

Next we'll define some parameters that we can tweak for various displays. The BORDER will be the size in pixels of the green border between the edge of the display and the inner purple rectangle. The FONTSIZE will be the size of the font in points so that we can adjust it easily for different displays.

 Download: file
  1. BORDER = 20
  2. FONTSIZE = 24

Next, just like in the previous example, we will set up the display, setup the rotation, and create a draw object. If you have are using a different display than the ILI9341, go ahead and adjust your initializer as explained in the previous example. After that, we will setup the background with a green rectangle that takes up the full screen. To get green, we pass in a tuple that has our RedGreen, and Blue color values in it in that order which can be any integer from 0 to 255.

 Download: file
  1. draw.rectangle((0, 0, width, height), fill=(0, 255, 0))
  2. disp.image(image)

Next we will draw an inner purple rectangle. This is the same color value as our example in displayio quickstart, except the hexadecimal values have been converted to decimal. We use the BORDER parameter to calculate the size and position that we want to draw the rectangle.

 Download: file
  1. draw.rectangle((BORDER, BORDER, width - BORDER - 1, height - BORDER - 1),
  2. fill=(170, 0, 136))

Next we'll load a TTF font. The DejaVuSans.ttf font should come preloaded on your Pi in the location in the code. We also make use of the FONTSIZE parameter that we discussed earlier.

 Download: file
  1. # Load a TTF Font
  2. font = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', FONTSIZE)

Now we draw the text Hello World onto the center of the display. You may recognize the centering calculation was the same one we used to center crop the image in the previous example. In this example though, we get the font size values using the getsize() function of the font object.

 Download: file
  1. # Draw Some Text
  2. text = "Hello World!"
  3. (font_width, font_height) = font.getsize(text)
  4. draw.text((width//2 - font_width//2, height//2 - font_height//2),
  5. text, font=font, fill=(255, 255, 0))

Finally, just like before, we display the image.

 Download: file
  1. disp.image(image)
arduino_compatibles_2.2_Breakout_Demo.jpeg

Displaying System Information

In this last example we'll take a look at getting the system information and displaying it. This can be very handy for system monitoring. Here's the code for that example:

  1. """
  2. This will show some Linux Statistics on the attached display. Be sure to adjust
  3. to the display you have connected. Be sure to check the learn guides for more
  4. usage information.
  5.  
  6. This example is for use on (Linux) computers that are using CPython with
  7. Adafruit Blinka to support CircuitPython libraries. CircuitPython does
  8. not support PIL/pillow (python imaging library)!
  9. """
  10.  
  11. import time
  12. import subprocess
  13. import digitalio
  14. import board
  15. from PIL import Image, ImageDraw, ImageFont
  16. import adafruit_rgb_display.ili9341 as ili9341
  17. import adafruit_rgb_display.st7789 as st7789 # pylint: disable=unused-import
  18. import adafruit_rgb_display.hx8357 as hx8357 # pylint: disable=unused-import
  19. import adafruit_rgb_display.st7735 as st7735 # pylint: disable=unused-import
  20. import adafruit_rgb_display.ssd1351 as ssd1351 # pylint: disable=unused-import
  21. import adafruit_rgb_display.ssd1331 as ssd1331 # pylint: disable=unused-import
  22.  
  23. # Configuration for CS and DC pins (these are PiTFT defaults):
  24. cs_pin = digitalio.DigitalInOut(board.CE0)
  25. dc_pin = digitalio.DigitalInOut(board.D25)
  26. reset_pin = digitalio.DigitalInOut(board.D24)
  27.  
  28. # Config for display baudrate (default max is 24mhz):
  29. BAUDRATE = 24000000
  30.  
  31. # Setup SPI bus using hardware SPI:
  32. spi = board.SPI()
  33.  
  34. # pylint: disable=line-too-long
  35. # Create the display:
  36. # disp = st7789.ST7789(spi, rotation=90, # 2.0" ST7789
  37. # disp = st7789.ST7789(spi, height=240, y_offset=80, rotation=180, # 1.3", 1.54" ST7789
  38. # disp = st7789.ST7789(spi, rotation=90, width=135, height=240, x_offset=53, y_offset=40, # 1.14" ST7789
  39. # disp = hx8357.HX8357(spi, rotation=180, # 3.5" HX8357
  40. # disp = st7735.ST7735R(spi, rotation=90, # 1.8" ST7735R
  41. # disp = st7735.ST7735R(spi, rotation=270, height=128, x_offset=2, y_offset=3, # 1.44" ST7735R
  42. # disp = st7735.ST7735R(spi, rotation=90, bgr=True, # 0.96" MiniTFT ST7735R
  43. # disp = ssd1351.SSD1351(spi, rotation=180, # 1.5" SSD1351
  44. # disp = ssd1351.SSD1351(spi, height=96, y_offset=32, rotation=180, # 1.27" SSD1351
  45. # disp = ssd1331.SSD1331(spi, rotation=180, # 0.96" SSD1331
  46. disp = ili9341.ILI9341(
  47. spi,
  48. rotation=90, # 2.2", 2.4", 2.8", 3.2" ILI9341
  49. cs=cs_pin,
  50. dc=dc_pin,
  51. rst=reset_pin,
  52. baudrate=BAUDRATE,
  53. )
  54. # pylint: enable=line-too-long
  55.  
  56. # Create blank image for drawing.
  57. # Make sure to create image with mode 'RGB' for full color.
  58. if disp.rotation % 180 == 90:
  59. height = disp.width # we swap height/width to rotate it to landscape!
  60. width = disp.height
  61. else:
  62. width = disp.width # we swap height/width to rotate it to landscape!
  63. height = disp.height
  64.  
  65. image = Image.new("RGB", (width, height))
  66.  
  67. # Get drawing object to draw on image.
  68. draw = ImageDraw.Draw(image)
  69.  
  70. # Draw a black filled box to clear the image.
  71. draw.rectangle((0, 0, width, height), outline=0, fill=(0, 0, 0))
  72. disp.image(image)
  73.  
  74. # First define some constants to allow easy positioning of text.
  75. padding = -2
  76. x = 0
  77.  
  78. # Load a TTF font. Make sure the .ttf font file is in the
  79. # same directory as the python script!
  80. # Some other nice fonts to try: http://www.dafont.com/bitmap.php
  81. font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 24)
  82.  
  83. while True:
  84. # Draw a black filled box to clear the image.
  85. draw.rectangle((0, 0, width, height), outline=0, fill=0)
  86.  
  87. # Shell scripts for system monitoring from here:
  88. # https://unix.stackexchange.com/questions/119126/command-to-display-memory-usage-disk-usage-and-cpu-load
  89. cmd = "hostname -I | cut -d' ' -f1"
  90. IP = "IP: " + subprocess.check_output(cmd, shell=True).decode("utf-8")
  91. cmd = "top -bn1 | grep load | awk '{printf \"CPU Load: %.2f\", $(NF-2)}'"
  92. CPU = subprocess.check_output(cmd, shell=True).decode("utf-8")
  93. cmd = "free -m | awk 'NR==2{printf \"Mem: %s/%s MB %.2f%%\", $3,$2,$3*100/$2 }'"
  94. MemUsage = subprocess.check_output(cmd, shell=True).decode("utf-8")
  95. cmd = 'df -h | awk \'$NF=="/"{printf "Disk: %d/%d GB %s", $3,$2,$5}\''
  96. Disk = subprocess.check_output(cmd, shell=True).decode("utf-8")
  97. cmd = "cat /sys/class/thermal/thermal_zone0/temp | awk '{printf \"CPU Temp: %.1f C\", $(NF-0) / 1000}'" # pylint: disable=line-too-long
  98. Temp = subprocess.check_output(cmd, shell=True).decode("utf-8")
  99.  
  100. # Write four lines of text.
  101. y = padding
  102. draw.text((x, y), IP, font=font, fill="#FFFFFF")
  103. y += font.getsize(IP)[1]
  104. draw.text((x, y), CPU, font=font, fill="#FFFF00")
  105. y += font.getsize(CPU)[1]
  106. draw.text((x, y), MemUsage, font=font, fill="#00FF00")
  107. y += font.getsize(MemUsage)[1]
  108. draw.text((x, y), Disk, font=font, fill="#0000FF")
  109. y += font.getsize(Disk)[1]
  110. draw.text((x, y), Temp, font=font, fill="#FF00FF")
  111.  
  112. # Display image.
  113. disp.image(image)
  114. time.sleep(0.1)

Just like the last example, we'll start by importing everything we imported, but we're adding two more imports. The first one is time so that we can add a small delay and the other is subprocess so we can gather some system information.

 Download: file
  1. import time
  2. import subprocess
  3. import digitalio
  4. import board
  5. from PIL import Image, ImageDraw, ImageFont
  6. import adafruit_rgb_display.ili9341 as ili9341

Next, just like in the first two examples, we will set up the display, setup the rotation, and create a draw object. If you have are using a different display than the ILI9341, go ahead and adjust your initializer as explained in the previous example.

Just like in the first example, we're going to draw a black rectangle to fill up the screen. After that, we're going to set up a couple of constants to help with positioning text. The first is the padding and that will be the Y-position of the top-most text and the other is x which is the X-Position and represents the left side of the text.

 Download: file
  1. # First define some constants to allow easy positioning of text.
  2. padding = -2
  3. x = 0

Next, we load a font just like in the second example.

 Download: file
  1. font = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', 24)

Now we get to the main loop and by using while True:, it will loop until Control+C is pressed on the keyboard. The first item inside here, we clear the screen, but notice that instead of giving it a tuple like before, we can just pass 0 and it will draw black.

 Download: file
  1. draw.rectangle((0, 0, width, height), outline=0, fill=0)

Next, we run a few scripts using the subprocess function that get called to the Operating System to get information. The in each command is passed through awk in order to be formatted better for the display. By having the OS do the work, we don't have to. These little scripts came from https://unix.stackexchange.com/questions/119126/command-to-display-memory-usage-disk-usage-and-cpu-load

 Download: file
  1. cmd = "hostname -I | cut -d\' \' -f1"
  2. IP = "IP: "+subprocess.check_output(cmd, shell=True).decode("utf-8")
  3. cmd = "top -bn1 | grep load | awk '{printf \"CPU Load: %.2f\", $(NF-2)}'"
  4. CPU = subprocess.check_output(cmd, shell=True).decode("utf-8")
  5. cmd = "free -m | awk 'NR==2{printf \"Mem: %s/%s MB %.2f%%\", $3,$2,$3*100/$2 }'"
  6. MemUsage = subprocess.check_output(cmd, shell=True).decode("utf-8")
  7. cmd = "df -h | awk '$NF==\"/\"{printf \"Disk: %d/%d GB %s\", $3,$2,$5}'"
  8. Disk = subprocess.check_output(cmd, shell=True).decode("utf-8")
  9. cmd = "cat /sys/class/thermal/thermal_zone0/temp | awk \'{printf \"CPU Temp: %.1f C\", $(NF-0) / 1000}\'" # pylint: disable=line-too-long
  10. Temp = subprocess.check_output(cmd, shell=True).decode("utf-8")

Now we display the information for the user. Here we use yet another way to pass color information. We can pass it as a color string using the pound symbol, just like we would with HTML. With each line, we take the height of the line using getsize() and move the pointer down by that much.

 Download: file
  1. y = padding
  2. draw.text((x, y), IP, font=font, fill="#FFFFFF")
  3. y += font.getsize(IP)[1]
  4. draw.text((x, y), CPU, font=font, fill="#FFFF00")
  5. y += font.getsize(CPU)[1]
  6. draw.text((x, y), MemUsage, font=font, fill="#00FF00")
  7. y += font.getsize(MemUsage)[1]
  8. draw.text((x, y), Disk, font=font, fill="#0000FF")
  9. y += font.getsize(Disk)[1]
  10. draw.text((x, y), Temp, font=font, fill="#FF00FF")

Finally, we write all the information out to the display using disp.image(). Since we are looping, we tell Python to sleep for 0.1 seconds so that the CPU never gets too busy.

 Download: file
  1. disp.image(image)
  2. time.sleep(.1)