yota3墨水屏设置_使用ESP32驱动电子墨水屏
未經(jīng)私信同意禁止轉(zhuǎn)載!
一、簡(jiǎn)介
顯示技術(shù)發(fā)展很快,高中的時(shí)候大家還在學(xué)習(xí)陰極射線管顯示,天天在算電子的軌跡。而如今隨處可見(jiàn)LED顯示液晶顯示。
今天給大家介紹一下電子墨水屏。目前生活中比較常見(jiàn)的是在kindle上使用的,顯示效果很像紙,質(zhì)感很好,不上眼睛。這篇文章就是介紹電子墨水屏,并給大家提供在 ESP32 上使用 MicroPython 驅(qū)動(dòng)墨水屏的demo。
電子墨水屏,又稱電子紙,采用“微膠囊電泳顯示”技術(shù)進(jìn)行圖像顯示, 其基本原理是懸浮在液體中的帶電納米粒子受到電場(chǎng)作用而產(chǎn)生遷移。電子紙顯示屏是靠反射環(huán)境光來(lái)顯示圖案的,不需要背光,即使是在陽(yáng)光底下,電子紙顯示屏依然清晰可視,可視角度幾乎達(dá)到了 180°。因此,電子紙顯示屏非常適合閱讀。具有耗低、視角寬、陽(yáng)光直射下仍可清晰顯示等優(yōu)點(diǎn),常用于貨架標(biāo)簽、工業(yè)儀表等顯示
應(yīng)用。電子紙不同于我們常見(jiàn)的顯示技術(shù),它的的特點(diǎn)是在掉電狀態(tài)下可以保持顯示狀態(tài),這點(diǎn)特性使得它在低刷新低功耗領(lǐng)域有很大的應(yīng)用潛力,比如電子書(shū)、電子廣告牌、電子標(biāo)簽等等。當(dāng)然目前電子墨水屏由以下三個(gè)缺點(diǎn):
1.造價(jià)很高,嚴(yán)重限制其廣泛應(yīng)用。
2.支持的顯示顏色很少,目前主流的是黑白兩色,市場(chǎng)上能看到支持黑白紅或者背白黃三色的,但是價(jià)格高多了。
3.刷新速率低,無(wú)法支持動(dòng)態(tài)顯示。
我這次試用的是微雪的1.54in黑白顯示模塊。在這里放一個(gè)帶彩色顯示的官方圖片(微雪應(yīng)該付我廣告費(fèi))。
微雪1.54inc黑白紅三色電子墨水屏電子墨水屏使用的SPI接口,其引腳定義以及和ESP32的連接關(guān)系如下
接口定義二、驅(qū)動(dòng)編寫
電子墨水屏的驅(qū)動(dòng)官方提供C語(yǔ)言版本和python版本,我寫的是Micropyon版本,主要是在pyhon版本的基礎(chǔ)拿掉Micropython中無(wú)法使用的圖片庫(kù),并且做了底層驅(qū)動(dòng)數(shù)據(jù)格式上的轉(zhuǎn)換,驅(qū)動(dòng)分為兩個(gè)文件epdif.py和epd1in54.py。
epdif.py中定義了硬件接口和數(shù)據(jù)寫入函數(shù),源碼如下
from machine import Pin, SPI import time# Pin definition reset_pin = Pin(2,Pin.OUT) dc_pin = Pin(4,Pin.OUT) cs_pin = Pin(5,Pin.OUT) busy_pin = Pin(0,Pin.IN)gpio_sck = Pin(18) gpio_mosi = Pin(23) gpio_miso = Pin(19)spi = SPI(-1, baudrate=100000, polarity=1, phase=0, sck=gpio_sck, mosi=gpio_mosi, miso=gpio_miso)def epd_digital_write(pin, val):pin.value(val)def epd_digital_read(pin):return pin.value()def epd_delay_ms(delaytime):time.sleep_ms(delaytime)def spi_transfer(data):spi.write(data)def epd_init():epd_digital_write(cs_pin, 0)spi.init(baudrate=200000)return 0epd1in54.py中定義了復(fù)位設(shè)置刷新區(qū)域等函數(shù),用于對(duì)顯示信息進(jìn)行設(shè)置。源碼如下:
import epdif from machine import Pin, SPI import ujson import struct # Display resolution EPD_WIDTH = 200 EPD_HEIGHT = 200# EPD1IN54 commands DRIVER_OUTPUT_CONTROL = b'x01' BOOSTER_SOFT_START_CONTROL = b'x0C' GATE_SCAN_START_POSITION = b'x0F' DEEP_SLEEP_MODE = b'x10' DATA_ENTRY_MODE_SETTING = b'x11' SW_RESET = b'x12' TEMPERATURE_SENSOR_CONTROL = b'x1A' MASTER_ACTIVATION = b'x20' DISPLAY_UPDATE_CONTROL_1 = b'x21' DISPLAY_UPDATE_CONTROL_2 = b'x22' WRITE_RAM = b'x24' WRITE_VCOM_REGISTER = b'x2C' WRITE_LUT_REGISTER = b'x32' SET_DUMMY_LINE_PERIOD = b'x3A' SET_GATE_TIME = b'x3B' BORDER_WAVEFORM_CONTROL = b' ' SET_RAM_X_ADDRESS_START_END_POSITION = b'x44' SET_RAM_Y_ADDRESS_START_END_POSITION = b'x45' SET_RAM_X_ADDRESS_COUNTER = b'x4E' SET_RAM_Y_ADDRESS_COUNTER = b'x4F' TERMINATE_FRAME_READ_WRITE = b'xFF'class EPD :def __init__(self):self.reset_pin = epdif.reset_pinself.dc_pin = epdif.dc_pinself.busy_pin = epdif.busy_pinself.width = EPD_WIDTHself.height = EPD_HEIGHTself.lut = self.lut_full_updatelut_full_update = [0x02, 0x02, 0x01, 0x11, 0x12, 0x12, 0x22, 0x22, 0x66, 0x69, 0x69, 0x59, 0x58, 0x99, 0x99, 0x88, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xB4, 0x13, 0x51, 0x35, 0x51, 0x51, 0x19, 0x01, 0x00]lut_partial_update = [0x10, 0x18, 0x18, 0x08, 0x18, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x14, 0x44, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]def digital_write(self, pin, value):epdif.epd_digital_write(pin, value)def digital_read(self, pin):return epdif.epd_digital_read(pin)def delay_ms(self, delaytime):epdif.epd_delay_ms(delaytime)def send_command(self, command):self.digital_write(self.dc_pin, 0)# the parameter type is list but not int# so use [command] instead of commandepdif.spi_transfer(command)def send_data(self, data):self.digital_write(self.dc_pin, 1)# the parameter type is list but not int# so use [data] instead of dataepdif.spi_transfer(data)def init(self, lut):if (epdif.epd_init() != 0):return -1# EPD hardware init startself.lut = lutself.reset()self.send_command(DRIVER_OUTPUT_CONTROL)self.send_data(struct.pack("B", (EPD_HEIGHT - 1) & 0xFF))self.send_data(struct.pack("B", ((EPD_HEIGHT - 1) >> 8) & 0xFF))self.send_data(b'x00') # GD = 0 SM = 0 TB = 0self.send_command(BOOSTER_SOFT_START_CONTROL)self.send_data(b'xD7')self.send_data(b'xD6')self.send_data(b'x9D')self.send_command(WRITE_VCOM_REGISTER)self.send_data(b'xA8') # VCOM 7Cself.send_command(SET_DUMMY_LINE_PERIOD)self.send_data(b'x1A') # 4 dummy lines per gateself.send_command(SET_GATE_TIME)self.send_data(b'x08') # 2us per lineself.send_command(DATA_ENTRY_MODE_SETTING)self.send_data(b'x03') # X increment Y incrementself.set_lut(self.lut) # EPD hardware init endreturn 0def wait_until_idle(self):while(self.digital_read(self.busy_pin) == 1): # 0: idle, 1: busyself.delay_ms(100) ### @brief: module reset.# often used to awaken the module in deep sleep,##def reset(self):self.digital_write(self.reset_pin, 0) # module resetself.delay_ms(300)self.digital_write(self.reset_pin, 1)self.delay_ms(300) ### @brief: set the look-up table register##def set_lut(self, lut):self.lut = lutself.send_command(WRITE_LUT_REGISTER)# the length of look-up table is 30 bytesfor i in range(0, len(lut)):self.send_data(struct.pack("B", self.lut[i]))### @brief: put an image to the frame memory.# this won't update the display.##def set_frame_memory(self, image, image_width,image_height,x, y):#if (image == None or x < 0 or y < 0):# return# x point must be the multiple of 8 or the last 3 bits will be ignoredx = x & 0xF8image_width = image_width & 0xF8if (x + image_width >= self.width):x_end = self.width - 1else:x_end = x + image_width - 1if (y + image_height >= self.height):y_end = self.height - 1else:y_end = y + image_height - 1 self.set_memory_area(x, y, x_end, y_end)self.set_memory_pointer(x, y)self.send_command(WRITE_RAM)# send the image data#pixels = image_monocolor.load()byte_to_send = 0x00for j in range(0, y_end - y + 1):# 1 byte = 8 pixels, steps of i = 8for i in range(0, (x_end - x + 1)/8):self.send_data(struct.pack("B", image[i+j*(image_width >>3)]))# Set the bits for the column of pixels at the current position.#if pixels[i, j] != 0:# byte_to_send |= 0x80 >> (i % 8)#if (i % 8 == 7):# self.send_data(struct.pack("B", byte_to_send))# byte_to_send = 0x00 ### @brief: clear the frame memory with the specified color.# this won't update the display.##def clear_frame_memory(self, color):self.set_memory_area(0, 0, self.width - 1, self.height - 1)self.set_memory_pointer(0, 0)self.send_command(WRITE_RAM)# send the color datafor i in range(0, self.width / 8 * self.height):self.send_data(struct.pack("B", color))### @brief: update the display# there are 2 memory areas embedded in the e-paper display# but once this function is called,# the the next action of SetFrameMemory or ClearFrame will # set the other memory area.##def display_frame(self):self.send_command(DISPLAY_UPDATE_CONTROL_2)self.send_data(b'xC4')self.send_command(MASTER_ACTIVATION)self.send_command(TERMINATE_FRAME_READ_WRITE)self.wait_until_idle()### @brief: specify the memory area for data R/W##def set_memory_area(self, x_start, y_start, x_end, y_end):self.send_command(SET_RAM_X_ADDRESS_START_END_POSITION)# x point must be the multiple of 8 or the last 3 bits will be ignoredself.send_data(struct.pack("B", (x_start >> 3) & 0xFF))self.send_data(struct.pack("B", (x_end >> 3) & 0xFF))self.send_command(SET_RAM_Y_ADDRESS_START_END_POSITION)self.send_data(struct.pack("B", y_start & 0xFF))self.send_data(struct.pack("B", (y_start >> 8) & 0xFF))self.send_data(struct.pack("B", y_end & 0xFF))self.send_data(struct.pack("B", (y_end >> 8) & 0xFF))### @brief: specify the start point for data R/W##def set_memory_pointer(self, x, y):self.send_command(SET_RAM_X_ADDRESS_COUNTER)# x point must be the multiple of 8 or the last 3 bits will be ignoredself.send_data(struct.pack("B", (x >> 3) & 0xFF))self.send_command(SET_RAM_Y_ADDRESS_COUNTER)self.send_data(struct.pack("B", y & 0xFF))self.send_data(struct.pack("B", (y >> 8) & 0xFF))self.wait_until_idle()### @brief: After this command is transmitted, the chip would enter the# deep-sleep mode to save power.# The deep sleep mode would return to standby by hardware reset.# You can use reset() to awaken or init() to initialize##def sleep(self):self.send_command(DEEP_SLEEP_MODE)self.wait_until_idle()還編寫了一個(gè)簡(jiǎn)單的測(cè)試demo:
def test():print('startn')epd = epd1in54.EPD()epd.init(epd.lut_full_update)print('epd init finish n')epd.clear_frame_memory(0xff)epd.set_frame_memory(gImage_imag,200,200, 0, 0)epd.display_frame()epd.delay_ms(2000)我將測(cè)試源碼和相關(guān)參考資料打包放在百度云盤中。
鏈接:https://pan.baidu.com/s/1RrKF14Nc21VC-coSittHQQ 密碼:jp6t
三、構(gòu)想
有了墨水屏和wifi功能,如果添加上簡(jiǎn)單的按鍵控制和電池,就具備一個(gè)kindle的基本結(jié)構(gòu)了,做一個(gè)小號(hào)的kindle應(yīng)該不難的哈。
最后,如果有大佬打賞,讓我買個(gè)彩色的墨水屏玩玩就好了。
歡迎關(guān)注我的專欄《電子工程師有多無(wú)聊》,你可以看到更多關(guān)于使用Python進(jìn)行硬件編程的文章。如果你有興趣,也歡迎投稿。
總結(jié)
以上是生活随笔為你收集整理的yota3墨水屏设置_使用ESP32驱动电子墨水屏的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: pyqt 子窗口控制主窗口绘图_实战Py
- 下一篇: 微博 用户画像_微博/抖音/快手/小红书