2017-02-22 1 views
1

J'ai créé un générateur de formes d'onde de base avec un Arduino Uno et une échelle de résistance sur une planche à pain. Je change le niveau de tension au besoin en utilisant la fonction loop et micros() pour retarder entre chaque changement de tension. Ce n'est pas parfait mais ça marche bien avec un piezo.analogRead prend trop de temps

Mon problème est que je règle la fréquence du signal dans mon code et je voudrais pouvoir le changer en utilisant un pot par exemple. Mais dès que je mets un analogRead quelque part dans mon code (tout le code est dans la fonction loop()) le signal de sortie change. J'ai découvert que la fonction analogRead peut prendre jusqu'à 100 us pour exécuter, et c'est plus grand que le délai entre chaque changement de tension de sorte que la période de signal réel est incorrect:

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 
    } 
} 

J'ai essayé quelques solutions, y compris des commutateurs à d'un pot, mais digitalRead combiné avec si l'instruction ne semble pas plus efficace. J'ai également essayé des commutateurs avec des interruptions mais le résultat est le même qu'avec digitalRead.

Est-ce que quelqu'un connaît une autre solution?

Merci!

+0

pourriez-vous s'il vous plaît fournir une description de votre tentative * basée interruption *? il me semble que pousser votre sortie de * loop() * vers une routine de service * interruptions devrait être le chemin à suivre .. cela devrait vous permettre d'utiliser 'analogRead()' sans altérer le signal, ce qui serait encore prendre la priorité grâce à être manipulé avec * interruptions * .. ou ai-je tort? –

Répondre

2

Le analogRead attend jusqu'à ce que la conversion soit terminée, donc si vous voulez faire quelque chose d'autre, vous devez le gérer différemment.

Vous pouvez utiliser l'interruption ADC et le mode libre. Ou vous pouvez déclencher le cycle de conversion ADC par plusieurs sources comme la comparaison de minuterie. Ou vous pouvez le faire par l'approche "événement" - en vérifiant que la conversion ADC est faite et réinitialiser en écrivant une logique à ce drapeau.

// 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: macro _BV(BIT) est remplacé à 1<<(BIT) (si vous vous demandez pourquoi je l'utilise)

+0

Merci pour votre réponse! Je vais le tester mais je suppose que cela prend moins de temps que l'AnalRead de l'Arduino – 695nb