树莓派使用 Nokia 5110 屏幕显示网速温度

Nokia 5110

长上图这样。

驱动

PCD8544

资料

Google 一搜各种博客都有介绍,毕竟我不是学硬件的,底层什么的就不说了。好玩就行。

引脚

rst:外部复位引脚

ce:显示屏使能引脚

dc:数据/命令引脚

din:串行数据输入端

clk:串行时钟输入端

vcc:电源引脚

bl: 亮度调节

gnd:接地

先看看驱动代码

修改自(Adafruit),这里用的是 BCM 编码。

# coding:utf-8 import time import Adafruit_GPIO as GPIO import Adafruit_GPIO.SPI as SPI LCDWIDTH = 84 LCDHEIGHT = 48 ROWPIXELS = LCDHEIGHT//6 PCD8544_POWERDOWN = 0x04 PCD8544_ENTRYMODE = 0x02 PCD8544_EXTENDEDINSTRUCTION = 0x01 PCD8544_DISPLAYBLANK = 0x0 PCD8544_DISPLAYNORMAL = 0x4 PCD8544_DISPLAYALLON = 0x1 PCD8544_DISPLAYINVERTED = 0x5 PCD8544_FUNCTIONSET = 0x20 PCD8544_DISPLAYCONTROL = 0x08 PCD8544_SETYADDR = 0x40 PCD8544_SETXADDR = 0x80 PCD8544_SETTEMP = 0x04 PCD8544_SETBIAS = 0x10 PCD8544_SETVOP = 0x80 FONT = { ‘ ‘: [0x00, 0x00, 0x00, 0x00, 0x00], ‘!’: [0x00, 0x00, 0x5f, 0x00, 0x00], ‘”‘: [0x00, 0x07, 0x00, 0x07, 0x00], ‘#’: [0x14, 0x7f, 0x14, 0x7f, 0x14], ‘$’: [0x24, 0x2a, 0x7f, 0x2a, 0x12], ‘%’: [0x23, 0x13, 0x08, 0x64, 0x62], ‘&’: [0x36, 0x49, 0x55, 0x22, 0x50], “‘”: [0x00, 0x05, 0x03, 0x00, 0x00], ‘(‘: [0x00, 0x1c, 0x22, 0x41, 0x00], ‘)’: [0x00, 0x41, 0x22, 0x1c, 0x00], ‘*’: [0x14, 0x08, 0x3e, 0x08, 0x14], ‘+’: [0x08, 0x08, 0x3e, 0x08, 0x08], ‘,’: [0x00, 0x50, 0x30, 0x00, 0x00], ‘-‘: [0x08, 0x08, 0x08, 0x08, 0x08], ‘.’: [0x00, 0x60, 0x60, 0x00, 0x00], ‘/’: [0x20, 0x10, 0x08, 0x04, 0x02], ‘0’: [0x3e, 0x51, 0x49, 0x45, 0x3e], ‘1’: [0x00, 0x42, 0x7f, 0x40, 0x00], ‘2’: [0x42, 0x61, 0x51, 0x49, 0x46], ‘3’: [0x21, 0x41, 0x45, 0x4b, 0x31], ‘4’: [0x18, 0x14, 0x12, 0x7f, 0x10], ‘5’: [0x27, 0x45, 0x45, 0x45, 0x39], ‘6’: [0x3c, 0x4a, 0x49, 0x49, 0x30], ‘7’: [0x01, 0x71, 0x09, 0x05, 0x03], ‘8’: [0x36, 0x49, 0x49, 0x49, 0x36], ‘9’: [0x06, 0x49, 0x49, 0x29, 0x1e], ‘:’: [0x00, 0x36, 0x36, 0x00, 0x00], ‘;’: [0x00, 0x56, 0x36, 0x00, 0x00], ‘<': [0x08, 0x14, 0x22, 0x41, 0x00], '=': [0x14, 0x14, 0x14, 0x14, 0x14], '>‘: [0x00, 0x41, 0x22, 0x14, 0x08], ‘?’: [0x02, 0x01, 0x51, 0x09, 0x06], ‘@’: [0x32, 0x49, 0x79, 0x41, 0x3e], ‘A’: [0x7e, 0x11, 0x11, 0x11, 0x7e], ‘B’: [0x7f, 0x49, 0x49, 0x49, 0x36], ‘C’: [0x3e, 0x41, 0x41, 0x41, 0x22], ‘D’: [0x7f, 0x41, 0x41, 0x22, 0x1c], ‘E’: [0x7f, 0x49, 0x49, 0x49, 0x41], ‘F’: [0x7f, 0x09, 0x09, 0x09, 0x01], ‘G’: [0x3e, 0x41, 0x49, 0x49, 0x7a], ‘H’: [0x7f, 0x08, 0x08, 0x08, 0x7f], ‘I’: [0x00, 0x41, 0x7f, 0x41, 0x00], ‘J’: [0x20, 0x40, 0x41, 0x3f, 0x01], ‘K’: [0x7f, 0x08, 0x14, 0x22, 0x41], ‘L’: [0x7f, 0x40, 0x40, 0x40, 0x40], ‘M’: [0x7f, 0x02, 0x0c, 0x02, 0x7f], ‘N’: [0x7f, 0x04, 0x08, 0x10, 0x7f], ‘O’: [0x3e, 0x41, 0x41, 0x41, 0x3e], ‘P’: [0x7f, 0x09, 0x09, 0x09, 0x06], ‘Q’: [0x3e, 0x41, 0x51, 0x21, 0x5e], ‘R’: [0x7f, 0x09, 0x19, 0x29, 0x46], ‘S’: [0x46, 0x49, 0x49, 0x49, 0x31], ‘T’: [0x01, 0x01, 0x7f, 0x01, 0x01], ‘U’: [0x3f, 0x40, 0x40, 0x40, 0x3f], ‘V’: [0x1f, 0x20, 0x40, 0x20, 0x1f], ‘W’: [0x3f, 0x40, 0x38, 0x40, 0x3f], ‘X’: [0x63, 0x14, 0x08, 0x14, 0x63], ‘Y’: [0x07, 0x08, 0x70, 0x08, 0x07], ‘Z’: [0x61, 0x51, 0x49, 0x45, 0x43], ‘[‘: [0x00, 0x7f, 0x41, 0x41, 0x00], ‘\\’: [0x02, 0x04, 0x08, 0x10, 0x20], ‘]’: [0x00, 0x41, 0x41, 0x7f, 0x00], ‘^’: [0x04, 0x02, 0x01, 0x02, 0x04], ‘_’: [0x40, 0x40, 0x40, 0x40, 0x40], ‘`’: [0x00, 0x01, 0x02, 0x04, 0x00], ‘a’: [0x20, 0x54, 0x54, 0x54, 0x78], ‘b’: [0x7f, 0x48, 0x44, 0x44, 0x38], ‘c’: [0x38, 0x44, 0x44, 0x44, 0x20], ‘d’: [0x38, 0x44, 0x44, 0x48, 0x7f], ‘e’: [0x38, 0x54, 0x54, 0x54, 0x18], ‘f’: [0x08, 0x7e, 0x09, 0x01, 0x02], ‘g’: [0x0c, 0x52, 0x52, 0x52, 0x3e], ‘h’: [0x7f, 0x08, 0x04, 0x04, 0x78], ‘i’: [0x00, 0x44, 0x7d, 0x40, 0x00], ‘j’: [0x20, 0x40, 0x44, 0x3d, 0x00], ‘k’: [0x7f, 0x10, 0x28, 0x44, 0x00], ‘l’: [0x00, 0x41, 0x7f, 0x40, 0x00], ‘m’: [0x7c, 0x04, 0x18, 0x04, 0x78], ‘n’: [0x7c, 0x08, 0x04, 0x04, 0x78], ‘o’: [0x38, 0x44, 0x44, 0x44, 0x38], ‘p’: [0x7c, 0x14, 0x14, 0x14, 0x08], ‘q’: [0x08, 0x14, 0x14, 0x18, 0x7c], ‘r’: [0x7c, 0x08, 0x04, 0x04, 0x08], ‘s’: [0x48, 0x54, 0x54, 0x54, 0x20], ‘t’: [0x04, 0x3f, 0x44, 0x40, 0x20], ‘u’: [0x3c, 0x40, 0x40, 0x20, 0x7c], ‘v’: [0x1c, 0x20, 0x40, 0x20, 0x1c], ‘w’: [0x3c, 0x40, 0x30, 0x40, 0x3c], ‘x’: [0x44, 0x28, 0x10, 0x28, 0x44], ‘y’: [0x0c, 0x50, 0x50, 0x50, 0x3c], ‘z’: [0x44, 0x64, 0x54, 0x4c, 0x44], ‘{‘: [0x00, 0x08, 0x36, 0x41, 0x00], ‘|’: [0x00, 0x00, 0x7f, 0x00, 0x00], ‘}’: [0x00, 0x41, 0x36, 0x08, 0x00], ‘~’: [0x10, 0x08, 0x08, 0x10, 0x08], ‘\x7f’: [0x00, 0x7e, 0x42, 0x42, 0x7e], } X = 13 Y = 5 class PCD8544(object): “””Nokia 5110/3310 PCD8544-based LCD display.””” def __init__(self, dc, rst, sclk=None, din=None, cs=None, gpio=None, spi=None, vcc=None, bl=None): self._sclk = sclk self._din = din self._dc = dc self._cs = cs self._rst = rst self._gpio = gpio self._spi = spi self._buffer = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFC, 0xFE, 0xFF, 0xFC, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0x80, 0xC0, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC7, 0xC7, 0x87, 0x8F, 0x9F, 0x9F, 0xFF, 0xFF, 0xFF, 0xC1, 0xC0, 0xE0, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFC, 0xFC, 0xFC, 0xFE, 0xFE, 0xFE, 0xFC, 0xFC, 0xF8, 0xF8, 0xF0, 0xE0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF1, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x1F, 0x0F, 0x0F, 0x87, 0xE7, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0x3F, 0xF9, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x0F, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x7E, 0x3F, 0x3F, 0x0F, 0x1F, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xE0, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x1F, 0x3F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x1F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ] if self._gpio is None: self._gpio = GPIO.get_platform_gpio() self._gpio.setup(vcc, GPIO.OUT) self._gpio.setup(bl, GPIO.OUT) self._gpio.output(vcc, 1) self._gpio.output(bl, 1) if self._rst is not None: self._gpio.setup(self._rst, GPIO.OUT) # Default to bit bang SPI. if self._spi is None: self._spi = SPI.BitBang(self._gpio, self._sclk, self._din, None, self._cs) # Set pin outputs. self._gpio.setup(self._dc, GPIO.OUT) # Initialize buffer to Adafruit logo. def command(self, c): “””Send command byte to display.””” # DC pin low signals command byte. self._gpio.set_low(self._dc) self._spi.write() def extended_command(self, c): “””Send a command in extended mode””” # Set extended command mode self.command(PCD8544_FUNCTIONSET | PCD8544_EXTENDEDINSTRUCTION) self.command(c) # Set normal display mode. self.command(PCD8544_FUNCTIONSET) self.command(PCD8544_DISPLAYCONTROL | PCD8544_DISPLAYNORMAL) def begin(self, contrast=40, bias=4): “””Initialize display.””” self.reset() # Set LCD bias. self.set_bias(bias) self.set_contrast(contrast) def reset(self): “””Reset the display””” if self._rst is not None: # Toggle RST low to reset. self._gpio.set_low(self._rst) time.sleep(0.1) self._gpio.set_high(self._rst) def display(self): “””Write display buffer to physical display.””” # TODO: Consider support for partial updates like Arduino library. # Reset to position zero. self.command(PCD8544_SETYADDR) self.command(PCD8544_SETXADDR) # Write the buffer. self._gpio.set_high(self._dc) self._spi.write(self._buffer) def clear(self): “””Clear contents of image buffer.””” self._buffer = [0] * (LCDWIDTH * LCDHEIGHT // 8) def set_contrast(self, contrast): “””Set contrast to specified value (should be 0-127).””” contrast = max(0, min(contrast, 0x7f)) # Clamp to values 0-0x7f self.extended_command(PCD8544_SETVOP | contrast) def set_bias(self, bias): “””Set bias””” self.extended_command(PCD8544_SETBIAS | bias) def draw_str(self, y, s): “””修改显示数据,y 为第几行,s 为要显示的数据””” if (y >= Y ) or (y < 0): return False x = 0 for c in s[0:14]: try: self._buffer[y*84+x*6: y*84+x*6 + 6] = FONT + [0] except KeyError: pass x += 1 def draw_char(self, x, y): pass def quit(self): self._gpio.cleanup() 接线(BCM) dc 13 rst 5 sclk 26 din 19 cs 6 vcc 20 bl 21 gnd 0v 显示信息 网速 显示路由器的网速,电脑网速就没必要了。 我用的是老毛子固件,所以用这个固件的可以参考我的代码。 代码量不大,我就没写注释了。 # coding:utf-8 import requests import time from math import fabs from base64 import b64encode # from demjson import decode class RaspberryMonitorNetSpeed: url = 'http://192.168.123.1/update.cgi?output=netdev' headers = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8', 'Cache-Control': 'max-age=0', # 'Connection':'keep-alive', 'Connection': 'close', 'Cookie': 'n56u_cookie_bw_rt_tab=WAN', 'Host': '192.168.123.1', 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36', } # 最近一次请求时间 last_time = 0 # 最近一次请求的下行数据总量 last_rbytes = 0 # 最近一次请求的上行数据总量 last_tbytes = 0 def __init__(self, username, passwd): self.headers['Authorization'] = 'Basic '+b64encode((username+':'+passwd).encode()).decode() data = self.__get_wan_rx_and_tx() self.last_rbytes = data[0] self.last_tbytes = data[1] self.last_time = data[2] def set_auth(self, username, passwd): self.headers['Authorization'] = 'Basic '+b64encode((username+':'+passwd).encode()).decode() def __get_wan_rx_and_tx(self): text = requests.get(self.url, headers=self.headers).text try: rx = int(text.split(',')[25].lstrip('rx:').strip(), 16) tx = int(text.split(',')[26].lstrip('tx:').rstrip('} ').strip(), 16) new_time = time.time() except (IndexError, ValueError, TypeError): return False return [rx, tx, new_time] def get_human_speed(self): """这里返回的是 M/s 这种网速,[下载,上传]""" data = self.__get_wan_rx_and_tx() if data: down_speed = 0 up_speed = 0 try: down_speed = self.__bytes_to_humanspeed((data[0] - self.last_rbytes) / (data[2] - self.last_time)) up_speed = self.__bytes_to_humanspeed((data[1] - self.last_tbytes) / (data[2] - self.last_time)) except ZeroDivisionError: pass self.last_rbytes = data[0] self.last_tbytes = data[1] self.last_time = data[2] return down_speed, up_speed def __bytes_to_humanspeed(self, B): absval = fabs(B) / 1024 megabyte = 1024 gigabyte = megabyte * 1024 terabyte = gigabyte * 1024 # petabyte = terabyte * 1024 if absval < megabyte: return str(round(absval, 2)) + ' KB/s' elif absval < gigabyte: return str(round(absval / megabyte, 2)) + ' M/s' else: return str(round(absval / gigabyte, 2)) + ' G/s' def get_bits_speed(self): """这里返回的是 Mbps 这种网速,[下载,上传]""" data = self.__get_wan_rx_and_tx() if data: down_speed = self.__bytes_to_bitrate((data[0] - self.last_rbytes) / (data[2] - self.last_time)) up_speed = self.__bytes_to_bitrate((data[1] - self.last_tbytes) / (data[2] - self.last_time)) self.last_rbytes = data[0] self.last_tbytes = data[1] self.last_time = data[2] return down_speed, up_speed def __bytes_to_bitrate(self, B): bits = B * 8 absval = fabs(bits) kilobit = 1000 megabit = kilobit * 1000 gigabit = megabit * 1000 if absval < megabit: return str(round(bits / kilobit, 2)) + ' Kbps' elif absval < gigabit: return str(round(bits / megabit, 2)) + ' Mbps' else: return str(round(bits / gigabit, 2)) + ' Gbps' if __name__ == '__main__': from lcd1602 import LCD1602 a = RaspberryMonitorNetSpeed('username', 'password') lcd = LCD1602() while True: tmp = a.get_human_speed() lcd.lcd_string('u:' + tmp[1], lcd.LCD_LINE_1) lcd.lcd_string('d:' + tmp[0], lcd.LCD_LINE_2) time.sleep(2) 温度 这里用的是 DTH11,驱动同样参考这个(Adafruit)。 开始显示 代码量同样不大,没写注释。 import time import datetime from PCD8544 import PCD8544 as lcd import threading import Adafruit_DHT from speed import RaspberryMonitorNetSpeed as rmn ns = [-1, -1] th = [-2, -2] def main(): a = lcd(dc=13, rst=5, sclk=26, din=19, cs=6, vcc=20, bl=21) a.begin(contrast=60) tmp = threading.Thread(target=network_speed) tmp.setDaemon(True) tmp.start() tmp = threading.Thread(target=temperature_humidity) tmp.setDaemon(True) tmp.start() while True: try: a.clear() # 上传速度 a.draw_str(0, 'U: ' + str(ns[1])) # 下载速度 a.draw_str(1, 'D: ' + str(ns[0])) # 温度 a.draw_str(2, 'T: ' + str(th[1]) + ' C') # 湿度 a.draw_str(3, 'H: ' + str(th[0]) + '%') # 时间 a.draw_str(4, datetime.datetime.now().__str__()[5:].lstrip('0').split('.')[0]) a.display() time.sleep(1) except KeyboardInterrupt: a.quit() exit(0) def network_speed(): global ns b = rmn('bankroft', '123456') while True: time.sleep(1) ns = b.get_human_speed() def temperature_humidity(): global th pin = 25 while True: time.sleep(10) th = Adafruit_DHT.read_retry(11, 25) if __name__ == '__main__': main() 运行 依赖 python3 安装 Python 库 Adafruit_GPIO Adafruit_DHT requests 运行 python main.py 成果 作者:简书 Bankroft