Написать парсинг аудио-сигнала проверки времени.

Тема в разделе "Arduino & Shields", создана пользователем Ariadna-on-Line, 23 май 2024.

  1. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Всем известны "Передаём сигнал проверки времени (СПВ). Начало шестого сигнала соответствует...". Ну и шесть пиков. Надо чтобы начало 6-го пика сбросило в ноль счетчики секунд и минут. А его длительность - выставила текущий час (опционально). Но для этого надо сначала убедиться что это именно СПВ, и именно шестой пик. Логично делать это по частоте тона и длительностям пиков и пауз. Выделить сигнал пиков (1000Гц) - не трудно преобразованием Герцеля. Соответственно время начала и конца пика и паузы. Надо сначала пять раз убедиться, что имеем правильные времена, и только после этого начало шестого сигнала принимать за истину. Нет тут ничего сверхумного, только логика. Но на эту логику у меня не хватает фантазии. Может у кого из участников есть готовое решение. С уважением.
    Вот здесь две рабочие лошадки алгоритма - получение времён начала и конца ПИКА,
    (то бишь наоборот - конца и начала паузы))))). Все остальное должно делаться на этих временах. Длительность ПИка - 100мС, паузы - 900мС. Длительность 6-го ПИКА зависит от часа - Тмс = 100мс + 20мс * Nчаса.
    boolean Flag1 = false;
    boolean Flag2 = false;
    //==================================
    void loop() {

    if (Goertz == true) { // Разрешаем искать сигнал проверки времени (СПВ)
    ***********
    Mag = TONE.Mag(Samples, numSampl); // Получаем значение сигнала 1000 Гц
    //---------------------------------------------------
    if ((Mag > MinMag && Mag < MaxMag) && (Flag1 == false)) {
    Start1 = millis();
    Flag1 = true;
    prints("1");
    putx('\r');
    Silents = (Start1 - Stop1);
    }
    //---------------------------------------------------
    if ((Mag < MinMag) && (Flag1 == true)) {
    Stop1 = millis();
    Flag1 = false;
    prints("0");
    putx('\r');
    Tones = (Stop1 - Start1);
    }
    //---------------------------------------------------
    if ((Tones > 95) && (Tones < 105) && (Silents > 865) && (Silents < 875)) { // Проверяем длительность Пика и Паузы с точностью 10%
    prints_P(PSTR(" Tone OK "));
    putx('\r');

    Tones = 0;
    Silents = 0;
    }
    }
    }
    //==================================
    ПС. Есть рабочий ассемблерный код для PIC-процессора. Но в нем существенный изъян. Он проверяет интервал между началами пиков. Но не проверяет длительность пика и паузы (скважность). То есть любые 1-герцные посылки тона 1КГц для него - СПВ.
     

    Вложения:

    • PICs.png
      PICs.png
      Размер файла:
      46,5 КБ
      Просмотров:
      16
    Последнее редактирование: 24 май 2024
  2. parovoZZ

    parovoZZ Гуру

    честно говоря. не понял, в чём вопрос. Подсчёт пиков проще всего делать на машине состояний. Что-то пошло не по условию - сброс машины в начальное состояние.
     
  3. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Ну да. Как всегда забыл знак вопроса.
    Может у кого из участников есть готовое решение ?
     
  4. DetSimen

    DetSimen Гуру

    не майся дурью, 21 век на дворе. Синхронизируйся по атомным часам, это существенно проще в наше время.
     
    b707 и Asper Daffy нравится это.
  5. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Дык тут первое - суметь ! Моё хобби - впихивать толстое в узкое. Тема ветки - в том же русле.
    ПС. На одной из хай-тек выставок распиаренный робот супер-позорно облажался. Не смог элементарно вымыть полы, потому что пропал сигнал GPS (!!!). А моя бабушка всю жизнь это делала весьма успешно без GPS-ов, а порой и без электричества !?!
    ППС. В предложенном выше коде проверяются длительности Пиков и Пауз. Можно конечно проверять длительность ПИКА и Интервал между началами Пиков. Но пока - что есть.
     
    Последнее редактирование: 24 май 2024
  6. Ariadna-on-Line

    Ariadna-on-Line Гуру

    За неимением лучшего, нарисовал сам. Отладочные сообщения конечно можно удалить.
    Goertz == true;
    //==================================
    void loop() {
    if (Goertz == true) { // Разрешаем искать сигнал проверки времени (СПВ)
    *****************
    // Получаем магнитуду для заданной частоты (Freq)
    Mag = TONE.Mag(Samples, numSampl);
    //---------------------------------------------------
    if ((Mag < MinMag) && (Flag == true)) { // Детектируем конец ПИКА (сигнала)

    Stop = millis(); // Получили момент конца ПИКа
    Flag = false; // Отключаем детекцию конца ПИКа
    prints("0");
    putx('\r');
    Tones = (Stop1 - Start1); // Вычисляем длительность ПИКа
    //------------------
    if (Picks == 6) { // Если это был 6-й пик -

    itoa(Tones, ValStr, 10); // Конвертируем число в строку для вывода в
    ValStr[6] = 0; // терминал в 10-ричной системе.
    prints_P(PSTR(" Hour is - ")); // Вычисляем номер часа.
    prints(ValStr);
    putx('\r');

    Picks = 0; // Обнуляем счетчик пиков
    // Goertz = false; // Можно выходить из процедуры
    ------ ??????????????????????????????????????????????? // выход из функции
    }
    //------------------
    // if ((Tones > 380) && (Tones < 420) && (Silents > 3460) && (Silents < 3500)) {
    if ((Tones > 380) && (Tones < 420) && (Period > 3950) && (Period < 4050)) {
    Picks++;

    itoa(Picks, ValStr, 10); // Конвертируем число в строку для вывода в
    ValStr[6] = 0; // терминал в 10-ричной системе.
    prints_P(PSTR(" Tone "));
    prints(ValStr);
    putx('\r');

    }
    else {
    Picks = 0;
    }
    //------------------
    }
    //---------------------------------------------------
    if ((Mag > MinMag && Mag < MaxMag) && (Flag == false)) { // Детектируем начало ПИКа (сигнала)

    if (Picks == 6) { // Если здесь начало шестого сигнала -
    prints_P(PSTR(" ZERO OK ")); // - переход на процедуру обнуления
    putx('\r'); // счетчиков секунд и минут
    } //

    StartPrev = Start;
    Start = millis(); // Получили момент начала ПИКа
    Flag = true; // Отключили детекцию начала ПИКа
    prints("1");
    putx('\r');
    // Silents = (Start - Stop); // Вычислили длительность паузы
    Period = (Start - StartPrev);
    }
    //---------------------------------------------------
    }
    }
    //==================================
    Возникает вопрос :
    1. Как и можно ли выйти из функции не оставляя следов ? То бишь полностью освободив память, стек до следующего вызова. Что надо синтаксически правильно дописать в точке выхода (где вопросительные знаки) ?
    В Протеусе работает. Критика приветствуется. С уважением.
    ПС. Насчет значений времен (миллисекунд) в коде - Почему-то Диджиспарка в реале работает вчетверо быстрее чем задано в коде. Это не глюк Протеуса, это в реале так. Например Сериал в коде 9600, в реале 38400. Поэтому все цифры времен - умножены в 4 раза. Причину искать мне пока не было интереса.
     
    Последнее редактирование: 26 май 2024
  7. parovoZZ

    parovoZZ Гуру

    если ты освободишь полностью память или стек, то приложение рухнет.
     
  8. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Мне полностью не надо. Надо правильно ЗА ФУНКЦИЕЙ вычистить. Иначе после каждого вызова функции (6-го пика Маяка) - будет уменьшаться свободная дин. память (как оно там называется - утечка памяти ?) , или стек переполнится.
     
    Последнее редактирование: 26 май 2024
  9. parovoZZ

    parovoZZ Гуру

    это где такое написано? У Кернигана и Ричи?
     
  10. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Ну ладно. Будем надеяться что компилятор позаботится о порядке на вверенной территории.
    Конечно размещать в главном цикле процедуру, которая нужна от силы 10 секунд в час - глупо. Лучше она смотрится в роли подпрограммы (функции).
    //==================================
    void loop() {

    if (Goertz == true) { // Разрешаем искать сигнал проверки времени (СПВ)

    TimeCorrection();
    }
    }
    //==================================
    //==================================
    void TimeCorrection() { // Функция обнуления минут и секунд и
    // установки номера часа.
    while (Goertz) {
    **********
    // Получаем магнитуду для заданной частоты (Freq).
    Mag = TONE.Mag(Samples, numSampl);
    //---------------------------------------------------
    if ((Mag < MinMag) && (Flag == true)) { // Детектируем конец ПИКА (сигнала)

    Stop1 = millis(); // Получили момент конца ПИКа
    Flag = false; // Отключаем детекцию конца ПИКа
    prints("0");
    putx('\r');
    Tones = (Stop1 - Start1); // Вычисляем длительность ПИКа
    //------------------
    if (Picks == 6) { // Если это был 6-й пик -

    itoa(Tones, ValStr, 10); // Конвертируем число в строку для вывода в
    ValStr[6] = 0; // терминал в 10-ричной системе.
    prints_P(PSTR(" Hour is - ")); // Вычисляем номер часа.
    prints(ValStr);
    putx('\r');

    Picks = 0; // Обнуляем счетчик пиков
    Goertz = false; // Блокируем цикл процедуры
    return; // Выход
    }
    //------------------
    // if ((Tones > 380) && (Tones < 420) && (Silents > 3460) && (Silents < 3500)) {
    if ((Tones > 380) && (Tones < 420) && (Period > 3800) && (Period < 3900)) {
    Picks++;

    itoa(Picks, ValStr, 10); // Конвертируем число в строку для вывода в
    ValStr[6] = 0; // терминал в 10-ричной системе.
    prints_P(PSTR(" Tone "));
    prints(ValStr);
    putx('\r');
    }
    else {
    Picks = 0;
    }
    //------------------
    }
    //---------------------------------------------------
    if ((Mag > MinMag && Mag < MaxMag) && (Flag == false)) { // Детектируем начало ПИКа (сигнала)

    if (Picks == 6) { // Если здесь начало шестого сигнала -
    prints_P(PSTR(" ZERO OK ")); // - переход на процедуру обнуления
    putx('\r'); // счетчиков секунд и минут
    } //

    Start2 = Start1;
    Start1 = millis(); // Получили момент начала ПИКа
    Flag = true; // Отключили детекцию начала ПИКа
    prints("1");
    putx('\r');
    // Silents = (Start1 - Stop1); // Вычислили длительность паузы
    Period = (Start1 - Start2); // Вычислили длительность периода
    }
    }
    }
    //---------------------------------------------------
    Не мешало бы задействовать управление усилением канала. Коль уж задаром .
     
    Последнее редактирование: 27 май 2024
  11. parovoZZ

    parovoZZ Гуру

    не компилятор, а линковщик.
     
    Ariadna-on-Line нравится это.
  12. parovoZZ

    parovoZZ Гуру

    на си нет процедур

    в ардуино проектах никаких стандартов нет. А в действительно больших проектах архитектура проекта очень важна.

    сишный компилятор никак не следит за действиями программиста и сборщика мусора у него тоже нет. Поэтому читаем книжку и вникаем в простейшие азы.
     
    Ariadna-on-Line и Igor68 нравится это.