Forum: Mikrocontroller und Digitale Elektronik Maximale Sampling Rate Atmega 20 MHz, mit parallelem externem ADC


von Hendrik (Gast)


Lesenswert?

Hallo Mikrocontroller.net Forum,

ich denke derzeit über eine einfache Möglichkeit nach, mit einem Atmega 
möglichst "schnell" (in Atmega-Zeitskalen, Samplingfrequenz von mehreren 
100 kHz, evtl sogar. 1 MHz?) über einen externen, parallelen ADC ein 
analoges Signal mit 8 bit Genauigkeit aufzunehmen. Dabei soll ein 
Datenblock von z.B. 12k Messpunkten aufgenommen werden. Da die 
Samplingraten ja schon nicht mehr so weit von der Taktfrequenz (20 MHz) 
entfernt sind, und ich mich damit schwertue die Zyklenzahlen für 
Operationen abzuschätzen (bin eher mit C unterwegs als mit Assembler) 
würde ich mich vorm "physischen Basteln" über Meinungen zu meinem 
Projekt freuen um es ggf. zu verwerfen. Gibt es eigentlich Möglichkeiten 
die benötigten Rechenzyklen aus dem C-Code heraus zu simulieren?

Grober Plan:
* Die Schaltung basiert z.B. auf einem Atmega 1284P, hauptsächlich 
aufgrund der 16k SRAM. Der sollte mit 20 MHz laufen.
* Da der Atmega ADC wohl zu langsam ist, würde ich einen schnellen (> 20 
MHz) 8 bit ADC verwenden, der kontinuierlich arbeitet und den digitalen 
Output parallel bereitstellt (D0-D7). Diesen würde ich bspw. an PA0 - 
PA7 des Atmegas hängen.[Hätte jemand da einen Tip für einen ADC IC?]
* Wenn ich Karl Heinz' Post in 
Beitrag "max. Eingangssignal für ISR" richtig verstehe, sind 
Interrupts zur Taktgebung solch einer Messung eher ungeeignet, da 
langsam. Daher würde ich einen Pin des Atmegas (z.B. PC0) an einen 
TTL-Taktgeber klemmen (z.B. Quarzoszillator, oder  ein 
Atmega-Timer-generiertes Signal), der die Messfrequenz von einigen 100 
kHz - 1 MHz vorgibt.
* Die Aufnahme eines 12 kiB Datenblocks soll über einen Triggerpuls, 
(z.B. an PC1) gestartet werden.


Das Programm sollte nicht viel können, und (ohne Interrupts) etwa so 
ablaufen ("Pseudocode"):

1. Initiiere Buffer:
1
char data[12288];  // (12kiB, hier sollen die ADC Bytes rein).

2. Warte auf ein definiertes char über den UART, bspw. '\n'. Wenn char 
da, dann:
1
int i = 0; // Zähler

3. Warte auf ein Triggersignal PC1 (polling) ->
1
while(!(PINC & 0x02));   // Wenn Trigger da, dann weiter:

4. Warte auf pos. Flanke an Taktgeberpin / PA auslesen und in 
data-Buffer  Zähler hochsetzen  Warte auf neg. Flanke an Taktgeberpin 
/ Warte auf pos. Flanke an Taktgeberpin / usw.
1
while((PINC & 0x01));
2
while(i<12288){
3
  while(!(PINC & 0x01));
4
  data[i] = PINA;
5
  i++;
6
  while((PINC & 0x01));
7
}

5. Wenn 12 kiB aufgenommen wurden, schreibe data binär an den UART, zur 
Auswertung mit PC / etc.

6. Zurück zu 2.


Meine Fragen wären nun:
- Ist der Plan einigermaßen sinnvoll?

Falls ja:
- Ich kann mir vorstellen, dass das Programm einen recht überschaubares 
Timing hat. Auch sollten keine störenden Interrupts Verzögerungen 
hervorrufen können. Wie schnell könnte der Takt an PC0 guten Gewissens 
gewählt sein, um verlässlich Daten abzuspeichern und keine Punkte zu 
verlieren?
- Bei Halbierung der Punkteanzahl könnten ja pro Mess-Taktsignal 2 Bytes 
abgelegt werden, etwa durch:
1
  dataA[i] = PINA;
2
  dataD[i] = PIND;
Hierdurch sollte bei Verwendung eines geeigneten (etwa 16 bit) ADC an 
PINA und PIND die Bittiefe erhöht, oder durch einen weiteren 8 bit ADC 
an PIND ein zweiter Kanal aufgenommen werden können. Würde dies die 
mögliche Sampling Rate deutlich verringern?

Vielen Dank im Voraus!

von Schreiber (Gast)


Lesenswert?

Hendrik schrieb:
> ich denke derzeit über eine einfache Möglichkeit nach, mit einem Atmega
> möglichst "schnell" (in Atmega-Zeitskalen, Samplingfrequenz von mehreren
> 100 kHz, evtl sogar. 1 MHz?) über einen externen, parallelen ADC ein
> analoges Signal mit 8 bit Genauigkeit aufzunehmen.

1MHz ist sehr sportlich, sollte aber noch im Bereich des möglichen sein.

Hendrik schrieb:
> Hierdurch sollte bei Verwendung eines geeigneten (etwa 16 bit) ADC an
> PINA und PIND die Bittiefe erhöht, oder durch einen weiteren 8 bit ADC
> an PIND ein zweiter Kanal aufgenommen werden können. Würde dies die
> mögliche Sampling Rate deutlich verringern?

Ja

Einfach mal rechnen: Bei 20MHz Taktfrequenz und 1MHz Samplingrate 
bleiben 20 Takte je Messwert. In diesen 20 Tkten müssen die Messwerte in 
den µC rein und ins RAM geschrieben werden. Viel Zeit bleibt da nicht.

Hendrik schrieb:
> * Wenn ich Karl Heinz' Post in
> Beitrag "max. Eingangssignal für ISR" richtig verstehe, sind
> Interrupts zur Taktgebung solch einer Messung eher ungeeignet, da
> langsam. Daher würde ich einen Pin des Atmegas (z.B. PC0) an einen
> TTL-Taktgeber klemmen (z.B. Quarzoszillator, oder  ein
> Atmega-Timer-generiertes Signal), der die Messfrequenz von einigen 100
> kHz - 1 MHz vorgibt.

Müll. Die Takterzeugung muss, wenn es schnell gehen soll direkt von der 
Taktfrequenz des Prozessors abgeleitet werden. Der Rest ist Software, 
ich würde mir mal Assembler ganz genau anschauen, da erkennt man besser 
was der µC gerade macht und wie lange er dafür benötigen wird.

von Reginald L. (Firma: HEGRO GmbH) (reggie)


Lesenswert?

Auf einem STM32F4 habe ich einen 16bit ADC parallel angestöpselt und 
schaufle die Daten mit 200kHz per Ethernet als Livestream raus, da 
geht's ohne Probleme. 1MHz müsste da auch noch drin sein, Blockweise 
rausschieben bestimmt noch mehr.

Falls das eine Alternative für dich wäre und Interesse besteht kannst du 
dich auch gerne bei mir melden, kann dir da unter die Arme greifen beim 
Einarbeiten in den STM32.

von S. Landolt (Gast)


Lesenswert?

> im Bereich des möglichen
Das denke ich auch.

> recht überschaubares Timing
Der Kern der Aufnahmeschleife sieht in Assembler wohl irgendwie so aus:
1
loop:
2
  in   tmp,PINA
3
  st   x+,tmp
4
  cpi  XH,high(data_end)
5
 brne  loop
Das sind 6 Takte, bleiben für etwelche allfällige Synchronisierungen 14 
Takte (bei 20 / 1 MHz).

> Atmega 1284P ... Der sollte mit 20 MHz laufen
So steht es im Datenblatt, man könnte es aber auch mit etwas mehr 
probieren, z.B. 22. Bei mir läuft einer seit Monaten problemlos mit 25 
MHz.

von Hendrik (Gast)


Lesenswert?

Vielen Dank für die Antworten!

Das klingt dann ja doch recht positiv, ich denke dann werde ich die 
Bastelei demnächst mal angehen.

@Schreiber:
> Einfach mal rechnen: Bei 20MHz Taktfrequenz und 1MHz Samplingrate bleiben 20 
Takte je Messwert. In diesen 20 Tkten müssen die Messwerte in den µC rein und ins 
RAM geschrieben werden. Viel Zeit bleibt da nicht.

Genau diese Überlegung war mein Ausgangspunkt für diesen Thread.

> Müll. Die Takterzeugung muss, wenn es schnell gehen soll direkt von der 
Taktfrequenz des Prozessors abgeleitet werden. Der Rest ist Software, ich würde 
mir mal Assembler ganz genau anschauen, da erkennt man besser was der µC gerade 
macht und wie lange er dafür benötigen wird.

Wenn möglich, würde ich gerne bei dem externen "Clock Signal" zur 
Taktung der Messungen bleiben, dieses hätte auch den Vorteil, dass ich 
mehrere Atmega/ADC Kombis synchronisiert messen lassen könnte.


@Reginald Leonczuk:
16 bit live mit 200 kHz über Ethernet klingt sehr gut, ich möchte über 
kurz oder lang auch gerne auf das Angebot zurückkommen und mich mit dem 
STM32 beschäftigen, allerdings würde ich dieses Projekt zunächst erst 
einmal mit den mir bekannten Atmegas umsetzen (sofern möglich).


@S. Landolt:
>
1
loop:
2
  in   tmp,PINA
3
  st   x+,tmp
4
  cpi  XH,high(data_end)
5
 brne  loop
> Das sind 6 Takte, bleiben für etwelche allfällige Synchronisierungen 14 Takte 
(bei 20 / 1 MHz).

Danke für die Umsetzung in ASM - das klingt für mich jetzt so, als 
würden sogar mit 20 MHz Takt die maximal angepeilten 1 MHz Sampling Rate 
erreicht werden können und vermutlich noch genug Zeit für das Polling 
des externen Clock-Pins bleiben (?).

Selbst wenn ich zusätzlich noch PIND auslesen würde (für 16 Datenbits 
pro Messung) müsste es doch immernoch passen (<=12 Takte pro Messung?)? 
Wäre es in diesem Fall sinnvoll (in C) die Bytes von PINA und PIND 
abwechselnd in den gleichen Buffer zu schreiben, oder zwei Buffer mit 
halber Größe anzulegen (wie in meinem ersten Post vorgeschlagen)? Oder 
wäre es egal, weil der C-Compiler es optimiert?

von S. Landolt (Gast)


Lesenswert?

Zu C kann/will ich nichts sagen. In Assembler mit 2 Speicherbereichen:
1
loop:
2
  in   tmp,PINA
3
  st   x+,tmp
4
  in   tmp,PIND
5
  st   y+,tmp
6
  cpi  XH,high(data_end)
7
 brne  loop
Mit 1 Bereich:
1
loop:
2
  in   tmp,PINA
3
  st   x+,tmp
4
  in   tmp,PIND
5
  st   x+,tmp
6
  cpi  XH,high(data_end)
7
 brne  loop
Sind jedesmal 9 Takte.
(Der Bereich muss am Ende auf einer 256-er Grenze liegen, sonst wird es 
1 Takt mehr)

von H-G S. (haenschen)


Lesenswert?

Soll der externe ADC 20MHz Samplingrate haben oder nur die 1MHz die der 
AVR ausgeben soll ?

von Schreiber (Gast)


Lesenswert?

Hendrik schrieb:
>> Müll. Die Takterzeugung muss, wenn es schnell gehen soll direkt von der
> Taktfrequenz des Prozessors abgeleitet werden. Der Rest ist Software,
> ich würde
> mir mal Assembler ganz genau anschauen, da erkennt man besser was der µC
> gerade
> macht und wie lange er dafür benötigen wird.
>
> Wenn möglich, würde ich gerne bei dem externen "Clock Signal" zur
> Taktung der Messungen bleiben, dieses hätte auch den Vorteil, dass ich
> mehrere Atmega/ADC Kombis synchronisiert messen lassen könnte.

Das kann man auch erreichen, indem man diese mit einem gemeinsamen 
Prozessortakt versorgt.

Die AVRs kann man nicht nur mit einenem normalen Quarz, sondern auch mit 
einem richtigen Quarzoszillator mit ihrem Takt versorgen. Letzterer hat 
den Vorteil, dass er mehrere AVRs versorgen kann, die dann syncron 
laufen

von Stefan F. (Gast)


Lesenswert?

Irgend etwas willst du mit den eingelesenen Daten auch anstellen. Bis zu 
sicher, dass der µC dafür schnell genug ist?

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Ich bin ja durchaus ein Freund der digitalen Signalverarbeitung auf AVR. 
Aber das scheint mir doch etwas zu ambitioniert, bzw. zu sehr mit 
Beschraenkungen verbunden. Da wuerd' ich doch aufn Prozessor eine Nummer 
groesser umsteigen, also irgendein STM32 oder sowas in der 
Leistungsklasse.

Gruss
WK

von Hendrik (Gast)


Lesenswert?

@ H-G Sch:
> Soll der externe ADC 20MHz Samplingrate haben oder nur die 1MHz die der
> AVR ausgeben soll ?

Meine Überlegung war einen ADC zu verwenden, der einfach deutlich 
schneller ist als meine Messung, damit die parallelen Bits an PINA/PIND 
immer "aktuell genug" sind, und der ADC den Messvorgang nicht limitiert. 
Ich könnte den ADC dann natürlich auch einfach mit dem Mess-Clock-Signal 
füttern, und so dafür sorgen, dass vor jedem Abfragen von PINA/PIND eine 
Wandlung initiiert wird. So ergäbe sich dann eine SR von z.B. 1 MHz. 
Dabei müsste dann natürlich die Conversion Time unterhalb der Zeit 
zwischen Clock-Signal Flanke und Abfrage der PIN-Bytes liegen, was aber 
auf jeden Fall gegeben sein sollte, wenn der ADC schneller ist als der 
Atmegatakt.


@ Schreiber:
Was spricht denn letztendlich gegen einen externen Messtakt, wenn es vom 
Timing her zeitlich passt?

Klar kann man Atmegas über einen gemeinsames Taktsignal synchronisieren, 
aber dann müsste ich ja (zumindest in C) immernoch über ein 
Timerinterrupt/etc. die Messung auslösen(?), welches - so wie ich es im 
oben zitierten Thread verstanden habe - auch einige Taktzyklen kostet. 
Über eine schnelle Alternative zum Timerinterrupt (am liebsten in C) 
würde ich mich natürlich freuen!

@ Stefan Us:
> Irgend etwas willst du mit den eingelesenen Daten auch anstellen. Bis zu
>sicher, dass der µC dafür schnell genug ist?

Ich möchte den (oder mehrere) µC eigentlich nur als "dummen" und 
einfachen Datenrekorder verwenden. Wie im Pseudocode oben soll dieser 
über UART/RS232 aktiviert werden, nach einem TTL Triggersignal >10 k 
Datenpunkte aufnehmen und diese dann wieder unbearbeitet als Binärblock 
seriell an einen Messcomputer senden. Die Bearbeitung der Signale findet 
dann nach der Messung auf dem Rechner mit Python/Matlab/etc. statt. 
Meine Überlegung war, dass ein so "einfaches" Programm, ohne viel 
Schnickschnack, auf einem Atmega vorhersagbar ablaufen sollte und mir 
die Möglichkeit gibt einen simplen, günstigen Datenrekorder zu bauen.

@ Dergute Weka:
Wie oben geschrieben, wenn der Atmega das packt, wüsste ich nichts was 
dagegen spricht. Würde mich aber auch trotzdem gerne für weitere 
Projekte mit dem STM32 beschäftigen - scheint ja deutlich 
Leistungsfähiger zu sein. Gibt es eine Empfehlung für den Einstieg? Ich 
fand z.B. die AVR Tutorials hier für den Einstieg in Atmega sehr 
hilfreich.

von S. Landolt (Gast)


Lesenswert?

> ... (für 16 Datenbits pro Messung) ...
> ... >10 k Datenpunkte aufnehmen ...
Also das schafft ein ATmega1284P mit seinen 16 KiB RAM natürlich nicht 
mehr  vom Volumen her, auch wenn es rein zeitlich problemlos ginge.

von Carl D. (jcw2)


Lesenswert?

Bei 128k Flash oder 64k Befehle und 4 Befehle pro Durchlauf:
12k * 4 -> 48k (96kB) mit 1+2+1+2 -> 6 Takten komm ich auf 3.33.. MHz 
Abtastrate.

Normalerweise bin ich ja für C++, aber vereinzelt braucht man eben 
Assembler ;-)

Update:
Es passen natürlich keine 12k int's ins RAM, noch nicht mal 8k, es sei 
denn, man kann sonst komplett auf RAM verzichten. D.h. kein Stack, kein 
call, keine Interrupts, ...

: Bearbeitet durch User
von Reginald L. (Firma: HEGRO GmbH) (reggie)


Lesenswert?

Ich habe mit dem STM32F4 Discovery angefangen. Da ist der 
Programmer/Debugger schon dabei.
Bei IDEs ist fast alles möglich, Eclipse oder aber auch Visual Studio.

Bei deinem Vorhaben und den erwähnten Anforderungen würde ich wechseln. 
Wenn man nachträglich doch noch ne kleine Erweiterung implementieren 
möchte, wäre es schade, wenn es dann am Speed mangelt.

Mein Angebot steht ;)

von Hendrik (Gast)


Lesenswert?

@ Carl Drexler (jcw2):
> Es passen natürlich keine 12k int's ins RAM, noch nicht mal 8k, es sei
> denn, man kann sonst komplett auf RAM verzichten. D.h. kein Stack, kein
> call, keine Interrupts, ...

...die >10 k Datenpunkte (sollte eigentlich ~10 k werden) bezogen sich 
natürlich auf 8 bit/Messung - bei 16 bit würde ich etwa 5 k Datenpunkte 
anpeilen, je nachdem wieviel SRAM vom Rest des Programms belegt wird.

> Ich habe mit dem STM32F4 Discovery angefangen. Da ist der
> Programmer/Debugger schon dabei.
> Bei IDEs ist fast alles möglich, Eclipse oder aber auch Visual Studio.

@Reginald Leonczuk:
Ich habe gerade mal 
https://www.mikrocontroller.net/articles/STM32F4-Discovery überflogen 
und festgestellt, dass es ja offenbar linuxlauffähige Compiler und Tools 
gibt - Eclipse ja sowieso - das werde ich demnächst mal angehen und dann 
gerne auf das Angebot zurückkommen. :) Ich hatte sowieso vor mich mit 
leistungsfähigeren µC zu beschäftigen...



Zusammenfassend scheint mein ursprünglicher Atmega - 1 MHz (8/16 bit) 
Sampling-Plan dann ja zwar am Limit aber durchaus möglich - daher werde 
ich trotzdem als Erstes diese Variante aufbauen (muss mich dann nicht 
neu einarbeiten), testen und berichten!

von S. Landolt (Gast)


Lesenswert?

Ich weiß nicht, wie das in C aussehen könnte, aber falls Sie in Erwägung 
ziehen, zumindest die Aufnahmeschleife in Assembler zu schreiben, so 
wären auch 12 bit bei 10 k Datenpunkten recht einfach möglich.

von Michael H. (Gast)


Lesenswert?

Texas hat spi adcs. Die schaffen 1msps und mehr...

von Sebastian S. (amateur)


Lesenswert?

Ach was muss Langeweile doch schön sein!

Üblicherweise ist das Messen doch kein Selbstzweck!

Ja, es mag ja, mit hängen und würgen, möglich sein diese Messung 
durchzuführen, aber:
In null Komma nichts ist der Speicher voll.
Natürlich nur, wenn ununterbrochen (Interrupt: Nein Danke) gearbeitet 
werden kann.
Keine "Zeit" zum Arbeiten, d.h. die Messwerte können nur durchgereicht 
werden. Wohin eigentlich.

Oder ist das ganze doch nur Selbstzweck? Weil keine Verarbeitung möglich 
ist, weil die Speichertiefe ein Witz ist?

Sicher theoretisch ist es möglich!

von c-hater (Gast)


Lesenswert?

Sebastian S. schrieb:

> Üblicherweise ist das Messen doch kein Selbstzweck!

Richtig.

> Ja, es mag ja, mit hängen und würgen, möglich sein diese Messung
> durchzuführen

Natürlich ist es möglich. Und zwar nicht mit "Hängen und Würgen", 
sondern einfach nur mit dem Werkzeug, welches Profis zumindest auch 
beherrschen sollten: Assembler, denn nur damit ist (beweisbar und 
reproduzierbar) die effizienteste Lösung jedes Problems für ein 
gegebenes Zielsystem möglich. Möglich wird das u.A. durch das 
deterministische Zeitverhalten, was höheren Programmiersprachen leider 
ziemlich abgeht...

> aber:
> In null Komma nichts ist der Speicher voll.

Na sicher. Es ist ja hier gerade das Ziel, den verfügbaren Speicherf 
möglichst schnell vollzuschreiben, du Nase!

> Keine "Zeit" zum Arbeiten, d.h. die Messwerte können nur durchgereicht
> werden. Wohin eigentlich.

Zum Speicher. Der tut nämlich das, was der Name verspricht: er 
speichert.

> Weil keine Verarbeitung möglich
> ist

Wieso sollte keine Verarbeitung möglich sein? Wenn der Messzyklus 
beendet ist, ist doch der Speicherinhalt immer noch da, oder nicht? Man 
kann ihn dann verarbeiten bis zum Abwinken. Schlimmstenfalls muss man 
halt dann, wenn's nicht mehr zeitkritisch ist, langsameren externen 
Speicher zu Hilfe nehmen.

Und übrigens ist das Prinzip, die Daten von 
Hochgeschwindigkeitsmessungen erstmal in schnellen Speicher zu puffern 
und hinterher zu verarbeiten so alt wie die Digitaltechnik selbst. Und 
es wird auch heute noch angewendet, nur die Grenze für den Einsatz 
dieses Prinzips hat sich im Laufe der Jahre immer weiter nach oben 
verschoben. Das ist alles.

von Lurchi (Gast)


Lesenswert?

Ein STM32 oder ähnlich wäre hier wirklich ein Vorteil. Je nach 
Ausführung schafft da der interne ADC sogar irgendwas im Bereich 5 MHz. 
Mehr RAM sollte man auch finden.

Bei der AVR Version kann man es sogar noch etwas schneller machen, indem 
an die Schleife entrollt, also in der Schleife 2 oder mehr Werte 
aufnimmt und so die Zeit für den Sprung und Vergleich am Ende auf mehr 
Durchläufe Verteilt. Im mittel bleibt dann nur 1 Zyklus dafür und man 
könnte ggf. noch etwa 2 Zyklen sparen.

Den externen ADC könnte man z.B. über einen PWM Ausgang des AVRs 
triggern / takten.

von Carl D. (jcw2)


Lesenswert?

Lurchi schrieb:
> Ein STM32 oder ähnlich wäre hier wirklich ein Vorteil. Je nach
> Ausführung schafft da der interne ADC sogar irgendwas im Bereich 5 MHz.
> Mehr RAM sollte man auch finden.
>
> Bei der AVR Version kann man es sogar noch etwas schneller machen, indem
> an die Schleife entrollt, also in der Schleife 2 oder mehr Werte
> aufnimmt und so die Zeit für den Sprung und Vergleich am Ende auf mehr
> Durchläufe Verteilt. Im mittel bleibt dann nur 1 Zyklus dafür und man
> könnte ggf. noch etwa 2 Zyklen sparen.
>
> Den externen ADC könnte man z.B. über einen PWM Ausgang des AVRs
> triggern / takten.

Maximales Entrollen hatte ich schon vorgeschlagen. Schafft 6,66..MB/s 
und hat keinen "Jitter".

von S. Landolt (Gast)


Lesenswert?

> die Schleife entrollt
Das liegt nahe und wurde von Carl Drexler ja auch schon vorgeschlagen; 
allerdings ist mir nicht ganz klar, welchen Vorteil ein teilweises 
Entrollen bringt, und ob ein vollständiges bei 10 k Datenpunkten in dem 
128 KiB Flash Platz hat, hängt davon ab, wie diese Triggerung aussieht. 
Zur Zeit aber sehe ich noch keine Notwendigkeit für eine solche Aktion.
  Auch noch nicht dafür, etwas Fetteres zu nehmen, dem ubiquitären 
Trend folgend nach der Devise 'fatter is better'.

von Carol (Gast)


Lesenswert?

Die vorherigen Beiträge haben ja schon gezeigt, dass dein
Vorhaben ohne Übertaktung und sonstigem Blödsinn möglich
ist, wenn du dafür sorgst, dass in diesem Zeitraum der µC
vollkommen ungestört dem Byte-Schaufeln nachkommen kann:

Alle (!) Interrupts müssen für die erforderlichen 1,23 ms
disabled sein, da das Byte-Schaufeln im Freilauf geschehen muss:

Also, (Sampletakt an PINX, BitY) :
1
  di                      ; KEINE INTERRUPTS!
2
3
loop:                     ; Takt
4
   in  tmp0, PINX         ;  0  Sampletakt, Daten bereit?
5
 andi  tmp0, BITMASK_Y    ;  1  Maske für BitY
6
 breq  loop               ;  3 (2)  Polling-Rate: 4 Takte
7
8
   in  tmp0, PINA         ;  3...7
9
   st  x+, tmp0           ;  5...9
10
  cpi  XH, high(data_end) ;  7..11  (Klappt nur an 256-er Grenze)
11
 brne  loop               ;  8..12  Umlauf: 8...12 Takte
12
13
  sei                     ; Interrupts wieder erlaubt

Hier gibt es aber eine Falle:
Ich gehe mal davon aus, dass der Sampletakt von 1 MHz
symmetrisch ist: 0,50 µs Hi, 0,50 µs Lo. µC-Takt = 0,05 µs
Im schlechtesten Fall (der Sampletakt geht gleich nach seiner
Abfrage auf High) braucht die Auslesung 12 µC-Takte, OK. Im
günstigsten Fall braucht die Auslesung nur 8 µC-Takte - bei
der nächsten Abfrage des Sampletakts (nach 0,40 µs) erwischt man
noch den selben Takt:
Der selbe ADC-Wert wird nochmal eingelesen!
Die Schleife darf also nicht zu schnell sein!!!

Besser (Sampletakt an PINX, BitY):
1
  di                      ; KEINE INTERRUPTS!
2
3
loop:                     ; Takt
4
   in  tmp0, PINX         ;  0  Sampletakt, Daten bereit?
5
 andi  tmp0, BITMASK_Y    ;  1  Maske für BitY
6
 breq  loop               ;  3 (2) Polling-Rate: 4 Takte
7
8
   in  tmp0, PINA         ;  3...7
9
   st  x+, tmp0           ;  5...9
10
  nop                     ;  6..10
11
  nop                     ;  7..11
12
  nop                     ;  8..12
13
  cpi  XH, high(data_end) ;  9..13  (Klappt nur an 256-er Grenze)
14
 brne  loop               ; 11..15  Umlaufzeit: 11...15 Takte
15
16
  sei                     ; Interrupts wieder erlaubt

Interessant wäre für mich eher die Wahl des ADC.
Hast du da schon einen in der Auswahl?

von (prx) A. K. (prx)


Lesenswert?

Hendrik schrieb:
> loop:
>   in   tmp,PINA
>   st   x+,tmp
>   cpi  XH,high(data_end)
>   brne  loop

Wie wärs mit
   in   tmp,PINA
   st   x+,tmp
   in   tmp,PINA
   st   x+,tmp
   in   tmp,PINA
   st   x+,tmp
   in   tmp,PINA
   st   x+,tmp
   in   tmp,PINA
   st   x+,tmp
   ...
   in   tmp,PINA
   st   x+,tmp

von Weinbauer (Gast)


Lesenswert?

und dann? ... wohin mit den Werten und was damit machen?

von Hendrik (Gast)


Lesenswert?

@ c-hater, Sebastian S:
> Wieso sollte keine Verarbeitung möglich sein? Wenn der Messzyklus
> beendet ist, ist doch der Speicherinhalt immer noch da, oder nicht? Man
> kann ihn dann verarbeiten bis zum Abwinken. Schlimmstenfalls muss man
> halt dann, wenn's nicht mehr zeitkritisch ist, langsameren externen
> Speicher zu Hilfe nehmen.

Genau das ist der Plan, die Daten sollen nach getaner Messung ganz in 
Ruhe über den UART/RS232 o.ä. als Binärblock an einen Rechner gesendet 
werden (evtl. von mehreren Trigger und Messtakt-synchronisierten 
Atmega/ADC Kombis) und dann weiter ausgewertet werden (Python etc.). Der 
Atmega soll einfach nur messen und die Daten zur Verfügung stellen.


@ Carol:
> Im günstigsten Fall braucht die Auslesung nur 8 µC-Takte - bei
> der nächsten Abfrage des Sampletakts (nach 0,40 µs) erwischt man
> noch den selben Takt:

Ich hatte oben im C-Entwurf angedacht in der Schleife erst durch Polling 
zu überprüfen ob der Messtakt-Pin auf low ist, um anschließend mit 
Polling zu prüfen ob er auf high ist. Das würde vermutlich wieder 4 
Takte mehr kosten (?) aber sicher die pos. Flanke erwischen. Da ich die 
Messtakt-Frequenz (duty cycle wäre dann ja auch mehr oder weniger egal) 
aber gerne variabel (und bei Bedarf deutlich langsamer) halten würde, 
komme ich um die Abfrage vermutlich nicht herum?

In Deinem Beispiel wird soweit ich sehe nur PINA ausgelesen (8 bit 
Fall). Wieviele Takte würde es kosten zusätzlich noch PIND (o.ä.) 
auszulesen um auf 16 bit pro Messung zu kommen? Vermutlich kratzt das 
dann in Summe  schon an der 20? Ich habe mich leider bisher noch 
überhauptnicht mit ASM auseinandergesetzt - vermutlich ist dieses 
Projekt ein guter Anlass das zu tun. :) - daher kann ich aber derzeit 
leider nur ahnen was Zeile für Zeile passiert.

Gibt es eigentlich die Möglichkeit den zeitunkritischen Teil des 
Programms in C zu realisieren und den zeitkritischen Teil mit der 
Messung in ASM zu coden? "inline assembler"?


> Interessant wäre für mich eher die Wahl des ADC.
> Hast du da schon einen in der Auswahl?

Noch nicht - ich wollte erstmal die Machbarkeit klären. Da es mir 
scheint, dass sowohl die ~10k Punkte bei 8 bit als auch die ~5k Punkte 
bei 16 bit realistisch sind, würde ich auch nach zwei verschiedenen ADCs 
Ausschau halten. Ich hatte beim schnellen Suchen den AD876 gesehen, der 
hat nur 10 bit und ich würde dabei dann halt 6/16 unnötige Bits 
aufnehmen (im 16 bit Modus). >12 bit wären schon ganz gut. Ich werde 
noch suchen und abwägen bzgl. Bittiefe, Kosten und Verfügbarkeit. 
Vielleicht hat jmd. einen Vorschlag?

von Andreas R. (daybyter)


Lesenswert?

Ich würde mir mal den stm32f103 (blue pill) anschauen. Gibt es für 3,- 
und auf der stm32duino Seite gibt es eine Software, wo er als 2 MHz Oszi 
arbeitet.

http://www.stm32duino.com/viewtopic.php?t=107

http://m.ebay.com/itm/STM32F103C8T6-ARM-STM32-Minimum-System-Development-Board-Module-For-Arduino-/182051337638

von Frank K. (fchk)


Lesenswert?

Wenn Du möglichst schnell abtasten willst, solltest Du:

1. einen AVR mit externem Adress-Datenbus verwenden. Dann wird einiges 
wie die Erzeugung des Read-Impulses per Hardware gemacht, was Takte 
spart. Außerdem kannst Du dann ein externes SRAM anschließen. Mit 
Bankswitching sind 512kByte kein Problem.
Als AVR empfiehlt sich dann ein Mega1280/1281, je nachdem, wie viele 
IO-Pins Du brauchst.

2. einen FIFO verwenden. Beispielsweise zwei von den hier:

https://www.idt.com/node/36925

Zwei deswegen, um auf 16 Bit Breite zu kommen. Der ADC schreibt parallel 
hinein, mit seinem festen Sampletakt. Der AVR muss nur das HALF-FULL 
Flag auswerten, und wenn das gesetzt ist, kann er die halbe 
FIFO-Kapazität in einem Rutsch ohne weitere Abfragen einlesen. Und dafür 
ist zusätzlicher, externer Speicher ganz hilfreich. Ohne externes RAM 
muss er nur warten, bis der FIFO voll ist und kann dann die volle 
FIFO-Kapazität in aller Ruhe abholen. Das können bis zu 128 kByte sein.

Diese Bausteine können in der 25ns-Version (Standard) alle 25 ns einen 
Wert aufnehmen, was 40 MHz entspricht. Man kann die auch kaskadieren, um 
eine größere Tiefe zu erhalten. Mit diesem Ansatz kann man schon einiges 
erreichen.

Es gibt auch noch schnellere FIFOs, aber 40 MHz sind auch schon nicht 
schlecht. Da brauchst Du erstmal einen ADC, der das mitmacht. Und ein 
ordentliches Leiterplattenlayout.

fchk

von Mooskopf (Gast)


Lesenswert?

Ein kleines FPGA, resp CPLD, entweder mit internem, oder externem RAM 
kann so eine Aufgabe um einiges besser. Da sind auch 50Ms kein Problem. 
Das rumsenden kann dann immer noch ein AVR machen.

von Schlaubischlumpf (Gast)


Lesenswert?

> Ein kleines FPGA, resp CPLD,

Mit solchen Extravaganzen darfst du den AVRern nicht kommen.
Die kennen nur Nagel und Hammer.
Wenn sie denn überhaupt über ihren Anduinotellerrand kommen.

Eine echte Schraube wäre ein TMS320F2809.
Der hat genug RAM und 12,5 MSPS-ADs schon an Bord.

Aber wie gesagt, lass sie sich quälen...

von Carol (Gast)


Lesenswert?

Klar kann man das Auswerte-Programm in C, oder BASIC, oder
COBOL, ... schreiben - nur die Ausleseroutine muss in
(Inline)-ASM laufen.

PinD auslesen und speichern kostet weitere 3 Takte. Damit
werden die 3 "nop" zum Verzögern überflüssig.
- Ergibt also maximal 16 Takte

Besser: Du sicherst vorher alle Register und machst dich nicht
von einer 256-er Grenze abhängig. Dann muss nur noch die
Startadresse deines 12 K Speicherbereichs BUFFER bekannt sein.
- Ergibt maximal 17 Takte in der Auslese-Schleife.

Wenn die Sampletakt-Pegel abgefragt werden, geht das noch
in 17 Takten für 1 Byte und 20 Takten für 2 Byte. Aber bei
2 Byte willst du es ja im 0,5 MHz Takt (40 Takte) machen.
Da kommt es hiermit nicht zu Doppel-Auslesungen.

Bei 1 MHz Takt gibt es hiermit nur 5 K 16-Bit-Werte, will man
10 K 8-Bit-Werte, müssen die Zeilen mit "High-Byte" weggelassen
werden - am besten baut man da 2 Routinen mit passendem Code.


1
 push r16                  ; Register sichern
2
 push r17
3
 push r18
4
 push xl
5
 push xh
6
7
  ldi xl,   low(BUFFER)   ; Register initialisieren
8
  ldi xh,  high(BUFFER)
9
  ldi r17,  low(BUFFER+12288)
10
  ldi r18, high(BUFFER+12288)
11
12
   di                      ; KEINE INTERRUPTS!
13
14
loop:                     ; Takt
15
   in  tmp0, PINX         ;  1  Sampletakt, Low?
16
 andi  tmp0, BITMASK_Y    ;  2  Maske für BitY
17
 breq  loop               ;  3 /  6  Nein, High: Bereit, (4  Noch nicht bereit)
18
19
   in  tmp0, PINA         ;  3 /  7    Low-Byte
20
   st  x+, tmp0           ;  5 /  9    Low-Byte
21
   in  tmp0, PIND         ;  6 / 10   High-Byte
22
   st  x+, tmp0           ;  8 / 12   High-Byte
23
24
wait:
25
   in  tmp0, PINX         ;  9 / 13  Sampletakt noch High?
26
 andi  tmp0, BITMASK_Y    ; 10 / 14  Maske für BitY
27
 brne  wait               ; 12 / 16  Polling-Rate: 4 Takte
28
29
   cp  XL, r17            ; 17  12 K Werte gelesen?
30
  cpc  XH, r18            ; 18
31
 brcs  loop               ; 20  Umlaufzeit: 20 Takte
32
33
  sei                     ; Interrupts wieder erlaubt
34
35
  pop xh                  ; Register freigeben
36
  pop xl
37
  pop r18
38
  pop r17
39
  pop r16

von Thomas F. (igel)


Lesenswert?

Hendrik schrieb:
> mit einem Atmega möglichst "schnell" (1 MHz?)
> über einen externen, parallelen ADC ein
> analoges Signal mit 8 bit Genauigkeit aufzunehmen.

Habe ich vor ca. 10 Jahren schon mal gebaut: Ein Atmega32 mit 18,4 MHz 
und zwei parallelen 8-Bit-ADCs dran zeichnet zwei analoge Kanäle mit 
max. 1MHz auf bis der RAM voll ist. Dann werden die Daten per UART an 
einen PC geschickt und dort in einem eigenen Programm angezeigt. Ich 
habe nie genau überprüft ob bei 1MHz noch alle Datenpunkte genau 
aufgezeichnet werden aber die Kurven am PC sahen immer richtig aus. Das 
Programm auf dem Atmega war in ASM geschrieben und über Timer1 
gesteuert.

Als ADC hatte ich wenn ich mich recht erinnere zwei MAX153, einen an 
Port A und einen an Port C. Dann noch 2x CS und 2x RD an PortB.

Prinzipiell ist das Projekt also machbar.

von M. K. (sylaina)


Lesenswert?

Thomas F. schrieb:
> Prinzipiell ist das Projekt also machbar.

Das denke ich auch aber es ist schon hart an der Grenze was Atmegas zu 
leisten vermögen.

von Hendrik (Gast)


Lesenswert?

@Carol:
> Wenn die Sampletakt-Pegel abgefragt werden, geht das noch
> in 17 Takten für 1 Byte und 20 Takten für 2 Byte.

Nach Carol braucht der Mega dann ja max. 17/20 Takte für 8/16 bit. 
Nachdem  das Mess-Takt Signal den ADC getriggert hat, hat der Mega dann 
grade eben genug Zeit die Daten abzuholen und in den SRAM zu schreiben. 
Damit sollten ja 8 bit (~10 k Samples) @ 1 MHz möglich sein. Bei 16 bit 
(~5 k Samples) würde ich dann sicherheitshalber eher knapp unter einem 
MHz (900 kHz o.ä.) bleiben.

Da der Mega sich ja deterministisch verhalten sollte, ist es knapp, 
sollte  aber laufen. Und so wird dem Mega dann auf jeden Fall nicht 
langweilig. Ich werde das Projekt dann demnächst mal praktisch angehen 
und hier berichten, was rausgekommen ist.

@reggie, daybyter
Ich finde allerdings den STM32, wie u.a. reggie u. daybyter 
vorgeschlagen haben, auch immer interessanter. Ich habe mir mal den 
STM32F411RET6 (auf den Nucleoboards bei R) angesehen, der hat ja schon 
einen >2 MHz ADC (12 bit) an Board, und 128 kByte SRAM (finde ich 
besonders interessant, da sind die Megas ja deutlich drunter), wordurch 
wesentlich längere Datenblöcke gespeichert werden könnten. 
Kostentechnisch liegt der ja auch in etwa beim Atmega mit 16k SRAM und 
soweit ich sehe kann man ihn (LQFP) auch grade noch so von Hand löten 
(letzteres wäre ein weiteres wichtiges Kriterium). Ich denke ich werde 
mir bei der nächsten Gelegenheit so ein Board zum  rumtesten 
mitbestellen (soweit ich hier lesen konnte gibt es keine signifikaten 
Unterschiede zwischen Nucleo und Discovery, außer weniger Peripherie?).
Interessanter als die Verwendung des internen ADC fände ich dann - um 
noch ne Schippe draufzupacken - wiederum die analoge Überlegung der 
Verwendung eines exterenen, parallelen ADC. Da müssten mit dem STM32F4 
(@100 MHz) ja gut 16 bit und Sampleraten >4 MHz drin sein (bei 
Blocklängen von 50k-60k Samples, wenn man sonst an SRAM spart)? (Die 
Fragestellung passt dann thematisch allerdings nicht mehr so richtig 
unter den Titel dieses Threads).


@fchk
Ich habe mir die FIFOs mal angesehen, wenn ich mich nicht vertan habe 
scheinen die aber recht teuer zu sein (grade wenn man dann in Richtung 
64k/128k Speicher wie beim o.g. STM32 möchte (da scheint man dann pro 9 
bit FIFO schon so vier STM32F4 mit je 128k SRAM, zu bekommen). Wie du 
schreibst wäre das dann ja wohl mit externem RAM, grade wenns schneller 
sein soll, die bessere Lösung. Bei den angepeilten Samplingraten würde 
ich so aber erstmal in Richtung STM gucken...

@Mooskopf / Schlaubischlumpf
Mir ist bewusst, dass FPGAs für schnelle Signalverarbeitung genutzt 
werden - ich hätte nur erwartet, dass ich bei den angepeilten <10 MHz 
bzw. <5 MHz Samplingraten noch ohne auskomme. Ich habe bisher zwar 
hauptsächlich mit AVRs gebastelt, bin aber nicht darauf festgenagelt und 
gucke mir auch gerne andere Systeme an. Allerdings wollte ich mir den 
Einstieg in FPGAs doch für später aufheben. :)

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.