Привет! Зацените систему мониторинга сервера/компьютера с управлением по СМС. Система позволяет управлять питанием компьютера (on/off, reset), сбрасывать питание маршрутизатора/точки доступа, USB-модема. Также возможно мониторить температуру, влажность, уровень шума, присутствие того или иного питания; можно позвонить на устройство и при подключении звуковой аппаратуры "пообщаться" с удаленной точкой, а можно нажав кнопку позвонить с устройства на первый номер в адресной книге. Есть функция авторизации входящих звонков и СМС по номерам, хранящихся в EEPROM. Возможно включить пересылку СМС с незнакомых номеров. Адресная книга редактируется через COM-порт. И наконец устройство снабжено автономным питанием от аккумулятора, параметры авторизации, отправки/пересылки СМС хранятся в EEPROM. Спойлер: Неинтересная история В далеком 2014 году решил я заняться темой проброса физической видеокарты в виртуальную машину. Но вот не задача - компьютер дома, а время этим заниматься на работе. Частенько в процессе экспериментов удаленная система зависала от слова совсем, и удаленный доступ в любом виде оказывался бесполезен. Нужна была удаленная кнопка reset... Короче, помимо ресета было решено добавить еще немного функционала типа мониторинга питания, температуры, уровня шума, а также возможность сброса питания маршрутизатора и USB-модема. Изначально за основу была взята Arduino Ethernet, но, как показала практика, памяти в ней настолько мало, что до применения Ethernet-порта дело вообще не дошло. Так и работала эта система в недоделанном виде живя в коробочке, однако неоднократно меня выручавшая. За основу обновленной системы версии взята Iskra Neo, на ней: SeeedStudio Energy Shield, SeeedStudio GPRS Shield V2.0, Amperka Relay Shield. Также используются кнопка и светодиод от Амперки, датчик температуры/влажности DHT11 и датчик шума от DFRobot, макетка с 3 делителями напряжения и внутренности USB-хаба. Корпус собран из #структора. Один из портов хаба подключен к Neo, еще два выведены на корпус. В итоге скоммутировано все таким образом: 1 реле NO-контакт подключен параллельно кнопке питания компьютера; 2 реле NO-контакт подключен параллельно кнопке сброса компьютера; 3 реле NС-контакт подключен в разрыв питания маршрутизатора (можно подключить NO к кнопке сброса, если таковая имеется); 4 реле NС-контакт подключен в разрыв питания USB порта на корпусе устройства; Поскольку в первой версии я использовал Arduino Ethernet - количество свободных портов было ограничено, для экономии управление реле было сделано через GPIO-модема. В этот раз решил оставить как есть. Делители напряжения построены на 100 кОм резисторах. 1 делитель - vin. Сейчас у меня устройство питается от БП компьютера, поэтому по напряжению на vin я сужу включен компьютер или нет. При питании от сети можно судить о наличии напряжения в сети. 2 делитель - напряжение на USB-хабе (чтобы не получить здесь +5В при фактически отключенном USB-кабеле питание +5В на плату подается через диод, следовательно питание от USB-хаба невозможно, однако в этом случае по наличию питания на хабе можно судить о том включен компьютер или нет). 3 делитель - напряжение резервной батареи (я использую старый аккумулятор от телефона на 1200 мАч). В качестве библиотеки для работы с модемом используется симбиоз библиотек от SeeedStudio и Амперки (которая судя по всему корнями также уходит к Seeed). Библиотеки пришлось существенно доработать - так, например, прием СМС у Seeed реализован через SIM-карту, у Амперки в последовательный порт, но в оригинале работает через раз. Seeed не умеет работать с портом Serial1 на Leonardo, а библиотека от амперки не умеет гарантированно принимать и СМС и звонки, т.к. обработка этих событий от модема реализована в разных функциях и если одна уже считала данные с порта, то второй они не достанутся... В общем, написал новую функцию, которая умеет ловить и СМС и звонки + переписал функции управления питанием под плату от Seeed. В первой версии у меня использовались куски от этой тяжеловесной библиотеки. Она реально сжирала 80% доступной памяти, в результате приходилось экономить на всем. Команды максимум по 3 буквы, скудный вывод для отладки... Это было ужасно. В этот раз при написании программы, помятуя прошлый опыт, я хорошенько постарался сэкономить память. По максимуму используются глобальные переменные (тру программистов прошу не пинать, сам плачу когда вижу такое), для которых память выделяется заранее, особенно это важно для больших буферов в десятки и сотни символов, которые постоянно используются повторно в разных функциях. Большие строки хранятся не в коде, а в EEPROM и достаются оттуда по необходимости. В результате при полной реализацией "хотелок" имеем: Даже есть куда "прикрутить" еще пару-тройку датчиков Единственный недостаток такой экономии - при первой прошивке в watchdog_3.h надо закомментить MAIN и раскомментить INIT Код (C++): //#define INIT #define MAIN Залить прошивку, набрать в отладке "fill", чтобы инициализировать EEPROM. Далее вернуть комменты и прошить заново. Также для работы потребуется библиотека от Амперки для DHT11, установленная стандартным способом. Вот так как-то.
Славный шедевр программирования. Вопрос такой - это очередной ПДУ от телевизора, или устройство мониторит параметры и САМО принимает решения о перезагрузка? Из описания не понял.
Была такая идея, но как показала практика это не требуется. Если я что-то делаю с удаленным компьютером, то я могу предположить, что произошло и перезагрузить руками. Если внезапно пропала связь с компьютером - можно попробовать перезагрузить сетевое оборудование после звонка провайдеру, но решение все равно за мной. Опять же, можно запросить состояние датчиков и увидеть, включен компьютер или нет, а при питании устройства от БП воткнутого в розетку - есть ли электричество в помещении. Ну и при небольшом допиливании можно сделать автоматическое уведомление по СМС об отключении электричества/компьютера. Еще была мысль написать службу, которая бы проверяла соединение с сетью, уровень заряда ИБП его состояние, состояние RAID-массивов и делилась бы данными с устройством, соответственно было бы больше информации для автоматического принятия решения о перезагрузке того или иного устройства. Но это потом.
Строки по сути константы -- лучше хранить во flash. А EEPROM использовать для хранения настроек устройства. Это недостаток не экономии, а организации хранения данных. Как уже говорил строки желательно поместить во flash, данные с настройками в EEPROM -- смотрите описание макросов PROGMEM и EEPROM EEMEM. При сборке проекта (компиляции и т.п.) будет сформировано два hex файла -- один для заливки во flash, другой для заливки в EEPROM. Эти два файла нужно будет залить в микроконтроллер без всяких не понятных действий вида: Вообще если правильно декларировать переменные, то вот это: Код (C++): /* * EEPROM mapping * 1024 Kb * 10 x 16 = 160 - address book | first addr 0 * 16 x 1 = 16 - parameters | first addr 160 * 24 x 16 = 384 - commands | first addr 176 * 4 x 32 = 128 - short strings | first addr 560 * 4 x 64 = 256 - long strings | first addr 688 * ------------- * 944 bytes * 80 bytes free */ за Вас сделает компилятор. Правильное декларирование переменных (с использованием макросов EEPROM EEMEM и PROGMEM) в свою очередь сильно упростит исходный код программы -- сможете избавится от лишних действий по вычислению адреса данных в памяти (той же EEPROM). Зачем делать то, что может сделать компилятор?
Действительно получился велосипед с EEPROM, надо будет переделать... Про PROGMEM я нашел документацию, но вот про аналогичный макрос EEPROM что-то не вижу, есть только это, чем я собственно и пользовался. Или имеется ввиду какая-то иная среда разработки? В любом случае, спасибо! PS Это ж вообще все константы можно во флеш закинуть...
Нашел. Называется макрос EEMEM. Обсуждение на форуме arduino.cc. Как я понял макрос лишь определяет адрес переменной, к которой все равно нужно будет обращаться через read и write. Ну а этот комментарий в примере вообще не радует: Код (C++): // A EEMEM structure or EEMEM variable is not located somewhere. // The compiler uses it only to calculate offsets. // When more EEMEM variables are used, the order is defined // by the compiler. // With a new compiler, that [B]order in EEPROM might change[/B]. Таким образом, имеет смысл объявлять единственную структуру с EEMEM, дабы не нарваться на внезапное изменение адресов по воле компилятора.
Прошу прощения, ввёл в заблуждение. Макрос действительно называется EEMEM. Да, но это из-за не доработок компилятора avr-gcc, который так же используется в Arduino IDE. Eсть компиляторы для AVR, которые правильно обработают чтение/запись в такую переменную. Вроде как IAR или CodeVision это умеет делать. Объявлять единственную структуру не обязательно. Ну раскидает компилятор по EEPROM как ему захочется, Вы же всё равно будете к ним обращаться через переменные. И компилятор будет знать к какой ячейке EEPROM нужно обращаться. Другое дело если захотите изменять содержимое EEPROM минуя прошивку, т.е. прошивать конфигурационные данные внешними средствами. Но в этом случае нужно как-то линковщику сказать каким образом компоновать переменные в памяти. На этот вопрос я пока не готов дать ответ... И да, единственную структуру компилятор так же может разместить где угодно (хотя он всегда начинает с нулевого адреса), поэтому закладываться на это не стоит.
Тыдыщ! Обновленная версия со строками во флеше. Стало: Почти без изменений, но кода действительно стало меньше и теперь не надо заранее инициализировать EEPROM Еще раз спасибо за наводку, буду пользовать