Arduino и Интернет Вещей (Internet Of Things)

Введение

Идея написать эту статью родилась у меня с появлением Arduino ADK. Саму Arduino ADK я не стал приобретать, поскольку с одной стороны заказать её можно было только в Arduino Store с их кусачими ценами за доставку в Россию, а с другой стороны в то время я был всецело занят портированием библиотеки Simple Dumping Monitor под использование кода библиотеки классов VE_AVR.

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

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

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

Поэтому вместо Arduino ADK я приобрёл себе Ethernet Shield и довольно симпатичную платку Etherten от компании Freetronics. Приобрёл, и первым же делом столкнулся с проблемой руссификации программного обеспечения для этих замечательных устройств.

"Что бы такое подключить к Интернету?" - спросил я самого себя.

"Но так, чтобы это было полезно в хозяйстве," - поставил я самому себе такое требование.

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

Представим себе, что у Вас есть 3D-принтер, и он там стоит себе в углу и периодически что-нибудь мастерит. Например, вы ставите +1 на фотку в Google+, а он Вам её тут же в виде пирожного из теста лепит. Сама по себе идея красивая, но на практике Вам ведь придётся самого себя контроллировать, чтобы случайно что-нибудь не лайкнуть.

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

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

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

Поэтому я решил не писать никаких статей на эту тему, до тех пор, пока не придёт время сделать какой-нибудь реальный проект. И вот, таким проектом стал вопрос, как подключить к Arduino 3 цифровых термометра и внешний источник импульсов (в данном случае сигнал от часов реального времени). То есть как наблюдать и давать отчёт по запросу.

"С чего же начать столь большой и сложный проект?" - спросил я самого себя.

Проект начинается с Blink

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

В данном проекте к микроконтроллеру будут подключены часы реального времени DS1307, которые подают с вывода SQW/OUT тактовый сигнал с заданной частотой (1Гц), поэтому сам микроконтроллер может всё это время пребывать с спящем режиме, до тех пор, пока DS1307 не подаст очередной импульс. Тогда Arduino проснётся, мигнёт светодиодом, увеличит значение счётчика имульсов, и опять погрузится в сон.

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

В качестве панели управления можно использовать как веб-интерфейс, так и терминал в компьютере, подключаясь к Arduino по последовательному порту. Следовательно потребуется использовать оба варианта, чтобы получив от сервера отчёт "нет данных" можно было подключится к Arduino через USB и проверить, есть ли связь с сервером. В таком режиме данные должны будут отправлять часто, а в штатном режиме вряд ли понадобится отправлять данные на сервер чаще, чем несколько раз в час или даже в сутки.

Итак, скачав даташиты и составив схему подключения, я получил следующую принципиальную схему:

Схема подключения к Arduino трёх DS18B20, одного DS1307 и Ethernet Shield
Arduino MEGA R2, Ethernet Shield R3, Freetronics Etherten R3 и прототип шилда

Прежде чем паять шилд, я задался вопросом, должен ли этот шилд быть совместим с Arduino MEGA. Ведь DS1307 подключен по интерфейсу TWI (I2C), и если его подключить к выводам Arduino A4 (SDA) и A5 (SCL), то он окажется несовместим с мегой. Между тем мне ведь не известно заранее, хватит ли мне возможностей Etherten или придётся использовать вариант с Arduino MEGA + Ethernet Shield.

Однако, уже делая эту фотографию (справа вверху), я вдруг выяснил, что MEGA у меня версии R2, поэтому шилд получился совместим только с версией R3, у которой контакты SDA и SCL выведены на старшую линейку Digital.

Подключаем часы реального времени DS1307

Подключив часы реального времени по вышеприведённой схеме, я скачал библиотеку и скетч, найденный среди проектов на сайте Instructables - Arduino Real-Time Clock (DS1307).

Чтобы Arduino мигал светодиодом D7, получая импульсы SQW/OUT, я добавил в скетч обработчик прерывания INT0 и заменил функцию delay(1000) в функции loop() циклом обработки мигания светодиода.

Исходный код тестового скетч можно скачать по ссылке.

Примечание. Чтобы скомпилировать скетч, используйте библиотеку VEduino версии 0.16 или новее.

Итак, часы идут, светодиод мигает, пора переходить к следующему шагу.

Подключаем термометр DS18B20

Приступая к этому проекту, я задавался следующим вопросом. Микроконтроллер Arduino не имеет встроенной поддержки интерфейса 1-Wire, и следовательно скорее всего он реализован без прерываний, на временных задержках. Но задержки эти вполне сравнимы с циклом в 1 Гц. Не будет ли прерывание от SQW/OUT теряться, из-за того, что прерывания могут периодически запрещаться в коде протокола 1-Wire, или наоборот - не будут ли прерывания от SQW/OUT мешать Arduino обмениваться данными с термометром.

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

Исходный код тестового скетча можно скачать по ссылке.

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

Разработка программного обеспечения

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

При этом выяснилось, что после нескольких (примерно 10-ти) отправок данных на сервер, Ethernet Shield перестаёт это делать. Попытки рестартовать микроконтроллер программно (переходом по вектору прерывания 0 - RESET_vect) не помогли, и я добавил в схему цепь аппаратного сброса. Так что раз в час микроконтроллер сам себя перезапускает, чтобы при этом сбросить Ethernet Shield.

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

Продолжение следует.