Arduino / Arduino LCD Informer

в 19:22, , рубрики: lcd, perl, хобби, метки: , ,

Arduino / Arduino LCD Informer
Заинтересовавшись таким хобби, как Ардуино, я вскоре понял, что суть этого замечательного проекта — позволить таким, как я, ничего не смыслящим в схемотехнике, пайке и микросхемах, зато немного понимающим в программировании, заставить работать что-либо кроме персонального компьютера; прошить микроконтроллер, не имея программатора и каких-либо специальных знаний на эту тему.
Поэтому я хочу помочь пропаганде этого проекта — программисты, это прекрасное развлечение именно для вас!
Пока моторчики для моего следующего, мобильного проекта едут в кибитке, запряжённой тройкою самых быстрых брюхоногих скакунов Почты России, я задумал и, надо сказать, осуществил, другой (разминочный) проект под звонким названием “Arduino LCD Informer”. Суть проекта в том, чтобы Ардуино отображал на LCD данные, получаемые с компьютера. На компьютере их собирает и отправляет отдельная программа.
Ингредиенты

Для проекта нам потребуются:
Ардуино

Этот смышлёный и ловкий малыш, обладает не только мозгами (ATmega328 ), но и органами чувств и манипуляторами — входы и выходы делают возможным как получать информацию с различных датчиков, так и отправлять команды разным устройствам, в том числе моторам, светодиодам, и конечно lcd-экранам. Кроме того, usb-соединение с компьютером используется не только для заливки на него готовых программ, но и для двустороннего общения с программами, на компьютере запущенными.
Текстовый LCD экран

Нам нужна наиболее распространённая модель, MT–20S4A (МЭЛТ), HD44780 (Hitachi), KS0066 (Samsung) или их аналоги.
Я рекомендую МЭЛТ — у меня именно такой. Сердце согревает гордая надпись — “МЭЛТ. Сделано в России”. Поддержим отечественного производителя! Тем более, что сделан экран не только аккуратно и опрятно, но и с поддержкой кириллицы, о чём позже.
Доска для резки хлеба

Breadboard, как её окрестили наши заокеанские супостаты, а по-нашему — доска для прототипирования. Вкратце поясню суть. По доске идут параллельные линии проводящего материала. Если вы воткнёте проводок в дырку, то все дырки сверху и снизу от него (если расположить доску так, чтобы центральная полоса шла справа налево — как на фото) окажутся с ним соединены. Точнее, все до центральной полосы — по обеим сторонам от неё находятся две не связанные меж собой части доски.
Таким образом, без пайки, без скрутки, шума и пыли можно спокойно перетыкать проводки, планируя и сразу проверяя схему работы устройства. Один проводок в дырку, второй — в соседнюю, и контакт готов.
На средних и больших досках предусмотрены с краю две полосы проводников, одна для земли, вторая для питания — поскольку эти два контакта требуются чаще всего.
Лапшичка проводная

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

Работать на пустой желудок — не только вредно, но и бесполезно. А по ходу работы приятно вознаградить себя сырничком-другим. Для сырников нам нужен творог (не изоморфный-гладкий, а с нормальной зернистостью) — 400 грамм творога, 2 яйца, 50 г сахара, пол-ложки (чайной) соды, щепотку соли. Перемешать, и потом помешивая, постепенно добавлять муку, всего около 200 грамм. Потом накрыть тесто и оставить часа на 2. Потом нагреть сковородку с небольшим количеством масла, скатывать колобки, плющить их и жарить.
Ну и по вкусу добавить потом сверху — кому вареньице малиновое, кому сгущёночку, кому как…
Приготовление

Сборка.

Чтобы LCD приветливо засветил нам своим мягким, тёплым, почти ламповым оранжевым светом, необходимо обеспечить его питанием (и землёй), а для вывода информации — подключить к выходам Ардуино.
Если на вашей доске есть полоски для земли и питания, можно вывести их с Ардуино именно туда. Но не отчаивайтесь — если их нет, обойдёмся и так.
См. фото — контакты 1, 3 и 5 требуют подключения к земле. Протягиваем провод от контакта Ардуино с пометкой GND (синий) к ряду дырочек на доске, соответствующих первому контакту, а к 3-му и 5-му ряду (которые идут к 3-му и 5-му контактам) проводим от первого ряда перемычки (красная и жёлтая).ВНИМАНИЕ!
1) Все работы по перетыканию проводов проводим, когда питание отключено от Ардуино — как usb, так и через разъём питания!
Кстати, поэтому рекомендую подключать Ардуино к usb через два кабеля — один обычный usb, второй — удлиннитель. Таким образом, вместо разбалтывания usb-порта на компьютере или на Ардуино нужно будет разнимать только место соединения удлиннителя с кабелем.
2) У разных LCD номера контактов могут отличаться. Ознакомьтесь с инструкцией своего экрана. Кроме того, нумерация контактов может идти как слева направо — 1, 2, 3,.., 16 — так и, например, 14, 13, 12,.., 2, 1, 15, 16. Контакты должны быть пронумерованы на самом экране.
Если вы начинающий ардуинист и не умеете паять, позаботьтесь о том, чтобы заказать экран с уже припаянными ногами-контактами. Все контакты имеют стандартный шаг, поэтому наш экран-шестнадцатиножка легко воткнётся в доску. Втыкаем ноги — ряд ног параллельно центральной полоске и ближе к ней так, чтобы оставшаяся часть доски с этой стороны полоски осталась в доступности для втыкания проводов.
Итак, протянув провод от контакта Ардуино с пометкой 5V до доски, подаём 5 вольт на 2-й (питание) и 15-й (подсветка) контакты. Земля — 1, 3, 5, 16.
При этом 3-й контакт — контрастность, чем больше напряжение, тем тусклее изображение. Земля = 0 = наибольшая контрастность.
После этого можно включить Ардуино (подключить к usb) и посмотреть, засветился ли LCD. Если да — поздравляю! Можно вознаградить себя сырничком. И снова отключить Ардуино от питания!
Далее подсоединяем контакты управления экраном. 4-й — к 4-му выходу Ардуино. (Все выходы, с которыми мы имеем дело в данном проекте, помечены на Ардуино как digital). Это адресный сигнал.
6-й контакт экрана — 5-й контакт Ардуино. Это разрешение доступа.
Далее каналы данных:
lcd — Arduino
11 — 10
12 — 11
13 — 12
14 — 13
Результат моего творчества виден на первом фото. Провода аккуратно собраны в узел, а для устойчивости экран снабжён элегантной подпоркой, взятой из детского металлического конструктора, согнутой в необходимую кривую. Соединена она с экраном болтом диаметром 3 мм в специально предусмотренное крепёжное отверстие.
Можно кодить!
Программное обеспечение

Arduino sketch

Для написания программ для Ардуино и отправки их в него требуется оболочка, которую можно скачать отсюда: arduino.cc/en/Main/Software
Вкратце об использовании. Подключаем Ардуино, выбираем его тип (в моём случае это Arduino Uno) в Tools/Board, затем номер порта в Tools/Serial port — обычно, это порт, отличный от COM1. У меня получился COM9.
Затем пишем программы. Кнопка с галочкой проверяет программу, стрелка вправо — компилирует и закачивает на Ардуино.
Программы, которые исполняет Ардуино, называются скетчами, и состоят из трёх частей. Вначале подключаются необходимые библиотеки. Потом наполняется содержимым функция setup, которая автоматически выполняется один раз. В ней происходит вся инициализация оборудования.
Затем — основная функция, loop, которая автоматически выполняется в бесконечном цикле.
Напишем первую программу-скетч:
// подключаем библиотеку для работы с LCD#include 
 void setup(){
  // инициализируем LCD, указывая контакты данных
  LiquidCrystal lcd(4, 5, 10, 11, 12, 13);
 
  // указываем размерность экрана и начинаем работать
  lcd.begin(20, 4);
 
  // пишем первую строку
  lcd.print("Hello, world!");
 
  // сдвигаем курсор на вторую строку, первый столбец (нумерация с 0)
  lcd.setCursor(0, 1);
 
  // Пишем вторую строку
  lcd.print("I love Habr!");}
 void loop(){
  // Делать особо нечего}
 

Перейдём теперь к нашей задаче.
Нам нужен скетч, который будет выводить данные на LCD, а также нужна программа, которая будет работать на компьютере, собирать эти данные и отправлять их Ардуино.
Выбор языка, на котором можно писать программу для компьютера, остаётся за вами — любой язык, позволяющий работать с COM-портами, подойдёт. Конечно, лучше всего было написать такую программу на C++ — памяти занимает мало, висит себе в фоне и висит. К сожалению, я не обладаю достаточными знаниями для написания такой программы на C++, поэтому, буду писать на том, что знаю — perl.
Рабочий скетч для проекта может выглядеть следующим образом:
#include 
 // RS, E, DB5, DB6, DB7, DB8
LiquidCrystal lcd(4, 5, 10, 11, 12, 13);
 int inb = 0;int pos = 0;int line = 0;
 void setup() {
  Serial.begin(9600);
  lcd.begin(20, 4);}
 void loop() {
  lcd.setCursor(pos, line);
  if (Serial.available() > 0) {
    inb = Serial.read();
 
    if (char(inb) == '|') {
      pos = 0;
      line++;
    }
    else if (char(inb) == '&') {
      pos = 0;
      line = 0;
    }
    else {
      lcd.print(char(inb));
      pos++;
    }  
    lcd.setCursor(pos, line);
  }}
 

Ардуино ждёт начала поступления данных, и сразу выводит их на экран.
Символ | будет работать переводом строки, а & — концом текущего набора данных.
Программа для сбора данных и отправки их в порт.

В программе мы подключаем библиотеки, необходимые для сбора данных, затем проводим инициализацию всего, и потом в цикле формируем строчку, содержащую собранные данные и отправляем её в порт.
#!/usr/bin/perl
 # Подключим нужные модулиuse LWP::Simple;use Encode qw(from_to _utf8_off);use Win32::SerialPort;use Win32::API::Prototype;use Win32::SystemInfo;use Win32::DriveInfo;use constant {IDLE => 0, KERNEL => 1, USER => 2};
 # Подключим функцию из Win32 API
InitWin32();
 # Стартовое значение тиков@lasttime = SystemTimes();
 # Установим порт для коммуникаций с Arduino$port = InitSerial();
 # Цикл Мёбиусаwhile (1) {
 
  # Формируем строку
  $data = sprintf("CPU: %3d%%  C: %03d Gb|MEM: %3d%%  D: %03d Gb|".
    "T: %02d'C      P: %03d|%02d %-8s    %02d:%02d|&",
    CPU(), Disk('C'), MEM(), Disk('D'), Weather('Moscow'), DateTime()
  );
 
  # Выводим в порт
  while ($data =~ s/(.)//s) {
    $port -> write($1);
    $port -> lookclear;
  }
 
  # Ожидание
  sleep(10);}
 

Дабы не загромождать статью кодом, привожу описание использованных функций, а полностью программу можно скачать по ссылке в конце статьи.
InitSerial — производит необходимые настройки для работы с портом из perl (модуль Win32::SerialPort)
closePort — правильно прекращает работу с портом, чтобы её можно было возобновить без проблем при следующем запуске. Вешается на сигнал прерывания программы.
CPU — подсчитывает загрузку CPU. Использует уличную магию (функция SystemTimes), которую я где-то подсмотрел. Для подсчёта загрузки использует функцию из библиотеки kernel32 GetSystemTimes, которая присоединяется к программе в функции InitWin32 (модуль Win32::API::Prototype).
MEM — возвращает отношение доступной физической памяти к общему её количеству (модуль Win32::SystemInfo)
Weather — читает температуру и давление со страницы Яндекс.Погода. Делает это не чаще, чем раз в два часа.
DateTime — возвращает текущие день месяца, месяц, часы и минуты
Disk — возвращает объём свободного места на диске (модуль Win32::DriveInfo).
Русский язык

Мой экран, как уже упоминалось, произведён в России. В связи с этим они имеет две кодовые страницы — на первой (№ 0) отдельно содержатся кириллические буквы, аналогов которых в латинице нет. На второй (№ 1) имеется полный русский алфавит, по кодам символов совпадающий с cp-1251. Поэтому, при желании, мы можем выводить русские буквы на экран без особых затрат.
Маленький минус, с которым я столкнулся — значка градуса на странице №1 нет (в отличие от страницы №0). Заменил апострофом.
Для управления экраном используется библиотека LiquidCrystal, рассчитанная на распространённую модель экрана. Но конечно, никто не делал в ней возможности переключения кодовых страниц, так как буржуины горя поддержки двух языков не знают. Проведём простые модификации библиотеки.
Находится она в %arduino_install_path%arduino-1.0librariesLiquidCrystal
Согласно документации на экран в разделе “Команды модуля” установка кодовой страницы проводится в команде Function set вторым битом.
Добавим в LiquidCrystal.h новую константу:#define LCD_CODEPAGE 0x02
Затем в LiquidCrystal.cpp найдём функцию void LiquidCrystal::init() и в ней добавим эту константу к остальным установкам, вот так:if (fourbitmode)
_displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS | LCD_CODEPAGE;
else
_displayfunction = LCD_8BITMODE | LCD_1LINE | LCD_5x8DOTS | LCD_CODEPAGE;
Таким образом, 2-й бит будет поднят, экран воспользуется кодовой страницей №1, и мы можем передавать ему данные на русском языке в кодировке cp-1251 (в моём случае — это название месяца).
Файлы
Скетч для АрдуиноПрограмма на perl по сбору данныхПодправленная библиотека LiquidCrystal для работы с кодовой страницей №1Документация на экран МЭЛТ
Применение

Применение LCD с Ардуино в качестве информера практически не ограничено.
Возможно, это не так удобно, как второй монитор, но пригодиться может. Время, погода, системная информация, дебаг… Кстати, ещё один пример, недавно пришедший мне в голову — отслеживание торрентов в uTorrent через его WebAPI…
Но главное, конечно — это удовольствие от хобби, которого вам и желаю!


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js