Forum: Mikrocontroller und Digitale Elektronik ADC (mal wieder) sehr schnell auslesen - andere Programmteile gestört?


von N. G. (newgeneration) Benutzerseite


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.

von Falk B. (falk)


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.

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?

if(adcCounter<15) ++adcCounter;
  else adcCounter = 0;

Wäre das schneller?

  ++adcCounter %= 16;

von N. G. (newgeneration) Benutzerseite


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
}

von N. G. (newgeneration) Benutzerseite


Lesenswert?

Markus Müller schrieb:
> if(adcCounter<15) ++adcCounter;
>   else adcCounter = 0;
>
> Wäre das schneller?
>
>   ++adcCounter %= 16;

GCC trau ich es zu, dass er diese Optimierung macht. Für so was hat man 
Compiler, sonst kann man(nicht ich) auch Assembler nehmen.

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


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.

von Falk B. (falk)


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.

von N. G. (newgeneration) Benutzerseite


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

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


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.

von N. G. (newgeneration) Benutzerseite


Lesenswert?

Das mit dem Oszi kann ich erst in ein paar Tagen testen, da ich zur Zeit 
keinen Zugang zu einem solchen habe.
Ich werde es aber probieren.

Danke nochmal an alle

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.