Forum: Mikrocontroller und Digitale Elektronik Atmega88 timing von ADC-Wandlungen und Datenverarbeitung


von David H. (Firma: FH Technikum Wien) (specialized0815)


Lesenswert?

Hallo allerseits,
zuerst möchte ich mich gleich entschuldigen, falls ich ein 
abgedroschenes Thema mit einem neuen Thread starte, wo evtl bereits ein 
Beitrag existiert, aber ich habe über die Suchfunktion nichts 
Spezifisches zum Thema gefunden. Wie man wahrscheinlich merkt bin ich 
relativ neu in der Materie, ich werde daher versuchen das Problem so gut 
wie möglich zu beschreiben.
Grundsätzlich geht es darum mittels µC einen Sensor (in unserem Fall 
Beschl.sensor) mit fixer sampling rate (dzt. 100Hz, wünschenswert wären 
aber bis zu 300Hz) abzutasten und das Ergebnis per SPI an ein Funkmodul 
zu übergeben (RFM70) welches dieses an einen Datenlogger sendet (also 
Kommunikation Sensornode zu Empfänger). Dabei ist momentan noch nicht 
fixiert, ob der Sensor analog bleibt (wie momentan) oder durch einen 
SPI-Sensor ersetzt wird.
Derzeit arbeiten wir mit einem Atmega8 mit externem Quarz (1,8432 Mhz). 
Der ADC wird per TimerInterrupt in einer Interruptroutine gestartet 
(wobei gewartet wird, bis das Ergebnis zur Verfügung steht --> ADC 
complete Interrupt). Das Verschicken findet nach Fertigstellung der 3 
Wandlungen (3 Wandlungen per Messvorgang da 3-achsiger Beschl.sensor) 
statt. Jetzt haben wir aus gewissen technischen Gründen auf einen 
Atmega88 umgestellt. Dabei ist mir aufgefallen, dass der ADC des 88er 
per Triggerevent gestartet werden kann (in unserem Fall wäre das ein 
Timerinterrupt); was doch bedeutet, dass ich keine Timer-ISR mehr 
benötige, in der ich den ADC starte, sondern nur mehr den Timer 
initialisiere und den ADC entsprechend konfiguriere?. Meine Überlegung 
ist nun folgende (ich hoffe ich kann`s halbwegs verständlich 
rüberbringen):
Der ADC wird mit dem Timer getriggert - das Starten erfolgt also in 
keiner ISR, sondern hardwaremäßig - ich kann nach dem Starten 
"quasiparallel" in meiner Main zeitlich unkritische Polling-Dinge (wie 
Verschicken von gepufferten Daten) abarbeiten, bis mein conversion 
complete flag gesetzt wird. Damit wird die ISR aufgerufen, ich lege mein 
Ergebnis im Puffer ab, starte den zweiten Wandlungsvorgang desselben 
Durchlaufes (also z.B. Wandlung des x-Wertes wurde beendet --> ADC 
complete flag --> ISR wird aufgerufen: x-Daten lesen und ablegen, 
y-Wandlung starten --> ISR verlassen) und wechsle wieder zur main für 
zeitunkritische Befehle und detto für die dritte Wandlung. Dann kommt 
der nächste Timerinterrupt und das ganze Spiel geht wieder von vorne 
los..Ist diese Variante grundsätzlich sinnvoll, oder ist es besser auf 
die 3 Werte zu warten und erst anschließend zeitunkritische Befehle 
auszuführen? Mir ist es deshalb unklar, da ich noch nicht ganz 
verstanden habe, ob die CPU durch die Aktivität des ADC blockiert ist 
und während der Wandlung keine anderen Dinge erledigen kann. 
Andererseits (ich hoffe ich verzapfe damit keinen kompletten blödsinn):
CPU .. 1.8432Mhz <--> ADC max 200kHz --> ADC Befehle werden etwa nur bei 
jedem 9. CPU-Takt ausgeführt, bleiben also 8 ungenützte Takte 
dazwischen..; ist das so richtig oder kann man das nicht so einfach 
umrechnen? Wenn es doch stimmt, dann wären das bei einer angestrebten 
CPU-Frequenz von 7.3728Mhz bereits 39 ungenützte Takte, sofern auf das 
Ergebnis gewartet wird
Ich hoffe es war nicht zu sehr verwirrend. Wäre sehr dankbar, wenn 
jemand weiß, wie das mit dem Timing genau aussieht
lg David

von Uwe (de0508)


Lesenswert?

Hallo David,

willst Du drei ADC Eingänge abfragen ?

Hast Du über Störrungen nachgedacht und evtl. eine Mittelwertbildung 
oder ein anderes Verfahren in betracht gezogen ?

Die ADC Wandlung erfolgt per Hardware und je nach deiner Software wird 
in der Main auf eine Wandlung gewartet.

Schau dir auch im Datenblatt die Synchronisierung von ADC Kanalwechseln 
an.
Ich würde die gesamte Messung aller drei Kanäle per ADC ISR ausführen 
lassen und nur den Event der Main über - ein Flag - signalisieren.

Die Ergebnisse lägen dann in einen uint16_t Array mit drei Elementen.
Die Index entsprechen deinen Kanälen.

Auch das Senden per SPI würde ich über einen FiFo im Interrupt erledigen 
lassen.

Link:

[1] www.atmel.com/images/doc2545.pdf -- Seite 247ff

-

von Absatz (Gast)


Lesenswert?

David Höftberger schrieb:
> verstanden habe, ob die CPU durch die Aktivität des ADC blockiert ist
> und während der Wandlung keine anderen Dinge erledigen kann.

Die CPU wird nicht blockiert. Der ADC ist eine unabhängige HW-Einheit.


> Andererseits (ich hoffe ich verzapfe damit keinen kompletten blödsinn):
> CPU .. 1.8432Mhz <--> ADC max 200kHz --> ADC Befehle werden etwa nur bei
> jedem 9. CPU-Takt ausgeführt, bleiben also 8 ungenützte Takte

ADC Befehle werden von der CPU mit CPU Geschwindigkeit ausgeführt. Der 
ADC mit seinen Transistoren benutzt die 200kHz für seine Wandlung 
unabhängig davon. Braucht ca 13 Takte von den 200kHz für eine Wandlung. 
Genaueres . Datenblatt. CPU arbeitet in der Zeit mit seinem CPU Takt 
weiter am Programm.

> CPU-Frequenz von 7.3728Mhz bereits 39 ungenützte Takte, sofern auf das
> Ergebnis gewartet wird

Warten tut man im Programm/ISR mit dem CPU Takt. Liegt aber an 
dir/Programm. Macht man nicht und wie ich den Aufbau des Programms 
verstanden habe, tust du das auch nicht. Dein Programm wird also zu 
jeder Zeit mit dem CPU Takt ausgeführt.

von David H. (Firma: FH Technikum Wien) (specialized0815)


Lesenswert?

Hall und danke für eure Antworten. Entschuldigt bitte, dass ich mich 
erst jetzt melde, aber ich habe wahrscheinlich bei meinen 
Forumseinstellungen vergessen die Emailbenachrichtigung für neue 
Antworten zu aktivieren und hab die neuen Beiträge daher erst jetzt 
gesehen

@ Uwe:

> willst Du drei ADC Eingänge abfragen ?

ja genau, so hätte ich das vor, allerdings weiß ich noch nicht genau, 
wie ich das mit dem Triggerevent handlen soll, da einerseits der 
Timerinterrupt die Wandlungen startet (für eine Messreihe bestehend aus 
3 Wandlungen x,y,z) aber andererseits es auch nicht schlecht wäre, wenn 
der ADC für diese 3 hintereinanderfolgenen Einzelwandlungen (also beim 
Übergang von x-->y und y-->z) im kontinuierlichen Wandlungsmodus 
arbeiten würde (also mit seinem eigenen Interruptflag als neues 
Startsignal). Das wird aber wahrscheinlich nur über eine 
Umkonfigurierung des ADC vor den entsprechenden Programmblöcken möglich 
sein (triggerquelle umstellen..)

> Hast Du über Störrungen nachgedacht und evtl. eine Mittelwertbildung
>oder ein anderes Verfahren in betracht gezogen ?

Hab ich mir noch nicht im Detail überlegt, welche Art Störungen sprichst 
du genau an, bzw. wie meinst du das mit einem anderen Verfahren?
Wie ich bereits angesprochen habe, wäre die Alternative ein Sensor mit 
digitalem Ausgang. Das ist allerdings abhängig davon, was vom Ablauf her 
schneller ist: 3 analoge Wandlungen oder die Abfrage eines 3-achsigen 
SPI-Sensors

Die restlichen Dinge handhabe ich auch so, wie von dir beschrieben, also 
über das Interruptflag vom ADC (ADC ISR), allerdings war mir nicht klar, 
ob der ADC nun als ein von der CPU unabhängiger Baustein angesehen 
werden kann, der seine Wandlungen ohne Blockierung der CPU durchführt
Das mit dem Synchronisieren der Kanalwechsel hört sich interessant an, 
werde ich mir demnächst zu Gemüte führen :)

>Auch das Senden per SPI würde ich über einen FiFo im Interrupt erledigen
>lassen.

Da war ich mir eben auch nicht 100%ig sicher; meinst du ich sollte die 
gewandelten Werte gleich nach Bereitstehen aller 3 Werte noch in der ADC 
ISR im SPI-FiFo ablegen und das Verschicken per UART durch das RFM70 in 
der main erledigen?

@ Absatz:

>Die CPU wird nicht blockiert. Der ADC ist eine unabhängige HW-Einheit.
>ADC Befehle werden von der CPU mit CPU Geschwindigkeit ausgeführt. Der
>ADC mit seinen Transistoren benutzt die 200kHz für seine Wandlung
>unabhängig davon. Braucht ca 13 Takte von den 200kHz für eine Wandlung.
>Genaueres . Datenblatt. CPU arbeitet in der Zeit mit seinem CPU Takt
>weiter am Programm.

Ok, danke, ich hatte es so vermutet. Das bedeutet also auch, nachdem der 
ADC seine 13 Zyklen bei 200kHz benötigt, dass die CPU bei einem 
gegebenen Takt von 7,..etc Mhz, da sie ja parallel in der main 
weiterarbeiten kann, ca. 13*39 Takte Zeit hat bis zum Eintreffen des 
ADC-Interrupts, was ja an und für sich eine Menge Holz ist ;-) um 
zeitunkritische Befehle zu erledigen (wie zum Bsp das Versenden per Uart 
durch das RFM70).
Oder sollte das Versenden nicht durch einen evtl. eintreffenden 
ADC-Interrupt unterbrochen werden?

von kopfkratzer (Gast)


Lesenswert?

AUTSCH
ADC-Wandlung im Timer-IRQ m(
Was Du willst geht relativ einfach:
1. ADC im Freerunning-Mode laufen lassen und da nacheinander 
durchschalten
2. ADC-Werte global ablegen und Flag setzen
3. Flag auswerten und ADC-Werte via SPI abschicken
Wenn Du 200Hz Sampling haben willst noch einen Timer nehmen und nur die 
ADC-Werte verschicken die das Kriterium erfüllen.

von David H. (Firma: FH Technikum Wien) (specialized0815)


Lesenswert?

@ kopfkratzer
Ja danke, du hast natürlich Recht :(, ich hatte nach der Erkenntnis, des 
von der CPU unabhängigen ADCs die Geschichte nicht zu Ende gedacht.. 
Genereller Freerunning-Modus mit zeitlich definiertem Zugriff ist die 
beste Lösung.

> ADC-Wandlung im Timer-IRQ m(

Ist zwar ohnehin obsolet, aber ich hätte eigentlich keine eigene Timer 
Interrupt routine vorgehabt, sondern nur den Start-Triggereingang des 
ADC mit dem Timer-Ticken belegt,.. kann aber natürlich sein, dass ich 
das beim 88er noch nicht richtig verstanden habe, da ich diese Info 
lediglich aus dem Datenblatt und noch nicht praktisch ausprobiert habe

von Uwe (de0508)


Lesenswert?

Hallo kopfkratzer,

>ADC im Freerunning-Mode laufen
und drei Kanäle Samplen passt nicht zusammen --> Datenblatt .

Es ist schon richtig, nach eine ADC-Wandlung den Wert per ADC-Interrupt 
abholen, den Kanalwechseln - ADC-Takte beachten - und eine neue Messung 
starten.

Nach drei Messungen x,y,z kann dann, z.B. das Tripel dem Uart Fifo 
übergeben werden.

Peter D. PeDa hat dazu alles schon programmiert.

von kopfkratzer (Gast)


Lesenswert?

Uwe S. schrieb:

>>ADC im Freerunning-Mode laufen
> und drei Kanäle Samplen passt nicht zusammen --> Datenblatt .

m(
Es geht um das allgemeine Prinzip nicht darum das er nun wegen des ATMEL 
in der ADC-IRQ den MUX umschalten muß, das hängt vom jeweiligen µC ab.

von Uwe (de0508)


Lesenswert?

Ok, ich verstehe deinen Ansatz.

Da sich der TE aber auf einen Atmega88 bezieht, betrachte ich das 
Problem jetzt speziell.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

In meinem FU Projekt starte ich den ADC des ATMega 88 einmal während der 
Intialisierung, danach sorgt der ADC Complete Interrupt fürs Auslesen 
des Wertes, schaltet dann den Kanal um und startet die nächste Wandlung. 
Das klappt so gut, das die PWM Erzeugung (der Kern des Projektes) keinen 
Moment aus dem Tritt gerät. Schaus dir mal an, der ADC Interrupt ist 
ganz am Ende des Codes:
http://www.mikrocontroller.net/articles/Frequenzumrichter_Wettbewerb

von David H. (Firma: FH Technikum Wien) (specialized0815)


Lesenswert?

Hallo, danke für eure Antworten,
habs jetzt von der ADC-Seite gelöst wie von euch geraten, also Wandlung 
im kontinuierlichen Modus - ADC-Interrupt für 3 Wandlungen aktiviert, 
dann am Ende des 3. nacheinanderfolgenden Aufrufs der ADC-ISR 
ADC-Interrupt deaktiviert und beim nächsten Timer-Interrupt wieder 
aktiviert. Messwerte werden am Ende der 3. Ausführung der ADC-ISR 
ausgelesen und in der main weiterverarbeitet. Funktioniert eigentlich 
soweit - allerdings nur beim Atmega8
Womit ich auch bei meiner nächste Frage wäre:
Verwendet von euch jemand Eclipse mit AVR-Plugin? Hätte die aktuellste 
AVR-Dude Version, Controller wird vom Projekt erkannt, auch vom 
AVR-Dude, die IO-Header enthält die Einträge zum 88er, aber die 
Rgisternamen werden nicht erkannt (z.B. Symbol OCIE2A could not be 
resolved, etc..). Hatte jemand bereits ein ähnliches Problem (beim 
Atmega8 ging eigentlich alles problemlos). Zu verändernde Register von 8 
auf 88er wurden von mir berücksichtigt, mir geht es wirklich nur darum, 
dass die Namen nicht erkannt werden.

@Matthias: Danke für den Hinweis auf dein Projekt, hab gesehen, dass die 
Implementierung des ADC ziemlich ähnlich ist wie bei mir

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.