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

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

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

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

-
Последний раз редактировалось roman.com Ср июн 15, 2022 10:15:41, всего редактировалось 1 раз.
Реклама
Аватара пользователя
olegue
Собутыльник Кота
Сообщения: 2977
Зарегистрирован: Сб май 21, 2016 11:04:52
Откуда: Беларусь

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

Сообщение olegue »

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

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

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

[uquote="olegue",url="/forum/viewtopic.php?p=4245732#p4245732"]начинает сходит с ума во время оцифровки, может прихватывает еще ADCH их оцифровки - я не знаю... Я грешу на то что ADCH и ADCL общие и гдето пересекаются.[/uquote]
напиши вот так и забудь об этом))

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


ADMUX = 0x41; // set ADC to read pin A1, ADLAR to 1 (right 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] = (ADCW>>2);
}
if (bufWrite == 1) {
buf01[bufByteCount] = (ADCW>>2);
}
Аватара пользователя
olegue
Собутыльник Кота
Сообщения: 2977
Зарегистрирован: Сб май 21, 2016 11:04:52
Откуда: Беларусь

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

Сообщение olegue »

roman.com,

rsValue=analogRead(A0);

если так то работает идеально,


.....
rsValue=(ADCL|ADCH<<8);

эта строка тоже работает аналогично, и дает те же значения.


но в момент одновременной работы двух каналов значения

rsValue=(ADCL|ADCH<<8);

становятся неадекватными, уходят в минус, например, удваиваются, начинают "прогать", хотя когда 2й канал не занят оцифровкой звука показывает все правильно

Добавлено after 1 minute 42 seconds:
roman.com писал(а):rsValue=ADCW;


roman.com,
ADMUX = 0x41; // set ADC to read pin A1, ADLAR to 1 (right adjust)
sbi(ADCSRA, ADSC); // start ADC sample
попробую , конечно, но объяснение почему это должно исправить ситуацию я не вижу.
Реклама
Эиком - электронные компоненты и радиодетали
roman.com
Друг Кота
Сообщения: 9147
Зарегистрирован: Вт мар 13, 2012 12:16:13
Откуда: .ru

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

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

тут ты делаешь всё сам... вручную))
rsValue=(ADCL|ADCH<<8);

тут ты перекладываешь всю ответственность за ADCL и ADCH на Ардуину))
rsValue=ADCW;

Ардуина сама разберётся как правильно...))

Добавлено after 3 minutes 42 seconds:
[uquote="olegue",url="/forum/viewtopic.php?p=4245732#p4245732"]когда оцифровка звука не работает второй канал показывает на экране правильные результаты.[/uquote]
а результаты чего ? интересно))
Реклама
Аватара пользователя
olegue
Собутыльник Кота
Сообщения: 2977
Зарегистрирован: Сб май 21, 2016 11:04:52
Откуда: Беларусь

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

Сообщение olegue »

roman.com, результат оцифровки напряжения . Ну типа вольтметр там получается.
Реклама
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

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

Сообщение Dimon456 »

olegue писал(а):Опишите хотя бы основные задачи
Ха, какие задачи, борьба за лишние такты.
roman.com, "господин с минусом", сколько тактов, примерно, тратится на преобразование АЦП?
Одинаковое ли количество тактов вне зависимости от результата преобразования?

А вообще что вас в моем коде смущает? Этот код с этого форума, перетрясли на сотню рядов, и проверили на реальном железе, если бы он не работал я бы не предлагал.
Образец записанного фала, допустим частота 1кГц, именно протеусом надо для сравнения? В железе сами будете проверять.
roman.com
Друг Кота
Сообщения: 9147
Зарегистрирован: Вт мар 13, 2012 12:16:13
Откуда: .ru

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

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

Dimon456 зачем примерно)) можно точно))
Одинаковое ли количество тактов вне зависимости от результата преобразования?
такты от результата не зависят))
[uquote="olegue",url="/forum/viewtopic.php?p=4245866#p4245866"]в момент одновременной работы двух каналов значения

rsValue=(ADCL|ADCH<<8);

становятся неадекватными, уходят в минус, например, удваиваются, начинают "прогать", хотя когда 2й канал не занят оцифровкой звука показывает все правильно[/uquote]
в AVR (например ATmega8 и др.) есть интересное явление...
каналы ADC имеют паразитную внутреннюю связь между собой...

например:
допустим pin 0 у нас подключён к батарейки 3,3 вольта.
допустим pin 1 у нас висит в воздухе (никуда не подключён).

когда мы измеряем напряжение на pin 0 то получаем 3,3 вольта.
когда мы измеряем напряжение на pin 1 то получаем те же 3,3 вольта. !

как так ? pin 1 у нас висит в воздухе (никуда не подключён) !
а просто напряжение 3,3 вольта из pin 0 попадает на pin 1 через внутренние паразитные связи мультиплексора ADC...

входное сопротивление пинов ADC имеют высокое входное сопротивление (>1MOм).
поэтому выходное сопротивление источника напряжение должно быть низким.

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

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

Сообщение olegue »

roman.com писал(а):а ещё в даташите написано чётко - все неиспользуемые пины МК должны быть подключены на массу))
а вот это надо бы попробовать
Martian
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32
Контактная информация:

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

Сообщение Martian »

есть мнение, что кое-кто опять соврал:

If some pins are unused, it is recommended to ensure that these pins have a defined
level. Even though most of the digital inputs are disabled in the deep sleep modes as
described above, floating inputs should be avoided to reduce current consumption in all
other modes where the digital inputs are enabled (Reset, Active mode and Idle mode).
The simplest method to ensure a defined level of an unused pin, is to enable the internal
pull-up. In this case, the pull-up will be disabled during reset. If low power consumption
during reset is important, it is recommended to use an external pull-up or pull-down.
Connecting unused pins directly to VCC or GND is not recommended, since this may
cause excessive currents if the pin is accidentally configured as an output.

страница 56 даташита 486P–AVR–02/06 ATmega8
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

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

Сообщение Dimon456 »

Martian писал(а):есть мнение, что кое-кто опять соврал:
да он много где соврал.

Мне вот интересно
Спойлер

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

ISR(TIMER2_COMPA_vect) {

  rsValue = ADCW;

  ADMUX = 0x41; // set ADC to read pin A0, ADLAR to 1 (right adjust)
  sbi(ADCSRA, ADSC); // start ADC sample
  while (bit_is_set(ADCSRA, ADSC)); // wait until ADSC bit goes low = new sample ready

  uint8_t temp = ADCW >> 2;

  ADMUX = 0x40; // set ADC to read pin A1, ADLAR to 1 (right 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] = (temp);
  }
  if (bufWrite == 1) {
    buf01[bufByteCount] = (temp);
  }
}
Сколько я им тактов сэкономил?
Еще когда писал - чего ждем? Седьмого пришествия?
roman.com
Друг Кота
Сообщения: 9147
Зарегистрирован: Вт мар 13, 2012 12:16:13
Откуда: .ru

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

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

[uquote="Martian",url="/forum/viewtopic.php?p=4245915#p4245915"]Connecting unused pins directly to VCC or GND is not recommended, since this may
cause excessive currents if the pin is accidentally configured as an output.[/uquote]
по-русски:
поскольку это может привести к чрезмерным токам, если источник питания СЛУЧАЙНО настроен в качестве выходного...
:)))
что значит СЛУЧАЙНО ???
т.е. ваш МК делает не то что вы ему говорите... а потому что ваш МК сам так захотел ! )))
:)))
что вы за программисты такие... что ваш МК делает что то без вашего разрешения ! )))
это просто какой то пипец ! )))
:))) :))) :)))
Martian
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32
Контактная информация:

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

Сообщение Martian »

Dimon456 писал(а):Мне вот интересно
Кстати, да. Хотя бы от одного while, но избавились.

Добавлено after 8 minutes 11 seconds:
roman.com, что это за программист, который врёт про то, что написано в даташитах, не знает про блокировки регистров, не понимает необходимости обработки аварийных событий и различных явлений, связанных с "горячим" сбросом, верит в непогрешимость свою и железа? И в данном случае, я уж точно доверюсь специалистам Атмел и прочих компаний, которые точно так же рекомендуют либо переводить порт принудительно в какое-либо состояние, исключающее паразитные явления, либо внешней подтяжкой через резистор, чем какому-то дилетанту, любящему рисовать картинки со стрелочками и кучу лишних смайликов.
Вот из-за таких, как roman.com, ардуино стала одуриной.
P.S. и даже перевести нормально не смог.
roman.com
Друг Кота
Сообщения: 9147
Зарегистрирован: Вт мар 13, 2012 12:16:13
Откуда: .ru

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

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

olegue писал(а):а вот это надо бы попробовать
попробуй ещё добавить стабилизацию входа... как советует даташит.

ISR(TIMER2_COMPA_vect) {
ADMUX = 0x40; // set ADC to read pin A0, ADLAR to 1 (right adjust)

delay_us(10); // стабилизация входа...

sbi(ADCSRA, ADSC); // start ADC sample
while (bit_is_set(ADCSRA, ADSC)); // wait until ADSC bit goes low = new sample ready
rsValue=ADCW;
...

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

в твоём случае (с учетом ограничениями таймера = 45 мкс) можно не ставить задержку delay_us(10), а сделать по другому...

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
rsValue=ADCW;


ADMUX = 0x41; // set ADC to read pin A1, ADLAR to 1 (right 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] = (ADCW>>2);
}
if (bufWrite == 1) {
buf01[bufByteCount] = (ADCW>>2);
}

ADMUX = 0x40; // set ADC to read pin A0, ADLAR to 1 (right adjust)
}

в этом случае, при следующем прерывании таймера, мультиплексор уже окажется подключён к каналу 0.
а так как следующее прерывание таймера наступит через 45 мкс... то за это время напряжение на канале 0 уже "устаканится"... ))
:tea:

стабилизация входа... нужна только при точных измерениях.
при записи звука точность не требуется.
:tea:

Добавлено after 32 minutes 21 second:
а тут что ты делаешь ?

////////////// НАЧИНАЕМ С ОБРАБОТКИ ВХОДА А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;
///////////////////////
}
}

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

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

Сообщение olegue »

roman.com, здесь я придумал 2 таймера

вот первый - каждый 50мс запускаем преобразование АЦП
и накапливаем их в переменной

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

// Каждые 50 мс мы накапливаем значения (для усреднения)
if (timerRSon==0){
timerRS=millis(); 
timerRSon=1;

}
if (timerRSon==1){
if (millis()-timerRS>50)
{

rsValue=analogRead(A0);
SrV=SrV+rsValue;

timerRSon=0;
}

вот второй, следует за первым по коду
этот цикл каждый 1000мс

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

// Каждые 1000 мс мы отображаем усредненное значение
if (timerLCLon==0){ 
timerLCL=millis(); 
timerLCLon=1;
}
if (timerLCLon==1){
if (millis()-timerLCL>1000)
{
lcd.setCursor(0,0);
SrVmid=SrV/20;   /// Когда попали сюда уже накопили 20 значений поэому делим на 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);

timerLCLon=0;
SrV=0;

}
}

в цифоровых вольтметрах делают тоже самое , но как-то по другом. Но я не нашел готовый год поэтому решил поупражняться с millis()

Добавлено after 2 minutes 39 seconds:
Измеряемое напряжение несколько нестабильно , ну скажем 0.116-0.123. Меня устроит стабильное показание усредненной величины.


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

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

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

olegue писал(а):Измеряемое напряжение несколько нестабильно , ну скажем 0.116-0.123. Меня устроит стабильное показание усредненной величины.
выше кидал кусок кода с фильтром для стабильного показания напряжения...
фильтр - это программная триггер-защелка... для устранения шума квантования ADC...

//объявляем переменные...
int a;
int u, ub;

//измеряем ADC...
adc(7);

//результат ADC фильтруем...
a=ADCW/2;
if (a>ub+1) {u=a/2; ub=a;};
if (a<ub-1) {u=a/2; ub=a;};

//отфильтрованный результат в переменной u

в троём коде будет так:

unsigned int a = 0;
unsigned int u = 0;
unsigned int ub = 0;

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

//результат ADC фильтруем...
a=ADCW/2;
if (a>ub+1) {u=a/2; ub=a;};
if (a<ub-1) {u=a/2; ub=a;};
rsValue=u;
...
...
...

усреднения не нужны))
:tea:

а у тебя есть индикатор уровня записи ? ))

а можно вообще... сделать аудио редактор ))
диктофон.jpg
(48.58 КБ) 48 скачиваний
:)
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

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

Сообщение Dimon456 »

Какой упрямый человек.
У тебя АЦП работает на запредельных частотах, да еще и между каналами прыгает, там одного только шума квантования будет предостаточно, из 8 то бит бит 5 будет так хорошо.
Ведь показал самый быстрый код усреднения.
Накапливаешь в переменную примерно за 0,4 секунды 8192 измерения и сдвигаешь на 13 бит. Ты где был когда эту тему проходили здесь?

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

В результате со всеми вытекающими последствиями.

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

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

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

нет... не всё))

все эти ваши усреднения... до фени ! показания как прыгали так и будут прыгать))
лучше выкинуть таймер с дуратскими усреднениями... и отдать такты фильтру...

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

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

Сообщение olegue »

ХОрошо, а вот кто нить заметил, что я свой таймер вызываю раз в 50мс и там проходит оцифровка напряжения. А если я в таймер 22кгц ставлю это преобразование то оно будет сильно часто вызывать а в этом нет никакой нужды Прокомментируейт пож!
Martian
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32
Контактная информация:

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

Сообщение Martian »

я бы перевел либо 22кГц в мс, либо 50мс в кГц, а то сравнивать неудобно...

то есть 22 кГц и 20 Гц.

Ну, если мощности мк не хватает на два канала, то, наверное, какой-то шум на 20Гц вряд ли был бы заметен. к тому же его можно минимизировать, записывая в момент обработки второго канала и в данные аудио, просто дублируя последние.

Однако, мне не верится, что этот мк не способен справиться.
Ответить

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