Ардуино - запись звука

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
Ivanoff-iv
Друг Кота
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Re: Ардуино - запись звука

Сообщение Ivanoff-iv »

можно измерять напряжение не задействуя ацп - при помощи ШИМа и компаратора:
если на выходе компаратора 1 - в OCR добавляем 1 иначе вычитаем.
входы компаратора прицеплены к измеряемому сигналу и к выходу ШИМ (через RC фильтр).
а АЦП пусть звук пишет...
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Реклама
Аватара пользователя
olegue
Собутыльник Кота
Сообщения: 2977
Зарегистрирован: Сб май 21, 2016 11:04:52
Откуда: Беларусь

Re: Ардуино - запись звука

Сообщение olegue »

roman.com, ниче не понял
Реклама
roman.com
Друг Кота
Сообщения: 9147
Зарегистрирован: Вт мар 13, 2012 12:16:13
Откуда: .ru

Re: Ардуино - запись звука

Сообщение roman.com »

[uquote="olegue",url="/forum/viewtopic.php?p=4245416#p4245416"]что если я увеличу время преобзования для А0 (напряжене) до 125кгц (делитель 128) - до 8мкс, сняв лишную нагрузку с процессоа, а время преобразования АЦП для звука оставлю тем же. -0.5мкс.[/uquote]
чтобы снять лишнюю нагрузку с процессора... надо не уменьшать частоту ADC, а увеличивать частоту ADC...
чем выше частота ADC, тем быстрей работает ADC ))
а чем быстрей работает ADC, тем меньше время ожидания процессора...
поэтому мы должны установить максимальную частоту для ADC...

максимальная частота ADC - это когда предделитель отключён... ))

ADCSRA = 0b10000000; // вкл. ADC без предделителя.

или так

ADCSRA=0x80; // вкл. ADC без предделителя.

где:
//ADCSRA
//1... .... ADEN - 1- вкл ADC. (0-ADC не потребляет мощности)
//.1.. .... ADSC - 1- Старт. При завершении преобразования сбрасывается аппаратно.
//..1. .... ADFR - 1- режим Непрерывного Преобразования.
//...1 .... ADIF - 1- флаг завершения преобразования
-сброс программно.
-для прерывания очищается аппаратно.
//.... 1... ADIE - 1- Разрешение прерывания
//.... .1.. ADPS2 - предделитель
//.... ..1. ADPS1 - предделитель
//.... ...1 ADPS0 - предделитель

в этом случаем ADC будет работать с частотой кварца Ардуино - 16 МГц !

это максимальная частота ADC...))

итого:
надо записать так:

ADCSRA=0x80; // вкл. ADC без предделителя. C частотой кварца Ардуино - 16 МГц

а как это будет на дуратском языке Ардуино... ? ))
[uquote="olegue",url="/forum/viewtopic.php?p=4245416#p4245416"]Хотя я вот все равно не понимаю, если таймер лопатит с частотой 22кгц, то какая разница каким будет время преобразования и как это повлияет на результ оцифровки звука???[/uquote]
тайминги... тайминги... тайминги...
не соблюдение таймингов приводит к срыву синхронизации ! и весь твой код... идёт в разнос)) :o

Добавлено after 1 minute 18 seconds:
[uquote="Ivanoff-iv",url="/forum/viewtopic.php?p=4245434#p4245434"]можно измерять напряжение не задействуя ацп - при помощи ШИМа и компаратора:
если на выходе компаратора 1 - в OCR добавляем 1 иначе вычитаем.
входы компаратора прицеплены к измеряемому сигналу и к выходу ШИМ (через RC фильтр).
а АЦП пусть звук пишет...[/uquote]
давайте сначала разберёмся с таймингами... а потом займёмся вашими самодельными преобразователями))
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: Ардуино - запись звука

Сообщение Dimon456 »

Martian писал(а):у меня нет протеуса
Ну дак поставь, это я с телефона, а вы (относится ко всем) за компами сидите.
От силы 30 мин потормошить протеус и все станет на свои места.
Не поверю что ардуиновский драйвер целиком сектор пишет.
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
olegue
Собутыльник Кота
Сообщения: 2977
Зарегистрирован: Сб май 21, 2016 11:04:52
Откуда: Беларусь

Re: Ардуино - запись звука

Сообщение olegue »

а АЦП успеет выполнить преобразование за 1/16 000 000 = 0.0625мкс?
Реклама
roman.com
Друг Кота
Сообщения: 9147
Зарегистрирован: Вт мар 13, 2012 12:16:13
Откуда: .ru

Re: Ардуино - запись звука

Сообщение roman.com »

шо ? опять ничего не понял ? :shock:
))

ну ты же сам пишиш... (пиши комментарии по-русски)

ISR(TIMER2_COMPA_vect) {
// циффруем напряжени с A0
ADMUX = 0x40; // выбираем канал с которого будем цифровать - pin A0
sbi(ADCSRA, ADSC); // запускаем ADC
while (bit_is_set(ADCSRA, ADSC)); // ждём пока ADC закончит работу по оцифровки...

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

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

так понятней или нет ?))
:)

Добавлено after 4 minutes 54 seconds:
[uquote="olegue",url="/forum/viewtopic.php?p=4245448#p4245448"]а АЦП успеет выполнить преобразование за 1/16 000 000 = 0.0625мкс?[/uquote]
можно посчитать вручную)) в даташите сказано что ADC цифрует за 13 тактов...
16 000 000 / 13 = ... мкс
Или около того))

давайте посчитаем))
допустим у нас ADC работает с частотой 250 000 Гц.
за сколько ADC завершит преобразование ?
1/250 000 * 13 = 52 мкс

а теперь давайте проверим наши расчёты в Протеусе))

вот я взял ADC с частотой 250 000 и закинул в Протеус...
протеус ответил - 57 мкс
ADC_250000Hz .jpg
(97.71 КБ) 49 скачиваний
что очень близко с нашими расчётам))

а теперь давайте посчитаем за сколько ADC завершит преобразование с частотой 16 000 000 ?
1/16 000 000 * 13 = 0,812 мкс

а теперь берём ADC с частотой 16 000 000 и закидываем в Протеус...
...

:tea:
Реклама
Аватара пользователя
olegue
Собутыльник Кота
Сообщения: 2977
Зарегистрирован: Сб май 21, 2016 11:04:52
Откуда: Беларусь

Re: Ардуино - запись звука

Сообщение olegue »

roman.com, дальше...

Добавлено after 6 minutes 9 seconds:
по моеей матиматике получается что такт это 1/16мгц=0.0625мкс
13 тактов *0.0625=0.8125 мкс - минимальное время преобразования
минимальная частота преобразования АДС =1/0.8125=1 230 769 гц

Добавлено after 1 minute 31 second:
тока к чему это привязать пока не понятно
Аватара пользователя
Ivanoff-iv
Друг Кота
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Re: Ардуино - запись звука

Сообщение Ivanoff-iv »

я не пробовал АЦП на таких частотах гонять... не уверен, что там чтото адекватное намеряется...
наверно рекоммендация в д.ш. о частоте тактирования АЦП не с потолка взята
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
roman.com
Друг Кота
Сообщения: 9147
Зарегистрирован: Вт мар 13, 2012 12:16:13
Откуда: .ru

Re: Ардуино - запись звука

Сообщение roman.com »

всё верно.
примерно так и получается...
на самом деле получается чуть-чуть больше тактов... потому что там идёт опрос флага ADC... несколько тактов нужно ещё самому процессору Ардуины... чтобы "подумать"... ))
но мы не будем углубляться в принцип работы процессоров Ардуины)) это уже отдельная тема...
:tea:
Аватара пользователя
olegue
Собутыльник Кота
Сообщения: 2977
Зарегистрирован: Сб май 21, 2016 11:04:52
Откуда: Беларусь

Re: Ардуино - запись звука

Сообщение olegue »

а преобразование - это процесс измерения и заполнения регистровой пары ADCH и ADCL?
roman.com
Друг Кота
Сообщения: 9147
Зарегистрирован: Вт мар 13, 2012 12:16:13
Откуда: .ru

Re: Ардуино - запись звука

Сообщение roman.com »

[uquote="Ivanoff-iv",url="/forum/viewtopic.php?p=4245480#p4245480"]я не пробовал АЦП на таких частотах гонять... не уверен, что там чтото адекватное намеряется...
наверно рекоммендация в д.ш. о частоте тактирования АЦП не с потолка взята[/uquote]
в даташите рекомендуют не делать частоту ADC больше 200 000 Гц.
иначе это приведёт к неправильным показаниям)))

но нам и не нужно супер точные показания ADC)) мы не собираемся запускать спутники в космос)) мы просто записываем ЗВУК !

на практике... при оцифровке звука... на повышенных частотах ADC... приводит просто к повышенному шуму... из-за всяких переходных процессов ADC...))
:roll:

Добавлено after 51 second:
[uquote="olegue",url="/forum/viewtopic.php?p=4245475#p4245475"]тока к чему это привязать пока не понятно[/uquote]
к таймеру

Добавлено after 24 seconds:
[uquote="olegue",url="/forum/viewtopic.php?p=4245485#p4245485"]а преобразование - это процесс измерения и заполнения регистровой пары ADCH и ADCL?[/uquote]
да
Аватара пользователя
olegue
Собутыльник Кота
Сообщения: 2977
Зарегистрирован: Сб май 21, 2016 11:04:52
Откуда: Беларусь

Re: Ардуино - запись звука

Сообщение olegue »

roman.com писал(а):в даташите рекомендуют не делать частоту ADC больше 200 000 Гц.
а у меня в коде стоит частота АДС -2мгц, то это сделано, что бы можно было хоть как-то хоть что то записать?

Добавлено after 1 minute 22 seconds:
так это больше чем я тут насчитал, как такое возможно?
olegue писал(а):13 тактов *0.0625=0.8125 мкс - минимальное время преобразования
минимальная частота преобразования АДС =1/0.8125=1 230 769 гц
Добавлено after 4 minutes 49 seconds:
roman.com писал(а):в даташите рекомендуют не делать частоту ADC больше 200 000 Гц.
иначе это приведёт к неправильным показаниям)))
Вывод: частоту АДС увеличивать нету смысла. Она и так 2мгц. ЗНачит надо дергать таймер. Увеличивать частоту дискретизации, ну типа в итоге это уже будет не частота дискретизатии, фиг пойми что, так подобрать придется так что бы этой частоты хватило чтобы из звук оцифровать и напряжение измерить на одновременно на разных каналах Адс
roman.com
Друг Кота
Сообщения: 9147
Зарегистрирован: Вт мар 13, 2012 12:16:13
Откуда: .ru

Re: Ардуино - запись звука

Сообщение roman.com »

сейчас у тебя ADC работает с частотой 2 мгц...
а сколько это по времени ?

1/2 000 000 * 13 = 6,5 мкс

дальше считаем тайминги...

а сколько времени у нас по таймеру ?

1/22000= 45мкс

а мы успеваем за 45 мкс оцифровать всё ?

одно преобразование сделать за 45 мкс успеваем)) поэтому качество звука хорошее))

а два преобразования за 45 мкс мы уже делать не успеваем... )) поэтому звук плохого качества ))

значит... надо дергать таймер)) будем уменьшать частоту таймера...
:tea:

Добавлено after 24 minutes 55 seconds:
olegue писал(а):Вывод: частоту АДС увеличивать нету смысла. Она и так 2мгц. ЗНачит надо дергать таймер.
выводы делать рано... пока всё не посчитаем))

в оригинальной программе частота ADC составляет 2мгц.
значит время преобразования ADC составляет 6,5 мкс.
и всё прекрасно работает))

затем мы добавили второе преобразование...
итого у нас получилось два преобразования 6,5 мкс * 2 = 13 мкс.
мы вышли за пределы таймера 45 мкс.

как вернуться обратно ?)) в пределы таймера 45 мкс ?
можно увеличить частоту ADC с 2 мгц до 16 мгц.
тогда получим одно преобразование 0.8125 мкс
а два преобразования 0.8125 мкс * 2 = 1,625 мкс.

замечательно)) мы вернулись в пределы таймера 45 мкс.

а как частота ADC = 16 мгц отразится на качестве звука ?
а это уже надо проверять на практике))
:tea:
Аватара пользователя
olegue
Собутыльник Кота
Сообщения: 2977
Зарегистрирован: Сб май 21, 2016 11:04:52
Откуда: Беларусь

Re: Ардуино - запись звука

Сообщение olegue »

так может не нужно сразу без делителя. Есть еще промежуточные значения. Поставлю делитель 4. Посмотрю че будут.
roman.com
Друг Кота
Сообщения: 9147
Зарегистрирован: Вт мар 13, 2012 12:16:13
Откуда: .ru

Re: Ардуино - запись звука

Сообщение roman.com »

блин... а форум никто не читает))
никто не заметил ошибку))

на самом деле ADC не может совсем работать без делителя... выше писал...

предделитель ADC:
ADPS2 -ADPS1 -ADPS0
----------
// 000: 1 МГц/2=500.000 Hz
// 001: 1 МГц/2=500.000 Hz
// 010: 1 МГц/4=250.000 Hz
// 011: 1 МГц/8=125.000 Hz
// 100: 1 МГц/16=62.500 Hz
// 101: 1 МГц/32=31.250 Hz
// 110: 1 МГц/64=15.625 Hz
// 111: 1 МГц/128=7.812,5 Hz
----------

даже если мы запишем нули... то частота будет делится на два ))
ADCSRA=0x80; // вкл. ADC с делителем на 2. C частотой кварца Ардуино - 16 МГц / 2 = 8 МГц
8 МГц - это максимальная частота ADC у Ардуины))
:))

как вернуться обратно ?)) в пределы таймера 45 мкс ?
можно увеличить частоту ADC с 2 мгц до 8мгц.
тогда получим одно преобразование 1,625 мкс
а два преобразования 1,625 мкс * 2 = 3,25 мкс.

замечательно)) мы вернулись в пределы таймера 45 мкс.
:tea:
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: Ардуино - запись звука

Сообщение Dimon456 »

О чем вы спорите?
Ниже 100Гц и выше 10кГц не хрена не слышите, ну разве что на хорошую акустику.
А человеческая речь лежит в пределах 300Гц - 3,4кГц.
Martian
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32
Контактная информация:

Re: Ардуино - запись звука

Сообщение Martian »

Dimon456, ща аудиофилы линчуют за такое оскорбление ;)
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: Ардуино - запись звука

Сообщение Dimon456 »

Martian, пусть выстраиваются в очередь .
Аватара пользователя
olegue
Собутыльник Кота
Сообщения: 2977
Зарегистрирован: Сб май 21, 2016 11:04:52
Откуда: Беларусь

Re: Ардуино - запись звука

Сообщение olegue »

Ну че сказать, оно работает

Перво-наперво я начал играться с частотой преобразования АЦП выставил делитель 4, ну стало типа 4 мгц. На слух это мало на что повлияло. Решил в итоге снижать битрейт, нашел что ближайшее вниз после 22050 - это 16кгц. Выставил число сравнения 125 в итоге

Код: Выделить всё

void Setup_timer2() {

  TCCR2B = _BV(CS21);  // Timer2 Clock Prescaler to : 8
  TCCR2A = _BV(WGM21); // Interupt frequency  = 16MHz / (8 x 125 + 1) = 16000Hz
  OCR2A = 125; // Compare Match register set to 125 (было 90) Перешл на 16кгц

}
в заголовке поменял тоже

Код: Выделить всё

unsigned long sampleRate = 16000;
unsigned long bytesPerSec = 16000;
unsigned int blockAlign = 1;
unsigned int bitsPerSample = 8;
частота потока стала 8*16000=128кгц вместо 174кгц


Ну вот после этого стало заметно лучше по звуку

Но пока не могу понять что происходит с оцифровкой напряжения. Если ставлю код АЦП измерения напряжения в начало скетца в loop() то выдает адекватные нормальные значения , но начинает сходит с ума во время оцифровки, может прихватывает еще ADCH их оцифровки - я не знаю. А если в прерывание засовываю, то увеличивает значения раза в 2. Я грешу на то что ADCH и ADCL общие и гдето пересекаются. Потому что когда оцифровка звука не работает второй канал показывает на экране правильные результаты.

в итоге вот это

Код: Выделить всё

ISR(TIMER2_COMPA_vect) {
 ADMUX = 0x40; // set ADC to read pin A0, ADLAR to 1 (left adjust)
        sbi(ADCSRA, ADSC); // start ADC sample
        while (bit_is_set(ADCSRA, ADSC)); // wait until ADSC bit goes low = new sample ready
        rsValue=(ADCL|ADCH<<8);

  
ADMUX = 0x61; // set ADC to read pin A1, ADLAR to 1 (left adjust)
  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 == 64 && bufWrite == 0) {
    bufByteCount = 0;
    bufWrite = 1;
  } else if (bufByteCount == 64 & bufWrite == 1) {
    bufByteCount = 0;
    bufWrite = 0;
  }

а весь код здесь
Спойлер

Код: Выделить всё

/* Dmitry OSIPOV. http://www.youtube.com/user/d36073?feature=watch
  Arduino Audio Recorder V.1-20160524.
  ----------------------------------------------------
   Arduino Projects: Digital Audio Recorder.
  http://apcmag.com/arduino-projects-digital-audio-recorder.htm/
  ----------------------------------------------------
  SD-карту лучше класс 10 и выше.
  Питание от батареи или аккумулятора.
  Микрофон подключить к pin (A5).
  ----------------------------------------------------
  Download - sketch "Arduino Audio Recorder V.1-20160524"
  Библиотеку - SdFat.
  Фото.
  https://yadi.sk/d/zqi8-L5xruhFq
  + sketch оставлю в комментарии - под видео.
  ----------------------------------------------------
*/
#include <LiquidCrystal_I2C.h>
#include <SdFat.h> // https://yadi.sk/d/zqi8-L5xruhFq
//#include <EEPROM.h>

#include <RTClib.h>

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

SdFat sd;
SdFile rec;
RTC_DS1307 rtc;
LiquidCrystal_I2C lcd(0x27,20,4);  // set the LCD address to 0x27 for a 16 chars and 2 line display
const int chipSelect = 4; /* Поменял на 10-pln */
unsigned long fileSize = 0L;
unsigned long waveChunk = 16;
unsigned int waveType = 1;
unsigned int numChannels = 1;
unsigned long sampleRate = 16000;
unsigned long bytesPerSec = 16000;
unsigned int blockAlign = 1;
unsigned int bitsPerSample = 8;
unsigned long dataSize = 0L;
unsigned long recByteCount = 0L;
unsigned long recByteSaved = 0L;
const int btnStart = 6;
const int btnStop = 5;
const int ledStart = 2;
const int ledStop = 3;
int recPressed = 0;
int stopPressed = 0;
unsigned long oldTime = 0L;
unsigned long newTime = 0L;
byte buf00[64]; // buffer array 1
byte buf01[64]; // buffer array 2
byte byte1, byte2, byte3, byte4;
unsigned int bufByteCount;
byte bufWrite;

unsigned long timer1;
int timer1on = 0;
//----------------------------------------------------
//char NameRecord[4]; /* Имя нового - записываемого файла на SD-карту. */
//int RecordNumber; /* Номер записи - храним в EEPROM. в диапазоне 0..255. */
//char filename[12]; 

char filename[22];
char foldername[10];

unsigned long timerLCL;
int timerLCLon=0;

unsigned long timerRS;
int timerRSon=0;

int SrV,rsValue, procSrV, SrVmid;

char buffer[16] ;
void setup() { // THIS RUNS ONCE
//
  lcd.init();
   lcd.backlight();
  //lcd.setCursor(3,0);
  //lcd.print("Hello, world!");
 

//
  
  rtc.begin();
//EEPROM.put(0, 20000);
  Setup_timer2();
  Setup_ADC();

  pinMode(10, OUTPUT);
  pinMode(ledStart, OUTPUT);
  pinMode(ledStop, OUTPUT);
  pinMode(btnStop, INPUT_PULLUP);
  pinMode(btnStart, INPUT_PULLUP);

  if (sd.begin(chipSelect, SPI_FULL_SPEED)) { // initialise card on SPI to 8MHz SPI bus speed
    for (int dloop = 0; dloop < 4; dloop++) {
      digitalWrite(ledStart, !digitalRead(ledStart));
      delay(100);
    }
  } else { 
      lcd.setCursor(0,1);
      lcd.print("SD Card not found");
    // if error, flash LED twice per second, until reset
    while (1) {
      digitalWrite(ledStart, !digitalRead(ledStart));
      delay(500);
    }
  }

}

void loop() { // THIS RUNS LOTS!
////////////// НАЧИНАЕМ С ОБРАБОТКИ ВХОДА А0 ////////////////////////
  
// Каждые 100 мс мы накапливаем значения (для усреднения)
 if (timerRSon==0){   // запустим таймер для отображения часов
  timerRS=millis();  // включим миллис
  timerRSon=1;
  
 }
 if (timerRSon==1){
  if (millis()-timerRS>50)
    {
      ////////////

      //rsValue=analogRead(A0);
     
         
          lcd.setCursor(0,0);
         ///sprintf(buffer, "Pow:%05i",rsValue);
         ///lcd.print(buffer);
 
      /////////////   
      SrV=SrV+rsValue; 
      timerRSon=0;
   }
 }
// Каждые 1000 мс мы отображаем усредненное значение
  if (timerLCLon==0){   // запустим таймер для отображения часов
  timerLCL=millis();  // включим миллис
  timerLCLon=1;
 }
 if (timerLCLon==1){
  if (millis()-timerLCL>1000)
    {
      //lcd.setCursor(0,0);
      
      SrVmid=SrV/20;
      if (SrVmid<125) SrVmid=125;    // меньше 125 - это 0%
      procSrV=((SrVmid-125)*100)/194;  //в % макс -318(320), мин 125, 320-125=195   
      sprintf(buffer, "Power:%04i (%02i)",SrV/20,procSrV); 
      lcd.print(buffer);
      //Show_time();
      timerLCLon=0;
      
      SrV=0;
      ///////////////////////
   }
 }

 ////////////// ЗДЕСЬ УЖЕ ОБРАБОТКА ВХОДА А1 ////////////////////////
 if (digitalRead(btnStart) == LOW && recPressed == 0) {
    
    DateTime now = rtc.now();
    String strFile,strFolder;  //declaring string.
    strFolder=String(now.timestamp(DateTime::TIMESTAMP_DATE));
    strFolder.replace("-", "");
    strFolder.toCharArray(foldername, sizeof(foldername));
    sd.mkdir(foldername);  // Создаю директорию - пробовал без этого - никак
    strFolder.concat("/");
    strFile=String(now.timestamp(DateTime::TIMESTAMP_TIME));
    strFile.replace(":", "-");
    strFile.concat(".wav");
    strFolder.concat(strFile);
    strFolder.toCharArray(filename, sizeof(filename));
    
    StartRec(); // launch StartRec method
    timer1on = 0;
  }
  else if (digitalRead(btnStart) == HIGH && recPressed == 1 && timer1on == 0)
    {
      timer1 = millis();
      timer1on = 1;
    }
    else if (digitalRead(btnStart) == LOW && recPressed == 1 && timer1on == 1) {
    timer1on = 0; 
    }
   
  else if (digitalRead(btnStart) == HIGH && recPressed == 1 && timer1on == 1 && (millis() - timer1) > 2000)
  {
    StopRec(); // launch StopRec method
    
    /*         Поэтому (Делаем программную перезагрузку). */
    ((void (*)())0x0000)(); /* Делаем программную перезагрузку - Arduino */
  }
 
  if (recByteCount % 128 == 64 && recPressed == 1) {
    rec.write(buf00, 64);  // save buf01 to card
    recByteSaved += 64;
  }
  if (recByteCount % 128 == 0 && recPressed == 1) {
    rec.write(buf01, 64);  // save buf02 to card
    recByteSaved += 64;
  }
}

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 dateTime(uint16_t* date, uint16_t* time) {
  DateTime now = rtc.now();

  // return date using FAT_DATE macro to format fields
  *date = FAT_DATE(now.year(), now.month(), now.day());

  // return time using FAT_TIME macro to format fields
  *time = FAT_TIME(now.hour(), now.minute(), now.second());
}

void writeWavHeader() { // write out original WAV header to file

  recByteSaved = 0;
  
   SdFile::dateTimeCallback(dateTime);
   ////
  
   ////
   rec.open(filename, O_CREAT | O_TRUNC | O_RDWR); /* Имя нового - записываемого файла на SD-карту. */
   
  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 125 + 1) = 16000Hz
  OCR2A = 125; // Compare Match register set to 125 (было 90) Перешл на 16кгц

}

void Show_time(){    
  DateTime now = rtc.now();
      lcd.setCursor(1, 1);
      lcd.print(now.hour());
      lcd.print(":");
      lcd.print(now.minute());
      lcd.print(":");     
      lcd.print(now.second());
       }

void Setup_ADC() {

  ADMUX = 0x61; // set ADC to read pin A5, ADLAR to 1 (left adjust)
  sbi(ADCSRA, ADEN);  // включить модуль АЦП
  //sbi(ADCSRA, ADATE); // Непрерывный режим работы АЦП (это не прокатило) Экран стал пуст
  cbi(ADCSRA, ADPS2); // set prescaler to 8 / ADC clock = 2MHz
  sbi(ADCSRA, ADPS1);
  sbi(ADCSRA, ADPS0);
}

ISR(TIMER2_COMPA_vect) {
 ADMUX = 0x40; // set ADC to read pin A0, ADLAR to 1 (left adjust)
        sbi(ADCSRA, ADSC); // start ADC sample
        while (bit_is_set(ADCSRA, ADSC)); // wait until ADSC bit goes low = new sample ready
        rsValue=(ADCL|ADCH<<8);

  
ADMUX = 0x61; // set ADC to read pin A1, ADLAR to 1 (left adjust)
  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 == 64 && bufWrite == 0) {
    bufByteCount = 0;
    bufWrite = 1;
  } else if (bufByteCount == 64 & bufWrite == 1) {
    bufByteCount = 0;
    bufWrite = 0;
  }

  if (bufWrite == 0) {
    buf00[bufByteCount] = ADCH;
  }
  if (bufWrite == 1) {
    buf01[bufByteCount] = ADCH;
  }


  //  if (recByteCount % 128 < 64) { // determine which buffer to store sample into
  //    buf01[recByteCount % 64] = ADCH;
  //  } else {
  //    buf02[recByteCount % 64 ] = ADCH;
  //  }

}

Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: Ардуино - запись звука

Сообщение Dimon456 »

olegue писал(а):

Код: Выделить всё

while (bit_is_set(ADCSRA, ADSC));
но кого вы тут ждете? Седьмого пришествия?

Код: Выделить всё

rsValue=(ADCL|ADCH<<8);
А это что такое?

Код: Выделить всё

buf00[bufByteCount] = ADCH;
ну а здесь тогда по чему так?
Вот не хотят идти по простому пути.
Вот вам с буферами
Спойлер

Код: Выделить всё

volatile uint8_t sum_adc;
volatile bool n0=0, n1=0;
byte buf00[256]; // buffer array 1
byte buf01[256]; // buffer array 2

// ADC interrupt service routine
ISR(ADC_vect) 
{
static uint8_t count = 0;
static uint8_t temp=0;
static uint32_t temp_adc=0;
static uint16_t count_buf = 0;

  if(ADMUX & (1<<MUX0)){
    temp = ADCH;    
    if(count_buf < 256) {
    buf00[count_buf] = temp; 
    } else buf01[count_buf - 256] = temp;

    if(count_buf == 255) { 
      n0=0; n1=1; 
    }
      
    if(++count_buf > 511) { 
      count_buf=0; n0=1; n1=0; 
    }
    ADMUX = ADC_VREF_TYPE | (0<<MUX0);//set ch 0 
  }else{
    temp_adc += ADCH;

  if (++count > ((127)))  { 
    count = 0;
    sum_adc = temp_adc>>7; 
    temp_adc=0;
  }

    ADMUX = ADC_VREF_TYPE | (1<<MUX0);//set ch 1
  }

}


void loop() {
   if (n0==0 && n1 == 1) {
      rec.write(buf00, 256);  // save buf01 to card
      n0=0; n1=0;
    }
    if (n0==1 && n1 == 0) {
      rec.write(buf01, 256);  // save buf02 to card
      n0=0; n1=0;
    }
}

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();
  ADCSRA |= (1<<ADEN);
}

void StopRec() { // stop recording process, update WAV header, close file
  ADCSRA &= ~(1<<ADEN);
  writeOutHeader();
  digitalWrite(ledStart, LOW); // turn off recording LED
  digitalWrite(ledStop, HIGH); // light stop LED
  recPressed = 0;
}

void Setup_ADC() {
// ADC initialization
DIDR0=(0<<ADC5D) | (0<<ADC4D) | (0<<ADC3D) | (0<<ADC2D) | (0<<ADC1D) | (0<<ADC0D);
ADMUX= (1<<MUX0) | ADC_VREF_TYPE;
ADCSRA=(0<<ADEN) | (1<<ADSC) | (1<<ADATE) | (0<<ADIF) | (1<<ADIE) | (1<<ADPS2) | (0<<ADPS1) | (1<<ADPS0);  // 500kHz
sampleRate = 19600; bytesPerSec = 19600;
//ADCSRA=(0<<ADEN) | (1<<ADSC) | (1<<ADATE) | (0<<ADIF) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (0<<ADPS0); // 250kHz
//sampleRate = 9800; bytesPerSec = 9800;
//ADCSRA=(0<<ADEN) | (1<<ADSC) | (1<<ADATE) | (0<<ADIF) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); // 125kHz
//sampleRate = 4900; bytesPerSec = 4900;

ADCSRB=(0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);
}
Если усреднения не достаточно будет корректируем только это

Код: Выделить всё

  if (++count > ((255)))  { 
    count = 0;
    sum_adc = temp_adc>>8; 
    temp_adc=0;
  }
511>>9 1023>>10 и т. д.
Соответственно

Код: Выделить всё

static uint8_t count = 0;
поменять надо на

Код: Выделить всё

static uint16_t count = 0;
Ответить

Вернуться в «AVR»