Скорость АЦП. Не понятное поведение
- Войдите на сайт для отправки комментариев
Здравствуйте. Пытаюсь понять сколько раз в секунду можно получить результат из АЦП.
Исходные данные: Arduino nano, atmega328, 16Мгц
написал тестовый скетч, вот он:
volatile unsigned int count=0;
volatile int analogVal;
ISR(ADC_vect){
//Считаем сколько раз возникло прерывание, раз в секунду в loop обнуляем
analogVal = ADCH;
count++;
}
void setup() {
Serial.begin(115200);
ADCSRA = 0;
ADCSRB = 0;
ADMUX = 0;
//REFS=01 - ACC
ADMUX |= (1<<REFS0);
ADMUX |= (1<<ADLAR);
ADCSRA |= (1<<ADEN);
ADCSRA |= (1<<ADATE);
ADCSRA |= (1<<ADIE);
//Предделитель. Макс скорость при предделителе = 32
ADCSRA |= (1<<ADPS2);
ADCSRA |= (0<<ADPS1);
ADCSRA |= (1<<ADPS0);
//Стартуем
sei();
ADCSRA |= (1<<ADSC);
}
void loop() {
unsigned int temp;
cli();
temp=count;
count=0;
sei();
Serial.println(temp);
delay(1000);
}
Проблема в следующем. Опытным путем выяснил что при предделителе = 32 (ADPS2:0 = 101) скорость максимальна, count = 38463
При уменьшении предделителя скорость падает в 3 раза, например при предделителе = 16 (ADPS2:0 = 100), ADCSRA |= (1<<ADPS2);
ADCSRA |= (0<<ADPS1);
ADCSRA |= (1<<ADPS0);
count = 11392
Итак, вопрос. это я где то накосячил или нет. если код в порядке то в чем проблема? Ведь при уменьшении предделителя частота выборки должна увеличиваться, а у меня уменьшается начиная с 32.
Приведу цифры(предделитель -> count):
128 -> 9618
64 -> 19236
32 -> 38463
16 -> 11392
8 -> 22819
4 -> 45910
2 -> 49623 //в документации написано что max скорость = 76.9kSPS, если я правильно ее понял
Почему при предделителе равном 16 такое аномальное значение?
Не вчитывался, но сразу видно что в unsigned int ничего не влезет, меняйте на unsigned long и все встанет на свои места
Тут в проектах есть несколько тем за осцилоскопы. Максимально, что мне удалось выжать с Нанки это 490 ksps с одной ноги АЦП .. кажется, точно не помню. Код не смотрел, но по прерываниям скорость в целом получается низкая из-за пролога и эпилога обработчика прерывания. В отличии от Мега2560, Нано нормально гонится до 27Мгц включительно, но на скорости АЦП это практически не сказывается.
79ksps это предельная скорость работы мультиплексора АЦП и при прямом чтении достигается на частоте АЦП = 1Мгц. Это для нормального сигнала. Для диф.режима 15ksps похоже "пердел".
По идее должно хватить. по документации максимальная частота Ацп 79000 выборок в секунду. т е на минимальном значении предделителя счетчик бы переполнился и значение было бы в районе 15000.
сделаю позже 4 байта, но помоему проблема не в этом
А я вот тогда не поленился взял уно взял ваш скетч и поигрался, поэтому пишу не с потолка. При предделителе 2 было значение если память не изменяет 250к или это на div4 было. В общем во всяком случае логика будет правильная, при уменьшении предделителя переменная будет увеличиваться. А дальше уже надо смотреть сколько там kSPS можно выжать
У вас какой контроллер?
Поменял на long, ничего не изменилось. Добавил проверку переполнения:
volatile unsigned long count=0; volatile unsigned long count2=0; volatile int analogVal; ISR(ADC_vect){ //Считаем сколько раз возникло прерывание, раз в секунду в loop обнуляем analogVal = ADCH; count++; if(count>1000000)count2++; }Переполнения не происходит. И самое непонятное, при предделителе 2 частота выросла до 52000. если ничего более не меняя закомментить строку "if(count>1000000)count2++;" значение count = 35300, хотя в прошлый раз было около 49к. я вообще перестал понимать что происходит, похоже нужно деасемблировать и смотреть что там накручено оптимизатором.
может дело в том что это китайский клон ардуины с алиэксперсса?
У меня китайская уна на 328атмеге. Дома буду еще раз скомпилирую и пришлю
Да, кстати, а в 38 строке меняли инт?
У меня с вашим кодом при делителе 2 и 4 получается 258к при делителе 8 получается 158к ну и так далее по убывающей
Огромное спасибо, действительно проблема в этом!
У меня при делителе 2 и 4 получается ~230к. вероятно в документации указано для частоты 1 мгц, не думал что частота будет 230к в сек...