Дисплей Nextion HMI. Работа с китайской версией TJC

nextion-lcdКак уже известно из предыдущих уроков, к Ардуино можно подключить множество разных дисплеев. Для самых простых проектов пригодится символьный ЖК дисплей 1602, который мы уже изучили на одном из уроков. Для вывода простейшей монохромной графики можно использовать дисплей от телефона Nokia 5110, либо более современный OLED дисплей. Ресурсов Ардуино хватает даже на цветные дисплеи с TFT матрицей.

Однако, чем сложнее дисплей, тем тяжелее приходится нашей Ардуино. Несмотря на самые изощренные и быстрые библиотеки, ресурсов микроконтроллера Atmega328 едва хватает для работы с цветной TFT матрицей. Для полезного кода остается менее половины флеш-памяти контроллера. Что делать в такой ситуации?

1. Технология HMI

Выход есть. Собственно, первое что приходит на ум — это наделить графический дисплей собственным микроконтроллером, который бы выделил весь свой вычислительный ресурс на обработку графики. Такой готовый модуль можно бы было подключать к Ардуино по одному из стандартных интерфейсов, и обмениваться с ним унифицированным командами.

Именно такой модуль мы и разберем на этом уроке. Называется этот графический модуль — Nextion HMI. Сокращение HMI означает Человеко-Машинный Интерфейс. Разработчики этого модуля предполагают, что именно такие устройства будут использоваться в элементах «умного дома», и разного рода гаджетах.

Существуют версии Nextion с различной диагональю, а также с версии с тачскрином. В нашем уроке мы используем самый простой дисплей с диагональю 2.2 дюйма и разрешением 320×240, без тачскрина.

2. Создание интерфейса

Как уже было сказано, дисплей Nextion имеет свой собственный контроллер, который отвечает за отрисовку графики. Чтобы этому контроллеру было что рисовать, мы должны заранее создать графические образы, связать их с командами, и загрузить всё это в память дисплея. Для этих целей мы воспользуемся специальным редактором интерфейсов, который был разработан командой Nextion. Скачать редактор можно на официальном сайте.

Для русификации редактора следует заменить файл cs.lang в папке с редактором. Переведенный файл можно взять тут:
http://git.robotclass.ru/download/NextionEditor

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

Итак, запускаем редактор. Перед нами появляется главная форма.

p1

1) Первое что мы сделаем — создадим новый проект. Жмем меню «Файл/Новый», выбираем папку где будет храниться файл проекта и его имя, например, test.hmi. Затем выбираем в появившемся окне подходящий формат и ориентацию дисплея.

p2

2) Теперь добавим фон нашего интерфейса. Жмем кнопку «Добав.» (Add) в разделе Изображения.

p3

В появившемся окне выбираем файл картинки с разрешением 320×240. Для урока мы нарисовали свой фон, в виде трех оранжевых прямоугольных областей.

3) Добавляем в интерфейс компонент «Изображение».

p4

По-умолчанию, компонент размещается в левом верхнем углу. Не будем его никуда двигать, и перейдем к настройкам компонента.

4) Ассоциируем компонент и ранее добавленную картинку. Для этого, в разделе настроек компонента жмем на параметр pic, и выбираем единственную в списке картинку.

p5

5) Аналогичным образом, добавляем компонент «Индикатор выполнения». Обычно этот блок служит для отображения статуса загрузки данных, но мы используем его для визуализации показаний с нашего датчика.

p6

Параметры bco и pco задают цвет фона элемента и цвет, которым заполняется индикатор. В нашем случае фон белый, и сам индикатор синий. Параметр val определяет степень наполнения индикатора, и варьируется от 0 до 100. Именно этот параметр мы и будем менять с помощью Arduino. Кстати, можно менять любой параметр, отмеченный зеленым цветом.

Остальные параметры отвечают за положение элемента на дисплее: x и y, а также за его размеры: w и h.

6) Добавляем на дисплей еще два таких же индикатора и настраиваем их. Затем добавляем компонент «стрелка» (gauge).

p8

Стрелка — это что-то вроде стрелки на спидометре автомобиля. Имеет диапазон значений от 0 до 360. Размещаем её в верхней правой части дисплея. Чтобы у стрелки был красивый круглый фон (можно и циферблат нарисовать), мы переключим параметр sta в режим crop image. Потребуется заполнить параметр picc; укажем там ту же картинку, что и для фона. Crop image означает, что фон компонента станет прозрачным, и через него будет просвечивать указанная в параметре picc картинка.

7) Перед тем, как добавить числовые поля, создадим шрифт. У дисплея нет такого же хранилища шрифтов, как в MS Windows, и он не умеет пользоваться стандартными файлами ttf. Чтобы добавить шрифт, нажмем кнопку «Добав.» (Add) в блоке «Шрифты», который находится в левой части редактора.

p9

Задаем высоту шрифта, жирность. Указываем имя шрифта. При изменении каждого параметра, в маленьком черном квадратике будет меняться написание буквы X. Не очень удобная настройка, но что поделать. Наконец, в поле «Имя шрифта» записываем подходящее название латинскими буквами и жмем «Создать шрифт». Генератор пробежится по всем буквам векторного шрифта, и создаст их растровые изображения, который мы потом загрузим в память дисплея вместе с графикой.

p10

8) Добавляем на форму три компонента «Число».

p11

В настройках компонента указываем номер шрифта font. У нас создан пока только один шрифт, так что его номер будет — 0. Параметр val отвечает за содержимое поля, его мы будем задавать через Arduino. В примере мы так же поменяли цвет и фон компонента.

9) Последний компонент, который мы разместим на нашем дисплее — «Текст». Мы не будем менять его содержимое, просто что-нибудь напишем в параметре text.

10) Наконец, скомпилируем все что мы сделали в файл, который затем отправится в память дисплея. Жмем кнопку «Компилировать» (Compile).

p13

Файл имеет расширение tft и хранится в папке, которую можно открыть через меню «Файл/Открыть папку с tft файлами».

С интерфейсом всё, переходим к самой ответственной части.

3. Nextion и TJC

Nextion HMI — марка дисплея для европейского рынка. В Китае существует версия для внутреннего рынка, которая носит название TJC (по названию чипа). С точки зрения электроники, они полностью идентичны. Как это обычно бывает, версия для Европы стоит значительно дороже. Подвох тут в том, что европейский редактор не позволяет загружать прошивку в китайский дисплей. Делать же интерфейс в китайском редакторе, немного неудобно.

Чтобы решить эту проблему, энтузиасты разработали различные варианты программ, которые позволяют загружать любую прошивку в любой дисплей, будь то Nextion или TJC. Одной такой программой, которую мы немного модернизировали, мы и воспользуемся.

4. Загрузка файла интерфейса

1) Скачиваем python-скрипт из репозитория на github: https://github.com/makeitlab/software_tools/tree/master/TJCUpload

2) Чтобы его запустить, потребуется установить интерпретатор Python 2.7.

3) После установки python, установим библиотеку для работы с последовательным портом —  pyserial.

4) Скрипт имеет несколько важных параметров, которые хранятся в отдельном файле config.py:

Последовательный порт, через который будет происходить загрузка. Меняем на актуальный:
PORT = ‘COM6′

Загрузка прошивки идет в два этапа, с разной скоростью. Обычно эти параметры менять не следует.
BAUDCOMM = 9600
BAUDUPLOAD = 115200

Идентификатор дисплея, который указан либо на самом дисплее, либо на коробке. В уроке мы использовали TJC3224T022.
CHECK_MODEL = ‘TJC3224T022′

Наконец, параметр определяющий временную задержку в протоколе обмена. Этот параметр нужно будет изменить только если процедура загрузки не удастся.
BAUDRATE_SWITCH_TIMEOUT = 0.5

5) Загружать прошивку будем через USB-UART мост, например такой:

DSC00981

Схема соединения моста и дисплея:

Nextion/TJC GND VCC RX TX
USB-UART GND +5V TX0 RX1

6) Скопируем скомпилированный файл интерфейса tft в папку со скриптом, и запустим скрипт через командную строку:

c:\путь_к_python\python.exe upload.py test.tft

7) После запуска скрипта на дисплее запустится процедура загрузки с индикатором хода выполнения. Если всё пошло как надо, то дисплей напишет об успешном выполнении процедуры и перезагрузится. Python-скрипт тоже отчитается о проделанной работе:

p14

Если загрузка остановилась на 0%

Если загрузка зависла на 0%, значит следует изменить тот самый временной параметр в настройках. Рекомендую присвоить ему значение 0.05.

Также предстоит починить прошивку дисплея, иначе он не даст повторить процедуру. Для этого понадобится microSD карта. Загружаем на карту подходящую прошивку из папки со скриптом «TJCUpload/Basic Recovery». Эта прошивка минимальная, и служит лишь для ремонта. Вставляем флешку в дисплей, подаем питание. Ждем несколько секунд, пока прошивка не загрузится автоматически.

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

5. Программа

Приступим к написанию программы для управления HMI дисплеем. Каждый компонент имеет свой идентификатор. Индикаторы выполнения, размещенные на форме: j0, j1 и j2. Числовые поля: n0, n1 и n2. Компонент «стрелка» получил идентификатор z0.

Чтобы изменить параметр val у компонента, нам нужно передать в последовательный порт команду вида:

j0.val=44

Каждая команда должна завершаться тремя байтами 0xFF. Тестовая программа будет менять значение индикатора j0 в цикле.

void setValueJ(uint32_t number){
  char buf[10] = {0};
  String cmd;

  utoa(number, buf, 10);
  cmd += "j0.val=";
  cmd += buf;

  sendCommand(cmd.c_str());
}

void sendCommand( const char* cmd ){
  Serial.print(cmd);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);
}

void setup() {
  Serial.begin(9600);
  delay(2000);
  sendCommand( "" );
  sendCommand( "page 0" );
}

void loop() {
  for(int i=0; i<100; i++){
    setValueJ(i);
    delay(10);
  }
}

Загружаем программу на Ардуино, и подключаем дисплей по схеме:

Nextion/TJC GND VCC RX TX
Ардуино Уно GND +5V 1 0

Подаем питание на Ардуино и наблюдаем движение самого верхнего индикатора.

Визуализация показаний акселерометра

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

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_ADXL345_U.h>

Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345);
float acc_lpf[3] = {0,0,0};

void setValueJ(uint8_t jn, uint32_t number){
  char buf1[3] = {0};
  char buf2[10] = {0};
  String cmd;

  utoa(jn, buf1, 3);
  utoa(number, buf2, 10);
  cmd += "j"; cmd += buf1; cmd += ".val="; cmd += buf2;
  sendCommand(cmd.c_str());
}

void setValueN(uint8_t nn, uint32_t number){
  char buf1[3] = {0};
  char buf2[10] = {0};
  String cmd;
  utoa(nn, buf1, 3);
  utoa(number, buf2, 10);
  cmd += "n"; cmd += buf1; cmd += ".val="; cmd += buf2;
  sendCommand(cmd.c_str());
}

void setValueZ(uint8_t zn, uint32_t number){
  char buf1[3] = {0};
  char buf2[10] = {0};
  String cmd;
  utoa(zn, buf1, 3);
  utoa(number, buf2, 10);
  cmd += "z"; cmd += buf1; cmd += ".val="; cmd += buf2;
  sendCommand(cmd.c_str());
}

void sendCommand( const char* cmd ){
  Serial.print(cmd);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);
}

void setup() {
  Serial.begin(9600);
  accel.begin();
  accel.setRange(ADXL345_RANGE_8_G);
  delay(2000);
  sendCommand( "" );
  sendCommand( "page 0" );
}

void loop() {
  int r[3];
  acc_lpf[0] = acc_lpf[0]*0.7 + accel.getX()*0.3;
  acc_lpf[1] = acc_lpf[1]*0.7 + accel.getY()*0.3;
  acc_lpf[2] = acc_lpf[2]*0.7 + accel.getZ()*0.3;

  r[0] = int((acc_lpf[0]+500+61)/10);
  r[1] = int((acc_lpf[1]+500+26)/10);
  r[2] = int(((acc_lpf[2]-1500)+73+500)/10);

  setValueZ(0, r[0]*3);
  setValueJ(0, r[0]); setValueN(0, r[0]);
  setValueJ(1, r[1]); setValueN(1, r[1]);
  setValueJ(2, r[2]); setValueN(2, r[2]);
  delay(1);
}

Библиотеки для работы с акселерометром можно скачать отсюда:
https://github.com/adafruit/Adafruit_ADXL345
https://github.com/adafruit/Adafruit_Sensor

Загружаем скетч на дисплей, и крутим акселерометр вокруг осей.

nextion_gif

Ну и небольшое видео, если у вас не грузится анимированный gif:

Заключение

На этом уроке мы разобрали работу Nextion/TJC дисплея с разрешением 320×240 без тачскрина — это самый простой вариант из линейки. Разумеется, гораздо интереснее будет поработать с компонентами, отвечающими за реакцию тачскрина. На следующем уроке мы изучим именно такой продвинутый вариант дисплея, и попробуем поработать со слайдбарами и кнопками.  Также построим график с помощью специального компонента, разберемся с таймером и переменными. Успехов!


Изменено:

Дисплей Nextion HMI. Работа с китайской версией TJC: Один комментарий

  1. Хотелось бы отметить, что tft файл, созданный при помощи программы Nextion Editor, корректно работает после загрузки в дисплей TJC только если версия программы меньше или равна v032. Загрузка tft файла, полученного при помощи более высоких версий, включая текущую, приводит к ошибке и потере работоспособности дисплея, восстановить его потом можно только загрузкой рабочего файла с SD карты.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>