Hands Free, но не телефон. Послушный дом, когда рук не хватает

Здравствуй, Сообщество!

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

Как известно, компьютерный стол – он же обеденный, чтобы смотреть Дробышевского или читать Гиктаймс / Зелёного Кота / etc. одновременно с ужином. Но есть проблема – из кухни я иду обычно с обеими занятыми руками, обратно тоже, ведь чашки копятся по 3 шт. Включать и выключать свет на кухне (выключатель тройной – кухня/ванна/туалет) приходится плечом, носом, мизинцем. То есть неудобно никак, а переставить ниже нельзя. Возникла задача управлять как-то дистанционно.

Всякие датчики присутствия и прохода отмёл сразу – не та точность, нет управления по воле хозяина. Решение найдено в звуковом управлении, голосом. Скажу сразу, я не планировал делать рапознавалку речи, она не нужна здесь. Свет, включающийся по хлопку, описан ещё в Радио-80х, но я так не хотел делать. Получилось своеобразное handsfree, когда руки заняты. Подробности — дальше.

Аппаратная часть.


Была в наличии плата с Atmega32 с кварцем и периферией SEM0007M-32A и россыпь электроники.

image

Нашёлся микрофончик и операционный усилитель. Для выхода – транзистор в sot32 корпусе на плате, там же реле на 7 Ампер. Всё собрано упихано в коробочку для визиток, реле запараллелено с выключателем, микрофон спрятан под розеткой. Схема банальна, я её даже не рисовал. Используется только один аналоговый вход и один дискретный выход МК. Плата SEM избыточна, но пока пусть так будет.

image
Плата и неприбранные провода. Потом переделал аккуратнее.

image
Сам выключатель, микрофон не виден под демонтированной розеткой.

Поиски алгоритма.


Цель: датчик должен реагировать на слово, например «свет!» при минимуме кода.
Задача: выявить командное слово на фоне возможного шума, стуков, щелчков этим же выключателем. То есть просто амплитудный анализ не подходит, а спектральный анализ показал, что гармоник в слове слишком много и они конечно изменяются. Поэтому надо было искать простое решение, но с приемлемой помехозащитой. Можно сделать несколько временно-частотных фильтров и сравнение с образцом слова, но заниматься распознаванием ни к чему. Решено анализировать наличие только гласного звука, например звука «Е» или «Е».

image
Звук «Е». Видно много гармоник, из-за этого анализ затруднён.

image
Звук «А». Спектр выглядит чище, есть главная частота.

Программная часть


Для того, чтобы узнать спектральные составляющие сигнала, можно использовать цифровые фильтры. В Интернете есть неплохая программа для построения цифровых КИХ и БИХ фильтров и вычисления их коэффициентов — там наглядно и код на Си генерируется автоматически.

Но я от цифровых фильтров отказался
Для приемлемой фильтрации (4 и более порядка) получались много коэффициентов, да ещё и float. Примерно вот так, плюс все расчёты фильтра во float:

float ACoef[NCoef+1] = {
        0.00000347268864059354,
        0.00000000000000000000,
        -0.00001389075456237415,
        0.00000000000000000000,
        0.00002083613184356122,
        0.00000000000000000000,
        -0.00001389075456237415,
        0.00000000000000000000,
        0.00000347268864059354
    };

    float BCoef[NCoef+1] = {
        1.00000000000000000000,
        -7.09708794063733790000,
        22.77454294680684300000,
        -43.03321836036351300000,
        52.29813665034108500000,
        -41.84199842886619100000,
        21.53121088556695300000,
        -6.52398963450972500000,
        0.89383378261285684000
    };

Микроконтроллер, возможно и справился бы, но с отладкой были бы проблемы – пододвинуть границы фильтра нелегко – это новые коэффициенты рассчитывать.

После некоторых поисков – остановился на одночастотном Фурье-преобразовании онлайн. То есть классическое дискретное Фурье-преобразование, выполняемое по приходу каждого отсчёта сигнала с частотой дискретизации (1600 Гц), прохода по частотам нет, частота одна, поэтому её легко настроить по RS-232 при наладке. В итоге анализ был сделан для частоты 128 Гц.

Вследствие коротких сэмплов (блоков) и прямоугольного окна — разрешение по частоте получается низким, что даёт избирательную чувствительность в диапазоне 114…140 Гц, а это тот П-фильтр, который и хотелось получить.

Сначала надо понять, где кричат начинается сигнал голосовой команды. Для этого сначала вычисляется нулевой уровень сигнала, через экспоненциальное сглаживание со сглаживающей константой 1/64. Код приведён ниже.

Часть кода таймера для обработки сигнала. Частота таймера 1600 Гц
Сигнал нормализуется к среднему. Для определения уровня интенсивности звука абсолютные значения сигнала также усредняются с константой 1/16, для ВЧ-фильтрации от отдельных полуволн сигнала (это аналог RMS, но проще в вычислениях). Превышение этого уровня над порогом является началом голосовой команды, и начинается последовательный анализ 5-ти блоков по 135 отсчётов (84,3 мс).

// Timer 0 output compare interrupt service routine
interrupt [TIM0_COMP] void timer0_comp_isr(void)
{

    a =  adc_data[0]  << 2 ;   // считывание с АЦП и умножение на 4 для улучшения точности.
    a0 = (a0*63 + a+ 63) >> 6;    // экспон. сглаживание для "0".  сход до 10% за 150 отсчётов 
    ae =  (int)(a - a0);      //  
    a = ae;   // теперь это нормализованное значение к среднему. 
    ae = abs(ae);
    if (ae < 32) {  // обнуление ошибки при целочисленном усреднении
      ae = 0;
    };
    
    d = (int)((15 * (long int) d + ae + 15) >> 4);  // средний эксп. уровень   // сход до 10% за 35 отсчётов
    
    if (d > 100)  { //превышение порога уровнем сигнала
        if (snd == 0) {  Yz=0;   snd++; } // начинается первый блок
       PORTB.1 = 1;  // зажигается светодиод индикатор превышения порога
    };

.....

На рисунке ниже показан сигнал, уровень сигнала, порог срабатывания и 5 блоков.

image

Защита от помех


На блоки сигнал разбивается для защиты от импульса – щелчка или стука. У импульса, как известно, равномерная АЧХ, то есть в любой частотной полосе будет ненулевой результат и вероятно, выше порога. Но волос длин, да ум импульс короток. То есть в следующем блоке импульса уже не будет, значит и уровень в частотной полосе будет ниже порога. Одновременно с этим преимуществом, короткие блоки дают низкое разрешение по частоте. Поэтому некоторые частотные отличия в сигнале всё равно попадают в выбранную частотную линию.

Частотное преобразование


В каждом блоке выполняется одночастотное Фурье – преобразование для одной частоты f.

Традиционно, для ускорения вычислений функции sin и cos сделаны табличными и масштабированы до -127..+127.
Индекс ps массива si(ps) вычисляется из аргумента sin(2 * π * f * t / T), конечно с закольцовкой внутри одного периода. Индекс pc для cos(2 * π * f * t / T) просто сдвинут на 12 позиций вперёд в этом же массиве si.

Результат Y — уровень спектральной линии получается как сумма абсолютных значений реальной и мнимой части за время одного блока.
Так-то
по-правильному надо делать сумму квадратов, и корень, но это жуть для 8-разрядного МК.

В том же таймере:
    a_si =   (long int) (a * si[ps]) >> 4;  // a*sin 
    a_co =  (long int) (a * si[pc]) >> 4; // a*cos
    Ysi = Ysi + a_si  ;    //сумма 
    Yco = Yco + a_co;   
    Y = (labs(Ysi) + labs(Yco)) >> 7;    //  деление на 128  для помещения в int и передачи по rs-232.

В конце каждого блока Y сравнивается с порогом, подсчитывается количество блоков с превышением порога – сработавших блоков. После экспериментов выяснилось, что минимальное количество сработавших блоков это 3 из 5-ти.

image
Пример спектральной интенсивности в блоках при голосовой команде. Команда прошла.

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

Время выполнения вычислений примерно 1600 тактов, таймер вызывается каждые 9000 тактов, так что загруженность МК невысока — есть место для дальнейших экспериментов с распознаванием. Или можно делать законченное решение меньших размеров и на слабом МК.

Контроль правильности алгоритмов вёлся посредством обмена по RS-232 необходимыми переменными (лог) с программкой на VBasic. Частота f и пороги хранятся в eeprom.

В итоге: датчик оказался очень удобен, реагирует на слова с «А», например «Вааау», «Тааам», «Лаайт»,«Мяаау», «Yao-Yao». Громкость — обычная для человеческого разговора. Слово «Свеет» упорно отказывается слушать. Щелчки, стуки дверьми, шаги, льющуюся воду игнорирует. Теперь можно ходить с полными руками чашек и тарелок)).
Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 44

    +1
    а на телевизор\радио реагирует? не будет мигать на фразу «папа! зачем тут эта штука прикручена!»?
      0
      Только если разговаривать в непосредственной близости и с эстонским акцентом. длительность должна быть более 250 мс, это растянутая гласная.
        +1
        (Капризным голосом)
        — Ну па-апа-а!..
        0
        Главное в такой ситуации — не быть эпилептиком. А то и скончаться недолго.
        +1
        Ноги наверняка свободны — можно их научить ВКЛ/ВЫКЛ делать.
          0
          Выключатель на уровне уха. Если я научусь с полной чашкой кофе и бутербродами в руках делать это ногами — напишу в спортивный паблик))
          0

          Всё-таки учитывая, что Вы именно идёте, то есть, двигаясь, датчик движения с задержкой сработал бы чище и лучше. И не надо так орать!

            0
            ДД точно удобнее, проще и дешевле. Главное на нём таймаут побольше выкрутить — у меня 7 минут.
              0
              не-не, есть во-первых день, когда светло. есть ситуации, когда включать не надо. Есть ситуации требующие длительного наличия света. Орать не приходится.
                0
                Даже у самых дешевых ДД есть датчик освещенности.
                есть ситуации, когда включать не надо
                — это самая большая проблема. Мне пришлось поверх тупого датчика ДД навернуть расписание, чтобы ночью электричество для основного освещения кухни в принципе отключалось. Остается только ночник на 2 диодных ватта, который горит всегда.
                Есть ситуации требующие длительного наличия света
                — а вот с этим вообще никаких проблем. Нужно лишь шевельнуться хотя бы раз за 7 минут.

                Лучший интерфейс — это отсутствие интерфейса. Надо стремиться, чтобы всё само работало, без участия человека.
            0
            Я бы добавил ключевое слово обращения к прибору, Киви свет.
              0
              не на atmega, тут с трудом прокатило детектирование гласной А
                0
                Тогда уж как правильно заметили, надоть сервер…
                  0
                  даже 40-ватный сервер, работающий на распознавание речи, может съесть больше энергии, чем экономия на постоянном выключении света

                  ну или сравнимо.

                  p.s. правда если делать на базе какого-нибудь android, там можно до 10ват догнать потребление, гугл и яндекс работают непокладая рук.
                    0
                    это если вы его добавляете к уже существующим. А если он у вас и так не выключался (домашний NAS или просто комп) — то там задача распознавания на энергопотреблении практически не сказывается.
                      0
                      Распознавание онлайн кушает процессорные ресурсы.

                      У меня есть смутное подозрение, что смартфоны в составе держат какой то аппаратный чип для ускорения этих задач, либо умудряются использовать gpu, так как они умудряются ok google отслеживать без нагрузки.
                0
                Если вдруг станет много приборов, у них же микрофоны в разных местах будут. и остальные не будут слышать. этого достаточно.
                Если понадобится, адресацию приборов можно сделать тоже гласной, последовательный протокол. И ходить с одним микрофоном-клипсой. И говорить «ИАИ», «АИО», короче как R2D2
                +1

                На будущее: вместо "одночастотного преобразования фурье" в таких приложениях часто используют алгоритм Гёрцеля — меньше работы.


                Ну а исходную задачу (точнее, подобную ей для прихожей) я для себя решил иначе: маломощный светильник с PIR-сенсором — достаточно, чтобы войти, не спотыкаясь. А дальше уже можно включить большой свет. В вашем случае, наверно, будет не оптимально, но приемлемо: выключил большой свет (включился дежурный), взял тарелку и пошёл. Зато шуметь не надо (важно, когда не один дома)

                  0
                  Спасибо за Гёрцеля, посмотрю что это.
                  маломощный светильник (тоже самодельный) с датчиком внешнего света есть и работает, но здесь не тот случай. Выключить большой свет — надо выйти из кухни на 1,5 метра. Потом возвращаться что ли? ))
                  0
                  Ваша идея отличная, но только как первый этап.
                  У меня так:
                  Простой минимальный анализ звука на наличие в нём слов.
                  Если слова есть — попытка понять, есть ли в нём Ключевая Стартовая Фраза.
                  Если решаем что может быть есть — отправка на локальный сервер, где крутится полноценная распознавалка.
                  Если сервер говорит — что там ключевая стартовая фраза.
                  Проигрывание приветствия и отправка всего остального потока в рантайме.
                    0
                    Круто у вас, алгоритмы или описание есть?
                    Здесь просто незачем…
                      0
                      Да ничего умного.
                      Просто анализ звука, если тишина — ничего не делаем.
                      Если звук есть и по длинне подходит — передаем на сервер.
                      В вышмате я не очень, поэтому до преобразования фурье и прочих вещей не дошел…
                        0
                        Это понятно, на сервере что? какой алгоритм на сервере, чей?
                          0
                          а на сервере можно перекидывать в амазон или гугл
                            0
                            У Яндекса тоже не плохая распознавалка.
                            Если вас, конечно, не смущает отдавать прослушку вашего дома каким-то левым чувакам.
                              0
                              Слова амазон, гугл и сервер мне ни о чём ни говорят. Под алгоритмом я понимаю статью с тех. описанием, например в научном/математическом журнале. К сожалению это большая редкость.
                                0
                                полагаю алгоритмы тут вторичны, в опенсорсе вроде гуляют неплохие, дороже обойдутся обученные нейроные сети
                              0
                              Самописный сервер на базе Sphinx. Вообще, есть готовые решения в инете, но они устарели и не поддерживаются. Пришлось свой маленький велосипедик сделать.
                                +1
                                Я наверно на днях напишу коротенькую статейку на тему этого сервера и выложу его на гитхаб
                        0
                        Когда у меня стояла такая проблема, то я просто свои выключатели заменил на подобные:

                        (выпуклый, с краёв тонкий и хорошо заметная клавиша), и повернул их на 90° так, чтоб когда ты заходил в помещение, то, проводя плечом по нему по ходу движения, ты включал свет, а выходя — соответственно наоборот. Даже если вы уже установили умный дом и подключили все выключатели к нему и оно само включает/выключает везде свет, поверьте, такой способ установки выключателя самый удобный. Особенно после того, как я вспомнил, как я в детстве прыгал до выключателя пытаясь попасть в верхний его край.
                          0
                          Те, кто делают умный дом как правило сразу и диммирование фигачат. Соответственно такой выключатель уже и не может использоваться.
                            0
                            если там димер на 220в вкорячен в выключатель, это не особо умный ход )
                              0
                              Зачем в выключатель диммер засовывать?
                              Одно из преиущество умного освещения — нет никакой необходимости таскать по всему помещению 220.
                                0
                                я думал вы как раз про вариант димера под лампы накаливания. Некоторые до сих пор их ставят.
                                  0
                                  У меня освещене 220 вольт. Но в выключателе у меня 5вольт. И вообще 220 только под крышей к лампе идет.
                            0
                            Я не могу сильно менять электрику в не своей квартире. Выключатель строенный, 3 в 1. в узкую клавишу, которая выше плеча на 12 см, попасть сложно в темноте.
                              0
                              Можно вообще его в пол зафигачить и ногой нажимать, главное, гальваническкую развязку для безопасности приделать.
                              0
                              А можете подсказать более подробно про микрофон? С какого расстояния ловит звук? Я хочу похожее подключить к Raspberry Pi и пытаюсь понять какой микрофон нужен мне, чтобы звук улавливался по квартире.
                                0
                                микрофон — это маленький динамик, диаметр 25 мм, они были тетрисах. Ловит хорошо, резкий звук голосом с двух метров. я программно делал пороги, большая чувствительность не нужна.
                                  0
                                  Напрямую не подойдёт почти никакой, только через усилитель. ОУ стоил 17 рублей.
                                  0
                                  По ссылке на программу построения цифровых фильтров пишет что:
                                  «You do not have permission to access this page or file
                                  Data files must be stored on the same site they are linked from.»
                                    0
                                    Ссылку подправил, спасибо.
                                    0
                                    А какие есть коммерческие микрофонные\динамиковые аппаратные решения для построения умного дома? Интересует как раз модули для улавливания голосовых команд с возможностью интегрировать их в том числе в свои проекты? Всякие Алексы и Алисы не в счет. Как критерий отбора — Наличие ПО и некоторого Plug&Play механизма.
                                      0
                                      в смысле — на локальном сервере, а не на облачном? (а иначе можно запилить на Алексе. Год назад коллега демонстрировал прототип — к фрагменту аудио добавляется «ОК Алекса ИмяСкилла », а на ее сервере принимается вызов распознанной команды из скилла)

                                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                    Самое читаемое