Найти в Дзене
Электроника, ESP32, Arduino

Как через UART затолкать картинку из Windows в ардуиновский дисплей часть 1

Есть файлик который лежит в папке с проектом C# в формате cote.jpg с разрешением 128*160 пикселей:

Задача - загрузить эту картинку в какой-нибудь дисплей который можно подключить к Arduino - например на контроллере ST7735S, через виртуальный COM порт, который создается в "форточках" при подключении Arduino.

-2

Для работы с этим дисплеем в Интернет есть замечательная "заготовка" от блогера AlexGyver

https://youtu.be/y_DoxUCI2ZI?si=aOW3nt2Rp3a6CkE3
https://youtu.be/y_DoxUCI2ZI?si=aOW3nt2Rp3a6CkE3

Там из обычного Ардуиновского дисплея он сделал монитор для компьютера- но в рамках нашей задачи нас интересует только код для Arduino, который принимает данные.

github.com

Приложение под Windows я буду писать сам. В рамках данной задачи - код для Arduino просто черный ящик, который может принимать данные и передавать их на дисплей. Код проекта AlexGyver писал в среде Arduino IDE, но без использования Arduino Wiring. Для чтения данных используется прямой доступ к регистрам интерфейса UART - никаких Serial.begin и прочих примочек класса Serial встроенного в среду Arduino IDE.

-4

В дисплей данные также передаются в обход библиотеки. Круче только яйца оптимизировать ничего не нужно - минус подхода, в любой другой Ардуине, основанной не на микроконтроллере ATMega 328P данный код разумеется работать не будет (нужно брать документацию на мк и переписывать названия регистров).

Перед написанием программы нужно знать протокол передачи 2 вещи:

1. Интерфейс UART может передавать данные только побайтно. Признаком начала передачи данных в своем проекте AlexGyver заложил цифру "1" (увидев это число все последующие приходящие байты Ардуино будет считать данными для дисплея). Отправлять 1 больше нельзя - при отправке изображения нужно это учитывать, и заменять 1 на 2, что приведет к небольшой потере качества цвета, но упростит задачу в целом.

2. Каким образом представляются цвета в дисплее. AlexGyver предлагает 2 варианта, которые задаются изменением одного параметра перед сборкой скетча и заливку его в Arduino:

-5

RGB16 2 байта на пиксел - заводской режим работы дисплея

-6

Чтобы полностью передать картину на дисплей потребуется отправить 1 и 160*128*2 = 40960 байт.

Упрощенный RGB8

-7

Чтобы полностью передать картину на дисплей потребуется отправить 1 и 160*128 = 20480 байт.

Упрощенный режим работы AlexGyver сделал, чтобы передавать меньше данных для полного обновления дисплея - не забываем, что он делал на нем монитор, а UART интерфейс не очень шустрый - на максимальной для Arduino скорости 2'000'000 baud обновлять дисплей быстрее чем 5 раз в секунду не получиться (ну такой себе телевизЕр)

Еще раз повторюсь - работу этого черного ящика кода разбирать в своей статье я не вижу особого смысла, кому интересно можете посмотреть видео AlexGyver, там он всё это подробно разжёвывает.

В рамках решаемой задачи, достаточно понимать, что и в какой последовательности нужно слать в Ардуину, чтобы отобразить картинку на дисплее.

Схему собираем прямо по коду:

-8

Дисплей подключен на аппаратный SPI интерфейс, поэтому для Arduino NANO схема подключения будет следующая:

  • GND - GND
  • VDD - +5V
  • SCL - SCLK — Serial Clock: тактовый сигнал (от ведущего)
    (Другие обозначения: SCK, CLK) Arduino: пин 13
  • SDA - MOSI — Master Output, Slave Input: данные от ведущего к ведомому
    Другие обозначения: SDI, DI, SI Arduino: пин 11
  • RST - пин 8
  • DC - пин 9
  • CS - Slave Select: выбор ведомого; устанавливается ведущим
    Другие обозначения: nCS, CS, CSB, CSN, nSS, STE Arduino пин 10
  • BLK - Подсветка дисплея (+5V)

Читать из дисплея нам нечего поэтому MISO — Master Input, Slave Output: данные от ведомого к ведущему (Другие обозначения: SDO, DO, SO)
Arduino: на пин 12 подключать ненужно - на дисплее этой ноги нет совсем.

Тестируем правильность подключения и сам дисплей. Для этого устанавливаем в среду Arduino IDE 2 библиотеки.

Adafruit-ST7735-Library

GitHub - adafruit/Adafruit-ST7735-Library: This is a library for the Adafruit 1.8" SPI display http://www.adafruit.com/products/358 and http://www.adafruit.com/products/618

Adafruit-GFX-Library

GitHub - adafruit/Adafruit-GFX-Library: Adafruit GFX graphics core Arduino library, this is the 'core' class that all our other graphics libraries derive from

Это можно сделать прямо из самой Arduino IDE установив при этом все зависимые библиотеки.

-9
-10
-11

Заливаем скетч ST7735_testV1 (все примеры кода будут в конце статьи в архиве). (пример просто демонстрирует все возможности библиотеки шрифты, графика)

-12
-13

Аппаратная часть проверена и работает как нужно. Можно заливать код от AlexGyver и начинать пилить приложение для "форточек" на С# под дот нет.

Для компиляции проекта пришлось заменить скачанные библиотеки - библиотеками от AlexGyver (тоже будут в архиве)

-14

Тестируем режим RGB16. Сначала просто нарисуем "матрасик"

-15

Заведем три переменные которые могут принимать значения:

  • r 0...31 (красный 5 бит 2^5 =32)
  • g 0...63 (зеленый 6 бит 2^6 =64)
  • b 0..31 (синий 5 бит 2^5 =32)

Младшие биты из этих байтов необходимо будет затолкать в 2 байта согласно картинке, поместить в массив в память компьютера, а потом отправить на дисплей одним чохом - но в С# есть нюанс....

Побитовые операторы определены для типов int, uint, long и ulong. Если оба операнда имеют другие целочисленные типы (sbyte, byte, short, ushort или char), их значения преобразуются в тип int, который также является типом результата операции. Если операнды имеют разные целочисленные типы, их значения преобразуются в ближайший содержащий целочисленный тип.

В UART мы отправляем тип byte (побайтно), а клеить исходные данные придется "интами". Поскольку int у нас по размеру больше чем byte придется указать компилятору что нам пофиг на потерянные биты использовать явное преобразование типов данных.

Для теста сначала мы будем увеличивать переменную r, потом b, потом g. Результат работы:

-16

Вроде работает как нужно. Для написания кода на C# была взята заготовка из прошлой статьи:

Только вместо мигания светодиодом при нажатии на кнопку 2 будем рисовать матрасик (хотя это больше на вентиляционную решетку получилось).

Не забываем поставить скорость 2000000 бод

-17

Код при нажатии на 2-й батон:

-18

Создаем однобайтный массив размером 40960 байт. В первому байту присваиваем значение 1 (не символ 1, а именно число 1) - Arduino товьсь, сейчас полетят данные для дисплея.

Матрас создается в памяти ПК построчно - у дисплея 128 строк

-19

Каждую строчку рисуем оттенком определенного цвета

-20

Отправляем сформированный матрасик в COM порт

-21

Первый параметр - массив, второй параметр - позиция с которой начинается отправка, третий параметр длина массива.

На зеленом цвете виден не большой артефакт - это как раз та самая 1-ца которая заменяется на 2-йку. Насколько это скажется на качестве изображения разберем в следующей статье. Там же поговорим о представлении цвета в винде.

ОГЛАВЛЕНИЕ КАНАЛА ТУТ

ОВНОКОД ТУТ

CSharp.zip

Всем удачи!