ADC (mal wieder) sehr schnell auslesen - andere Programmteile gestört?

OP Persönliche Seite #3471772
Lesenswert?

Hallo,
ich melde mich wieder einmal mit einer kleinen Frage:
ich habe nun folgendes Code-Stück für einen mega2560
1
ISR(ADC_vect)
2
{
3
  //saves the channel that is currently to read
4
  static uint8_t adcCounter=0;
5
  //an ADC-value is arrived, so we can save it in the array
6
  adc[adcCounter]=ADCH;
7
  //increase the channel or set it to zero if all channels are read
8
  if(adcCounter<15) ++adcCounter;
9
  else adcCounter = 0;
10
  //so we can start the next meassure
11
  ADMUX=(adcCounter & 0x7)|(1<<ADLAR);
12
  ADCSRB = (ADCSRB & ~(1<<MUX5)) | (adcCounter & (1<<MUX5));
13
  ADCSRA|=(1<<ADIF)|(1<<ADSC);
14
}//ISR ADC_vect
Wenn mein Kollege nicht völlig verkokst war, als er es gecodet hat, 
sollte es nach dem ersten auslesen des ADCs immer wieder alle Kanäle 
nacheinander auslesen.
Soweit, so gut, und hoffentlich noch fehlerfrei ;)

Nur kam mir vorhin die Idee, dass die ISR vielleicht zu schnell 
hintereinander aufgerufen wird und dabei andere Programmteile behindert. 
Es gibt nämlich nebenbei noch 5 SRF05-Ultraschallsensoren auszulesen, 
und alle werte und die von 4 Lichtsensoren auszuwerten und zu reagieren, 
sowie die PWM für 4 Motoren zu generieren.
Im Data-Sheet steht etwas von 13us-260us. Welcher wert ist eher 
realistisch?
Was sagen die Profis dazu?
Und funktioniert das "Konzept" überhaupt.
Takt ist übrigens 16MHz. Der ADC-Prescaler ist 16
Wer noch Fragen hat, nur zu, ich hab sowieso was vergessen ;)

mfG
N.G.
#3471791
Lesenswert?

@ N. G. (newgeneration)

>Wenn mein Kollege nicht völlig verkokst war, als er es gecodet hat,
>sollte es nach dem ersten auslesen des ADCs immer wieder alle Kanäle
>nacheinander auslesen.
>Soweit, so gut, und hoffentlich noch fehlerfrei ;)

Jo.

>Nur kam mir vorhin die Idee, dass die ISR vielleicht zu schnell
>hintereinander aufgerufen wird und dabei andere Programmteile behindert.

So schnell, wie der ADC halt läuft. Er braucht 13 Takte pro Wandlung.

>Es gibt nämlich nebenbei noch 5 SRF05-Ultraschallsensoren auszulesen,
>und alle werte und die von 4 Lichtsensoren auszuwerten und zu reagieren,
>sowie die PWM für 4 Motoren zu generieren.

Alles eine Frage der Organisation.

>Im Data-Sheet steht etwas von 13us-260us. Welcher wert ist eher
>realistisch?

Rechnen?

>Was sagen die Profis dazu?
>Und funktioniert das "Konzept" überhaupt.

Im Prinzip schon.

>Takt ist übrigens 16MHz. Der ADC-Prescaler ist 16

Mach 1 MHz ADC-Takt, bissel viel, geht aber.
13 Takte sind dann 13 us. Dazu kommt die Laufzeit der ISR.
Damit ist dein AVR gut beschäftigt, denn es sind nur 13*16=208 Takte 
zwischen den ISR Aufrufen.

Wenn es determinierter sein soll, könnte man ggf. die zeitkritischen 
Dinge zusammenfassen und per Timer aufrufen.
OP Persönliche Seite #3471811
Lesenswert?

Danke Falk. Also nach deiner Erklärung is mir auch klar, dass meine 
Zweifel berechtigt sind. Das wird verdammt eng. ich glaub das geht so 
nicht

Würde alternativ dieser Code in der PWM-ISR (alle 40us) funktionieren?
1
static bool adcMeasureStarted=false;
2
static uint8_t adcCounter=0;//Next channel to be read
3
if(adcCounter>15) adcCounter=0;//at least we have 16 channels
4
if(!adcMeasureStarted){//Measure not started yet
5
    ADMUX=(adcCounter & 0x7)|(1<<ADLAR);
6
    ADCSRB = (ADCSRB & ~(1<<MUX5)) | (adcCounter & (1<<MUX5));
7
    ADCSRA|=(1<<ADIF)|(1<<ADSC);
8
    adcMeasureStarted=true;
9
}
10
else{//Measure started
11
    if(ADCSRA&(1<<ADIF)){//Measure finished
12
        adc[adcCounter]=ADCH;
13
        ++adcCounter;
14
    }
15
}
(Firma: EleLa - www.elela.de) #3471839
Lesenswert?

Wenn 40µs ADC reichen, kann das noch mit einem mega klappen, wobei das 
bei deinem Programm (das wohl mehr als diese paar Zeilen hat) auch schon 
grenzwertig ist.

Ich rate zu einer Code-Analyse um heraus zu finden ob das der Prozessor 
wirklich alles packt und wie viel Reserve man noch hat. Schließlich 
sollte das ganze (ein Produkt) auch erweiterungsfähig sein.

Bei 13µs ADC sollte man über ein Redesign mit anderem µC nachdenken, 
Richtung 100MHz und mehr und mit DMA.
#3471868
Lesenswert?

@ N. G. (newgeneration)

>Würde alternativ dieser Code in der PWM-ISR (alle 40us) funktionieren?

Sicher. Wobei man es nicht unbedingt so kompliziert machen muss. Einfach 
den ADC starten und im nächsten Interrupt auslesen. Der Code ist 
identisch zu deinem Original. adcMeasureStarted ist nicht nötig.
OP Persönliche Seite #3471977
Lesenswert?

Falk Brunner schrieb:
> adcMeasureStarted ist nicht nötig.

okay, machmal sieht man den Wald vor lauter Bäumen nicht...
Dann werde ich wohl das umsetzten, da, wie Markus erwähnte, mein 
Programm schon ein paar Zeielen lang ist. Codeanalyse ist eigentlich 
eine gute Idee, aber da das Hauptprogramm noch nicht einmalö angefangen 
wurde, noch nicht sinnvoll.
Auf jeden Fall danke an alle, die mir geholfen haben.

PS: wie macht man eine Codeanalyse und welche Methode ist die beste? Ich 
kann/möchte kein Geld für Profi-Tools ausgeben
(Firma: EleLa - www.elela.de) #3472200
Lesenswert?

Wenn der ISR startet dann ein Portpin setzen, wenn der beendet wird 
wieder weg nehmen.
Das für alle ISR machen und die Zeiten mit dem Oszilloskop ansehen und 
zusammen rechnen ob für den Hintergrundtask genügend Zeit bleibt.
Es benötigt zwar noch zusätzlich Rechenzeit, aber wenn man die nicht 
hat, dann ist ohnehin ein Redesign nötig.

Bei uC mit einem Cortex-M3/M4 Kern könnte man die ISR priorisieren damit 
kann ein wichtiger ISR einen unwichtigen unterbrechen.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren