April 9, 2023

Подключаем дисплей к EPS8266

Всем привет! Недавно я копался в своих побрякушках и нашёл пару интересных вещей, которые были куплены где-то в том году.

Вот они(слева-направо): ESP8266, Китайский нн дисплей и Arduino nano

От нано я сразу откажусь, т.к. впоследствии я хочу написать или приспособить к ESP wifi-deauther, а на дисплей выводить информацию. Так что поехали!

Информация к дисплею

Дисплей китайского происхождения, так что расчитывать на step-by-step инструкцию просто не расчитываю, но почему бы не попробовать?

Да, я использую DuckDuckGo)

И первая же ссылка ведёт нас на DataSheet, уже хорошо.

FanMade? DataSheet, ссыль в конце

Так, это нас не интерисует, листаем дальше. И... Бинго! Pinout дисплея

Display Pinout

У неподготовленного читателя можев возникнуть вопрос: "А к каким пинам ESP это цеплять?". Для этого обратимся к Pinout'у нашего ESP8266, благо найти его можно почти на каждом углу.

Pinout for ESP8266

Подключаем!

"И чо с этими дш делать? Пиши что куда цеплять и расходимся!" (С)

Собственно, сопоставляем(Дисплей - ESP8266):

  • GND - GND
  • VCC - 3V
  • SCL(Serial CLock) - High Speed CLocK(Пин D5)
  • SDA(Serial DAta) - High-speed Master Output/Slave Input(Пин D7)

Это те пины, которые мы не можем переназначить. Если с землёй и питанием всё предельно понятно, то за SCL и SDA попытаюсь немного пояснить.
Всё это дело пашет по I2C и получается следующее:

  • Serial Data - Отвечает за передачу данных
  • Serial Clock - Отвечает за синхронизацию этой самой передачи данных с доской

Их можно изменить, но т.к. они заранее определены производителем, то их переопределение повлечёт за собою кучу лишних телодвижений и неприятных последствий, которые нам пока не нужны. Тем, кто знал это, я не помог, а всем остальным... Ладно, едем дальше.

Прямо сейчас мы можем просто запитать наш ESP8266 и увидеть

Пустой экран...

А что вы ещё надеялись увидеть?)

У нас осталось ещё 4 пина, точнее 3 так как один не такой уж жизненно важный. Все эти пины мы определим сами, в коде, по ходу пьессы попытаюсь пояснить за что они отвечают.
А пока отправляемся в Arduino IDE.

Код

Будем делать всё в Arduino IDE, потому что мне лень ставить и настраивать расширения на VSCode эта среда проще в использовании, но из коробки в ней нет поддержки ESP8266. Исправить это можно в настройках(File -> Preferences), добавив в параметр Additions boards manager URLs следующее значение(без ковычек) "http://arduino.esp8266.com/stable/package_esp8266com_index.json" и нажав Ok.

Выглядеть это будет так

Список платформ обновится. После этого заходим во вкладку Boards Manager и в фильтер пишем "ESP8266", после чего устанавливаем

У меня уже всё установлено, таким же образом, но уже во вкладке Library Manager проверьте установку следующих библиотек:

  • Adafruit ST7735 and ST7789
  • Adafruit GFX
  • Adafruit BusIO

Они, вроде как, идут из коробки, но не будет лишним проверить.

Приступим к написанию мини-скетча, для вывода текста

//Импорты
#include <Adafruit_ST7735.h>
#include <Adafruit_GFX.h>

//Пины
#define CS D8
#define DS D4
#define RST D3

//Создаём объект дисплея
Adafruit_ST7735 display = Adafruit_ST7735(CS,DC,RST);

Здесь вы можете изменить пины CS, DS и RST на любые свободные и удобные вам. Дальше будем работать с созданым объектом и выводить текст на дисплей.

void setup() {
//Инициализируем дисплей, с нужными параметрами
display.initR(INITR_MINI160x80_PLUGIN);

//Изначально дисплей инициализируется вертикально
//Устанавливаем горизонтально, головой к пинам
display.setRotation(3);

//Заполняем фон синим цветом
display.fillScreen(ST7735_BLUE);

//Устанавливаем цвет текста в белый
display.setTextColor(ST7735_WHITE);

//Ставим курсор в позицию 1-1
display.setCursor(1,1);

//Выводим текст
display.print("Hello from // ADK Lab");
}

void loop() {}
Дам небольшое пояснение к координатам постановки курсора. По «госту» надо ставить курсор в позицию 0-0, но в этом случае первая строка будет впритык к физической границе дисплея, поэтому, чтобы «не царапать глаз об это», я делаю отступ, дабы был минимально-видимый промежуток.
О пинах CS, DS, RST и BLK

CS (Chip Select) - Используется для подключения/отключения к шине SPI для передачи данных

DS (Data/Command) - Используется для того чтобы указать тип передаваемых данных, то бишь по шине передаются данные или команда

RST (ReSeT) - Используется чтобы сбросить дисплей в стартовое состояние

BLK (BLacK) - Используется для управления подсветкой дисплея(включения/отключения)

Подключаем пины. Прошиваем, предварительно выбрав в качестве платформы NodeMCU 1.0(ESP-12E) и указав порт на котором висит ESP8266, и видим наш текст

При прошивке в Linux можно столкнуться с проблемой, точнее с невозможностью записать что-то на мкк. Решается это дело просто, надо вручную разрешить запись в блочный девайс, на котором у вас висит мкк, делается это командой

sudo chmod 777 /dev/ttyUSB<номер usb-порта>

Это решит проблему на один раз, далее придётся разрешать повторно, так что не закрываем терминал. Номер usb-порта можно узнать в Arduino IDE или командой

ls /dev | grep USB

На этом можно было бы и завершить, но почему бы нам не расширить функционал нашей прошивки, например добавить обновление дисплея и вывод своего текста без перепрошивки микроконтроллера. Это и сделаем!

Допиливаем скетч

Во-первых, добавим работу с Serial-портом, с его помощью мы будем отправлять текст на микроконтроллер, а также получать информацию для отладки.
До блока setup добавим определение, это будет скорость Serial-порта, а также сделаем пару импортов, они нам пригодятся чуть дальше.

#include <strings.h>
#include <stdlib.h>

#define BAUDRATE 921600

Теперь в блоке setup, первой строкой определим Serial-порт

Serial.begin(BAUDRATE);

А в выводимое на дисплей сообщение добавим значение скорости

display.print("// ADK Lab | Display v1\n\nBaudrate: "+String(BAUDRATE));

Можете прошить, дабы проверить результат, мы вас подождём)

А мы теперь напишем обработчик для данных поступающих через Serial-порт
На вход я принимаю строку вида

<режим> <цвет фона> <цвет текста>|<текст>\x03

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

//Переменные
String user_input, params, mode, bg, fg, to_print;
int idx = 0;

void loop() {
 //Отчистка переменных от мусора
 memset(&user_input, 0, sizeof(user_input));
 memset(&params, 0, sizeof(params));
 memset(&mode, 0, sizeof(mode));  
 memset(&bg, 0, sizeof(bg));
 memset(&fg, 0, sizeof(fg));
 memset(&to_print, 0, sizeof(to_print));

 //Читаем буфер до символа \x03
 user_input = Serial.readStringUntil('\x03');

 //Проверка на не-пустой буфер
 if (user_input.length() > 2){

  //Разделение полученного буфера
  params = user_input.substring(0,user_input.indexOf("|"));
  mode = params.substring(0,(idx=params.indexOf(" ",idx+1)));
  bg = params.substring(idx+1,(idx=params.indexOf(" ",idx+1)));
  fg = params.substring(idx+1,(idx=params.indexOf(" ",idx+1)));
  to_print = user_input.substring(user_input.indexOf("|")+1,user_input.length());

  //Отправляем лог
  Serial.println(params+"\nmode: "+mode+"\nbg: "+bg+"\nfg: "+fg+"\nString to print: "+to_print+"\n");

  //Делаем сравнения
  if (mode == "rw"){
   display.setCursor(1, 1);
  if (bg == "black")
   display.fillScreen(ST7735_BLACK);
  else if (bg == "blue")
   display.fillScreen(ST7735_BLUE);
  if (fg == "white")
   display.setTextColor(ST7735_WHITE);
  else if (fg == "red")
   display.setTextColor(ST7735_RED);
}
  //Выводим текст
  display.print(to_print);
}
}

Прошиваем и смотрим

Ничего нового, надо как-то отправить запрос на мкк. Открываем любой другой удобный редактор и фоном ставим на загрузку интерпретатор Python.

Для работы с Serial-портом в Python3 есть встроенная библиотека serial

import serial

#Определяем порт
port = serial.Serial(input('Enter port: '),921600)

#Переменные
cm = ''
params = ['rw','black','white']

#Справка по параметрам
#Mode:
#rw - Rewrite
#<any> - Add to exist

#BackGround colors:
#black, blue

#Text(foreground) colors:
#white, red

while True:
    try:
        cm = input(": ")
    except KeyboardInterrupt:
        exit(0)
    try:
        #Переназначение параметров
        if (cm[0] == '/'):
            cm = cm.split('=')
            if (cm[0] == '/mode'):
                params[0] = cm[1]
            if (cm[0] == '/bg'):
                params[1] = cm[1]
            elif (cm[0] == '/fg'):
                params[2] = cm[1]
            continue
    except Exception as e:
        print('\nПроизошла ошибка при обработке вашего ввода:',e,'\n')
    #Отправляем данные + обрабатываем переносы строки и возврат каретки
    port.write(f'{params[0]} {params[1]} {params[2]}|{cm}\x03'.replace('\\n','\n').replace('\\r','\r').encode())

Запускаем, подцепляемся и пробуем отправить текст

Отправляем наш текст через python скрипт

И смотрим на результат

Возможные ошибки:

[Errno 13] could not open port <ваш порт>: [Errno 13] Permission denied
Решение: Вручную разрешите доступ к блочному устройству или закройте программу, которая может сейчас взаимодействовать с мкк

[Errno 5] Input/output error
Решение: Возможно мкк плохо подключен, проверьте его подключение к хосту

Ну, что же, на этом пока всё! Мы разобрали как подключается дисплей к нашему мкк ESP8266 и написали под него простенькую прошивку. В следующих частях разберём работу с WiFi на этом мкк. Всем удачи, добра!


Исходники на PrivateBin(Истекают 10 Мая 2023г):


Интересные ссылки: