Непрерывная передача данных с АЦП на ЦАП Arduino Nano

Столкнулся с проблемой, есть плата Arduino Nano ATmega 328, Микрофонный усилитель MAX9814 подключенный к аналоговому пину, есть ЦАП MCP4921 12 битный подключенный к SPI портам.
Задача в том чтобы непрерывно производить АЦП сигнала с микрофона и передавать непрерывно на ЦАП через SPI. АЦП произвожу через analogRead() и передача по SPI через библиотеку для ардуино. Тк как цап 12 битный за один такт работы передаю по 2 байта информации. Проблема в том что между тактами передачи происходит очень большая пауза, как на фото сверху синхронизация, снизу данные. Пробовал менять все параметры тактовую частоту, дискретизацию SPI, однако пауза есть всегда, приведу пример кода, вариантов пробовал очень много, подскажите можно ли осуществить непрерывную передачу с несущественными паузами и как это сделать.


#define MicPin A0 //22

void setup() {
  Serial.begin(9600);
  /*DEFAULT: стандартное опорное напряжение 5 В (на платформах с напряжением питания 5 В) или 3.3 В (на платформах с напряжением питания 3.3 В)
  EXTERNAL: внешний источник опорного напряжения, подключенный к выводу AREF*/
  analogReference(DEFAULT);
  pinMode(SS, OUTPUT);
  digitalWrite(SS, HIGH); 
  pinMode(MicPin,INPUT);
  //SPI.beginTransaction(SPISettings(SPI_CLOCK_DIV8, MSBFIRST, SPI_MODE0)); //20000000
  SPI.begin();
  send_data();
  /*
  digitalWrite(SS, LOW);
  digitalWrite(SCK, LOW);
  */
}

void send_data() {
  while(1){
    unsigned int digital_signal = analogRead(MicPin); // Получаем цифровой сигнал от 0 до 1023
    MCP4921_Send_data(digital_signal); //передаем сигнал в mcp4921
  }
}

void MCP4921_Send_data(unsigned int value)
{
  byte data;
  PORTB &=~ (1 << 2);
  data = highByte(value);
  data = B00001111 & data;
  data = B00110000 | data;
  SPI.transfer (data);
  data = lowByte(value);
  SPI.transfer (data);
  PORTB |= (1 << 2);
}

перепиши с analogread на прерывания
а лучше сразу возьми процессор под задачу вместо этого мазохизма

То есть вполне вероятно что ограничения процессора не позволят выполнять задачу непрерывно?

больше 10кгц не получится. Сколько тебе надо7

Хотелось бы получить приемлемую частоту для передачи голоса, на данный момент даже 10кгц не получается достичь, максимум ~4 с паузами

10 получится. см ответ ркит.

И далеко ты собрался его передавать?

Для начала хотелось бы научиться передать с микрофона на ЦАП в нормальном качестве

А потом брать другой процессор и полностью переделывать уже под другую задачу?

Да, это единственная задача которой хотелось бы достичь на этом процессоре. Это больше экспериментальный проект

Ну валяй. Как - я написал. Голос будет звучать нормально, если соблюсти всю матчасть.

Можете пожалуйста какие-то референсы привести? Искал информацию по данной теме, но во всех местах все по-разному:) Просто чтобы было понятно куда копать

даташит на амтегу328, раздел про ацп

1 лайк

На амперке был проект (по крайней мере видел в видеоролике на ютуб) самодельный телефон.

@artem_alish, присоединюсь к ранее озвученному мнению, что Вы выбрали неподходящий контроллер.
Функция analogRead() занимает на AVR около 112 мкс. Т.е. только АЦП (без дальнейшего ЦАП) уже будет иметь частоту порядка 8 кГц, так что по теореме Котельникова-Шеннона-Найквиста верхняя передаваемая частота не будет превышать 4 кГц, что для передачи голоса уже на пределе.
Необходимость ЦАП еще больше снизит эту частоту.
Можно, конечно, по совету rkit вместо analogRead() написать свой код на прерываниях, но вряд ли это серьезно улучшит ситуацию. Еще можно уменьшить время АЦП, снизив разрядность с 10 до 8 разрядов.
Но все это много работы с неочевидным результатом.
Лучше сразу ориентируйтесь на Arduino Due либо на stm32. Помимо прочего, они имеют DMA, что позволит производить обмен с АЦП и ЦАП параллельно, а не поочередно.

Если хочется именно на AVR, можно использовать внешний АЦП (внешний ЦАП ведь все равно нужен), например MCP3008. И запас по скорости будет и с точки зрения программирования явно проще.

1 лайк

Может посмотришь на реальные голосовые кодеки, прежде чем нести такое?

При чем здесь вообще кодеки?
Физику не обманешь!

  1. Андриано! Ты же знаешь, что сев в лужу, Ркит замолкает.
  2. Штатный gsm- кодек жмёт в 9600 бод. Какое отношение это имеет к выборке, знает только наша “затычка от каждой бочки”. Жмёт он (gsm) штатный PCM 64 Kbit. PCM штатный это как раз 8КГц выборки по 8 бит.
    ;))
  3. Я точно уверен, что все это ты знаешь без меня. Я просто для истории и для иллюстрации… ;))

При чем здесь средства передачи голоса, работающие каждый день в каждом телефоне ровно на частоте захвата 8кГц? Ну не знаю.

А, ну да.
У нас же теперь не “средства передачи” проектируют с учетом физики, а, наоборот, физику каждый день подстраивают под каждый телефон.

PS. Опять же, между “микрофоном” (диапазон частот 20-20000Гц) и “телефоном” (диапазон частот 300-4000Гц) есть некоторая разница. Поэтому и исходить нужно из физики для каждого конкретного процесса, а не из особенностей реализации аппаратуры для одного частного случая.