Ардуино - запись звука
Re: Ардуино - запись звука
-
Последний раз редактировалось roman.com Ср июн 15, 2022 10:15:41, всего редактировалось 1 раз.
- Реклама
Re: Ардуино - запись звука
Dimon456, очень мало коментов в Вашем кода. Опишите хотя бы основные задачи, мне разобраться и уловить основную мысль руководствуясь только кодом очень трудно.
Re: Ардуино - запись звука
[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);
}
напиши вот так и забудь об этом))
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);
}
Re: Ардуино - запись звука
roman.com,
rsValue=analogRead(A0);
если так то работает идеально,
.....
rsValue=(ADCL|ADCH<<8);
эта строка тоже работает аналогично, и дает те же значения.
но в момент одновременной работы двух каналов значения
rsValue=(ADCL|ADCH<<8);
становятся неадекватными, уходят в минус, например, удваиваются, начинают "прогать", хотя когда 2й канал не занят оцифровкой звука показывает все правильно
Добавлено after 1 minute 42 seconds:
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
Re: Ардуино - запись звука
тут ты делаешь всё сам... вручную))
rsValue=(ADCL|ADCH<<8);
тут ты перекладываешь всю ответственность за ADCL и ADCH на Ардуину))
rsValue=ADCW;
Ардуина сама разберётся как правильно...))
Добавлено after 3 minutes 42 seconds:
[uquote="olegue",url="/forum/viewtopic.php?p=4245732#p4245732"]когда оцифровка звука не работает второй канал показывает на экране правильные результаты.[/uquote]
а результаты чего ? интересно))
rsValue=(ADCL|ADCH<<8);
тут ты перекладываешь всю ответственность за ADCL и ADCH на Ардуину))
rsValue=ADCW;
Ардуина сама разберётся как правильно...))
Добавлено after 3 minutes 42 seconds:
[uquote="olegue",url="/forum/viewtopic.php?p=4245732#p4245732"]когда оцифровка звука не работает второй канал показывает на экране правильные результаты.[/uquote]
а результаты чего ? интересно))
- Реклама
Re: Ардуино - запись звука
roman.com, результат оцифровки напряжения . Ну типа вольтметр там получается.
Re: Ардуино - запись звука
Ха, какие задачи, борьба за лишние такты.olegue писал(а):Опишите хотя бы основные задачи
roman.com, "господин с минусом", сколько тактов, примерно, тратится на преобразование АЦП?
Одинаковое ли количество тактов вне зависимости от результата преобразования?
А вообще что вас в моем коде смущает? Этот код с этого форума, перетрясли на сотню рядов, и проверили на реальном железе, если бы он не работал я бы не предлагал.
Образец записанного фала, допустим частота 1кГц, именно протеусом надо для сравнения? В железе сами будете проверять.
Re: Ардуино - запись звука
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м).
поэтому выходное сопротивление источника напряжение должно быть низким.
а ещё в даташите написано чётко - все неиспользуемые пины МК должны быть подключены на массу))
Одинаковое ли количество тактов вне зависимости от результата преобразования?
такты от результата не зависят))
[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м).
поэтому выходное сопротивление источника напряжение должно быть низким.
а ещё в даташите написано чётко - все неиспользуемые пины МК должны быть подключены на массу))
Re: Ардуино - запись звука
а вот это надо бы попробоватьroman.com писал(а):а ещё в даташите написано чётко - все неиспользуемые пины МК должны быть подключены на массу))
Re: Ардуино - запись звука
есть мнение, что кое-кто опять соврал:
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
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
Re: Ардуино - запись звука
да он много где соврал.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);
}
}Еще когда писал - чего ждем? Седьмого пришествия?
Re: Ардуино - запись звука
[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]
по-русски:
поскольку это может привести к чрезмерным токам, если источник питания СЛУЧАЙНО настроен в качестве выходного...
что значит СЛУЧАЙНО ???
т.е. ваш МК делает не то что вы ему говорите... а потому что ваш МК сам так захотел ! )))
что вы за программисты такие... что ваш МК делает что то без вашего разрешения ! )))
это просто какой то пипец ! )))

cause excessive currents if the pin is accidentally configured as an output.[/uquote]
по-русски:
поскольку это может привести к чрезмерным токам, если источник питания СЛУЧАЙНО настроен в качестве выходного...
что значит СЛУЧАЙНО ???
т.е. ваш МК делает не то что вы ему говорите... а потому что ваш МК сам так захотел ! )))
что вы за программисты такие... что ваш МК делает что то без вашего разрешения ! )))
это просто какой то пипец ! )))
Re: Ардуино - запись звука
Кстати, да. Хотя бы от одного while, но избавились.Dimon456 писал(а):Мне вот интересно
Добавлено after 8 minutes 11 seconds:
roman.com, что это за программист, который врёт про то, что написано в даташитах, не знает про блокировки регистров, не понимает необходимости обработки аварийных событий и различных явлений, связанных с "горячим" сбросом, верит в непогрешимость свою и железа? И в данном случае, я уж точно доверюсь специалистам Атмел и прочих компаний, которые точно так же рекомендуют либо переводить порт принудительно в какое-либо состояние, исключающее паразитные явления, либо внешней подтяжкой через резистор, чем какому-то дилетанту, любящему рисовать картинки со стрелочками и кучу лишних смайликов.
Вот из-за таких, как roman.com, ардуино стала одуриной.
P.S. и даже перевести нормально не смог.
Re: Ардуино - запись звука
попробуй ещё добавить стабилизацию входа... как советует даташит.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 уже "устаканится"... ))
стабилизация входа... нужна только при точных измерениях.
при записи звука точность не требуется.
Добавлено 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;
///////////////////////
}
}
как ты подключаешь батарейку ? где схема ?
и зачем накапливаем ? и зачем усреднения ?
Re: Ардуино - запись звука
roman.com, здесь я придумал 2 таймера
вот первый - каждый 50мс запускаем преобразование АЦП
и накапливаем их в переменной
вот второй, следует за первым по коду
этот цикл каждый 1000мс
в цифоровых вольтметрах делают тоже самое , но как-то по другом. Но я не нашел готовый год поэтому решил поупражняться с millis()
Добавлено after 2 minutes 39 seconds:
Измеряемое напряжение несколько нестабильно , ну скажем 0.116-0.123. Меня устроит стабильное показание усредненной величины.
ну это я делал на analogRead, а потом уже начал делать чисто на регистрах и на таймере , который цифрует звук.
вот первый - каждый 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, а потом уже начал делать чисто на регистрах и на таймере , который цифрует звук.
Re: Ардуино - запись звука
выше кидал кусок кода с фильтром для стабильного показания напряжения...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;
...
...
...
усреднения не нужны))
а у тебя есть индикатор уровня записи ? ))
а можно вообще... сделать аудио редактор ))
Re: Ардуино - запись звука
Какой упрямый человек.
У тебя АЦП работает на запредельных частотах, да еще и между каналами прыгает, там одного только шума квантования будет предостаточно, из 8 то бит бит 5 будет так хорошо.
Ведь показал самый быстрый код усреднения.
Накапливаешь в переменную примерно за 0,4 секунды 8192 измерения и сдвигаешь на 13 бит. Ты где был когда эту тему проходили здесь?
Ты когда на флешку собираешься писать? Тебе каждый такт важен, чем меньше тактов в прерывании тем лучше.
Ты, наверное, запамятовал, что у тебя еще один таймер каждые 1мс долбится, отбирая твои драгоценные такты, которые на вес золота.
В результате со всеми вытекающими последствиями.
Усе. Точка на этом.
У тебя АЦП работает на запредельных частотах, да еще и между каналами прыгает, там одного только шума квантования будет предостаточно, из 8 то бит бит 5 будет так хорошо.
Ведь показал самый быстрый код усреднения.
Накапливаешь в переменную примерно за 0,4 секунды 8192 измерения и сдвигаешь на 13 бит. Ты где был когда эту тему проходили здесь?
Ты когда на флешку собираешься писать? Тебе каждый такт важен, чем меньше тактов в прерывании тем лучше.
Ты, наверное, запамятовал, что у тебя еще один таймер каждые 1мс долбится, отбирая твои драгоценные такты, которые на вес золота.
В результате со всеми вытекающими последствиями.
Усе. Точка на этом.
Re: Ардуино - запись звука
нет... не всё))
все эти ваши усреднения... до фени ! показания как прыгали так и будут прыгать))
лучше выкинуть таймер с дуратскими усреднениями... и отдать такты фильтру...
где ты был когда мы это всё подробно разбирали...

все эти ваши усреднения... до фени ! показания как прыгали так и будут прыгать))
лучше выкинуть таймер с дуратскими усреднениями... и отдать такты фильтру...
где ты был когда мы это всё подробно разбирали...
Re: Ардуино - запись звука
ХОрошо, а вот кто нить заметил, что я свой таймер вызываю раз в 50мс и там проходит оцифровка напряжения. А если я в таймер 22кгц ставлю это преобразование то оно будет сильно часто вызывать а в этом нет никакой нужды Прокомментируейт пож!
Re: Ардуино - запись звука
я бы перевел либо 22кГц в мс, либо 50мс в кГц, а то сравнивать неудобно...
то есть 22 кГц и 20 Гц.
Ну, если мощности мк не хватает на два канала, то, наверное, какой-то шум на 20Гц вряд ли был бы заметен. к тому же его можно минимизировать, записывая в момент обработки второго канала и в данные аудио, просто дублируя последние.
Однако, мне не верится, что этот мк не способен справиться.
то есть 22 кГц и 20 Гц.
Ну, если мощности мк не хватает на два канала, то, наверное, какой-то шум на 20Гц вряд ли был бы заметен. к тому же его можно минимизировать, записывая в момент обработки второго канала и в данные аудио, просто дублируя последние.
Однако, мне не верится, что этот мк не способен справиться.


