Использование прерываний аналогового компаратора параллельно с прерываниями счётчика на arduino mega 2560

unisonic
Offline
Зарегистрирован: 09.01.2018

Mega 2560 через аналоговый вход должна снимать данные о напряжении на нём. На входе присутствует сигнал, схожий по форме с синусоидой с частотой около 3Гц. Стоит задача считать колебания. Каждый, скажем, десятый цикл является контрольным. В этом цикле необходимо каждую миллисекунду снимать значение с АЦП и записывать их в массив. Допустим их 370. По окончании цикла определяется его период по количеству значений, и далее идёт расчёт теоретического значения для каждой точки (370 раз по сложной функции, в которой присутствуют вычисления с плавающей точкой и тригонометрические функции) и сравнение с полученными значениями. Результаты по ошибкам отправляются в серийный порт.

Если коротко - вычисляется абсолютная ошибка реальных значений относительно рассчитанных. И времени этот процесс займёт много, поэтому он будет производиться периодически.

Я вижу всё это так:
1. Аналоговый компаратор, настроенный на внутреннее опорное напряжение 2.56В, при каждом изменении состояния взывает прерывание и увеличивает счётчик. Два тика счетчика - одно колебание;
2. Когда наступает время для контрольного периода, начинают происходить прерывания по таймеру каждую миллисекунду, в которых происходит получение данных с АЦП и запись значения в массив;
3. По окончании контрольного замера начинаются длительные и неспешные расчёты.

Ну а теперь вопросы...

По п.1: А, собственно, куда подключать входное напряжение? AIN0 у меги вообще не выведен с МК, только внутренние источники, а AIN1 выведен на цифровой пин 5. Как цифровой пин будет принимать аналоговый сигнал? И как изменить опорное напряжение на 2.56? Везде написано "на меге возможно переключение с 1.1 на 2.56".

По п.2: как расставить приоритеты прерываний? У меня прерывание компаратора должно быть приоритетнее прерывания по таймеру. Также, наверное, в теле каждого прерывания надо в начале запрещать прерывания, а в конце разрешать, чтобы не произошло прерывание в прерывании?
А сколько времени займёт получение данных с АЦП в теле прерывания и запись в массив? Меньше 1мс? 

По п.3 вопросов, вроде, нет, прерывание счётчика будет останавливать расчёты, а по окончании прерывания продолжать их.

Заранее спасибо всем отозвавшимся =)

unisonic
Offline
Зарегистрирован: 09.01.2018

Вопрос с подключением отпал. Кинул с A0 на D5 провод и заработало. Вот только работает как-то совсем не так, как ожидалось. До 1.1В на входе компаратора ничего не происходит. А вот при любых изменениях выше 1.1В происходят прерывания. При увеличении напряжения и при уменьшении. 

volatile uint16_t count=0;
int prCount=0;
void setup(){
Serial.begin(9600);
pinMode(5,INPUT);
ACSR=(1<<ACBG)|(1<<ACIE)|(1<<ACIS1)|(1<<ACIS1); 
// включить компаратор, включить сравнении с ион, включить прерывание
}
ISR (ANALOG_COMP_vect) { 
count++;
}
void loop() {
if(count != prCount){  
Serial.println(count);
prCount=count;
}
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А чего две темы? Два прерывания надо использовать, что-ли?

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

unisonic пишет:

начинают происходить прерывания по таймеру каждую миллисекунду, в которых происходит получение данных с АЦП

....

А сколько времени займёт получение данных с АЦП в теле прерывания и запись в массив? Меньше 1мс? 

Это смотря как получать собираешься. Если аккуратно, то меньше, а если как попало, то как полуичтся.

unisonic пишет:

в теле каждого прерывания надо в начале запрещать прерывания, а в конце разрешать, чтобы не произошло прерывание в прерывании?

Это и без тебя уже аппаратно делается - не лезь туда.

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

unisonic пишет:

...сигнал, схожий по форме с синусоидой с частотой около 3Гц. Стоит задача считать колебания.

...необходимо каждую миллисекунду снимать значение с АЦП

Вы что-нибудь о теореме Котельникова-Шеннона слышали?

unisonic
Offline
Зарегистрирован: 09.01.2018

Слышал. А к чему Вы это?

Проблема в том, что частота не постоянна. Требуемый период - 0.37мс. И МК постоянно будет пытаться подогнать период колебаний под заданный посредством изменения скважности ШИМ на питание электродвигателя с каким-то допуском.

Поэтому придётся записывать данные в массив с какой-то дискретностью, а по окончании периода (узнав его длительность) считать по функции теоретические значения и сравнивать с полученными.

Можно сделать как-то иначе?

P.S. После раздумий и совещания с умным человеком было решено отказаться нафиг от компаратора и тупо мерить по таймеру раз в миллисекунду напряжение. Тут будет и период определяться, и сразу замеры для контрольного цикла. Уж больно много проблем с внутренним компаратором... А городить внешний с положительной обратной связью для получения гистерезиса нецелесообразно.