Модуль display
Работа с графическим дисплеем
Контроллер имеет виртуальный монохромный графический дисплей с разрешением 128x64 пикселей. Дисплей может использоваться как средство визуализации в пользовательских алгоритмах.
Модуль display предоставляет функции для управления дисплеем, рисования графических примитивов и вывода текстовой информации на дисплей.
Начало координат находится в нижнем левом углу дисплея: x растёт вправо, y — вверх. Видимые координаты: x от 0 до 127, y от 0 до 63. Передавайте целые координаты и разумные размеры в пределах экрана; отрисовка отдельных пикселей за границами экрана отсекается.
Все функции рисования возвращают None. Параметры передаются позиционно; исключение — именованный step у lines.
Функции
clear
Функция clear() очищает весь текущий графический буфер. Форма clear(x, y, w, h) очищает прямоугольную область. Допустимы только 0 или 4 позиционных аргумента. Область обрезается по границам экрана, в том числе при отрицательных x/y; используйте размеры w/h в пределах 0…255.
update
Функция update(doClear=True) копирует содержимое текущего графического буфера в результирующий.
Если параметр doClear установлен в True (по умолчанию), текущий буфер очищается после копирования.
Если передать False или 0 позиционно, буфер очищаться не будет: update(False). Именованный вызов update(doClear=False) не поддерживается.
from display import clear, update
update() # Копирует и очищает буфер
# равносильно
update(False)
clear()
Контроллер имеет два идентичных графических буфера:
- Результирующий буфер: хранит итоговое изображение дисплея, которое отображается в веб-интерфейсе.
- Текущий буфер: с которым работают все функции рисования графических примитивов.
Алгоритм рисования на виртуальном дисплее предполагает:
- Очистку графического буфера с помощью
clear() - Рисование графических элементов
- Обновление результирующего буфера с помощью
update()
from display import clear, rect, update
clear()
rect(0, 0, 40, 40)
update()
dot
Функция dot(x, y, mode=1) рисует один пиксель с координатами (x, y). Без третьего аргумента пиксель закрашивается. Фактические режимы:
1— установить пиксель;0— очистить пиксель;INVERT(2) — инвертировать.
Особенность текущих констант: экспортируется ON=0 и OFF=1, то есть имена не совпадают с фактическим действием. Для однозначного управления используйте dot(x, y, 1) и dot(x, y, 0) либо вызов без mode.
# Рисуем кривую изменения значения с датчика температуры
from dev import count, Ai, conv
from display import dot, clear, update, WIDTH, HEIGHT
from time import sleep
from math import isfinite
count(Ai=1)
temp = Ai(0).conf(type='ntc', access='rr')
clear()
for x in range(WIDTH):
temperature = temp.val() # Уже градусы Цельсия, без деления на 10
if isfinite(temperature):
y = int(conv(temperature, 15.0, 35.0, 0, HEIGHT - 1))
dot(x, y)
update(False)
sleep(0.5)
# Рисуем "белый шум"
from display import dot, clear, update, WIDTH, HEIGHT, INVERT
from random import randint
clear()
while True:
x = randint(0, WIDTH - 1)
y = randint(0, HEIGHT - 1)
dot(x, y, INVERT)
update(False)

line
Функция line(x, y, w, h, step=1) рисует линию от (x, y) до (x + w, y + h). w/h — приращения, они могут быть отрицательными. Необязательный пятый аргумент step передаётся позиционно и должен быть положительным, иначе возникает ValueError.
Особенность отрисовки с step > 1: точки между шагами сейчас инвертируются, а не пропускаются. Поэтому на пустом буфере линия может выглядеть сплошной. Для обычной линии используйте step=1.
from display import line, clear, update, WIDTH, HEIGHT
from random import randint
clear()
for _ in range(50):
x = randint(0, WIDTH - 1)
y = randint(0, HEIGHT - 1)
w = randint(-WIDTH, WIDTH)
h = randint(-HEIGHT, HEIGHT)
line(x, y, w, h)
update(False)

lines
Функция lines(start, *increments, step=1) рисует набор линий, в котором конец каждой линии соединен с началом следующей.
start— координаты начала первой линии(x, y).*increments— последовательность приращений(w1, h1), (w2, h2), ..., определяющих направление и длину каждой линии относительно предыдущей точки.step— необязательный именованный положительный шаг с тем же поведением, что уline.
Нужны начальная точка и хотя бы одно приращение. Каждая пара — список или кортеж ровно из двух целых чисел. Неверные значения вызывают исключение; ранее нарисованные сегменты при ошибке следующей пары не отменяются.
Пример использования:
# Рисуем параллелепипед
from dev import run
from display import clear, lines, update
def parallelepiped(x, y, w, h, d):
lines((x, y), (w, 0), (d, h), (-w, 0), (-d, -h))
clear()
parallelepiped(0, 0, 40, 40, 10)
update()

circle
Функция circle(x, y, r, mode=1) рисует окружность с центром (x, y) и неотрицательным радиусом r. Необязательный четвёртый позиционный аргумент — режим пикселя: 1 для установки, 0 для очистки, INVERT для инверсии. Используйте радиусы, соизмеримые с экраном.
# Анимация с окружностями
from dev import run
from display import clear, circle, update, WIDTH, HEIGHT
def step(c):
for i in range(12):
circle(WIDTH // 2, HEIGHT // 2, i * 6 + int(c % 6))
update()
run(step, 0.25)

image
Функция image(x, y, h, data) рисует битовое изображение (bitmap), где:
x,y— координаты изображения (нижний левый угол).h— высота изображения 1…64 пикселя.data— непустойbytesилиarray('B')(беззнаковые байты).array('b'), другие типы array, bytearray и memoryview не принимаются этой функцией.
Координаты x/y должны помещаться в signed int16 (−32768…32767). Число байт должно быть кратно (h + 7) // 8, а вычисленная ширина — от 1 до 255. Неверная геометрия/длина вызывает ValueError, тип данных — TypeError.
Битовое изображение представляет собой массив байт, в котором каждый байт определяет отображение столбца из 8 пикселей.
Например, байт 0xff закрасит все 8 пикселей, 0x01 — только первый (нижний) пиксель в столбце.
Байты идут по столбцам: сначала все байты первого столбца снизу вверх, затем следующего. Внутри байта младший бит соответствует нижнему пикселю; лишние верхние биты последнего байта столбца игнорируются. Изображение заменяет пиксели прямоугольника, включая нулевые биты.
Ширина изображения определяется автоматически: w = len(data) // ((h + 7) // 8).
Например, если высота изображения не превышает 8 пикселей, его ширина равна числу байт битового изображения; если 8 < h <= 16, то w = len(data) / 2.
from display import clear, image, update
# Пример битового изображения: простой смайлик 8x8 пикселей
smiley_data = bytes([
0x3C, # 00111100
0x42, # 01000010
0xA5, # 10100101
0x81, # 10000001
0xA5, # 10100101
0x99, # 10011001
0x42, # 01000010
0x3C # 00111100
])
clear()
image(60, 28, 8, smiley_data)
update()

icon
icon(x, y, num, type=0) выводит символ из встроенного набора. Все аргументы позиционные; num — числовой индекс символа, а не строка. Три аргумента выбирают системный шрифт.
Наборы (ширина × высота): 0 — системный шрифт 5×8; 1 — Arial 19×28; 2 — Arial 9×14; 3 — иконки 11×11; 4 — иконки 15×11; 5 — иконки 15×15; 6 — иконки 6×15. Другой type также выбирает системный шрифт. Наличие символа зависит от набора; универсального списка Unicode для этих индексов нет.
import display
display.clear()
display.icon(0, 0, 65) # Символ A системного шрифта.
display.update()
text
Функция text(x: int, y: int, s: str, align: int = LEFT) выводит строку текста на дисплей.
x,y— координаты начала текста приalign == LEFT, середины приalign == CENTERили конца приalign == RIGHT.s— строка текста.align— выравнивание текста относительно координат(x, y). Возможные значения:LEFT(по умолчанию),CENTER,RIGHT.
Текст выводится с помощью системного шрифта, каждый символ которого имеет размер 5 пикселей в ширину и 8 пикселей в высоту.
Шрифт поддерживает кириллицу. Входная строка UTF-8 переводится во внутренний однобайтный буфер на 128 байт, включая завершающий ноль: выводится не более 127 преобразованных символов. Ограничение относится к этому буферу, а не к числу байт исходного UTF-8. Символы вне поддерживаемого набора не отображаются корректно. Перевод строки \n переносит вывод вниз на 9 пикселей; суммарный лимит включает все строки.
from display import clear, text, update, CENTER, WIDTH, HEIGHT
clear()
text(WIDTH // 2, HEIGHT // 2 - 4, "Привет, мир!", CENTER)
update()

rect
Функция rect(x, y, w, h, step=1) рисует контур прямоугольника. Пятый позиционный аргумент step, если задан, должен быть положительным; особенности шага такие же, как у line. Используйте положительные размеры. Аргументы:
x,y— координаты начала прямоугольника.w,h— ширина и высота прямоугольника.
rectfull
Функция rectfull(x, y, w, h) рисует закрашенный прямоугольник. Передавайте положительные ширину и высоту.
from display import clear, rectfull, update
clear()
rectfull(10, 10, 50, 30)
update()

invert
Функция invert() инвертирует весь текущий буфер. Форма invert(x, y, w, h) инвертирует прямоугольную область. Другие количества аргументов вызывают TypeError. Используйте положительные размеры в пределах 0…255. Аргументы области:
x,y— координаты начала области.w,h— ширина и высота области.
При инвертировании закрашенные пиксели становятся незакрашенными и наоборот.
from display import clear, invert, update
clear()
invert(10, 10, 30, 30)
invert(20, 20, 30, 30)
update()

Константы
WIDTH
Ширина дисплея. WIDTH == 128
HEIGHT
Высота дисплея. HEIGHT == 64
LEFT
Выравнивание текста по левому краю. LEFT == 0
CENTER
Выравнивание текста по центру. CENTER == 2
RIGHT
Выравнивание текста по правому краю. RIGHT == 1
ON
Экспортируемое значение ON == 0. В текущей реализации передача этого значения в dot/circle очищает пиксель; для закрашивания используйте 1.
OFF
Экспортируемое значение OFF == 1. В текущей реализации передача этого значения в dot/circle устанавливает пиксель; для очистки используйте 0.
INVERT
Режим инвертирования пикселя. INVERT == 2
Проверено на контроллере
Проверены circle с четвёртым аргументом, icon с тремя/четырьмя аргументами, изображения высотой 1/7/8/9/63/64, проверки длины и типа bitmap, отказ при нулевом шаге и неверных координатах lines, а также очистка области с отрицательным y. Результат очистки сверялся по 1024 байтам LCD через HTTP. Это не визуальная проверка каждого символа и каждого графического примитива.