У моего друга какие-то непонятные проблемы со здоровьем. Врачи говорят, что это «криптогенная эпилепсия». Суть в том, что иногда у него ночью во сне начинается приступ «трясучки». В итоге меня попросили сделать устройство, которое должно надеваться на руку и противно пищать, если его трясти секунд десять, чтобы оповестить близких и своевременно помочь.
Самое очевидное решение — использовать акселерометр. Я купил один из первых попавшихся — BMA150 от Bosch.

Маленький, зараза, всего 3x3мм, но мы и не такое паяли.
Сразу скажу, что занимаюсь этим исключительно на любительском уровне, поэтому сильно не критикуйте.
После чтения даташита выяснилось, что общаться с акселерометром можно по I²C или SPI, но ко всему прочему у него есть специальный вывод под внешнее прерывание. Т.е. можно один раз настроить его так, чтобы он при определённых условиях выводил туда логическую единицу. В нашем случае это идеально — не надо постоянно опрашивать датчик, он сам будет выводить микроконтроллер из спящего режима при наличии тряски определённой силы. Это очень важно, учитывая, что нужно сделать устройство максимально экономным в плане питания.
Для экспериментов и настройки я вытравил плату, чтобы можно было легко подпаяться:

Почему-то по I²C акселерометр не захотел работать. Возможно, что я где-то ошибся. А вот по SPI всё заработало без проблем. Датчик доступен как массив памяти, который делится на две части:
Радости моей не было предела, когда я наконец-то получил данные:

Акселерометр умеет автоматически генерировать внешнее прерывание в самых разных случаях. Нам нужно простейшее событие — любое достаточно сильное движение. Датчик делает это, если верно следующее условие по любой из осей:
any_motion_thres задаётся в специальном регистре. Опытным путём я выяснил, что при частоте обновления в 25Гц оптимальным значением является 20h. При таком раскладе флаг прерывания устанавливается, если легко потрясти датчиком. Снимается же флаг автоматически, если условие перестаёт выполняться в течении некоторого времени.
Убедившись, что все параметры выставлены оптимально, я сохранил эти настройки уже в EEPROM. Таким образом, акселерометр сразу же после включения будет выводить на INT вывод логическую единицу, если есть движение, и SPI больше не нужен.
Я выбрал микроконтроллер ATMEGA8A. Он имеет два внешних прерывания (одно из них я решил использовать для кнопки, а другое для самого акселерометра), работает в диапазоне напряжений 2.7-5.5В, и в самом глубоком режиме сна «power down» потребляет всего 0.5мкА. Предполагается, что почти всё время микроконтроллер будет спать, ведь очень важно энергосбережение. Однако, для пробуждения из такого спящего режима необходимо з��мкнуть INT0/INT1 ногу на землю, а акселерометр при наличии движения наоборот даёт высокий уровень, поэтому для инвертирования нужно поставить транзистор. Сам датчик я решил питать прямо от ног самого микроконтроллера, чтобы можно было без лишних потерь его включать и выключать. Динамик тоже подключил напрямую. Для отладки было решено поставить ещё и один светодиод. Схему я не рисовал, а плата в итоге выглядела так:

Готовая плата:

Увы, в наличии у меня была только пищалка, которая оказалась больше самой платы:

Тут всё достаточно просто. У устройства два режима работы:
У акселерометра, кстати, тоже есть режим сна, из которого он может просыпаться через заданные интервалы времени, но я решил его не использовать, чтобы не повлиять на точность и надёжность. По документации этот датчик потребляет 200мкА, этого должно хватит на много ночей.
Корпус было решено напечатать на 3D принтере.

В итоге внутри всё выглядело так:

Увы, в конце концов устройство получилось очень громоздким и колхозным:

Но это всё-таки первый экспериментальный образец. Думаю, что позже размеры и внешний вид можно будет сильно оптимизировать. Ну и не стоит забывать, что даже в таком виде оно может спасти человеку жизнь.
Видео устройства в работе:
Простите за грязные пальцы, они всё ещё в пластмассе и хлорном железе.
Предвижу определённые вопросы, отвечу на них сразу:
Как я и обещал, не смог остановиться на первой версии, тем более в итоге меня попросили уменьшить время срабатывания и увеличить чувствительность.
Увы, в магазине уже не было в наличии акселерометров BMA150, зато был BMA250. Беглый взгляд на даташит показал, что он даже гораздо круче. Правда, ещё меньше:

Два на два миллиметра, при этом 12 контактов. Однако, проблем с размерами и на этот раз не возникло. Это скорее даже плюс.
У этой модели появился ряд очень приятных настроек. И полярность прерывания можно указать (прощай, дополнительный транзистор), и их длительность, и многое другое. Да это же просто великолепно! Я уже был очень рад, когда подобрал оптимальные параметры всех регистров, но вся радость сошла на нет, когда понял, что у BMA250 нет возможности сохранять эти настройки в EEPROM. Это такая ложка дёгтя в бочке мёда, что я долго не мог в это поверить.
Пришлось развести на плате и SPI до акселерометра, чтобы каждый раз при включении настраивать его заново.

Зато если придётся изменить какую-то из настроек, его не надо будет выпаивать. И да, я прислушался к советам в комментариям и воспользовался маленькой пьезопищалкой, батарейка же помещается под платой, в итоге устройство сильно уменьшилось в размерах. Ещё при включении теперь измеряется напряжение на батарейке, и если оно ниже 2.8В, то издаётся дополнительный сигнал. Для этого используется ADC с внутренним стабилизатором на 2.56В и делитель напряжения, чтобы вписываться в этот диапазон.
В корпусе:

И в закрытом виде:

Самое очевидное решение — использовать акселерометр. Я купил один из первых попавшихся — BMA150 от Bosch.

Маленький, зараза, всего 3x3мм, но мы и не такое паяли.
Сразу скажу, что занимаюсь этим исключительно на любительском уровне, поэтому сильно не критикуйте.
После чтения даташита выяснилось, что общаться с акселерометром можно по I²C или SPI, но ко всему прочему у него есть специальный вывод под внешнее прерывание. Т.е. можно один раз настроить его так, чтобы он при определённых условиях выводил туда логическую единицу. В нашем случае это идеально — не надо постоянно опрашивать датчик, он сам будет выводить микроконтроллер из спящего режима при наличии тряски определённой силы. Это очень важно, учитывая, что нужно сделать устройство максимально экономным в плане питания.
Настройка акселерометра
Для экспериментов и настройки я вытравил плату, чтобы можно было легко подпаяться:

Почему-то по I²C акселерометр не захотел работать. Возможно, что я где-то ошибся. А вот по SPI всё заработало без проблем. Датчик доступен как массив памяти, который делится на две части:
- EEPROM с настройками по умолчанию, т.е. которые используются в момент включения
- Операционные регистры с текущими настройками и самими показаниями датчика
Радости моей не было предела, когда я наконец-то получил данные:

Акселерометр умеет автоматически генерировать внешнее прерывание в самых разных случаях. Нам нужно простейшее событие — любое достаточно сильное движение. Датчик делает это, если верно следующее условие по любой из осей:
|acc(t0)-acc(t0+3/(2*bandwidth))| >= any_motion_thresany_motion_thres задаётся в специальном регистре. Опытным путём я выяснил, что при частоте обновления в 25Гц оптимальным значением является 20h. При таком раскладе флаг прерывания устанавливается, если легко потрясти датчиком. Снимается же флаг автоматически, если условие перестаёт выполняться в течении некоторого времени.
Убедившись, что все параметры выставлены оптимально, я сохранил эти настройки уже в EEPROM. Таким образом, акселерометр сразу же после включения будет выводить на INT вывод логическую единицу, если есть движение, и SPI больше не нужен.
Разработка платы
Я выбрал микроконтроллер ATMEGA8A. Он имеет два внешних прерывания (одно из них я решил использовать для кнопки, а другое для самого акселерометра), работает в диапазоне напряжений 2.7-5.5В, и в самом глубоком режиме сна «power down» потребляет всего 0.5мкА. Предполагается, что почти всё время микроконтроллер будет спать, ведь очень важно энергосбережение. Однако, для пробуждения из такого спящего режима необходимо з��мкнуть INT0/INT1 ногу на землю, а акселерометр при наличии движения наоборот даёт высокий уровень, поэтому для инвертирования нужно поставить транзистор. Сам датчик я решил питать прямо от ног самого микроконтроллера, чтобы можно было без лишних потерь его включать и выключать. Динамик тоже подключил напрямую. Для отладки было решено поставить ещё и один светодиод. Схему я не рисовал, а плата в итоге выглядела так:

Готовая плата:

Увы, в наличии у меня была только пищалка, которая оказалась больше самой платы:

Прошивка
Тут всё достаточно просто. У устройства два режима работы:
- Выключенное. В этом состоянии мы не подаём питание на акселерометр и просыпаемся только по нажатию кнопки. В таком виде микроконтроллер может проработать не менее года (проверено), разряд батарейки близок к саморазряду.
- Включенное. Когда же устройство включено, мы питаем акселерометр и просыпаемся как от нажатия кнопки, так и от сигнала со стороны датчика. Если кнопка держится полторы секунды, устройство переходит назад в выключенное состояние. Если же прерывание сгенерировал сигнал от датчика, и он повторяется в течении 10 секунд как минимум один раз за две секунды, то трубим тревогу, пока не будет нажата кнопка.
У акселерометра, кстати, тоже есть режим сна, из которого он может просыпаться через заданные интервалы времени, но я решил его не использовать, чтобы не повлиять на точность и надёжность. По документации этот датчик потребляет 200мкА, этого должно хватит на много ночей.
Создание корпуса
Корпус было решено напечатать на 3D принтере.

В итоге внутри всё выглядело так:

Увы, в конце концов устройство получилось очень громоздким и колхозным:

Но это всё-таки первый экспериментальный образец. Думаю, что позже размеры и внешний вид можно будет сильно оптимизировать. Ну и не стоит забывать, что даже в таком виде оно может спасти человеку жизнь.
Видео устройства в работе:
Простите за грязные пальцы, они всё ещё в пластмассе и хлорном железе.
Предвижу определённые вопросы, отвечу на них сразу:
- Да, приступы у этого человека только во сне
- Да, все приступы сопровождаются тряской
- Кнопка утоплена, поэтому случайно выключить устройство сложно
Обновление от 06.07.2014
Как я и обещал, не смог остановиться на первой версии, тем более в итоге меня попросили уменьшить время срабатывания и увеличить чувствительность.
Увы, в магазине уже не было в наличии акселерометров BMA150, зато был BMA250. Беглый взгляд на даташит показал, что он даже гораздо круче. Правда, ещё меньше:

Два на два миллиметра, при этом 12 контактов. Однако, проблем с размерами и на этот раз не возникло. Это скорее даже плюс.
У этой модели появился ряд очень приятных настроек. И полярность прерывания можно указать (прощай, дополнительный транзистор), и их длительность, и многое другое. Да это же просто великолепно! Я уже был очень рад, когда подобрал оптимальные параметры всех регистров, но вся радость сошла на нет, когда понял, что у BMA250 нет возможности сохранять эти настройки в EEPROM. Это такая ложка дёгтя в бочке мёда, что я долго не мог в это поверить.
Пришлось развести на плате и SPI до акселерометра, чтобы каждый раз при включении настраивать его заново.

Зато если придётся изменить какую-то из настроек, его не надо будет выпаивать. И да, я прислушался к советам в комментариям и воспользовался маленькой пьезопищалкой, батарейка же помещается под платой, в итоге устройство сильно уменьшилось в размерах. Ещё при включении теперь измеряется напряжение на батарейке, и если оно ниже 2.8В, то издаётся дополнительный сигнал. Для этого используется ADC с внутренним стабилизатором на 2.56В и делитель напряжения, чтобы вписываться в этот диапазон.
В корпусе:

И в закрытом виде:
