Раз уж сегодня посыпались публикации про Raspberry Pi, вставлю свои пять копеек. Выложил на днях на Youtube лекцию с демонстрацией, как из Raspberry Pi и USB-сканера сделать девайс для сканирования с сетевым диском, используя SANE, Samba и WiringPi, владея немного электрикой и bash-ем. Всё продемонстрированное эксплуатируется в реале, хоть и в несколько адаптированном виде. Интересующихся приглашаю посмотреть… ну и покритиковать тут в комментах и карме. :)

Лекция получилась почти на 2 часа, так что, наверное, лучше смотреть прямо на Youtube; в описании к ролику есть оглавление. Под видео пойдёт текстовая расшифровка в сокращённом виде (special for Habr).

Приятного просмотра или прочтения. :)



Описание задачи и концепция решения


Начнём с исходных данных. У нас есть обыкновенный сканер (в моём случае Canon CanoScan LiDE 120), который подключается к USB-порту компьютера и может сканировать в компьютер. Но вот, например, появляется второй компьютер, и при общей нужде в сканировании переключать сканер каждый раз между компьютерами неудобно. Что делать? Да, сейчас есть сетевые МФУ, но по каким-то причинам это для нас не вариант.

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

Итак, мы выбираем место для размещения сканера, подводим к нему кабель от роутера нашей локальной сети (можно и WiFi, но это оставим на факультатив), ставим розетку для электропитания 220В – а что дальше?

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

В нашем проекте мы задействуем одноплатный компьютер Raspberry Pi 2 Model B. Он хоть и не новый и не особо мощный, но его мощи нам для задачи вполне достаточно, энергии он не особо жрёт, ну и GPIO пригодится.

Тем, кто сразу захочет всё повторить на базе имеющегося сканера, рекомендую предварительно зайти на сайт проекта SANE, перейти в список поддерживаемых устройств и убедиться, что конкретная модель сканера в должной степени поддерживается проектом. Иначе усилия и, возможно, деньги могут улететь в трубу. Мало того – возможно, стоит у себя организовать машинку (виртуалку или реальную) с Debian 10 (точнее, актуальной на момент проверки версии, из которой Raspberry Pi Foundation сделал операционку) и sane из коробки и проверить работу, используя утилиту scanimage; если всё норм, тогда наверняка заработает и на малинке.

Вспомогательное необходимое


Что касается питания малинки и сканера – в демо-проекте я использую обычную двухамперную MicroUSB-зарядку. Но, если предполагается круглосуточная работа малинки, то не советую их использовать. Это не их задача, и не факт, что конкретная зарядка не выйдет из строя, если будет долго отдавать не такой уж и маленький ток в режиме 24/7. Лучше не экономить и взять или фирменный блок питания, или приспособить другой подходящий для такой работы.
Также не рекомендую подключать сканер USB-кабелем большой длины или невесть какого происхождения. Это уже из более чем полугодового опыта эксплуатации; сюрприз может случиться в самый неподходящий момент.

По «дисковой» памяти – в малинках, как известно, используются карты MicroSD. Десятая Raspberry Pi OS помещается на карту в 4 гига. Но у нас там ещё будет прилично устанавливаемого ПО, плюс сетевая папка для сканов. Так что ориентируемся минимум на 8; в проекте использованы 16. Также для первоначальной записи образа ОС потребуется компьютер с картридером, в который можно будет карту подключить. Я использовал переходник под SD-картридер, встроенный в ноут.

Ещё нам потребуется корпус. Тут вариантов масса. В показанном варианте я использовал неоригинальный корпус повышенной толщины; это позволило смонтировать на верхней крышке предусмотренную проектом схему из двух кнопок и светодиода (об этом будет дальше), и высоты корпуса хватило и на кнопки, и на малинку, и на BLS-разъёмы для подключения к штырькам GPIO. Выполнен этот корпус из оргстекла. Вот как выглядит он с собранной схемой, но без малинки:



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

Ещё одна проблема малинок — нагрев проца. Если планируется круглосуточная работа, приклеиваем чем-нибудь подходящим теплопроводящим маленький радиатор.

Подготовка карты памяти


Начнём подготовку карты памяти. Недавно Raspberry Pi Foundation не только переименовал Raspbian в Raspberry Pi OS, но и выложил программу под названием Raspberry Pi Imager для Windows, macOS и Ubuntu. Скачиваем эту программу, ставим на компьютер и запускаем.

Первым делом в окне программы сделаем Choose OS. Вариантов там много. По умолчанию предлагается Raspberry Pi OS (32-bit), но он с десктопом, а для двойки десктоп так себе. Поэтому идём в Raspberry Pi OS (other) и там выбираем вариант lite; нам вряд ли потребуется что-то кроме командной строки. Дальше ставим и выбираем карту памяти и пишем на неё образ. Этот процесс показан в видео на 00:12:15.

Первоначальная настройка


Карту памяти можно поставить в малинку и перейти к её настройке. Для этого, помимо питания, сети с Интернетом и сканера нам потребуется подключить USB-клавиатуру и монитор с HDMI-кабелем (для четвёртого поколения малинок идёт MicroHDMI). Питание подключаем в последнюю очередь. И помним о безопасности при работе с открытыми проводящими частями, особенно если малинка не в корпусе, а блок питания сомнительный в плане электрического контакта с 220В.

Включаем, грузимся, логинимся с дефолтным логином pi и паролем raspberry. Процесс настройки в видео идёт с 00:18:43.

Первым делом обязательно отрабатываем sudo apt update и sudo apt upgrade. На момент записи ролика репозиторий предложил обновить 30 пакетов, хотя образ карты памяти я записал непосредственно перед первоначальной настройкой. Видимо, он собирается не при каждом обновлении репозитория.

Дальше по желанию решаем проблему квадратиков в консоли вместо русских букв. Вызываем sudo dpkg-reconfigure console-setup и идём по менюшкам. Ставим (или оставляем) следующие параметры:

  • Encoding to use on the console — UTF-8
  • Character set to support — Guess optimal character set
  • Font size — 8x16


Первый раз перезагружаемся. Делаем это штатным образом, через sudo reboot. Снова логинимся, запускаем sudo raspi-config и приступаем к первоначальному заданию параметров. Делаем в ней следующие задачи:

  1. смена дефолтного пароля (в меню: System options — Password и далее по инструкциям)
  2. включение удалённого доступа по SSH (Interface options — SSH)
  3. русская локаль (Localisation options — Locale; я снял en_GB.UTF-8 UTF-8, поставил en_US.UTF-8 UTF-8 и ru_RU.UTF-8 UTF-8, затем выбрал дефолтную русскую)
  4. часовой пояс (Localisation options — Timezone; там выбрать континент, затем город)
  5. расширение файловой системы (Advanced options — Expand filesystem).


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

Дальше снова логинимся (уже под новым паролем), идём в sudo raspi-config, выбираем Localisation options и далее Keyboard. Программа настройки клавиатуры будет уже писать по-русски.

В модели клавиатуры стандартно выбираем «Обычный ПК с 105-клавишной (межд.)

В раскладке выбираем сначала „Другая“, затем „Русская“ и далее вариант (просто „Русская“ или какой-то более подходящий к имеющейся клавиатуре).

Далее выбираем способ переключения раскладок и прочие разные клавиши, если хочется. Всё достаточно быстро переключится. Осталось в главном меню raspi-config дойти до Finish. Больше мы к этой утилите возвращаться не будем.

Установка и настройка дополнительного ПО, используемого проектом



Делаем sudo apt install wiringpi samba sane. Я в этот список (и в лекцию) добавил ещё mc и показываю работу с ним, но это вопрос сугубо личных предпочтений, никому не навязываю.

Дальше (желательно в большинстве случаев) задаём малинке постоянный IP-адрес. Считаю, что лучше это сделать на роутере, но, если такой возможности нет, можно задать статические настройки сети, отредактировав /etc/dhcpcd.conf после коммента Example static IP configuration. Пакет dhcpcd включен в Raspberry Pi OS из коробки, доустанавливать его не нужно.

Следующая задача — создать каталог для размещения файлов сканов. Я выбрал под это дело и создал каталог /var/scanned. Этому каталогу нужно задать такие права, чтобы с ним могла работать самба.

Теперь, разумеется, идёт настройка samba. Идём в /etc/samba/smb.conf и прописываем там глобальные настройки и секцию с данными нового сетевого ресурса и путём к созданному нами каталогу. В видео это есть на 00:41:51. Но, конечно, специфика сети может давать определённые отличия от приведённых там настроек.

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

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

Начнём с железной части. Для этого выполняем gpio readall. Малинка выведет нам нумерацию выводов на разъёме GPIO в графах Physical и их назначение в графах Name. Нам для схемы потребуются три порта GPIO и один общий провод (в графе Name обозван как 0v; на разъёме их немало, но нам столько не надо, просто выберем любой один из них). Записываем себе их наименования и номера на разъёме. Я для себя выбрал GPIO.1 на выводе номер 12, GPIO.2 на выводе 13 и GPIO.3 на выводе 15. Общий провод подцеплю на вывод номер 9.

image

Теперь определимся со сканером, который у нас уже подключен в USB. Делаем sudo sane-find-scanner. Если сканер этой утилитой не виден, возможна проблема со сканером, малинкой, кабелем или блоком питания; это нужно решать отдельно. Теперь делаем sudo scanimage –help | less и смотрим опции, разрешённые для нашего устройства. Для себя я запишу опции l, t, x, y, resolution и format. Эти опции пойдут в командную строку программы сканирования.

Первоначальная настройка малинки на этом завершена. Перед тем, как собрать схему, малинку нужно выключить. Это, если кто не помнит, делается командой sudo shutdown –h now. Через некоторое время изображение на экране пропадёт, и на малинке погаснут все светодиоды, кроме светодиода питания. Это будет означать, что система завершила работу, можно отключать питание и начинать рукоделие.

Схемные решения



GPIO в малинках только цифровой (то есть, двухуровневый 0 и 1) и умеет работать в трёх режимах: просто вход (режим называется in), вход с подтягивающим питание резистором сопротивлением 50-65 килоом (название up) и выход (название out). Мы будем использовать два последних режима.

Как я писал ранее, нам нужно будет подключить по GPIO две кнопки (назовём их „Старт“ и „Стоп“) и светодиод. Естественно, для ограничения тока нужно будет последовательно с ним подключить ограничительный резистор; я выбрал выводной резистор номиналом 2,2 килоома и мощностью рассеивания 0,25 Вт; этого обычно хватает. Схема подключения получается такая:



Исходя из использования режима up запомним, что при нажатой кнопке с входа GPIO будет считываться значение 0, а при отпущенной — 1. Кнопки у нас обе нормально разомкнутые, без фиксации.

На деталях исполнения здесь я особо останавливаться не буду, тем более ранее я показывал фото допиленного корпуса, где всё уже было. В целях безопасности порекомендую только выбирать кнопки, у которых наружные части все пластиковые, чтобы не торчать наружу открытыми проводящими частями. Подключался к пинам GPIO я одноконтактными BLS-разъёмами, похожими на используемые в компьютерных корпусах; для этого демо просто взял пучок проводов от Arduino-проектов с подходящими разъёмами, отобрал четыре разноцветных, ненужные концы откусил, зачистил и припаял к деталям. Ещё вариант — использование 40-контактного двухрядного разъёма с плоским шлейфом или даже куска старого IDE-шлейфа от жёстких дисков или CD-приводов, если у кого осталость. Этот вариант, к слову, подходит и для корпусов стандартной высоты; в них под такой шлейф предусмотрена щель для вывода наружу.

Ну и ещё, помнится, помучился с тем, что на платах малинок (во всяком случае, 2 model B и 3 model B) не указана нумерация пинов разъёма GPIO. Это сейчас исправлю; у этих двух моделей в этом плане отличий нет.



Реализация программной части



Программная часть реализована (тадам!) в виде двух bash-скриптов — конфига и собственно рабочего скрипта. Подробное объяснение алгоритма работы на блок-схеме и реализация есть в видео на 01:08:30. Здесь не думаю, что есть смысл подробно расписывать детали; исходники скриптов можно скачать здесь и на досуге изучить.

Запуск основного рабочего скрипта прописывается в автозагрузку в /etc/rc.local. Единственное — пришлось сперва прописать смену рабочего каталога на каталог со скриптами. Но страшного тут ничего нет, работать дальше это не мешает. И, конечно, не забываем после команды запуска дописать значок &, иначе будут проблемы с загрузкой системы.

Ну и дальше осталось собственно только вживую показать процесс собственно сканирования, а также подключения по ssh и донастройки параметров — то, как это было у меня. В видео это можно посмотреть на 01:41:04.

Как-то так получилось. В боевом варианте из отличий у меня только сканирование идёт на отдельное NAS, соответственно скрипты несколько изменены. А так, думаю, сканы можно даже куда-нибудь в мессенджер ботом отправлять, было бы только желание разобраться с соответствующим API и сделать что-то такое на curl. Вариантов полно. Удачи в реализации. :)