Скрыть объявление
На нашем форуме недоступен просмотр изображений для неавторизованных пользователей. Если Вы уже зарегистрированы на нашем форуме, то можете войти. Если у Вас еще нет аккаунта, мы будем рады, если Вы к нам присоединитесь. Зарегистрироваться Вы можете здесь.

Нужна помощь Работа с ADC (микрофоном)

Тема в разделе "ESP32 - все о железе", создана пользователем unreg, 26 апр 2019.

Метки:
  1. unreg

    unreg Новичок

    Сообщения:
    55
    Симпатии:
    0
    Доброго! Разбираюсь вот с этим примером ESP32 Voice Streamer - Hackster.io, и не могу понять как же все-таки работать с ADC... В статье автор говорит, что ADC принимает сигнал от 0-1v, поэтому нужен делитель, т.к. микрофон выдает от 0-2.25v. Почему ADC работает 0-1v, а не 0-3.3v? Как использовать флаг adc_atten_t ? Может им можно решить проблему без всяких делителей? Буду благодарен за объяснение "на пальцах" хотяб на моем примере:
    ESP32-wrover-b .Есть микрофон, подключен к GPIO36. на OUT выдает 60 mV-2.45v (реально по даташиту). Нужно потоком читать с него сигнал (пусть 12 bit). Все питается от 3.3v
    Если возможно - кусочек кода с пояснениями и схему хотя бы словами (нужен делитель или нет и почему). Спасибо!
     
  2. Юрий Ботов

    Юрий Ботов Moderator Команда форума

    Сообщения:
    1.037
    Симпатии:
    173
    По моему с АЦП вы в общем все правильно понимаете, а вот как работать с микрофоном - нет.
    Для начала внимательно посмотрите на даташит и ретранслируйте сюда что там написано: вы говорите что
    Это...
    - пиковое напряжение ноль - пик? Vpeak
    - пиковое напряжение пик - пик? V2peak = Vpeak*2
    - действующее значение напряжения? Vd = Vpeak*0.707
    - что то иное, китайское?
    Причем...
    - это измерено на максимуме АЧХ?
    - это измерено на краю частотного диапазона?
    - это среднее значение по диапазону?
    Неравномерность в в частотном диапазоне у дешевых микрофонов реально достигает 6 дб. (Китайцы в бытовухе мыслят иными понятиями нежели наши радисты, у китайцев на крохотном приемнике может быть наклейка "200Wt!!!" и указание в инструкции, что потребляемая мощность не превышает 17 Вт...)

    Разберитесь какая постоянная составляющая напряжения присутствует на выходе микрофона. Обычно конечно ноль, но не факт. Есть микрофоны которые питаются по сигнальному проводу, некоторые китайцы на активных (с усилителем) микрофонах не ставят на выходе конденсатор - "все равно на усилителе он есть"... а на АЦП его нет. Не забывайте что вам нужно будет "передвинуть" эту постоянную составляющую напряжения на середину диапазона АЦП, так что от пары резисторов точно никуда не денетесь.
     
  3. unreg

    unreg Новичок

    Сообщения:
    55
    Симпатии:
    0
    Спасибо за внимание к вопросу!
    Вот даташит на микрофон: https://datasheets.maximintegrated.com/en/ds/MAX9814.pdf
    Поскольку ориентровался на приведенную выше статью, обратил внимание вот на эту инфу:
    MICOUT High Output Voltage - 2.45V и MICOUT Low Output Voltage - 3mV (в топе указал неверно)
    Vpeak вообще не нашел, но нашел цифру 0.707 :)
    На счет постоянной сигнала с микрофона это та постоянная относительно которой меняется уровень аналогового сигнала?
    Где найти постоянную составляющую и самое главное - как применить эти знания относительно моей задачи?
    Прада в теме с микрофонами у меня большой пробел.
     
  4. Юрий Ботов

    Юрий Ботов Moderator Команда форума

    Сообщения:
    1.037
    Симпатии:
    173
    Я правильно понимаю что вас есть некий динамический микрофон, в который встроена эта микросхема и вы хотите в него же встроить wifi?
    У вас есть уже готовая плата микрофонного усилителя или вы ее будете делать самостоятельно?

    по Даташиту: 2.45 это пик-пик - абсолютный неискаженный максимум. Это обусловлено тем что постоянная составляющая на выходе микросхемы = 1.23 вольта.
    Так что максмиум ноль-пик = 1.225 В, а действующее значение примерно 0.866 В.

    Получается интересная вещь: реальный диапазон измерений АЦП esp32 в режиме ADC_ATTEN_DB_11 как раз "150 to 2450mV". (Analog to Digital Converter — ESP-IDF Programming Guide v4.0-dev-402-ga20d02b7f documentation)

    То есть, с определенной долей везения можно подключить вход АЦП непосредственно НА ВЫХОД микросхемы MICOUT, там уже присутствует нужное смещение. Не после конденсатора, а именно на выход микросхемы (можно выпаять конденсатор и вместо него поставить такой-же по габаритам резистор 10-100 Ом) . И все само-собой заработает. Понаблюдав за результатами работы возможно вы обнаружите что на сильном сигнале (микрофон близко ко рту) есть искажения. Но и тут возможно не потребуется особого согласования, поскольку у max9814 есть вход GAIN изменением напряжения на котором можно регулировать усиление. Попробуйте посадить его на "землю". Если уж и это не поможет - тогда придется городить внешний аттенюатор и цепь смещения по постоянному току...
     
  5. Юрий Ботов

    Юрий Ботов Moderator Команда форума

    Сообщения:
    1.037
    Симпатии:
    173
    У вышеописанного способа есть и недостаток: Реально вы теряете 1 бит АЦП: 1024 при таком подключении подразумевает 3.9 вольта, которые на самом деле подавать на вход нельзя. С внешним аттенюатором и цепями смещения можно избавиться от этой проблемы... Но сначала определитесь насколько она для вас страшна.
     
  6. unreg

    unreg Новичок

    Сообщения:
    55
    Симпатии:
    0
    У меня микрофон уже сидит на этой плате. ссылка али. А задача пока разобраться с ацп, пример с микрофоном интересен тем что в последствии собираюсь делать анализатор спектра только от линейного выхода. Попробую приготовить по Вашему рецепту ). raw буду писать на внешнюю флэшку, ну и попробую проиграть что получилось. Спасибо!
     
  7. Алексей.

    Алексей. Авторитетный участник сообщества

    Сообщения:
    532
    Симпатии:
    60
    Тема интересная, подпишусь.
    Анализатор мне не требовался, а вот sip звонилка для встраивания в СКУД пригодилась бы.
     
  8. Юрий Ботов

    Юрий Ботов Moderator Команда форума

    Сообщения:
    1.037
    Симпатии:
    173
    Для начала "классический" пример: espressif/esp-idf
    Тут есть все включая встроенный аттенюатор (правда он устанавливается в 0 дБ - вам надо 11 дБ)
     
  9. nikolz

    nikolz Гуру

    Сообщения:
    3.971
    Симпатии:
    426
    В описании по Вашей ссылке написано:
    The chip at the heart of this amp is the MAX9814, and has a few options you can configure with the breakout. The default 'max gain' is 60dB, but can be set to 40dB or 50dB by jumpering the Gain pin to VCC or ground. You can also change the Attack/Release ratio, from the default 1:4000 to 1:2000 or 1:500. The ouput from the amp is about 2Vpp max on a 1.25V DC bias, so it can be easily used with any Analog/Digital converter that is up to 3.3V input. If you want to pipe it into a Line Input, just use a 1-100uF blocking capacitor in series (100uF sounds best).
    Чип в основе этого усилителя-MAX9814 и имеет несколько параметров, которые вы можете настроить.
    По умолчанию максимальное увеличение составляет 60 дБ, но может быть установлен на 40 дБ и 50 дБ при замыкании получить PIN-код к VCC и землей. Вы также можете изменить соотношение атаки/выпуска с 1:4000 по умолчанию до 1:2000 или 1:500.
    Выход из усилителя составляет около 2vpp max при смещении постоянного тока 1,25 В, поэтому его можно легко использовать с любым аналого-цифровым преобразователем до 3,3 В.
    Если вы хотите передать его в линейный вход, просто используйте конденсатор 1-100uF последовательно (100uF звучит лучше всего).
    -------------------------------
    вот здесь читаем:
    Analog to Digital Converter — ESP-IDF Programming Guide v4.0-dev-402-ga20d02b7f documentation
    Полномасштабное напряжение АЦП по умолчанию составляет 1,1 В. для считывания более высоких напряжений (до максимального напряжения pin, обычно 3,3 в) требуется настройка >0dB затухания сигнала для этого канала АЦП.
    --------------
    для диапазона до 3.3 вольт надо использовать функцию:
    esp_err_t adc1_config_channel_atten(канал adc1_channel_t, adc_atten_t atten )
    Установите ослабление определенного канала на ADC1 и настройте связанный с ним GPIO pin mux.
    Для любого канала эта функция должна быть вызвана до первого вызова adc1_get_raw () для этого канала.
    Эта функция может вызываться несколько раз для настройки нескольких каналов АЦП одновременно. затем можно вызвать adc1_get_raw () для любого настроенного канала.
    Когда VDD_A 3,3 в:
    • 0dB амортизатор (ADC_ATTEN_DB_0) дает полномасштабное напряжение 1.1 V
    • 2.5 DB амортизация (ADC_ATTEN_DB_2_5) дает полномасштабное напряжение 1.5 V
    • 6dB (ADC_ATTEN_DB_6) дает полномасштабное напряжение 2.2 V
    • 11dB (ADC_ATTEN_DB_11) дает полномасштабное напряжение 3.9 V
     
  10. unreg

    unreg Новичок

    Сообщения:
    55
    Симпатии:
    0
    Вроде что-то получилось. Видно, что входящий сигнал с микрофона раскладывается по частотам, и четко видна реакция на низ, средние и высокие. Выделить конкретную "чистую" частоту (например 1KHz) не получается. Как-то грязновато выходит. Сравнивал со смартфоном. Скетч из статьи в топе немного подправил под использование OLED от Adafruit, ну и экран у меня оказался не ssd1306, а SH1106 (алиэкспресс бл). Микрофон на max9814 подключен: OUT -> PIN VP (GPIO36), OLED: SDA->GPIO26, SCL->GPIO25.
    Скетч:
    Код (C):
    1. #include <Adafruit_GFX.h>
    2. #include <Adafruit_SSD1306.h>
    3. #include <Adafruit_SH1106.h>
    4. #include <splash.h>
    5.  
    6.  
    7. #include <Wire.h>
    8. #include "arduinoFFT.h" // Standard Arduino FFT library
    9. // https://github.com/kosme/arduinoFFT, in IDE, Sketch, Include Library, Manage Library, then search for FFT
    10. arduinoFFT FFT = arduinoFFT();
    11.                              
    12. #define OLED_SDA 26
    13. #define OLED_SCL 25      
    14.  
    15. Adafruit_SH1106 display(OLED_SDA, OLED_SCL);
    16.  
    17.  
    18. #define SAMPLES 512              // Must be a power of 2
    19. #define SAMPLING_FREQUENCY 40000 // Hz, must be 40000 or less due to ADC conversion time. Determines maximum frequency that can be analysed by the FFT Fmax=sampleF/2.
    20. #define amplitude 200            // Depending on your audio source level, you may need to increase this value
    21. unsigned int sampling_period_us;
    22. unsigned long microseconds;
    23. byte peak[] = { 0,0,0,0,0,0,0 };
    24. double vReal[SAMPLES];
    25. double vImag[SAMPLES];
    26. unsigned long newTime, oldTime;
    27.  
    28. bool save = true;
    29.  
    30. void setup() {
    31.  
    32.     Serial.begin(115200);
    33.  
    34.     display.begin(SH1106_SWITCHCAPVCC, 0x3C);
    35.  
    36.     display.clearDisplay(); // Adjust to suit or remove
    37.     display.setTextSize(1);
    38.     display.setTextColor(WHITE);
    39.     sampling_period_us = round(1000000 * (1.0 / SAMPLING_FREQUENCY));
    40. }
    41.  
    42. void loop() {
    43.     display.clearDisplay();
    44.     display.setCursor(0, 0);
    45.     display.println(".1 .2 .5 1K 2K 4K 8K");
    46.  
    47.         for (int i = 0; i < SAMPLES; i++) {
    48.             newTime = micros() - oldTime;
    49.             oldTime = newTime;
    50.             vReal[i] = analogRead(A0); // A conversion takes about 1uS on an ESP32
    51.             vImag[i] = 0;
    52.  
    53.             while (micros() < (newTime + sampling_period_us)) { /* do nothing to wait */ }
    54.         }
    55.  
    56.     FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
    57.     FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD);
    58.     FFT.ComplexToMagnitude(vReal, vImag, SAMPLES);
    59.     for (int i = 2; i < (SAMPLES / 2); i++) { // Don't use sample 0 and only first SAMPLES/2 are usable. Each array eleement represents a frequency and its value the amplitude.
    60.         if (vReal[i] > 2000) { // Add a crude noise filter, 10 x amplitude or more
    61.  
    62.             if (i <= 2)             displayBand(0, (int)vReal[i] / amplitude); // 125Hz
    63.             if (i >3 && i <= 5)   displayBand(1, (int)vReal[i] / amplitude); // 250Hz
    64.             if (i >5 && i <= 7)   displayBand(2, (int)vReal[i] / amplitude); // 500Hz
    65.             if (i >7 && i <= 15)  displayBand(3, (int)vReal[i] / amplitude); // 1000Hz
    66.             if (i >15 && i <= 30)  displayBand(4, (int)vReal[i] / amplitude); // 2000Hz
    67.             if (i >30 && i <= 53)  displayBand(5, (int)vReal[i] / amplitude); // 4000Hz
    68.             if (i >53 && i <= 200) displayBand(6, (int)vReal[i] / amplitude); // 8000Hz
    69.             if (i >200) displayBand(7, (int)vReal[i] / amplitude); // 16000Hz
    70.                                                                  //  Serial.println(vReal[i]);
    71.                                                                  
    72.         }
    73.         for (byte band = 0; band <= 6; band++) drawHorizontalLine(18 * band, 64 - peak[band], 14);//  display.drawHorizontalLine(18 * band, 64 - peak[band], 14);
    74.     }
    75.     if (millis() % 4 == 0) { for (byte band = 0; band <= 6; band++) { if (peak[band] > 0) peak[band] -= 1; } } // Decay the peak
    76.  
    77.     display.display();
    78.  
    79. }
    80.  
    81. void displayBand(int band, int dsize)
    82. {
    83.     int dmax = 50;
    84.     if (dsize > dmax) dsize = dmax;
    85.     if (band == 7) drawHorizontalLine(18 * 6, 0, 14);
    86.     for (int s = 0; s <= dsize; s = s + 2)
    87. { drawHorizontalLine(18 * band, 64 - s, 14); }
    88.     if (dsize > peak[band]) { peak[band] = dsize; }
    89. }
    90.  
    91. void drawHorizontalLine(int16_t x, int16_t y, int16_t l)
    92. {
    93.     display.drawLine(x, y, x + l, y, WHITE);
    94. }
     
  11. nikolz

    nikolz Гуру

    Сообщения:
    3.971
    Симпатии:
    426
    чистой частоты в нестационарном сигнале, каким является речь, не существует.
    чистая частота лишь у генератора синусоиды на бесконечном интервале.
     
  12. unreg

    unreg Новичок

    Сообщения:
    55
    Симпатии:
    0
    nikolz, да я это понимаю конечно. генерил звук со смарта в 1 кгц и анализатор показыввал 1кгц и 2кгц, все рстальные около нуля. жаль нету генератора, наверное можно было бы откалиьровать код и получить эталон. сейчас сложно судить о качестве разложения сигнала.
     
  13. nikolz

    nikolz Гуру

    Сообщения:
    3.971
    Симпатии:
    426
    качество разложение сигнала определяется
    стабильностью частоты дискретизации, числом отсчетов и используемым окном.
    и определяется этими параметрами однозначно.
    Но есть еще методическая погрешность определения амплитуды гармоники, которая составляет примерно 12% и не зависит от этих параметров.
     
  14. unreg

    unreg Новичок

    Сообщения:
    55
    Симпатии:
    0
    это для меня темный лес на текущий момент, пытабсь разобраться. если правильно понимаю, для определения частоты необходимо учитывать много факторов вплоть до тактов процессора. + погрешность не маленькая. Это не совсем то что нужно для конечной задачи. Выйти хотя бы на явное выделение частоты процентов в 50. Сейчас готовлю еще вопрос. Пытаюсь записать то что идет с микрофона. Новая тема
     

Поделиться этой страницей