Глюки записи Ардуино Диктофона
- Войдите на сайт для отправки комментариев
Всем привет! Нашел интересный проект Ардуино микрофона: https://www.youtube.com/watch?v=WV5bLv1erxk
Скетч (Много мусора!):
/* Dmitry OSIPOV. http://www.youtube.com/user/d36073?feature=watch V.2 Arduino Audio Recorder VAS 20160903. ____________. Этот видео урок, продолжение предыдущего видео урока. Arduino Самый маленький диктофон The smallest Audio Recorder Лайфхак Своими руками https://www.youtube.com/watch?v=E9LKPFY3GGI _____________. Обновление: 1. Функция Активация по голосу (VAS). Запись начинается, как только сигнал, поступающий с микрофона, превышает определенный уровень. + Установка продолжительности записи. 2. Шумоподавление. EXTERNAL: внешний источник опорного напряжения, подключенный к выводу AREF. Желательно отдельный источник питания, к выводу AREF и AVCC, или DC/DC преобразователь питания B0505, или через конденсатор. _____________. SD-карту лучше класс 10 и выше. Питание от батареи или аккумулятора. Микрофон подключить к pin (A5). Внешний источник опорного напряжения, подключаем! к выводу AREF. _____________. Download - sketch V.2 Arduino Audio Recorder VAS 20160903. Библиотеку - SdFat. TEST - Аудио файл. Фото. https://yadi.sk/d/TDgjuyY8uikzP _____________. */ #include <SdFat.h> /* Библиотека для SD-карты */ #include <EEPROM.h> #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) SdFat sd; SdFile rec; const int chipSelect = 10; /* Поменял на 10-pln */ unsigned long fileSize = 0L; unsigned long waveChunk = 16; unsigned int waveType = 1; unsigned int numChannels = 1; unsigned long sampleRate = 22050; unsigned long bytesPerSec = 22050; unsigned int blockAlign = 1; unsigned int bitsPerSample = 8; unsigned long dataSize = 0L; unsigned long recByteCount = 0L; unsigned long recByteSaved = 0L; const int ledStart = 2; /* PIN LED Start */ const int ledStop = 3; /* PIN LED Stop */ int recPressed = 0; int stopPressed = 0; unsigned long oldTime = 0L; unsigned long newTime = 0L; byte buf00[512]; // buffer array 1 byte buf01[512]; // buffer array 2 byte byte1, byte2, byte3, byte4; unsigned int bufByteCount; byte bufWrite; /*_____________*/ char NameRecord[6]; /* Имя нового - записываемого файла на SD-карту. */ int RecordNumber; /* Номер записи - храним в EEPROM. в диапазоне от 0 до 32767. */ /* Время - интервал - остановки записи - time interval stop recording */ unsigned long TimeIntervalStopRecording; byte OnOffRecord; /* подготовка - к старту записи */ /*_____________*/ void setup() { // THIS RUNS ONCE pinMode(10, OUTPUT); pinMode(ledStart, OUTPUT); pinMode(ledStop, OUTPUT); /*_____________*/ /* Функция analogReference определяет опорное напряжение относительно которого происходят аналоговые измерения в analogRead(). EXTERNAL: внешний источник опорного напряжения, подключенный к выводу AREF. 1. Чтобы уменьшить шумы во время записи. 2. Возможность аппаратного изменения звукового порога, срабатывания авто записи, подключив переменный резистор к (выводу-AREF). */ analogReference(EXTERNAL); /*_____________*/ Setup_timer2(); Setup_ADC(); /* Если SD-карта не обнаружена - включаем ledStop и ledStart*/ if (!sd.begin(chipSelect, SPI_FULL_SPEED)) { // if error, flash LED twice per second, until reset. while (1) { // digitalWrite(ledStart, !digitalRead(ledStart)); // delay(500); digitalWrite(ledStop, HIGH); digitalWrite(ledStart, HIGH); } } digitalWrite(ledStop, HIGH); /* Читаем значение (int - (2-byte) из EEPROM (ячейки - №0 и №1). И записываем в RecordNumber. */ EEPROM.get(0, RecordNumber); // delay(50); OnOffRecord = EEPROM.read(5); /* Подготовка - к старту записи */ // delay(50); } /*_____________*/ void loop() { if (recPressed == 0 && OnOffRecord == 1) { /* Для конвертации из int в char / из RecordNumber в NameRecord */ String str; //declaring string. str = String(RecordNumber); //converting integer into a string. str.toCharArray(NameRecord, 6); //passing the value of the string to the character array. TimeIntervalStopRecording = millis(); /* Запоминаем millis */ StartRec(); /* launch StartRec method - Включаем запись */ } /*_____________*/ /* Останавливаем запись - по таймеру */ /* Продолжительность записи 10 секунд - можно изменять */ if (OnOffRecord == 1 && millis() - TimeIntervalStopRecording >= 10000) { StopRec(); /* launch StopRec method - Останавливаем запись. */ /* Блокируем повторный старт записи. */ EEPROM.write(5, 0); OnOffRecord = 0; } /*_____________*/ if (recByteCount % 1024 == 512 && recPressed == 1) { rec.write(buf00, 512); // save buf01 to card recByteSaved += 512; } if (recByteCount % 1024 == 0 && recPressed == 1) { rec.write(buf01, 512); // save buf02 to card recByteSaved += 512; } /*_____________*/ /* Подготовка к старту записи "Активация по голосу (VAS)." Запись начнётся, как только сигнал, поступающий с микрофона, превышает определенный уровень. */ /* Если уровень микрофона превысит порог 1023. порог - можно изменять! программно, И аппаратно - с помощью переменного резистора - "делитель напряжения" подключённого к выводу AREF, изменяем опорное напряжение "analogRead" */ if (recPressed == 0 && analogRead(A5) == 1023) { EEPROM.write(5, 1); /* подготовка - к старту записи */ if (RecordNumber == 32767)RecordNumber = 0; /* Записываем значение (int - (2-byte) в EEPROM (ячейки - №0 и №1). Переменная RecordNumber - увеличенная на 1. */ EEPROM.put(0, RecordNumber + 1); // delay(100); /* После окончания записи, в памяти контроллера остаются данные. И за этого следующая запись бывает качеством хуже. Поэтому (Делаем программную перезагрузку) перед стартом новой записи. */ ((void (*)())0x0000)(); /* Делаем программную перезагрузку - Arduino */ } } /*_____________*/ void StartRec() { // begin recording process digitalWrite(ledStart, HIGH); digitalWrite(ledStop, LOW); recByteCount = 0; recByteSaved = 0; recPressed = 1; // recording button has been pressed stopPressed = 0; writeWavHeader(); sbi (TIMSK2, OCIE2A); // enable timer interrupt, start grabbing audio } void StopRec() { // stop recording process, update WAV header, close file cbi (TIMSK2, OCIE2A); // disable timer interrupt writeOutHeader(); digitalWrite(ledStart, LOW); // turn off recording LED digitalWrite(ledStop, HIGH); // light stop LED recPressed = 0; } void writeOutHeader() { // update WAV header with final filesize/datasize rec.seekSet(4); byte1 = recByteSaved & 0xff; byte2 = (recByteSaved >> 8) & 0xff; byte3 = (recByteSaved >> 16) & 0xff; byte4 = (recByteSaved >> 24) & 0xff; rec.write(byte1); rec.write(byte2); rec.write(byte3); rec.write(byte4); rec.seekSet(40); rec.write(byte1); rec.write(byte2); rec.write(byte3); rec.write(byte4); rec.close(); } void writeWavHeader() { // write out original WAV header to file recByteSaved = 0; // rec.open("rec00000.wav", O_CREAT | O_TRUNC | O_RDWR); /* Имя нового - записываемого файла на SD-карту. */ rec.open(NameRecord, O_CREAT | O_TRUNC | O_RDWR); rec.write("RIFF"); byte1 = fileSize & 0xff; byte2 = (fileSize >> 8) & 0xff; byte3 = (fileSize >> 16) & 0xff; byte4 = (fileSize >> 24) & 0xff; rec.write(byte1); rec.write(byte2); rec.write(byte3); rec.write(byte4); rec.write("WAVE"); rec.write("fmt "); byte1 = waveChunk & 0xff; byte2 = (waveChunk >> 8) & 0xff; byte3 = (waveChunk >> 16) & 0xff; byte4 = (waveChunk >> 24) & 0xff; rec.write(byte1); rec.write(byte2); rec.write(byte3); rec.write(byte4); byte1 = waveType & 0xff; byte2 = (waveType >> 8) & 0xff; rec.write(byte1); rec.write(byte2); byte1 = numChannels & 0xff; byte2 = (numChannels >> 8) & 0xff; rec.write(byte1); rec.write(byte2); byte1 = sampleRate & 0xff; byte2 = (sampleRate >> 8) & 0xff; byte3 = (sampleRate >> 16) & 0xff; byte4 = (sampleRate >> 24) & 0xff; rec.write(byte1); rec.write(byte2); rec.write(byte3); rec.write(byte4); byte1 = bytesPerSec & 0xff; byte2 = (bytesPerSec >> 8) & 0xff; byte3 = (bytesPerSec >> 16) & 0xff; byte4 = (bytesPerSec >> 24) & 0xff; rec.write(byte1); rec.write(byte2); rec.write(byte3); rec.write(byte4); byte1 = blockAlign & 0xff; byte2 = (blockAlign >> 8) & 0xff; rec.write(byte1); rec.write(byte2); byte1 = bitsPerSample & 0xff; byte2 = (bitsPerSample >> 8) & 0xff; rec.write(byte1); rec.write(byte2); rec.write("data"); byte1 = dataSize & 0xff; byte2 = (dataSize >> 8) & 0xff; byte3 = (dataSize >> 16) & 0xff; byte4 = (dataSize >> 24) & 0xff; rec.write(byte1); rec.write(byte2); rec.write(byte3); rec.write(byte4); } void Setup_timer2() { TCCR2B = _BV(CS21); // Timer2 Clock Prescaler to : 8 TCCR2A = _BV(WGM21); // Interupt frequency = 16MHz / (8 x 90 + 1) = 22191Hz OCR2A = 90; // Compare Match register set to 90 } void Setup_ADC() { ADMUX = 0x65; // set ADC to read pin A5, ADLAR to 1 (left adjust) cbi(ADCSRA, ADPS2); // set prescaler to 8 / ADC clock = 2MHz sbi(ADCSRA, ADPS1); sbi(ADCSRA, ADPS0); } ISR(TIMER2_COMPA_vect) { sbi(ADCSRA, ADSC); // start ADC sample while (bit_is_set(ADCSRA, ADSC)); // wait until ADSC bit goes low = new sample ready recByteCount++; // increment sample counter bufByteCount++; if (bufByteCount == 512 && bufWrite == 0) { bufByteCount = 0; bufWrite = 1; } else if (bufByteCount == 512 & bufWrite == 1) { bufByteCount = 0; bufWrite = 0; } if (bufWrite == 0) { buf00[bufByteCount] = ADCH; } if (bufWrite == 1) { buf01[bufByteCount] = ADCH; } // if (recByteCount % 1024 < 512) { // determine which buffer to store sample into // buf01[recByteCount % 512] = ADCH; // } else { // buf02[recByteCount % 512] = ADCH; // } }
Собрал, вроде работает, но есть одна странность: если питать ардуино от компьютера, то почти нет посторонних шумов. А если запитать от аккумулятора, то запись получается просто ужасной! Вот ссылка на Гугл диск с примерами записи: https://drive.google.com/open?id=1K6BrjRhTSzYjrvIRmf6IJEgVOv9GfAN5
Файл 69.wav - запись с питанием от компьютера. Усиление микрофона стоит почти на минимуме. Файл 101.wav - запись от аккумулятора (4.1 вольт). Схема устройства крайне простая: MicroSD подключена по SPI, к пину А5 подключен выход микрофонного усилителя MAX4466, светодиоды к пинам 2 и 3, и TL431 в качестве опорника. Пробовал собирать на Arduino UNO и на PRO MINI - в обоих случаях результат одинаков - питается от компьютера - запись по-лучше, а если от аккумулятора - запись плохая, много шумов и "рипит"... Аккумуляторы пробовал разные. Пробовал разные флешки, как "НоНейм" - так и качественные с 10-й скоростью.
Не могу понять почему идут шумы при работе от аккумулятора... по идее должно быть наоборот...
Может у вас есть идеи?
Идеи есть - не хватает питания. Запитайте от ардуинку от БП. Если все хорошо - то точно в питании.
В Общем, решается все это диодом и конденсатором на микрофоне.