差别
这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
mp_oled [2021/10/05 17:43] gongyusu [6. 汉字的显示] |
mp_oled [2023/08/01 10:49] (当前版本) group003 |
||
---|---|---|---|
行 13: | 行 13: | ||
import utime | import utime | ||
- | sda=machine.Pin(20) | + | sda=machine.Pin(11) |
- | scl=machine.Pin(21) | + | scl=machine.Pin(10) |
i2c=machine.I2C(0, sda=sda, scl=scl, freq=400000) | i2c=machine.I2C(0, sda=sda, scl=scl, freq=400000) | ||
行 536: | 行 536: | ||
</code> | </code> | ||
+ | ### 7. 滚动屏幕的程序 | ||
+ | [[https://randomnerdtutorials.com/micropython-ssd1306-oled-scroll-shapes-esp32-esp8266/|滚动屏幕]] | ||
+ | <code python> | ||
+ | oled_width = 128 | ||
+ | oled_height = 64 | ||
+ | oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c) | ||
+ | screen1_row1 = "Screen 1, row 1" | ||
+ | screen1_row2 = "Screen 1, row 2" | ||
+ | screen1_row3 = "Screen 1, row 3" | ||
+ | screen2_row1 = "Screen 2, row 1" | ||
+ | screen2_row2 = "Screen 2, row 2" | ||
+ | |||
+ | screen3_row1 = "Screen 3, row 1" | ||
+ | |||
+ | screen1 = [[0, 0 , screen1_row1], [0, 16, screen1_row2], [0, 32, screen1_row3]] | ||
+ | screen2 = [[0, 0 , screen2_row1], [0, 16, screen2_row2]] | ||
+ | screen3 = [[0, 40 , screen3_row1]] | ||
+ | |||
+ | # Scroll in screen horizontally from left to right | ||
+ | def scroll_in_screen(screen): | ||
+ | for i in range (0, oled_width+1, 4): | ||
+ | for line in screen: | ||
+ | oled.text(line[2], -oled_width+i, line[1]) | ||
+ | oled.show() | ||
+ | if i!= oled_width: | ||
+ | oled.fill(0) | ||
+ | |||
+ | # Scroll out screen horizontally from left to right | ||
+ | def scroll_out_screen(speed): | ||
+ | for i in range ((oled_width+1)/speed): | ||
+ | for j in range (oled_height): | ||
+ | oled.pixel(i, j, 0) | ||
+ | oled.scroll(speed,0) | ||
+ | oled.show() | ||
+ | |||
+ | # Continuous horizontal scroll | ||
+ | def scroll_screen_in_out(screen): | ||
+ | for i in range (0, (oled_width+1)*2, 1): | ||
+ | for line in screen: | ||
+ | oled.text(line[2], -oled_width+i, line[1]) | ||
+ | oled.show() | ||
+ | if i!= oled_width: | ||
+ | oled.fill(0) | ||
+ | |||
+ | # Scroll in screen vertically | ||
+ | def scroll_in_screen_v(screen): | ||
+ | for i in range (0, (oled_height+1), 1): | ||
+ | for line in screen: | ||
+ | oled.text(line[2], line[0], -oled_height+i+line[1]) | ||
+ | oled.show() | ||
+ | if i!= oled_height: | ||
+ | oled.fill(0) | ||
+ | |||
+ | # Scroll out screen vertically | ||
+ | def scroll_out_screen_v(speed): | ||
+ | for i in range ((oled_height+1)/speed): | ||
+ | for j in range (oled_width): | ||
+ | oled.pixel(j, i, 0) | ||
+ | oled.scroll(0,speed) | ||
+ | oled.show() | ||
+ | |||
+ | # Continous vertical scroll | ||
+ | def scroll_screen_in_out_v(screen): | ||
+ | for i in range (0, (oled_height*2+1), 1): | ||
+ | for line in screen: | ||
+ | oled.text(line[2], line[0], -oled_height+i+line[1]) | ||
+ | oled.show() | ||
+ | if i!= oled_height: | ||
+ | oled.fill(0) | ||
+ | |||
+ | while True: | ||
+ | |||
+ | # Scroll in, stop, scroll out (horizontal) | ||
+ | scroll_in_screen(screen1) | ||
+ | sleep(2) | ||
+ | scroll_out_screen(4) | ||
+ | |||
+ | scroll_in_screen(screen2) | ||
+ | sleep(2) | ||
+ | scroll_out_screen(4) | ||
+ | |||
+ | scroll_in_screen(screen3) | ||
+ | sleep(2) | ||
+ | scroll_out_screen(4) | ||
+ | |||
+ | # Continuous horizontal scroll | ||
+ | scroll_screen_in_out(screen1) | ||
+ | scroll_screen_in_out(screen2) | ||
+ | scroll_screen_in_out(screen3) | ||
+ | |||
+ | # Scroll in, stop, scroll out (vertical) | ||
+ | scroll_in_screen_v(screen1) | ||
+ | sleep(2) | ||
+ | scroll_out_screen_v(4) | ||
+ | |||
+ | scroll_in_screen_v(screen2) | ||
+ | sleep(2) | ||
+ | scroll_out_screen_v(4) | ||
+ | |||
+ | scroll_in_screen_v(screen3) | ||
+ | sleep(2) | ||
+ | scroll_out_screen_v(4) | ||
+ | |||
+ | # Continuous verticall scroll | ||
+ | scroll_screen_in_out_v(screen1) | ||
+ | scroll_screen_in_out_v(screen2) | ||
+ | scroll_screen_in_out_v(screen3) | ||
+ | </code> | ||
+ | |||
+ | ### 8. 绘图 | ||
+ | 使用[[https://github.com/adafruit/micropython-adafruit-gfx/blob/master/gfx.py|Adafruit GFX Arduino library to MicroPython]] | ||
+ | |||
+ | <code python> | ||
+ | # Port of Adafruit GFX Arduino library to MicroPython. | ||
+ | # Based on: https://github.com/adafruit/Adafruit-GFX-Library | ||
+ | # Author: Tony DiCola (original GFX author Phil Burgess) | ||
+ | # License: MIT License (https://opensource.org/licenses/MIT) | ||
+ | |||
+ | |||
+ | class GFX: | ||
+ | |||
+ | def __init__(self, width, height, pixel, hline=None, vline=None): | ||
+ | # Create an instance of the GFX drawing class. You must pass in the | ||
+ | # following parameters: | ||
+ | # - width = The width of the drawing area in pixels. | ||
+ | # - height = The height of the drawing area in pixels. | ||
+ | # - pixel = A function to call when a pixel is drawn on the display. | ||
+ | # This function should take at least an x and y position | ||
+ | # and then any number of optional color or other parameters. | ||
+ | # You can also provide the following optional keyword argument to | ||
+ | # improve the performance of drawing: | ||
+ | # - hline = A function to quickly draw a horizontal line on the display. | ||
+ | # This should take at least an x, y, and width parameter and | ||
+ | # any number of optional color or other parameters. | ||
+ | # - vline = A function to quickly draw a vertical line on the display. | ||
+ | # This should take at least an x, y, and height paraemter and | ||
+ | # any number of optional color or other parameters. | ||
+ | self.width = width | ||
+ | self.height = height | ||
+ | self._pixel = pixel | ||
+ | # Default to slow horizontal & vertical line implementations if no | ||
+ | # faster versions are provided. | ||
+ | if hline is None: | ||
+ | self.hline = self._slow_hline | ||
+ | else: | ||
+ | self.hline = hline | ||
+ | if vline is None: | ||
+ | self.vline = self._slow_vline | ||
+ | else: | ||
+ | self.vline = vline | ||
+ | |||
+ | def _slow_hline(self, x0, y0, width, *args, **kwargs): | ||
+ | # Slow implementation of a horizontal line using pixel drawing. | ||
+ | # This is used as the default horizontal line if no faster override | ||
+ | # is provided. | ||
+ | if y0 < 0 or y0 > self.height or x0 < -width or x0 > self.width: | ||
+ | return | ||
+ | for i in range(width): | ||
+ | self._pixel(x0+i, y0, *args, **kwargs) | ||
+ | |||
+ | def _slow_vline(self, x0, y0, height, *args, **kwargs): | ||
+ | # Slow implementation of a vertical line using pixel drawing. | ||
+ | # This is used as the default vertical line if no faster override | ||
+ | # is provided. | ||
+ | if y0 < -height or y0 > self.height or x0 < 0 or x0 > self.width: | ||
+ | return | ||
+ | for i in range(height): | ||
+ | self._pixel(x0, y0+i, *args, **kwargs) | ||
+ | |||
+ | def rect(self, x0, y0, width, height, *args, **kwargs): | ||
+ | # Rectangle drawing function. Will draw a single pixel wide rectangle | ||
+ | # starting in the upper left x0, y0 position and width, height pixels in | ||
+ | # size. | ||
+ | if y0 < -height or y0 > self.height or x0 < -width or x0 > self.width: | ||
+ | return | ||
+ | self.hline(x0, y0, width, *args, **kwargs) | ||
+ | self.hline(x0, y0+height-1, width, *args, **kwargs) | ||
+ | self.vline(x0, y0, height, *args, **kwargs) | ||
+ | self.vline(x0+width-1, y0, height, *args, **kwargs) | ||
+ | |||
+ | def fill_rect(self, x0, y0, width, height, *args, **kwargs): | ||
+ | # Filled rectangle drawing function. Will draw a single pixel wide | ||
+ | # rectangle starting in the upper left x0, y0 position and width, height | ||
+ | # pixels in size. | ||
+ | if y0 < -height or y0 > self.height or x0 < -width or x0 > self.width: | ||
+ | return | ||
+ | for i in range(x0, x0+width): | ||
+ | self.vline(i, y0, height, *args, **kwargs) | ||
+ | |||
+ | def line(self, x0, y0, x1, y1, *args, **kwargs): | ||
+ | # Line drawing function. Will draw a single pixel wide line starting at | ||
+ | # x0, y0 and ending at x1, y1. | ||
+ | steep = abs(y1 - y0) > abs(x1 - x0) | ||
+ | if steep: | ||
+ | x0, y0 = y0, x0 | ||
+ | x1, y1 = y1, x1 | ||
+ | if x0 > x1: | ||
+ | x0, x1 = x1, x0 | ||
+ | y0, y1 = y1, y0 | ||
+ | dx = x1 - x0 | ||
+ | dy = abs(y1 - y0) | ||
+ | err = dx // 2 | ||
+ | ystep = 0 | ||
+ | if y0 < y1: | ||
+ | ystep = 1 | ||
+ | else: | ||
+ | ystep = -1 | ||
+ | while x0 <= x1: | ||
+ | if steep: | ||
+ | self._pixel(y0, x0, *args, **kwargs) | ||
+ | else: | ||
+ | self._pixel(x0, y0, *args, **kwargs) | ||
+ | err -= dy | ||
+ | if err < 0: | ||
+ | y0 += ystep | ||
+ | err += dx | ||
+ | x0 += 1 | ||
+ | |||
+ | def circle(self, x0, y0, radius, *args, **kwargs): | ||
+ | # Circle drawing function. Will draw a single pixel wide circle with | ||
+ | # center at x0, y0 and the specified radius. | ||
+ | f = 1 - radius | ||
+ | ddF_x = 1 | ||
+ | ddF_y = -2 * radius | ||
+ | x = 0 | ||
+ | y = radius | ||
+ | self._pixel(x0, y0 + radius, *args, **kwargs) | ||
+ | self._pixel(x0, y0 - radius, *args, **kwargs) | ||
+ | self._pixel(x0 + radius, y0, *args, **kwargs) | ||
+ | self._pixel(x0 - radius, y0, *args, **kwargs) | ||
+ | while x < y: | ||
+ | if f >= 0: | ||
+ | y -= 1 | ||
+ | ddF_y += 2 | ||
+ | f += ddF_y | ||
+ | x += 1 | ||
+ | ddF_x += 2 | ||
+ | f += ddF_x | ||
+ | self._pixel(x0 + x, y0 + y, *args, **kwargs) | ||
+ | self._pixel(x0 - x, y0 + y, *args, **kwargs) | ||
+ | self._pixel(x0 + x, y0 - y, *args, **kwargs) | ||
+ | self._pixel(x0 - x, y0 - y, *args, **kwargs) | ||
+ | self._pixel(x0 + y, y0 + x, *args, **kwargs) | ||
+ | self._pixel(x0 - y, y0 + x, *args, **kwargs) | ||
+ | self._pixel(x0 + y, y0 - x, *args, **kwargs) | ||
+ | self._pixel(x0 - y, y0 - x, *args, **kwargs) | ||
+ | |||
+ | def fill_circle(self, x0, y0, radius, *args, **kwargs): | ||
+ | # Filled circle drawing function. Will draw a filled circule with | ||
+ | # center at x0, y0 and the specified radius. | ||
+ | self.vline(x0, y0 - radius, 2*radius + 1, *args, **kwargs) | ||
+ | f = 1 - radius | ||
+ | ddF_x = 1 | ||
+ | ddF_y = -2 * radius | ||
+ | x = 0 | ||
+ | y = radius | ||
+ | while x < y: | ||
+ | if f >= 0: | ||
+ | y -= 1 | ||
+ | ddF_y += 2 | ||
+ | f += ddF_y | ||
+ | x += 1 | ||
+ | ddF_x += 2 | ||
+ | f += ddF_x | ||
+ | self.vline(x0 + x, y0 - y, 2*y + 1, *args, **kwargs) | ||
+ | self.vline(x0 + y, y0 - x, 2*x + 1, *args, **kwargs) | ||
+ | self.vline(x0 - x, y0 - y, 2*y + 1, *args, **kwargs) | ||
+ | self.vline(x0 - y, y0 - x, 2*x + 1, *args, **kwargs) | ||
+ | |||
+ | def triangle(self, x0, y0, x1, y1, x2, y2, *args, **kwargs): | ||
+ | # Triangle drawing function. Will draw a single pixel wide triangle | ||
+ | # around the points (x0, y0), (x1, y1), and (x2, y2). | ||
+ | self.line(x0, y0, x1, y1, *args, **kwargs) | ||
+ | self.line(x1, y1, x2, y2, *args, **kwargs) | ||
+ | self.line(x2, y2, x0, y0, *args, **kwargs) | ||
+ | |||
+ | def fill_triangle(self, x0, y0, x1, y1, x2, y2, *args, **kwargs): | ||
+ | # Filled triangle drawing function. Will draw a filled triangle around | ||
+ | # the points (x0, y0), (x1, y1), and (x2, y2). | ||
+ | if y0 > y1: | ||
+ | y0, y1 = y1, y0 | ||
+ | x0, x1 = x1, x0 | ||
+ | if y1 > y2: | ||
+ | y2, y1 = y1, y2 | ||
+ | x2, x1 = x1, x2 | ||
+ | if y0 > y1: | ||
+ | y0, y1 = y1, y0 | ||
+ | x0, x1 = x1, x0 | ||
+ | a = 0 | ||
+ | b = 0 | ||
+ | y = 0 | ||
+ | last = 0 | ||
+ | if y0 == y2: | ||
+ | a = x0 | ||
+ | b = x0 | ||
+ | if x1 < a: | ||
+ | a = x1 | ||
+ | elif x1 > b: | ||
+ | b = x1 | ||
+ | if x2 < a: | ||
+ | a = x2 | ||
+ | elif x2 > b: | ||
+ | b = x2 | ||
+ | self.hline(a, y0, b-a+1, *args, **kwargs) | ||
+ | return | ||
+ | dx01 = x1 - x0 | ||
+ | dy01 = y1 - y0 | ||
+ | dx02 = x2 - x0 | ||
+ | dy02 = y2 - y0 | ||
+ | dx12 = x2 - x1 | ||
+ | dy12 = y2 - y1 | ||
+ | if dy01 == 0: | ||
+ | dy01 = 1 | ||
+ | if dy02 == 0: | ||
+ | dy02 = 1 | ||
+ | if dy12 == 0: | ||
+ | dy12 = 1 | ||
+ | sa = 0 | ||
+ | sb = 0 | ||
+ | if y1 == y2: | ||
+ | last = y1 | ||
+ | else: | ||
+ | last = y1-1 | ||
+ | for y in range(y0, last+1): | ||
+ | a = x0 + sa // dy01 | ||
+ | b = x0 + sb // dy02 | ||
+ | sa += dx01 | ||
+ | sb += dx02 | ||
+ | if a > b: | ||
+ | a, b = b, a | ||
+ | self.hline(a, y, b-a+1, *args, **kwargs) | ||
+ | sa = dx12 * (y - y1) | ||
+ | sb = dx02 * (y - y0) | ||
+ | while y <= y2: | ||
+ | a = x1 + sa // dy12 | ||
+ | b = x0 + sb // dy02 | ||
+ | sa += dx12 | ||
+ | sb += dx02 | ||
+ | if a > b: | ||
+ | a, b = b, a | ||
+ | self.hline(a, y, b-a+1, *args, **kwargs) | ||
+ | y += 1 | ||
+ | </code> | ||
+ | |||
+ | |||
+ | 绘图示例: | ||
+ | <code python> | ||
+ | oled_width = 128 | ||
+ | oled_height = 64 | ||
+ | oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c) | ||
+ | |||
+ | graphics = gfx.GFX(oled_width, oled_height, oled.pixel) | ||
+ | |||
+ | while True: | ||
+ | |||
+ | graphics.line(0, 0, 127, 20, 1) | ||
+ | oled.show() | ||
+ | sleep(1) | ||
+ | oled.fill(0) | ||
+ | |||
+ | graphics.rect(10, 10, 50, 30, 1) | ||
+ | oled.show() | ||
+ | sleep(1) | ||
+ | oled.fill(0) | ||
+ | |||
+ | graphics.fill_rect(10, 10, 50, 30, 1) | ||
+ | oled.show() | ||
+ | sleep(1) | ||
+ | oled.fill(0) | ||
+ | |||
+ | |||
+ | graphics.circle(64, 32, 10, 1) | ||
+ | oled.show() | ||
+ | sleep(1) | ||
+ | oled.fill(0) | ||
+ | |||
+ | graphics.fill_circle(64, 32, 10, 1) | ||
+ | oled.show() | ||
+ | sleep(1) | ||
+ | oled.fill(0) | ||
+ | |||
+ | graphics.triangle(10,10,55,20,5,40,1) | ||
+ | oled.show() | ||
+ | sleep(1) | ||
+ | oled.fill(0) | ||
+ | |||
+ | graphics.fill_triangle(10,10,55,20,5,40,1) | ||
+ | oled.show() | ||
+ | sleep(1) | ||
+ | oled.fill(0) | ||
+ | </code> |