Авторизация
Зарегистрироваться

avatar RSS блога Подписка

То, что вы не очень хотели знать о дисплеях Nextion


Долго ли, коротко ли, а так давно, что уже почти не помню, товарищи из ITEAD предложили познакомиться с их продукцией — на мой вкус. Про Wi-Fi выключатель Sonoff я рассказал довольно быстро, а вот знакомство с дисплеем Nextion затянулось.

Причина банальна: ITEAD разослали на обзоры многие множества этих дисплеев, а мне не хотелось быть совсем банальным. Поэтому я сначала придумал, как бы разнообразить текст, а потом начались муки творчества, бессонные ночи, позорные отступления и проч., и проч.

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



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

Перечислю:


И чтобы вы понимали, сколько их раздали на MySKU:


Поэтому конспективно. Изначально задумка ITEAD превосходна: дисплей с собственным простым API и сенсорной панелью. Просто чудо, чтобы изготавливать блоки управления с графическими меню без особых хлопот.

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

Грубо говоря, здесь не нужно мучиться и собирать массивы точек или подключать тучу всяких библиотек. Одна строчка — и на экране поменялся фон. Нажали — открылось меню. Подключили Arduino — строим графики по данным, которые поступают через последовательный порт.

Для обзора я выбрал экран NX4832TO35 из серии Basic с диагональю 3.5 дюйма и разрешением 320х480 точек. Выбор был связан с тем, что я до конца не был уверен в том, что буду писать текст, поэтому подбирал агрегат, за который мог бы потом без особого сожаления рассчитаться с товарищами из ITEAD.

Кроме этих экранов в линейке Nextion есть так называемые модели Enhanced, улучшение которых, если я правильно понял, сводится к операциям энергонезависимой памятью (EEPROM) и портам ввода/вывода (GPIO).

Но вернемся к моему экземпляру, где необходимо добавить некоторые размеры к уже имеющемуся эскизу от ITEAD:



Добавляю: дисплей выступает над платой примерно на 3,5 мм, толщина текстолита — 1,5 мм, интерфейсный разъем имеет толщину 6,5 мм, и это самый толстый элемент обратной стороны экрана. С вставленной ответной частью разъема есть шансы уложиться в 107 мм по длине всей конструкции.

Геометрия, как видите, не сложная, но и не совсем элементарная:







Качество экрана не идеально, что объяснимо — это не IPS. Но матрица имеет неплохие углы обзора и яркость. Разумеется, просто обязан пожаловаться на некоторую белесость черного оттенка и характерную, хотя и не фатальную инверсию.





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

Что касается сенсорного управления, то здесь оно такое же архаичное, как и матрица — резистивное. И удивительно адекватное — продавливать экран не нужно, а сами нажатия ну буквально что-то среднее между прикосновением, характерным для емкостных экранов, и легким нажатием.

Вот что немного раздражает, так это хорошо видимые дорожки сенсорной панели, которая во всей красе уложена поверх экрана. Причина моего негодования проста: при таком раскладе невозможно сделать аккуратный корпус, где экран был бы вровень с поверхностью. То есть, можно, конечно, но тогда или будет видна служебная часть, или же нужно будет изуродовать поверхность какой-нибудь компактной, но выступающей заглушкой.

Если смириться, то будет как-то так:





И сразу хочу сказать, что в попытках сделать корпус вровень с экраном, я все-таки что-то повредил у Nextion, и сенсорная панель хотя и работает, но только если посильнее сжать экран в месте крепления шлейфа сенсорной панели (отсюда и странное видео).

К чести дисплея, сломал я его не с первой попытки, а после десятка с лишним примерок под разные корпуса. И решающую роль, полагаю, сыграло то, что вырез под экран я старался сделать максимально плотным — чтобы, по возможности, не было зазоров между экраном и корпусом. По этой причине я, конечно, был готов, что в конечном итоге переломлю шлейф, который прямо располагает к этому.

Но все равно огорчился.

Впрочем, для тех, кто не столь придирчив и допускает корпус, где дисплей утоплен, Nextion сразу предлагает макет рамки к 3D-печати. Это для 3.5 дюймов, но рамки имеются на весь ассортимент на страничке Nextion HMI Solution.

Вот такая рамка (картинка от ITEAD, я не печатал):



В целом, понимаете, все выглядит почти прекрасно (мелочи не в счет), пока не начинаешь задумываться о чем-то более-менее симпатичном.

Я, к примеру, задумался о метеостанции и даже мечтал, что сейчас быстренько все соберу, подключу и напишу текст, изобилующий восторженными эпитетами в отношении просветленного китайского гения. По идее, у меня буквально сразу же должно было бы получиться что-то вроде такого (простите за музыку, но я помню, что мое сопение вам нравится еще меньше):



Но вышло не совсем так и далеко не сразу. А чтобы понять, почему, следует вкратце ознакомиться с ТЗ на проектируемый прибор.

Именно:

1) Температура в помещении и на улице
2) Влажность в помещении и на улице
3) Атмосферное давление
4) Концентрация углекислого газа в помещении
5) Концентрация механических примесей типа PM2.5 в помещении
6) Тенденции изменения всех показателей за последние несколько часов
7) График изменения показателей за сутки (или около того)

Из этого понятно, что нужно:

1) Симпатичную фоновую картинку
2) Шрифты
3) Графики

Как хорошо, думал я, что Nextion сам это все может и умеет. Только загружу в него картинку и шрифты, скормлю данные от Arduino и буду самым крутым самодельщиком. И тут начинается самое интересное.

Начиная со среды разработки Nextion Editor, которая является ключевым элементом всей экосистемы. Здесь можно не только собрать весь интерфейс будущего устройства, но и полностью протестировать, не отходя от кассы — встроен полный эмулятор Nextion, включая даже взаимодействие с внешним микроконтроллером.

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

Поэтому вот такой исходник в GIMP:



Превращается в такую штуку в Nextion:



Во-вторых, все добавляемые элементы нумеруются. Это, разумеется, правильно, потому что именно по этим номерам они впоследствии адресуются скриптами и микроконтроллером. Проблема в том, что нумерация автоматическая и поменять ее крайне сложно. К чести ITEAD можно упомянуть, что они предусмотрели некий способ перемещения элементов вверх-вниз, но это обычно не помогает.

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

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

К слову, так выглядит макет главного экрана для спейсбоев:



Другие варианты экранов
Для хоббитов:



Для колонистов:



Для романтиков:



Для кофеманов:



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

На этом же экране, конечно, следует иметь и кнопки — для возврата на главную страницу и для перехода к просмотру отдельного показателя, если это возможно.

Для наглядности пара макетов — первого и третьего экрана с графиками:





Здесь на переднем плане мы наблюдаем невидимые в рабочем режиме кнопки типа Hotspot (по версии Nextion), а на заднем — клетку элементов Waveform, предназначенных для вывода графиков.

При этом кнопки слева служат для возврата на шаг назад, а справа — к более детальному представлению данных. А так как на первом экране все и так детальнее некуда, то кнопка детализации ведет (сюрприз-сюрприз) на главный экран.

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

Грубо говоря, кнопка «Назад» на первой странице имеет номер 5, на второй — 3, а третьей — 6. И если бы я хотел их адресовать из Arduino (а я хотел), то мне пришлось бы делать таблицу соответствий для каждой страницы. Наоборот, если сделать правильно, то кнопка «Назад» на любой странице будет иметь один и тот же номер, к примеру, 2. А это, между прочим, существенно упрощает код.

Когда я в первый раз так жестоко ошибся (т.е. понакидал элементов, как попало), то надолго ушел в депрессию. Поскольку уже нарисовал весь интерфейс, как я себе его представлял. Но потом взял себя в руки и все перерисовал, как следует. Потому что альтернатива (фиксированный код) меня пугала еще больше.

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

Третья особенность — отображение текста. Изначально тоже выглядит фантастически, поскольку предполагает использование любого шрифта. Достаточно лишь прогнать его через встроенный конвертер и загрузить полученный результат в дисплей.

Конвертер очень простой, нельзя даже выбрать разновидность шрифта, если их несколько:



Однако конвертер ужасен. Да что там! У любого уважающего себя хипстера-ламберсека борода бы разом выпала, когда бы он увидел, во что превратились изящные очертания того, что я нагуглил по словосочетанию «хипстерские шрифты».

Смотрите сами:



На мой взгляд, здесь вполне очевидно, что — конвертированный шрифт, а что — чистая графика.

Решение, как и в случае с автонумерацией, не слишком простое. Опять же, нужно взять себя в руки и сделать табличку потребных символов в любом приличном графредакторе (тот же GIMP подойдет).

. Вот так выглядит табличка символов:



А затем вместо того, чтобы непринужденно хохоча, посылать в Nextion прямой текст, следует составлять надписи из подготовленной таблички символов. Здесь, кстати, здорово выручает функция вырезки фрагмента изображения, предусмотренная в Nextion.

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

В моем случае координатный массив выглядит таким образом:


// ширина символов 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
byte symbolW[5][11] = {{25, 15, 30, 25, 30, 30, 25, 30, 25, 30, 5},
                       {11, 6, 12, 12, 14, 13, 12, 13, 12, 12, 3},
                       {11, 6, 12, 12, 14, 13, 12, 13, 12, 12, 3},
                       {11, 6, 12, 12, 14, 13, 12, 13, 12, 12, 3},
                       {11, 6, 12, 12, 14, 13, 12, 13, 12, 12, 3}};


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

Но к индикации. Например, чтобы отобразить символ 0 в позиции x = 10, y = 20 следует отправить в Nextion команду:

xpic 10, 20, 25, 60, 0, 0, 1


Здесь 60 — известная заранее высота символа (известная потому, что именно такой высоты символы в моей табличке), «0,0» — координаты верхнего левого угла области обрезки, а следующая за ними единица — уникальный номер изображения, загруженного в Nextion:



Самое печальное, что другого способа сделать красивый текст без ущерба хипстерам я не придумал. Если вы знаете больше моего — пишите.

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

Дело в том, что элемент Waveform, который логичнее всего использовать для графиков, рассчитан на непрерывный поток входных данных. Иными словами, при попытке показать десяток значений, все они будут скромно жаться в левом (или в зависимости от ориентации графика) уголке.

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

Кроме того, существует печальное ограничение на формат входных данных: строго положительные значения от 0 до 255. Перевожу на русский: если хочется строить график по произвольному набору данных, все значения нужно привести к указанному диапазону (сдвинуть, нормализовать, масштабировать).

Например, если на входе ряд вида

-1586, -300, -280, -100, 0, 20, 185, 550, 2567


То мой алгоритм выглядит так:

1) Поиск минимального и максимального значения
2) Расчет коэффициента масштаба (по моей версии y=255/|(max-min)|)
3) Получение расчетной точки по формуле z = (x + |min|)*y, где x — исходное значение, а y — коэффициент масштабирования

Тогда, скажем, значение -280 трансформируется следующим образом:

1) min = -1586, max = 2567
2) y = 255/|(2567-(-1586)| = 0,06
3) z = (-280+|-1586|)*0,06 = 78,36


При этом выплывает еще одна особенность. Помните, я говорил про одновременное отображение нескольких графиков. Например, влажности, температуры и давления?

Так вот, у элемента графика Nextion есть четыре канала. Здорово, подумал я, мне как раз столько и нужно, потому что больше на дисплее с 320 точками по вертикали — издевательство. А вот по 80 точек на график — еще куда ни шло.

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

Если не верите — попробуйте понять сами:



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

Т.е. это уже не от 0 до 255, а гораздо меньше. Как так — уму непостижимо, но судя по всему, именно так, поскольку график, который нормально смотрится на Waveform в весь экран, внезапно обрезается при переходе на Waveform меньшей высоты.

В конечном итоге я решил, что дисплей отображает 255 логических точек в текущую физическую высоту элемента типа Waveform. И по этому поводу выдумал еще один масштабирующий коэффициент, равный соотношению физической и логической высот Waveform. То есть, если высота Waveform, скажем, 100 точек, то дополнительный коэффициент масштабирования получается 100/255.

В общем, сам сдвинешься, пока график нарисуешь. Мне, между прочим, так это до конца и не удалось (хотя графики стали выглядеть лучше), но я утешаю себя тем, что у меня все же не прецизионный прибор, а так, демонстрация.

Чтобы понимать, что вышло, вот сравнение графиков, отрисованных на Nextion и построенных примерно по тем же данным сервисом Народный Мониторинг:




Еще несколько менее успешных визуализаций









Еще одна не совсем очевидная вещь — переключение скорости порта Nextion. По умолчанию это 9600 бит/с, что довольно мало для отрисовки графиков. Точнее, достаточно для тех, кто любит медленно и печально, но когда я наблюдал вывод четырех кривых, в голову настойчиво просился анекдот про хочешь я расскажу тебе сказочку?

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

Нужно так:

1) Дать команду на переключение скорости Nextion
2) Закрыть порт, поменять скорость внешнего контроллера
3) Открыть порт на новой скорости
4) Дать команду на переключение скорости Nextion

В моем коде это выглядит следующим образом:

Serial1.begin(9600); // открытие порта дисплея на стандартной скорости
  Serial1.print("baud=57600"); // команда на изменение скорости
  sendToNextion();
 Serial1.end(); // закрытие порта

 Serial1.begin(57600); // открытие порта на новой скорости
 Serial1.print("baud=57600"); // команда на изменение скорости
 sendToNextion();


Если вы думаете, что это все проблемы, спешу заверить: не все. Просто потому, что я не ставил целью использовать все команды Nextion и еще не рассказал об особенностях сборки образа интерфейса для загрузки в дисплей.

А особенность в том, что при наличии скриптовых (встроенных в Nextion Editor) действий, они обрабатываются компилятором, который суров, как чугунный лом. Сообщения об ошибках в нем настолько же точны, насколько бесполезны.

Особенно, если учесть некоторую несуразность системы команд. Поясню. Например, для перехода на нулевую страницу дисплею нужно сказать:

page 0


А чтобы обновить выбранный элемент, хоть ту же страницу —
ref page0


Все заметили, что в первом случае пробел между page и 0 есть, а во втором — нет? То-то. С точки зрения программиста концепция, конечно, довольно прозрачна: сначала команда, а затем — аргумент.

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

На данном примере это могло бы выглядеть так:


page page0 // переход на страницу 0
ref page0 // обновление страницы 0


Плюс к тому я сталкивался, что даже лишний пробел может стать причиной того, что код не компилируется или команда исполняется не так, как следует.

Например, вот эта работает:

add 1,0,227


А вот эта — нет:

add 1, 0, 227


И это нужно помнить тем, кто избалован приличными компиляторами, которые и за ручку возьмут, и проведут, и сами исправят, что могут. Я уже молчу о том, что описание системы команд содержит очевидные ошибки вроде вот такого:


xpic: Advanced crop picture
xpic x, y, w, h, x0, y0, picid

[удалено]

Example:
picq 20, 50, 30, 20, 15, 15, 0  


Т.е. в примере команда xpic волшебным образом превращается в picq. Скажете, что не смертельно, и будете правы. Но крайне неприятно.

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

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

Что касается текущей реализации, то при моему подходе к написанию кода закономерно вышло, что я подобрался вплотную к пределам Arduino Pro Mini, а точнее — ATmega328p. По счастью, компиляция прошла без проблем, и при исполнении программа не имеет тенденции к зависанию.

Данные дисплей получает от самодельного «мультисенсора», в котором установлен комплект из четырех датчиков:

  • BMP085 измеряет давление и температуру
  • DHT22 измеряет влажность
  • MQ135 измеряет содержание газов (условно — CO2)
  • Sharp GP2Y1010AU0F измеряет содержание твердых частиц (условно — PM2.5)

Данные передаются моим излюбленным способом — с помощью элементарного передатчика с амплитудной модуляцией на частоте 433,92 МГц посредством библиотеки RC-Switch. Это для совместимости с уже имеющейся немудреной домашней автоматикой.

Я прекрасно понимаю, что с таким комплектом о точности речь не идет, однако данные базовых датчиков (температура, влажность, давление) хорошо соотносятся с показаниями простой бытовой метеостанции.

Что касается более затейливых датчиков, то показания MQ135 хорошо отражают состояние атмосферы в комнате: чем выше показания, тем более душно. Датчик Sharp измеряет более тонкие материи, поэтому я пока не готов рассуждать о достоверности его данных.

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

Для желающих повторить сей беспримерный подвиг, но на другой платформе, сразу показываю, где в коде происходит получение данных:

Дополнительная информация
// ПОЛУЧЕНИЕ ДАННЫХ ОТ РАДИОДАТЧИКОВ

   if (mySwitch.available()) { // проверяем датчики
    int value = mySwitch.getReceivedValue();
    if (value != 0) {
   
// ВЛАЖНОСТЬ И ТЕМПЕРАТУРА СНАРУЖИ
      if (mySwitch.getReceivedValue() / 100000 == 161) {

        weatherData = mySwitch.getReceivedValue() - 16100000;
        if (weatherData > 10000) { // пришла влажность
          parameterS[3] = (weatherData - 10000)/10;
          statusS[3] = statusS[3]+1;   
          statusBoolean[3] = true;  
        }
        else { // пришла температура
          if (weatherData > 1000) { // минусовая температура
            parameterS[1] = -(weatherData - 1000);
            minusOut = true;
          }
          else { // плюсовая температура
            parameterS[1] = weatherData;
            minusOut = false;
          }
        }
          statusS[1] = statusS[1]+1;
          statusBoolean[1] = true;
      }

// ДАВЛЕНИЕ И ТЕМПЕРАТУРА ВНУТРИ
      if (mySwitch.getReceivedValue() / 10000 == 1210) {
        parameterS[4] = (mySwitch.getReceivedValue() - 12100000) / 1.33; // пришло давление
        statusS[4] = statusS[4]+1;   
        statusBoolean[4] = true;   
       
      }

      if (mySwitch.getReceivedValue() / 100000 == 131) {
        weatherData = mySwitch.getReceivedValue() - 13100000;
        if (weatherData > 1000) { // минусовая температура
          parameterS[0] = -(weatherData - 1000);
          minusIn = true;
        }
        else { // плюсовая температура
          parameterS[0] = weatherData;
          minusIn = false;
        }
          statusS[0] = statusS[0]+1;
          statusBoolean[0] = true;
      }

// ВЛАЖНОСТЬ ВНУТРИ      

      if (mySwitch.getReceivedValue() / 10000 == 1212) {
        parameterS[2] = (mySwitch.getReceivedValue() - 12120000)/10; // влажность
        statusS[2] = statusS[2]+1;   
        statusBoolean[2] = true;   
       
      }
// CO2 PPM
      if (mySwitch.getReceivedValue() / 10000 == 1213) {
        parameterS[5] = (mySwitch.getReceivedValue() - 12130000); // CO2
        statusS[5] = statusS[5]+1;   
        statusBoolean[5] = true;   
        
      }      
// PM2.5
      if (mySwitch.getReceivedValue() / 10000 == 1214) {
        parameterS[6] = (mySwitch.getReceivedValue() - 12140000); // PM2.5
        statusS[6] = statusS[6]+1;   
        statusBoolean[6] = true;   
        
      } 

    }
    mySwitch.resetAvailable();
    //    mySwitch.enableReceive(0); // включение RC Switch
  }   


Здесь смысловое значение имеют конструкции вида


parameterS[индекс параметра] = значение параметра];
statusS[индекс параметра] = statusS[индекс параметра]+1;   
statusBoolean[индекс параметра] = true; 


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

Код не для слабонервных. Это, в принципе, рабочая версия, которая вписывается в ограничения по памяти ATmega328p. Но не до конца почищенная и, вероятно, не финальная, потому что с графиками надо что-то делать.

Для экрана еще потребуется интерфейс:

1) Версия для редактирования
2) Вариант для загрузки в дисплей

Несколько комментариев. Для экономии памяти (может быть, субъективной) я остановился на размере архива в 48 значений по каждому параметру. С учетом того, что значения отправляются в архив каждые полчаса, график охватывает период примерно в сутки.

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

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

Время «жизни» датчиков — полчаса. Т.е. если в течение получаса датчик не передавал показания (или они не были приняты), он считается отключенным и не отображается на дисплее.

Общее количество разрядов в параметрах — не более четырех. При этом для температуры и PM2.5 это включает и десятичный разряд.

Проверок, обработок ошибок и защит от всяких бед вроде переполнения, неверных форматов и прочего практически нет. Это мой сознательный выбор, как человека ленивого.

Кроме того, чтобы все было приемлемо и с эстетической точки зрения, я нарисовал очень простой корпус для 3.5-дюймового Nextion. Экран здесь вровень с поверхностью, много прямых углов, заглушки на контактах сенсорной панели нет — то, что надо для ценителей сурового промдизайна. Но у меня подозрение, что это не финальный вариант.



Больше корпуса














Сборка








С предыдущей итерацией, которая мне больше симпатична за счет тонких рамок:



В окрасе:



Мультисенсор из обычной коробчонки переместил в дизайнерскую лампу за авторством тов. Markellov. Штука, считаю, идеальная: хорошо маскирует бардак внутри и одновременно прекрасно продувается всеми ветрами, что актуально для всех датчиков (ну разве что кроме давления).

Если подсадить кота, получится как на картинке «Настало время удивительных историй»:



Размеры артобъекта, разумеется, менял под свои потребности. И впоследствии покрасил его невероятной «каменной» краской Rust-Oleum American Accents Stone.





Итог в двух словах: дисплеи Nextion — превосходная по своей концепции задумка (как, по-моему, вообще все идеи ITEAD), по поводу реализации которой лично у меня ощущения двоякие.

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

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

Но несмотря на то, что мне не все понравилось, а некоторые вещи совсем не понравились, не могу сказать, что это гадость или еще что-то в таком роде.

Что касается оправданности цены экрана, то вряд ли смогу сказать что-то толковое. По сравнению с любимыми текстовыми дисплеями типа 1602 или экранами Nokia, которые работают с Arduino, конечно, дорого.

Однако если хочется укомплектовать терпимым (не идеальным) сенсорным дисплеем свою самоделку, сэкономив некоторое время на проектировании и макетировании интерфейса — уже неплохо.

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

Небольшая сессия вопросов-ответов.

Q: У Nextion куча команд и возможностей, а ты рассказал про полторы функции и решил, что все плохо. Как так?
A: Ну, каждый кулик свое болото хвалит. У меня не было задачи перемалывать каждую букву руководства. Поэтому я рассказал, на какие грабли наступил при решении типовой задачи.

Q: А ты смешной, использовать датчики за 2 бакса, чтобы оценивать качество атмосферы. И что они у тебя показывают, погоду на Луне?
A: Про датчики мне уже все рассказали еще в обзоре MQ135, но меня все устраивает.

Q: А не проще было взять старый смартфон, закачать апп и поставить все на видном месте?
A: Наверное, проще, но цель была другая.

Q: Прямо просятся часы, игры другие фичи. Почему не сделал?
A: Если честно, еще много чего просится. Смена фона прямо из интерфейса, к примеру. Но мне эта конструкция уже и так всю душу вынула. Сил больше никаких нет.

Q: Да за такие деньги можно целый планшет купить!
A: Я не призываю покупать Nextion.

Q: Ты вообще в курсе, что в Nextion процессор круче, чем в Arduino, которую к нему прикрутил?
A: Да, в курсе. Нет, разбираться со встроенным не собираюсь.

Товар предоставлен для написания обзора магазином. Обзор опубликован в соответствии с п.18 Правил сайта.
Планирую купить +39 Добавить в избранное +105 +181
свернуть развернуть
Комментарии (67)
RSS
+
avatar
  • s0me0ne
  • 17 ноября 2016, 11:51
+2
абалдеть!
+
avatar
+5
Хоть и букафф слишком много, но прочитал с удовольствием. Экран позывов «купить» не вызвал, но будем надеяться, что ITead будет продвигать эти технологии в массы и мы увидим качественные компоненты для «домашних» нужд в скором времени. Разумеется, не без помощи таких людей как Вы. Я думаю, ITead Вам уже должен зарплату платить, а не просто высылать предметы на обзор.
+
avatar
  • sir0ta
  • 17 ноября 2016, 13:36
+3
За более гуманную сумму денег.
+
avatar
  • 5077070
  • 17 ноября 2016, 16:13
0
Поддержу! Ибо минидисплейчик стоимостью в половину планшета не вызывает желания его покупать.
+
avatar
+14
Вот это я понимаю, человек постарался, для народа написал.
+
avatar
  • Alf
  • 17 ноября 2016, 12:14
0
Ну что сказать, круто!

Я понимаю, что пункт 18 надо как-то отрабатывать, но стоит ли овчинка выделки?
Мороки с этим дисплеем просто жесть.

И да, как Вы и указали, расположение шлейфа крайне неудачное.
Для красоты еще нужно колхозить тонкую накладку.
+
avatar
  • spc
  • 17 ноября 2016, 12:28
+12
Я технику люблю со страшной силой, поэтому когда предложили взять на посмотреть интересные штуки — отказаться тяжело. Хотя после этого случая в голове что-то вроде «больше — никогда!». Причем дело не столько в замороченности экрана, сколько в обязаловке — взял, значит давай скорее пиши.

Опять же, к чести ITEAD хочу сказать, что они меня вообще не терзали — за что им большое и человеческое спасибо. Но тем не менее, необходимость сделать обзор все-таки была занозой где-то там в уголке головы.

Подводя итог — возможно, впечатления были бы более светлыми, если бы я купил экран за свои и не был бы никому ничем обязан.
+
avatar
  • Alf
  • 17 ноября 2016, 12:47
0
То что пункт 18 это заноза и обязывает, что-то рожать против воли, это понятно.

Стоит ли покупать экран при всей его сырости !?
Скажем так, имеет ли место целесообразность использования данного продукта в проектах при том, что есть и альтернативные решения, хоть и менее красивые.
+
avatar
  • spc
  • 17 ноября 2016, 13:05
+1
С альтернативами я дела пока не имел. Ну разве что убил однажды растровый (128х64) OLED-дисплей, работа с которым мне тоже не очень понравилась.

Здесь привлекает сам подход: вот экран, вот среда разработки. Особенно, если учесть, что интерфейс все же лучше делать в какой-то визуальной среде и еще лучше — с возможность обкатки прямо в ней, без железа. У Nextion это есть.

Если это есть у других, более доступных и грамотных решений, то, конечно, стоит выбирать их.
+
avatar
+1
Пленка-самоклейка Вам в помощь ;) Ну или шпон.
+
avatar
0
круто, но все таки проще сделать что-то на андроиде с датчиками на USB.
Интерфейс там все таки проще городить еще и к интернету можно нормально подключиться и что-то оттуда тянуть.
+
avatar
  • spc
  • 17 ноября 2016, 12:31
+1
Я, к сожалению, не совсем готов еще одну среду осваивать. Может быть потом, когда с Arduino совсем скучно станет.
+
avatar
  • sir0ta
  • 17 ноября 2016, 13:38
0
Ну зачем такой ужасный огород. те же малинки/апельсинки. там тебе и экраны не дорогие и сенсоры и прочее и прочее. Да к тому же не надо ни какие usb, GPIO и все те же DTH11, DS18B20 и все что есть копеечного. А так же легкая возможность вскажем в случае чего вытяжку ту же включить или свет или отопления прибавить.
+
avatar
+1
все эти экраны отстой с ужасным разрешением и резистивным тачем, а также головная боль с созданием интерфейса. А с сдк андроида все станет проще, и по usb как раз подключить хоть ту же дуино и по протоколу дергать ножками сколько влезет.
+
avatar
  • ded1971
  • 17 ноября 2016, 12:17
+1
Щель между корпусом и дисплеем портит всю малину конечно. Разрабам руки надо оторвать за такую задумку
+
avatar
  • civil
  • 17 ноября 2016, 12:24
0
Да, не взлетит. При цене выше $10 проще использовать старые планшеты и телефоны.
Может подойти для мелкосерийного производства, где цена комплектующих особого значения не имеет, но нужно продемонстрировать, что все сделано самостоятельно, а не набрано из блоков Ардуины.
+
avatar
  • sir0ta
  • 17 ноября 2016, 13:40
0
Этот дисплей и есть блок ардуино. так что… Плюс как юзать смартфоны? Это же какой огород будет смарт, какой-то мк который будет со смарта или своим драйвером через отг тянуть одавать, или ноги занять на сетевой стек и прочее и прочее. А ну ка подключите к смарту на ведре 2 десятка датчиков, и дс18б20 и дхт11 и еще чего. Хотя да, экранчик не из приятных. В смысле не вызывает желания вот так вот взять и попробовать.
+
avatar
  • loole
  • 17 ноября 2016, 14:10
0
Какой OTG? ESP8266 за 1.5$ отлично со всем разбирается.
А из этой приблуды уже третий год вымучивают одни метеостанции.
+
avatar
  • RussII
  • 17 ноября 2016, 12:28
0
Вот что немного раздражает, так это Цена: $27,4 + доставка, подождем, когда появятся его копии значительно дешевле на алиэкспресс.
+
avatar
  • loole
  • 17 ноября 2016, 14:21
+1
Вряд ли — уже два года прошло. Не особо оно кому то надо.
+
avatar
+1
Истории на самом деле не удивительные, а немного другие.
+
avatar
  • spc
  • 17 ноября 2016, 13:05
+2
Ну так у меня и кота на снимке нет
+
avatar
0
Аплодирую стоя!
Обзор шикарен.
+
avatar
  • DrBOBAH
  • 17 ноября 2016, 12:50
0
Труд не вероятен!!! Но вот почему разработчики не предоставляют корпуса для такого не понятно. Не все же имеют 3д принтеры. Копеечная вещь но многих остановит. Кстати Sonoff термодатчик купил сразу как появился в корпусе.
+
avatar
+11
По мне трак отличный дисплей для болванчиков вроде меня. Быстро с ним разобрался, сделал что хотел. Не знаю всех приблуд для ардуино, но из мне известного это лучший вариант для меня, что бы без заморочек.

Одни из программистов, за прогу переключения 13-ти реле запросили 10т.р. В итоге сам разобрался ща пару вечеров, написал прогу, да еще и визуализировал. Мало того, разобравшись — получил возможность дополнять и улучшать систему в целом. Для технических целей идеален.
+
avatar
  • sir0ta
  • 17 ноября 2016, 13:45
0
Экраны 3'' стоят порядка 10 баксов потолок, так рябчиков 500. интерфейс подключения SPI. туда же втыкаем SD карту со сценами в BMP и все тоже самое. да нет какого-то дизайнера, обработчик нажатий своими руками, но все же все это легко реализуемо при среднем знании ЯП как такового любого. Хотя конечно отображение не молниеносное, жрет ресы МК, но я сейчас поступаю проще — 1мк напаивается на экран и на выход 4 провода (питание и RX/TX). А вторая дуня уже занимается обработчиками датчиков, релей и прочего. А первая занята чисто интерфейсом и отображением и работой с кнопками.
+
avatar
+2
А если нет знаний ЯП? Сама задумка то и была в том что бы 5-ти классник взял и сделал что хотел. Мне, человеку далекому от программирования не составило труда работа с ним.

А на счет двух ардуино — у меня та же фигня. Одна обрабатывает данные с датчиков и отправляет на дисплей, другая принимает команды на переключение. Плюсы: не тормозит, не требует подборки сложных алгоритмов с циклами…
+
avatar
  • sir0ta
  • 17 ноября 2016, 13:59
0
А если нет знаний ЯП
ну дуня и создавалась как учебное пособие.
это потом уже взрослые дядьки потом переходят на всякие STM, а перед этим они гордо разводят свои платы. Но лично мне вполне хватает и навесного монтажа и той же дуни. Я бы тоже юзал этот экран, но его цена… а интерфейс, ну лично как по мне что отрисовать где-то BMP и заюзать массив кнопок с атрибутом видимости и поверх отрисовать текст… ну не стоит это дело 20 бачей. В смысле мне проще это сделать, тем более 1 раз создал макет отработок кнопок и макет отрисовки сцены и больше не варишься. Все ни как не соберусь причесать код да увести в либу подключаемую. И на выходе за 30 баксов я имею 3 экрана при чем с ардуино нано или мини в купе по одной на экран )
+
avatar
  • ersivv
  • 18 ноября 2016, 11:19
0
Обратите внимание на esp8266(хотя и он имеет свои недостатки). Мощности хватает и для графики (полная отрисовка экрана 320х240 на библиотеке arduino ~55 мс, на sdk ~35мс) и для работы с датчиками и прочей логики программы. Плюсом получаем wifi со всеми плюшками. Ну и цена получается очень бюджетно $3,5 + $8,5. Конструктора конечно нет, но даже делать в среде ArduinoIDE доступно многим.

+
avatar
  • sir0ta
  • 18 ноября 2016, 11:38
0
Да я знаю. Но она излишня. Скажем та же промини на 168 мк стоит бакс, и ее дури вполне хватает что бы рисовать на этом же экране и заниматься обработчиками кнопок и прочего. Есп стоит под дороже. Плюс она 3.3В.
+
avatar
  • ersivv
  • 18 ноября 2016, 12:59
0
за дополнительных 2,5 бакса мы получаем вагон возможностей и про мини тут даже рядом не стоит по производительности, а экран очень успешно работает и на 3.3В
+
avatar
  • sir0ta
  • 18 ноября 2016, 13:32
0
Да я все понимаю и не отрицаю. Но… у меня есть esp12-e штук 5, есть так же нодки, они удобные в работе, но их я буду юзать в чем-то более требовательном к ресурсам.
+
avatar
0
тоже пишу прогу для переключения 16 реле (матричный коммутатор потоков spdif)
не так там все просто, как кажется

а такие картинки ты можеш нарисовать на андроиде в скаде
flprog.ru/forum/18-992-1
+
avatar
-2
У Автора видимо больше психологическое расстройство — он ждал, планировал, мечтал что все будет идеально, а когда столкнулся с трудностями начал нервничать, спешить, делать ошибки… Отсюда и перебитый шлейф… Нужно готовиться к плохому, я вообще думал что хрен что получится. Ан-нет, оказалось все не так иж сложно.
+
avatar
  • spc
  • 17 ноября 2016, 13:50
+6
Говорят, что вообще абсолютно здоровых людей не бывает — есть недообследованные. Но уверяю, что когда я дисплей примерял к рамкам, то никуда не спешил. Просто проем действительно получился (на удивление) размер-в размер. Чуть меньше — и экран бы не встал на место, чуть больше — был бы зазор.

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

Поэтому я думаю, что привытягивании платы, вероятно, отошел контакт под самим дисплеем. Я бы проверил, но пока не имею понятия, как он разбирается. Наверное, следует начать с отжатия металлической рамки, но сначала попробую поговорить с ITEAD. Вдруг расскажут, что там можно сделать.
+
avatar
0
Отлично, спасибо, тогда я не буду делать такую коробку. Просто из шпона сделаю накладку, которая закроет все сопли и рамку тачскрина… А вообще может быть все расположить на панели и накрыть прозрачным акрилом… Сейчас электроника красивая, грех скрывать такую красоту… Как моддинг на ПК…
+
avatar
  • spc
  • 17 ноября 2016, 14:00
0
Ну я бы не стал. Одним из вариантов была тонюсенькая накладка, тоже печатная, во всю площадь передней панели. Но что-то не пришлась. Мне больше понравился дисплей со всеми потрохами (может и правда, какое психическое расстройство — не знаю).

Однако несмотря на последнее, мне не очень симпатична идея показывать вообще все внутренности. Собственно, я вообще хотел отлить все в граните бетоне, но оказалось, что это тоже не очень простая задача. Один прототип корпуса сделал, ужаснулся и решил не повторять.
+
avatar
0
Да что там сложного? Силиконом брызни и в ведро! )) Потом болгаркой пошлифовать и готово. Кстати, отличная идея на счет бетона! Надо замутить чего ни будь с электроникой в бетоне ;))) Есть один дисплей на 1,44" наверное закажу ненужную ардуинку, аккум, солнечную паннельку и датчик влажности и температуры, все в бетон и на улицу, пусть гости фигевают :) Интересно — интересно ли будет людям?
+
avatar
  • spc
  • 17 ноября 2016, 14:09
0
Судя по ютубу, откуда я набрался этой гадости, бетон сейчас очень в моде. Лампы всякие делают, аксессуары настольные и т.п.
+
avatar
0
Может у Вас брак? Я со своим дисплеем не особо аккуратно обращался и он работает отлично… Теперь видимо буду аккуратнее :)
+
avatar
  • spc
  • 17 ноября 2016, 14:01
0
Да вряд ли. Просто экран на это не рассчитан.
+
avatar
  • prom77
  • 17 ноября 2016, 14:06
0
Офигеть просто мего-обзор, к концу уже забыл что мы не хотели знать про экранчеги )))
+
avatar
  • X7Desu
  • 17 ноября 2016, 18:38
-2
Не осилить Nextion и ныть по этому поводу — ЛОЛ.
Автору стоило купить готовое или хотя бы переделать официальный пример метеостанции.
+
avatar
  • Vipeg
  • 17 ноября 2016, 20:01
+3
Экран не заинтересовал, но хочу выразить благодарность автору за потрясающий стиль изложения: логичный, последовательный, с грамотной лексикой и точечно приправленный легким юмором. Испытал огромное удовольствие от прочтения. Спасибо. Плюсану везде, где можно.
P.S. (to admin): А спойлеры в комментариях нормально не работают? Жаль.
+
avatar
  • sim31r
  • 19 ноября 2016, 01:30
0
Превосходный экран, вернее целый фреймворк (железо тут вторично наверное даже, главное отлаженное ПО). Основа ПЛК.
+
avatar
  • vtoryh
  • 19 ноября 2016, 22:28
+3
Один я из всего обзора заценил только краску под камень? :)
+
avatar
  • BobaQPE
  • 21 ноября 2016, 11:14
0
не, не один :) я тоже заценил!
+
avatar
  • AndrVU
  • 21 ноября 2016, 17:43
+1
Тенденция к изменению параметров строится по шести точкам из архива (по этому методу), что вместе с тем же получасовым интервалом дает период в 3 часа. Т.е. тенденция отражает изменение конкретного параметра за последнюю четверть суток.
Почему за четверть? Это же 6 часов. Ошиблись или я что-то недопонимаю?
Кстати, спасибо за ссылку на вышеупомянутый метод — очень простое и наглядное объяснение способов выравнивания данных.
+
avatar
  • spc
  • 21 ноября 2016, 18:06
+1
Это я ошибся. Действительно, за одну восьмую. Сейчас поправлю в тексте, спасибо!
+
avatar
0
Прошу помощи: можете подсказать — как отправить данные дисплею для построения графиков? Не могу понять принцип…

Все что есть на сайте это:

add objid, ch, val
objid: Waveform component ID
ch: Waveform component channel number
val: value (maximum 255, minimum 0)

А вот что с этим делать и как ему дать показания температуры?

p.s. Показания всегда положительные.
+
avatar
0
Хочу построить график изменеия температуры длительный…
+
avatar
  • spc
  • 28 ноября 2016, 16:45
0
Сначала в Nextion Editor добавляете элемент графика на нужную страницу. Предположим, на страницу 0. После этого щелкаете на элементе графика и в окне свойств (справа внизу) видите, какой у него ID, запоминаете его (это objid). Предположим, что ID получился 1.

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

А дальше отправляете показания командой вида:

add 1,1,8

Здесь первая единичка — ID элемента графика, вторая — номер кривой, а 8 — значение, которое надо отобразить.
+
avatar
0
Допустим создали такой график, присвоили значению температуры с сенсора один: sensor1.

Отправить команду в виде:
myNextion.sendCommand( add 1, 1, sensor1); и все, одна строка?
+
avatar
  • spc
  • 28 ноября 2016, 17:32
0
У меня не было опыта с библиотекой Nextion, но на всякий случай рекомендую строго придерживаться формата команды в части пробелов, т.е. передавать вот так:

myNextion.sendCommand(add 1,1,sensor1);

А так, да — одна строка на одну точку. Соответственно, если передача показаний крутится в цикле (loop) или еще каком, то при каждом проходе через эту строку будет дорисовываться очередная точка со сдвигом всей конструкции вправо. Т.е. при таком раскладе справа будут самые старые показания, слева — самые новые. По-моему, я ничего не путаю.
+
avatar
0
Не работает, но буду искать ответ :))) Спасибо.
+
avatar
0
Как отправить эту команду на дисплей? ))) Блин, чую, все просто, но не могу втыкнуть :)))
+
avatar
0
Ага, отпавка с ардуино имеет вид: myNextion.sendCommand(«add 1,1,100»); только вот если отправить команду
int x = ds.getTempC(sensor1); //присваиваем переменной х значение температуры с сенсора 1.
myNextion.sendCommand(«add 1,1,x»);
то ничего нет, только полоса в 0-м значении… т.е. как то нужно сделать х понятным для nextion…
+
avatar
  • spc
  • 28 ноября 2016, 20:40
0
С библиотекой все немного по-другому. Сразу прошу прощения: похоже, я ошибся, и каналы нумеруются с 0 по 3. Т.е. первый канал на графике — 0, а четвертый — 3. Еще прошу прощения, что я пока не буду проверять на своем экране: поскольку я его почти доломал, очень дорожу каждым днем, пока работает сенсорная панель. А стоит чуть тронуть — и она работать перестает.

Так вот, судя по всему, sendCommand просто отправляет строку на экран. Строка по сути своей константа и должна быть подготовлена до отправки. Поэтому переменные в ней недопустимы, поскольку тот самый x так и остается символом x и не принимает значение переменной x.

А для графика в библиотеке Nextion существует специальная функция NexWaveform.

Опять же, если я правильно понял, то работает она следующим образом.

Сначала в секции переменных объявляем объект графика:

NexWaveform s0 = NexWaveform(0, 1, «s0»);

Зесь s0 — имя для использования в коде, «s0» уникальное имя объекта, которое можно посмотреть в свойствах графика в Nextion Editor в строке objname.

А потом в нужном месте кода можно добавлять точки следующим образом:

s0.addValue(0, x);

Здесь 0 — номер канала на графике, ну а x — значение которое нужно добавить.
+
avatar
0
Возможно, но у меня нет библиотеки NexWaveform.h
Хз где найти ее, гугл не помог…
+
avatar
  • spc
  • 28 ноября 2016, 22:24
0
А это же все одной кучей вот здесь: github.com/itead/ITEADLIB_Arduino_Nextion
+
avatar
0
Да я уже час там кручусь — не могу понять как скачать ее оттуда :))) В первый раз же :)))
+
avatar
0
Пошло… откуда то выпало всетаки это меню…
+
avatar
  • spc
  • 28 ноября 2016, 22:56
0
А, да, там с первого раза нетривиально. Я тоже долго искал сначала ) По факту нужно только нажать на зеленую кнопку Clone or download, а потом Download ZIP

+
avatar
0
попробовал — почему то начало конфликтовать с библиотекой OneWire…
+
avatar
  • spc
  • 28 ноября 2016, 23:31
0
А в чем конфликт заключается? И, если не лечится, тогда только конструировать строку на лету и отправлять ее методом sendCommand.

Например:

stringToNextion = String(«add 1,1,»);
stringToNextion = stringToNextion + String(x);
myNextion.sendCommand(stringToNextion);
+
avatar
0
Спасибо за ссылку на динамические ряды!
Тоже балуюсь со всяким ардуинством и умение показывать тенденцию очень нужно…
+
avatar
  • spc
  • 01 декабря 2016, 23:29
0
Если честно, то я рад, что мое оказавшееся несколько неуемным желание разобраться со всеми (в том числе и возникающими по пути — а тренды появились по пути) хотелками оказалось так кстати!

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.