2017-02-22 52 views
1

Я сделал базовый генератор сигналов с Arduino Uno и резисторной лестницей на макете. Я изменяю уровень напряжения по мере необходимости с помощью функции loop и micros() для задержки между каждым изменением напряжения. Это не идеально, но хорошо работает с пьезо.analogRead занимает слишком много времени

Моя проблема в том, что я установил частоту сигнала в своем коде, и я хотел бы иметь возможность изменить его, используя банк, например. Но как только я положил analogRead где-то в моем коде (весь код находится в функции loop()), выходной сигнал изменяется. Я обнаружил, что функция analogRead может занять до 100 мкс, чтобы бежать, и это больше, чем задержка между изменением напряжения так фактическим периодом сигнала не является правильным:

unsigned long now, next; 
int freq; 

void loop(){ 

    //if I put analogRead() here it takes to much time 

    now = micros(); 

    if(now >= next){ 
     //Here I change the output analog value using a R-2R ladder 
     //then I change the value of next 
    } 
} 

Я попробовал несколько решений, в том числе с помощью переключателей вместо банка, но digitalRead в сочетании с утверждением if не кажутся более эффективными. Я также пробовал переключатели с прерываниями, но результат такой же, как и с digitalRead.

Кто-нибудь знает другое решение?

Спасибо!

+0

могли бы вы предоставить описание вашей * попытка прерывания на основе *? мне кажется, что вытеснить обработку вывода из * loop() * в подпрограмму обслуживания прерываний * должно быть возможным. Это должно позволить вам использовать 'analogRead()' без изменения сигнала, который все равно будет имеют приоритет благодаря обработке * прерываний * .. или я ошибаюсь? –

ответ

2

analogRead ожидает завершения преобразования, поэтому, если вы хотите сделать что-то еще, вам придется обрабатывать его по-разному.

Вы можете использовать прерывание ADC и режим свободного хода. Или вы можете инициировать цикл преобразования АЦП несколькими источниками, такими как сравнение таймера.

Или вы можете сделать это с помощью подхода, основанного на «событии», - проверив, что преобразование АЦП выполнено, и сбросьте его, написав логику один на этот флаг.

// in setup: 
ADCSRA |= _BV(ADATE); // enable auto trigger mode 
ADCSRB = 0; // free running mode for the auto trigger 

// and in the loop: 
if (ADCSRA & _BV(ADIF)) { 
    value = ADC; // get ADC value 
    ADCSRA |= _BV(ADIF); // reset flag by writing logic one into it 
    // whatever you want with the current value 
    // or ADCSRA |= _BV(ADSC); // start another conversion if you don't want free running mode 
} 

Btw: макро _BV(BIT) заменяется на 1<<(BIT) (если вам интересно, почему я использую его)

+0

Спасибо за ваш ответ! Я проверю это, но я думаю, это занимает меньше времени, чем аналог Arduino – 695nb