WeatherStation. Часть 1: Основной модуль


Часть 0: Описание и концепция
Часть 2: Ethernet модуль

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

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

Сразу хочу оговорить некоторые термины, которые я буду использовать — просто я привык к ним и все равно где-нибудь ляпну.
Динамика — динамическая индикация (в данном случае — времени)
Либа, библиотека — подключаемый файл .h с функциями
Событие — функция, которая отвечает за смену состояния чего-либо. Например, событие динамики отвечает за переключение кадров-цифр

Основные элементы
Сердцем является микроконтроллер ATmega32 в TQFP корпусе, тактируемый от внешнего кварца на 8 МГц. К SPI-порту (SCK, MISO, MOSI и несколько отдельных пинов) подключена цепочка из 18 сдвиговых регистров HC595 — они обеспечивают вывод информации на 14 семисегментных индикатора (вывод даты, температуры, влажности и прогноза температур), 28 светодиодов (день недели, состояние погоды по прогнозу), трансивер nRF24L01+ и разъем ISP-6 для программирования. К порту I2C подключена DS1307 (синоним по тексту — RTC) и внешний EEPROM (модель не помню — идет вместе с DS1307 на одной плате Mini I2C Modules). 12 пинов (8 анодов и 4 катода) идут на семисегментный четырехразрядный индикатор (общий катод) отображающий текущее время и работающий в режиме динамической индикации. Оставшиеся свободные пины Атмеги выведены на PLS-гребенку — мало ли, пригодятся.

Вывод информации
Для вывода информации через сдвиговые регистры я создал массив и несколько функций, с помощью которых можно легко изменить определенные значения (что-то наподобие УстановитьДеньНедели(Суббота) и т.д. ). Для выдачи через SPI использовал немного модифицированную библиотеку (найти можно в моем репозитории на BitBucket, называется libSPI.h)

А вот с динамикой пришлось думать — ведь нужно отображать время без скачков яркости, тормозов и прочего мусора, и при этом не забывать опрашивать трансивер, RTC-модуль и прочую периферию. Решил выкрутиться прерыванием, срабатывающим каждые 2,5 миллисекунды (т.е. частота смены кадров-цифр — 400 Гц, за секунду полная картинка из 4 цифр пробегает 100 раз — вполне достаточно, чтобы самый придирчивый глаз не заметил моргания). В начале прерывания поставил событие работы с динамикой (да простят мне мои термины — AutoIt как первый ЯП сильно повлиял), а в конец вставил всю остальную работу. Как выяснилось на практике, такая схема оказалась несколько ошибочной — в прерывании таймер не считает, и получалась задержка, из-за которой определенная цифра горела дольше остальных. Пришлось перенести все события в основной цикл функции main (все равно пустой был), в начале запускать таймер, выполнять все действия и ждать его переполнения (флага в регистре TIFR).

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

Я решил эту проблему следующим образом. Из-за достаточно большого потребления четырехразрядного индикатора катоды подключены не напрямую к МК, а через управляющие транзисторы. Чтобы упростить программу, для управления яркостью динамики добавил еще по одному транзистору на канал катода. Появилась возможность управлять яркостью динамики обычным общим ШИМ-ом. На коллектор первого транзистора подаем сигнал включения определенной цифры индикатора, на базу — ШИМ, в результате с эмиттера на базу следующего транзистора каждого канала катодов идут пачки импульсов по 2,5 мс, с паузой 7,5 мс. Причем пачки являются «вырезками» из общего ШИМ-а, в общем получился AND-GATE. Появилась возможность не заморачиваться отдельной регулировкой яркости динамического индикатора, а использовать один канал ШИМ-а на все. Изначально в цепи анодов динамики были установлены токоограничивающие резисторы заведомо меньшего номинала, чем на семисегментные индикаторы. В легкодоступном месте платы на дорожках этих же цепей предусмотрены дополнительные резисторы. Сделано это для выравнивания воспринимаемой яркости динамики и семисегментных индикаторов подбором номиналов этих резисторов.

C динамикой разобрались, а как быть с светодиодами и индикаторами, подключенными через сдвиговые регистры? Очень просто. У сдвигового регистра HC595 есть пин OE — если он в LOW, все выводы работают в обычном режиме, а если в HIGH — в режиме Hi-Z (т.е. с большим сопротивление, что сродни отсутствию контакта) Проще говоря, если на ноге логический ноль — светодиоды горят, а если логическая единица — не горят. Подаем на него тот же ШИМ, что на динамику — и все, яркость регулируется на всех «лампочках» одновременно и одним каналом.

Сам ШИМ генерится обычным образом, частоту меняем в соответствии с освещенностью фоторезистора, данные с которого идут на АЦП Меги. В алгоритм обработки данных с АЦП включено преобразование, обеспечивающее плавное, несколько замедленное изменение частоты ШИМ-а, сглаживающее шумы АЦП и ложные скачки освещенности (люстра в комнате например «моргнула»).

Алгоритм работы
Я старался сделать программу как можно более гибкой — номера пинов на плате и порядок сдвиговых регистров мог поменяться. Поэтому реализация получилась через макросы (и еще одну удобную либу, основанную на коде Neiver @ easyelectronics, найти можно в моем BitBucket, port.h). Очень удобно — проставил правильные значения, и все работает. Что-то изменилось — поменял цифру, и снова все хорошо.

Так как потребляемый устройством ток может быть довольно большим, возникли опасения за программатор и USB порт компьютера. Были выбраны два способа прошивки: 1) питать устройство от стандартного блока питания и не подавать напряжение питания с программатора (предусмотрен джампер разрыва между линией питания и плюсовым пином ISP-6); 2)питать всю систему от программатора. В первом варианте есть засада. При отсутствии гальванической развязки можно поиметь неприятности. При использовании импульсных БП (на компьютере именно такой)и отсутствии общей «правильной» земли можно много чего попалить (и само устройство, и программатор, и USB на компе, а то и материнку туда же прихватить). Поэтому будьте осторожны, подключайте все правильно (относится не только к этому проекту). Для второго варианта предусмотрена установка яркости индикаторов на минимальном уровне, около 2% от максимальной, потребление в данном режиме — 60-70 мА. Этот режим устанавливается джампером, закорачивая 2 свободных пина МК (помните, я их вывел отдельно на всякий случай? Пригодилось…). Джампер есть — данные с фотодатчика игнорируются, и яркость светодиодов ставится на ~ 2%, нет джампера — обычный режим.

При включении МК инициализирует периферию и запускает прерывание по таймеру, срабатывающее каждые 2,5 мс, причем есть переменная-счетчик количества прерываний переполнения, который обнуляется через каждые N прерываний — я сделал это затем, чтобы можно было отследить прошедшее время о какого-то момента (N будет кратно 400 — можно примерно оперировать секундами).
• В начале цикла идет обработка события динамики — переключение общего катода на следующий в очереди и вывод цифры.
• После запускается опрос периферии. Каждые X количеств прерываний я запускаю обработку какого-либо события. Например, каждые 50 прерываний (8 раз в секунду) опрашиваю DS1307, 10 прерываний (40 раз в секунду) — фоторезистор. Реализовано через команду ‘количество_прерываний % X == 0’ (% <=> mod — остаток от деления — равен нулю ->кратно этому числу), причем операции, требующие довольно большого времени, не кратны другим. Сделано это для того, чтобы все успеть за 2.5 мс и исключить возможность превышения этого лимита. Например, полный цикл чтения с DS1307 занимает около 0.5-0.8 мс. Если после этого запустить обработку данных с трансивера, вывод на сдвиговые регистры и еще чего-нибудь — есть шанс, что времени не хватит.
• В конце просто жду прерывание по переполнению, анализируя в цикле бит в регистре TIFR.

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

Файл для DipTrace — *click* (.dch)
Картинка справа — кликабельна (та же схема, что и выше, но в JPG формате)

Печатные платы
Разведены вручную в программе DipTrace. В основном модуле получилось 8 плат — 6 с регистрами (на двух из них по 4 регистра, на четырех по 1), передняя панель и задняя панель. Все платы двусторонние. Выполнены с использованием фоторезиста (ЛУТ-ом тоже должно получиться), травились в персульфате аммония.
Вот ссылки:
Схема (.dip) — *click* (.zip)
Необходимые нестандартные библиотеки — *click* (.zip)

Исходник программы
Сразу предупреждаю — он, мягко говоря, несколько неоптимизированный. Используется несколько самописных библиотек, они хорошо прокомментированы. А вот основной файл — не очень хорошо… Если что-то непонятно — спрашивайте, на все отвечу.
Вы можете встретить в комментариях два ника: Sky-WaLkeR и shadowalker, Это одно лицо, то бишь я, Набоко Александр.
Ссылка на архив (исходники со всеми библиотеками, готовый файл тестовой прошивки) — *click*

Фото (кликабельны)
К сожалению, фотографий всего процесса нет. Фотоаппарат не всегда под рукой…
Лицевая панель, после травления, два слоя


Задняя панель, напаяны элементы, два слоя


Лицевая панель, напаяна одна большая плата со сдиговыми регистрами

Лицевая панель, напаяны все платы со сдвиговыми регистрами

Устройство в сборе


Видео
Первый тест — работа сдвиговых регистров и DS1307

В ближайшее время добавлю видео с рабочей динамической индикацией и изменением яркости на основе фоторезистора.

Состояние проекта
В принципе, основной модуль почти готов — осталось сделать корпус и немного доработать прошивку. Схема для модуля с DHT наконец стала не абстрактной (тут МК, тут DHT а там питание), а получила названия всех компонентов и тоже практически готова. А вот Ethernet-модуль дальше пока не развился — у меня сейчас мало времени (ЕГЭ 27, 29 мая и 3, 6 июня все-таки требуют подготовки…). Закончить проект до 31 мая затруднительно, но постараюсь довести его до конца 🙂


0 комментариев на «“WeatherStation. Часть 1: Основной модуль”»

    • Просто под рукой были DIP-ы 20 штук, надо же их куда-то девать, да и другие корпуса не намного облегчили бы жизнь… Ну и попрактиковаться хотелось 🙂

    • Ну, закрома родины — самый весомый аргумент, решают. А так, двусторонка — SMD компоненты бы на ура, было бы существенно все меньше. И дырок сверлить меньше 🙂

    • Да 🙂 Только хотел сказать что всё бы влезло и дырок в 10 раз меньше надо бы было если использовать СМД детали 🙂 Сам когда-то купил случайно ленту СМД 74НСТ595 — 100 шт. Тогда первый раз плевался когда делал плату — 10 лет назад — а теперь красота!!!

    • Так оно и есть, но для меня это первый проект такого масштаба. Много чего пришлось делать в первый раз — и фоторезист, и пайка SMD компонентов (а TQFP — это вообще отдельная история… самый-самый первый раз 🙂 ). Все приходилось осваивать на ходу, кое-что изменять… Это сейчас мне уже не страшно паять такие вещи, а сначала все в новинку было — SMD в том числе.

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

Arduino

Что такое Arduino?
Зачем мне Arduino?
Начало работы с Arduino
Для начинающих ардуинщиков
Радиодетали (точка входа для начинающих ардуинщиков)
Первые шаги с Arduino

Разделы

  1. Преимуществ нет, за исключением читабельности: тип bool обычно имеет размер 1 байт, как и uint8_t. Думаю, компилятор в обоих случаях…

  2. Добрый день! Я недавно начал изучать программирование под STM32 и ваши уроки просто бесценны! Хотел узнать зачем использовать переменную типа…

3D-печать AI Android Arduino Bluetooth CraftDuino DIY IDE iRobot Kinect LEGO OpenCV Open Source Python Raspberry Pi RoboCraft ROS swarm ИК автоматизация андроид балансировать бионика версия видео военный датчик дрон интерфейс камера кибервесна манипулятор машинное обучение наше нейронная сеть подводный пылесос работа распознавание робот робототехника светодиод сервомашинка собака управление ходить шаг за шагом шаговый двигатель шилд юмор

OpenCV
Робототехника
Будущее за бионическими роботами?
Нейронная сеть - введение