python - 尝试将 Python 代码从电子纸显示器更改为驱动 mini PiTFT
问题描述
我正在研究这个ISS Tracker 项目,但我不想使用电子纸显示器,而是想使用240x135 Mini PiTFT 显示器。我一直在尝试重写 Python 代码来完成此操作,因为渲染代码是相同的,但我无法将其正确输出到新显示器。当涉及到 Python 代码时,我非常讨厌,所以您可以提供的任何帮助将不胜感激。源代码可在上面的 ISS Tracker 链接中找到,我修改后的代码如下:
# International Space Station Tracker.
# using Raspberry Pi B+, Waveshare ePaper Display and ProtoStax enclosure
# --> https://www.waveshare.com/product/modules/oleds-lcds/e-paper/2.7inch-e-paper-hat-b.htm
# --> https://www.protostax.com/products/protostax-for-raspberry-pi-b
#
# It displays the current location of the ISS and also its tracked trajectory. The
# current location is shown by the ISS icon, and the trajectory by small circles.
# 15 minute markers are shown as small rectangles.
#
# ISS Current Location is obtained using Open Notify ISS Current Location API
# http://open-notify.org/Open-Notify-API/ISS-Location-Now/
#
# Written by Sridhar Rajagopal for ProtoStax.
# BSD license. All text above must be included in any redistribution
# *
import sys
sys.path.append(r'lib')
if sys.version_info[0] < 3:
raise Exception("Must be using Python 3")
from enum import Enum
import signal
import board
import digitalio
import adafruit_rgb_display.st7789 as st7789
import epd2in7b
import epdconfig
from PIL import Image, ImageDraw, ImageFont, ImageOps
from datetime import datetime
from time import time, sleep
import requests
# START mini pitft code
# Configuration for CS and DC pins (these are FeatherWing defaults on M0/M4):
cs_pin = digitalio.DigitalInOut(board.CE0)
dc_pin = digitalio.DigitalInOut(board.D25)
reset_pin = None
# Config for display baudrate (default max is 24mhz):
BAUDRATE = 64000000
# Setup SPI bus using hardware SPI:
spi = board.SPI()
# Create the ST7789 display:
disp = st7789.ST7789(
spi,
cs=cs_pin,
dc=dc_pin,
rst=reset_pin,
baudrate=BAUDRATE,
width=135,
height=240,
x_offset=53,
y_offset=40,
)
# Create blank image for drawing.
# Make sure to create image with mode 'RGB' for full color.
height = disp.width # we swap height/width to rotate it to landscape!
width = disp.height
image = Image.new("RGB", (width, height))
rotation = 90
# Get drawing object to draw on image.
draw = ImageDraw.Draw(image)
# Draw a black filled box to clear the image.
draw.rectangle((0, 0, width, height), outline=0, fill=(0, 0, 0))
disp.image(image, rotation)
# Draw some shapes.
# First define some constants to allow easy resizing of shapes.
padding = -2
top = padding
bottom = height - padding
# Move left to right keeping track of the current x position for drawing shapes.
x = 0
# Turn on the backlight
backlight = digitalio.DigitalInOut(board.D22)
backlight.switch_to_output()
backlight.value = True
# END mini pitft code
# Update Interval for fetching positions
DATA_INTERVAL = 30 #seconds
# Update interval for the display
DISPLAY_REFRESH_INTERVAL = 2 # Number of DATA_INTERVAL between successive display updates (e.g. 2 => update display every second deta fetch)
# Note:
# The dimensions of the 2.7 in ePaper display are
# 264 x 176
# The dimensions of the Mini PiTFT display are
# 240 x 135
class Display(object):
def __init__(self, imageWidth, imageHeight):
self.imageWidth = imageWidth
self.imageHeight = imageHeight
# Draws the ISS current location and trajectory from array of positions
def drawISS(self, positions):
imageWhite = Image.new('1', (self.imageWidth, self.imageHeight), 255) # 1: clear the frame
imageMap = Image.open('world_map_m.bmp').convert('L')
imageWhite.paste(imageMap, (0,0))
imageRed = Image.new('1', (self.imageWidth, self.imageHeight), 255) # 1: clear the frame
issLogo = Image.open('iss.bmp').convert('L')
drawred = ImageDraw.Draw(imageRed)
for i,t in enumerate(positions):
(lat,lon) = t
# Map the lat, lon to our x/y coordinate system
(x,y) = self.mapLatLongToXY(lat, lon)
# last position in the positions array is the latest location
# Every 15 minutes, we add a rectangular marker
# and a small red circle to mark other locations
if (i == len(positions) - 1):
s = 10
# drawred.rectangle((x-s,y-s,x+s,y+s), fill=0)
imageRed.paste(issLogo, ((int)(x-s), (int)(y-s)))
elif (((i+1) % (15 * 60 / DATA_INTERVAL)) == 0): # every 15 minutes (so 15 * 60s / DATA_INTERVAL = number of readings within 15 minutes)
s = 2
drawred.rectangle((x-s,y-s,x+s,y+s), fill=0)
else:
s = 1
drawred.ellipse((x-s,y-s,x+s,y+s), outline=0)
# drawred.point((x,y), fill=0)
# Rotate image 180 degrees - Remove the # comments of the lines below to rotate the image and allow for alternate positioning/mounting of the Raspberry Pi
# imageRed = imageRed.transpose(Image.ROTATE_180)
# imageWhite = imageWhite.transpose(Image.ROTATE_180)
# return the rendered Red and White images
return imageWhite, imageRed
# Maps lat, long to x,y coordinates in 264x181 (the size of the world map)
# (90 to -90 lat and -180 to 180 lon) map to 0-181 (y) and 0-264 (x) respectively
# Simple algebra gives us the equations below
# Recalculate as appropriate for map size and coordinates
def mapLatLongToXY(self, lat, lon):
x = (int)(0.733 * lon + 132)
y = (int)(-1.006 * lat + 90.5)
return x, y
# The main function
def main():
# API to get ISS Current Location
URL = 'http://api.open-notify.org/iss-now.json'
# Initialize and clear the 2in7b (tri-color) display
disp = st7789.ST7789(
spi,
cs=cs_pin,
dc=dc_pin,
rst=reset_pin,
baudrate=BAUDRATE,
width=135,
height=240,
x_offset=53,
y_offset=40,
)
display = Display(disp.height, disp.width)
# Store positions in list
positions = []
while(True):
t0 = time()
r = requests.get(url = URL)
# extracting data in json format
data = r.json()
print(data)
lat = float(data['iss_position']['latitude'])
lon = float(data['iss_position']['longitude'])
positions.append((lat, lon))
print(positions)
# Refresh the display on the first fetch and then on every DISPLAY_REFRESH_INTERVAL fetch
if ((len(positions) >= 1) and ((len(positions)-1) % DISPLAY_REFRESH_INTERVAL)):
disp.init()
(imageWhite, imageRed) = display.drawISS(positions)
# We're drawing the map in white and the ISS location and trajectory in red
# Swap it around if you'd like the inverse color scheme
disp.display(disp.getbuffer(imageWhite), disp.getbuffer(imageRed))
sleep(2)
disp.sleep()
t1 = time()
sleepTime = max(DATA_INTERVAL - (t1 - t0), 0)
sleep(sleepTime) # sleep for 30 seconds minus duration of get request and display refresh
# gracefully exit without a big exception message if possible
def ctrl_c_handler(signal, frame):
print('Goodbye!')
# XXX : TODO
#
# To preserve the life of the ePaper display, it is best not to keep it powered up -
# instead putting it to sleep when done displaying, or cutting off power to it altogether.
#
# dispconfig.module_exit() shuts off power to the module and calls GPIO.cleanup()
# The latest disp library chooses to shut off power (call module_exit) even when calling disp.sleep()
# disp.sleep() calls dispconfig.module_exit(), which in turns calls cleanup().
# We can therefore end up in a situation calling GPIO.cleanup twice
#
# Need to cleanup Waveshare disp code to call GPIO.cleanup() only once
# for now, calling dispconfig.module_init() to set up GPIO before calling module_exit to make sure
# power to the ePaper display is cut off on exit
# I have also modified dispconfig.py to initialize SPI handle in module_init() (vs. at the global scope)
# because slepe/module_exit closes the SPI handle, which wasn't getting initialized in module_init
# dispconfig.module_init()
# dispconfig.module_exit()
# print("Remeber to clear the display using cleardisplay.py if you plan to power down your Pi and store it, to prevent burn-in!")
exit(0)
signal.signal(signal.SIGINT, ctrl_c_handler)
if __name__ == '__main__':
main()
解决方案
你不能做
disp.display(disp.getbuffer(imageWhite), disp.getbuffer(imageRed))
因为您的 disp 对象没有名为“display”的方法
相反,您需要像这样在 disp 对象中设置图像:
disp.image(imageRed, 旋转)
在原始代码中,显示分为两部分 - 红色和黑色。它们分别由 ePaper 渲染,因此您需要两个图像。
在您的显示中,您可以构建具有所有颜色的单个图像,然后将该图像设置为您的 disp.display
disp.display(newImage, 旋转)
其中 newImage 将是 Display.drawISS 方法返回的图像。您将需要修改 drawISS 方法(或创建一个新方法,比如名为 drawISS_TFT,它返回一个 RGB 中的单个图像,其中包含地图和轨迹,以不同的颜色(而不是 drawISS 绘制一个黑色图像和其他红色图像 - 只需使用单个图像)。
这应该够了吧。
但首先,要查看您的 TFT 显示内容,只需更换
disp.display(disp.getbuffer(imageWhite), disp.getbuffer(imageRed))
和
disp.image(imageRed,旋转)或 disp.image(imageWhite,旋转)
如果你适当地看到国际空间站的轨迹或世界地图,那么你会在做其他事情之前知道你在正确的轨道上。
-斯里达尔
推荐阅读
- c - 我想知道这段代码内部发生了什么?
- apache-kafka - AvroSpecificRecord : Json 格式
- jenkins - Ansible Plugin CredentialsID 被 ansible_ssh_key 变量覆盖
- c# - Linq Where 尝试检查范围时失败
- clojure - 如何使用统一命名空间的键获取地图的命名空间?
- sql - 如何通过传递多个值来参数化 SQL 查询
- azure - 用于 Powershell 命令执行的访客与用户
- javascript - 如何将选项的值解析为输入值
- airflow - 将 XCom 与 BashOperator 一起使用:将多行 sdout 输出推送到其他任务?
- svg - 用 SVG 打破墙壁