Пост раскрывает реализацию подачи школьного звонка с использованием отладочной платы FEZ Domino. Управление расписанием осуществляется через веб-страницу. На FEZ Domino портирована платформа .NET Micro Framework. Язык программирования C#. Предистория поста такова…
Хабровчан prostosergik опубликовал пост Новогодняя малина — прикручиваем экран HD44780 к Raspberry Pi. В комментариях между мною и prostosergik завязался спор о целесообразности использования для этих задач Raspberry Pi. prostosergik в комментариях сообщил о уже готовом проекте школьного звонка на Raspberry Pi.
Позже был опубликован пост Школьный звонок на Raspberry Pi с удаленным управлением. Теперь настала моя очередь в реализации этой задачи.
По итогу переписки сформировал следующее ТЗ:
Цель: включать звонок в соответствии с расписанием школьных звонков в учебном заведение
Механизм работы: звонок подается в соответствие с поданным сигналом «1» на контактном реле. При замыкания реле, звенит звонок.
Требования
- Возможность изменения расписания звонков через Web-интерфейс
- Синхронизация времени с NTP сервером с сети Интернет
- Наличие кнопка сброса к “заводским” настройкам
- Время подачи звонка не изменяется, и всегда 5 секунд
- Безопасность. Задание списка IP адресов, с которых возможно управление системой. Авторизация по логин/пароль(не было реализовано, но технически возможно)
- Время расписание звонков на каждый рабочий день, одинаково
- Кнопка подачи звонка в любое время
Реализация
Сразу скажу, из-за технический ограничений на Arduino UNO R3, не удалось реализовать этот проект в полной мере.
При выборе контроллера руководствовался следующими правилами
- Arduino-совместимый по шилдам и методологии работы.
- Отсутствие Linux в любом проявление
- Доступная цена
- Не для сегмента промышленности
В заголовке не упоминается FEZ Domino, не случайно. Программный код между микроконтроллерами работающие на .NET Micro Framework, практически без изменений переносим всегда, при соблюдение версии. В данном случае FEZ Domino легко заменяется на плату NET Duino Plus 2, без ущерба в функциональности.
Список используемых компонентов:
- Отладочная плата FEZ Domino или аналог по характеристикам
- Реле – для подачи звонка
- Светодиод – загорается в момент подачи звонка
- Кнопка — для сброса к заводским настройкам
- Кнопка – ручной подачи звонка
- LCD двухстрочный – отображение служебной информации
- SD-карта – на 8 Гб
- Шилд подключения – подключения кнопок, LCD, реле, LED
- Ethernet Shield — локальная сеть
Все компоненты можно врассыпную купить на Aliexpress.com, будет существенно дешевле.
Спецификация FEZ Domino:
- Arduino совместимые контакты с Arduino
- 72Mhz 32-bit ARM7 LPC2388 процессор
- USBizi-144 Chipset
- ~148KB доступной памяти Flash
- ~62KB доступной памяти RAM
- Порт USB Host (USB-разветвители, джойстик, клавиатура, мышь, принтер, CDC, виртуальный последовательный интерфейс и т.д.)
- Порт USB client (для отладки, выборочно для эмуляции клавиатуры, мыши или CDC)
- Поддержка карт памяти microSD (SDHC support, 4-bit SD Bus, поддержка более 2GB, успешно использовалась microSDHC 8 GB class 10 Transcend)
- RTC realtime clock — часы реального времени
- Поддержка TCP/IP используя Ethernet shield (WIZnet W5100 chip)
- 30 программируемых IOs
К сожалению FEZ Domino давно снята с производства, поэтому ниже ближайшие аналоги
Схема подключения
Связка Fez Domino, Ethernet Shield, I/O Expansion Shield, в режиме стека
Запуск устройства
При запуске устанавливается WatchDog на 20 секунда, в случае зависание устройства.
//Enable Watchdog
GHI_LowLevel.Watchdog.Enable(1000 * 20);
Сброс счётчика осуществляется
GHI_LowLevel.Watchdog.ResetCounter();
Инициализация прерываний на кнопки
//Кнопка подачи звонка в ручном режиме
FEZ_Components.Button Button_ManualCall = new FEZ_Components.Button(FEZ_Pin.Interrupt.Di5);
//Кнопка аппаратного сброса и перезагрузки
FEZ_Components.Button Button_HardReset = new FEZ_Components.Button(FEZ_Pin.Interrupt.Di6);
// установление прерывания на кнопку
Button_ManualCall.ButtonPressEvent += new FEZ_Components.Button.ButtonPressEventHandler(Button_ManualCall_ButtonPressEvent);
// установление прерывания на кнопку
Button_HardReset.ButtonPressEvent += new FEZ_Components.Button.ButtonPressEventHandler(Button_HardReset_ButtonPressEvent);
Затем устанавливается ждущий режим на 5 с для сброса настроек по умолчанию. Горит светодиод и высвечивается надпись на экране “Starting ...”.
Чтение настроек с SD карты памяти
//загрузка настроек
appset = new AppSettings();
appset.ReadSettings();
Инициализация сети
netinter = new netinteface();
Чтение времени из RTC. RTC интегрирован в чип. Для обеспечения хода часов необходимо подключит батарейку v3.3 к контактам
Utility.SetLocalTime(RealTimeClock.GetTime());
Запуск потока синхронизации времени с NTP сервером. Интервал синхронизации задается в настройках.
Thread ThreadUpdateTimeNTP = new Thread(UpdateTimeNTPThread);
ThreadUpdateTimeNTP.Start();
Запуск потока подачи звонка. Сопоставляет текущее время и время звонков. В случае совпадения подает звонок.
Thread ThreadTimeBells = new Thread(TimeBells);
ThreadTimeBells.Start();
Запуск Web сервера
Webserver server = new Webserver();
подготовка массива для передачи. Небольшой велосипед для экономии памяти
string[] confstr = {appset.SyncTimeDelayMin.ToString(),
appset.CurTimeBell[0].ToString("HH:mm"),
…
appset.CurTimeBell[7].ToString("HH:mm")};
server.StartServer(confstr);
Особенности реализации
От Arduino UNO пришлось практически сразу отказаться по следующим причинам:
Одновременно не поддерживается работа с сетью и SD картой. Есть реализация у ladyada Arduino Ethernet+SD, но к у меня не получилось запустить.
Arduino поддерживает два параллельных потока или два прерывания.
В моей реализации получилось 4 потока: прерывание на кнопку для ручной подачи звонка, синхронизация с NTP сервером, поток отслеживания времени подачи звонка, поток обслуживания http сервера. Для Arduino UNO это слишком много.
По сравнению с проектом на Raspberry pi, простота реализации поддержки Watchdog.
К сожалению, не работает отслеживание состояния Ethernet кабеля. При отключение кабеля, необходимо проводить инициализацию сети. Как вариант решения этой проблему периодически опрашивать ping какой ни будь узел в сети. В случает отсутствия ответа, заново инициализировать сеть. Но это недоработка CLR для микроконтроллера FEZ Domino.
Отслеживание времени звонка осуществляется с секундной точность. Поэтому, для того что бы звонок не проскочил, сохраняется предыдущее время и новое. Если время звонка попадает в этот интервал, звенит звонок. Процедура засыпает на 1 секунду, но так же еще тратится время на выполнение самой процедуры, поэтому и был сделан интервал.
public static void TimeBells()
{
string NowLocalTime = "";
DateTime NewTime;
DateTime OldTime = DateTime.Now.ToLocalTime();
OpredCallZvon ocz;
while (true)
{
//текущее время
NewTime = DateTime.Now.ToLocalTime();
//отображение текущего времени
NowLocalTime = NewTime.ToString("HH:mm:ss");
//проверка подачи звонка
foreach (DateTime dt in appset.CurTimeBell)
{
ocz=new OpredCallZvon(NewTime,OldTime,dt);
if (ocz.isCall)
{
LCD.setCursor(0, 1);
LCD.print("NOW ZVONOK ");
RunBell();
}
}
OldTime = NewTime;
Thread.Sleep(1000);
}
}
В момент подачи звонка горит светодиод.
RTC встроен. Достаточно подвести питание на пины VBAT IN и Ground.
Для упрощения шаблоны html страниц были помещены в ресурсы к проекту.
Использовались библиотеки:
- Веб-сервер. Panda based web server от Dave
- Синхронизация времени с NTP сервером. NTP time adjustement for Wiz5100 от Nicolas3
- Неожиданностью оказалось отсутствие замены строки в подстроки в Net Micro Framework. Библиотека String.Replace() от William
На реализацию ушло 3 дня x 4 часа = 12 человеко-часов.
Иногда при http запросах получалось исключение о превышение оперативной памяти(~62KB). Из-за этого пришлось применять новые настройки только при перезагрузке, не в оперативном режиме.
Смета расходов
№ | Название | кол-во | цена | Сумма, $ |
1 | Netduino Plus 2 | 1 | 59,95 | 59,95 |
2 | Relay Module | 1 | 1,74 | 1,74 |
3 | RGB 3 Color Full Color LED любой цвет | 1 | 1,99 | 1,99 |
4 | Standard Button Switch Sensor Module | 2 | 1,29 | 2,58 |
5 | LCD module Blue screen IIC/I2C 2004 5V | 1 | 7,6 | 7,6 |
6 | Карта памяти MicroSD | 1 | 3,14 | 3,14 |
7 | Основа для монтажа, провода | 1 | 10 | 10 |
ИТОГО | 87 |
Видео:
Автор: devzona
а на чем вы писали код?