Forum: Mikrocontroller und Digitale Elektronik STM32F103 eleganter Triggergenerator für analogen Signalverlauf mit Analog Watchdog?


von Robin S. (der_r)


Lesenswert?

Hallo zusammen,


ich baue mir gerade mit einem STM32F103 eine kleine Schaltung auf, um 
analoge Spannungen betrachten zu können. Ähnlich einem "Oszi für Arme" 
habe ich mir mit Timer, ADC und DMA Circular Mode schon die 
Aufzeichnungsfunktionen realisiert, die Werte landen durch DMA in einem 
Array und werden (derzeit) einfach endlos wie ein Ringpuffer 
überschrieben. Nehmen wir mal an, dieser hat 512 Elemente.


Nun würde ich gerne auf wiederholende Signalverläufe triggern, um die 
Aufzeichnung irgendwann zu stoppen und das Array auf ein Grafikdisplay 
zu plotten, bevor eine neue Runde startet. Logischerweise sollte der 
Triggerpunkt einigermaßen mittig liegen.
Wenn ich jetzt jeden ADC-Wert mittels Interrupt auf überschreiten der 
Triggerschwelle prüfen muss und ab da z.B. auf 256 Zähle und dann die 
Aufnahme händisch stoppe, wäre dieses Soll zwar erfüllt und das Bild 
mittig, aber die CPU hat ohne Ende zu tun und die DMA ist irgendwo auch 
sinnlos.


Hat jemand eine Idee, wie man das eleganter lösen könnte? Ich würde 
gerne auf zu viele Interrupts verzichten.

Meine Idee war: Den Analog Watchdog verwenden, um die Werte zu 
beobachten und ein Interrupt auszulösen, sobald die Triggerbedingung 
erfüllt ist. Dabei deaktiviert sich der Watchdog selbst, sodass nicht 
erneut getriggert wird. In der ISR aktiviere ich einen weiteren Timer 
als Zähler, der seinen Takt vom Update-Ausgang des ersten Timers (der, 
der den ADC auslöst) erhält. Der Reload-Wert wird auf 256 gesetzt. 
Sobald nun dieser Timer überläuft, sind (in der Theorie) 256 Werte seit 
der Triggerung aufgenommen worden und das Bild mittig.

Allerdings läuft die Timer->ADC->DMA Geschichte während der ISR ja 
fröhlich weiter, sodass je nach Samplerate wohl mehr als 256 Werte 
genommen werden. Das Bild ist dann leicht aus der Mitte, aber die 
Verzögerung wäre ja für alle weiteren Durchläufe reproduzierbar.



Trotzdem: Hat jemand eine Idee, wie man das eleganter lösen könnte? 
Vielleicht sogar so, dass ohne Zutun der CPU getriggert wird und dann 
noch genau 256x gewandelt wird, bis die Aufnahme stoppt?

von holger (Gast)


Lesenswert?

>wäre dieses Soll zwar erfüllt und das Bild
>mittig, aber die CPU hat ohne Ende zu tun

ROFL. Das langweilt deine CPU vermutlich nur.

von Jan H. (jan_h565)


Lesenswert?

Die Werte in zwei/drie Buffer schreiben. Sobald das Ereignis kommt, wird 
den actuelle Buffer+1 weiter gefullt. Jetzt haben sie alle Daten 
gespeichert, und is est nur noch ein Problem von Wiedergabe.
Ubrigens ist den STM32 F3 hier noch besser geignet : hat OPAMP + 
Hardware comparator.
MFG

von W.S. (Gast)


Lesenswert?

Robin S. schrieb:
> die Werte landen durch DMA in einem
> Array und werden (derzeit) einfach endlos wie ein Ringpuffer
> überschrieben. Nehmen wir mal an, dieser hat 512 Elemente.

Tja, so ein DMA kann eben nur Daten herumschaufeln, aber nicht selbst 
bewerten. Das kann nur die CPU per geeignetem Programm. Also wenn man 
diesen Gedanken konsequent weiterdenkt, dann kommt nur in Frage, ohne 
DMA zu arbeiten, auch ohne Interrupts. Stattdessen in der Grundschleife 
in main mit so wenig Code wie möglich den ADC abzufragen, dessen Werte 
in den Ringpuffer zu schreiben und zu bewerten.

Aber nimm für sowas lieber einen Cortex M4F, denn du willst ja deine 
Werte auch noch skalieren, bevor du sie auf das Display losläßt. Die 
hohe Schule wäre so ein 200 MHz LPC43xx mit zwei CPU's drin. Eine macht 
nur die ADC-Abfragen und die andere die Bedienung, Displayansteuerung 
sowie Berechnungen.

W.S.

von Marcus H. (Firma: www.harerod.de) (lungfish) Benutzerseite


Lesenswert?

Hi Robin,
welchen F103 setzt Du denn ein?

Bei einem, ggf. pinkompatiblen, F40x @ 168MHz würde ich für Deine 
Anwendung kein großes Problem sehen. Dessen Interrupt-Latenzzeiten sind 
zwar nicht berauschend, allerdings stehst Du so schnell in der ISR, dass 
Du innerhalb ein/zwei Samplezeiten einen Timer aktiviert bekommst.

Oder, bei entsprechend großen Puffern, Dir einfach nur einen Zeitstempel 
aus einem freilaufenden Timer merkst und daraus später die Bildlage 
zusammenbaust.

Dasselbe Konzept sollte auch bei einem F1 funktionieren, ggf. mit ca. 
der doppelten Latenzzeit.

OHNE CPU und ohne Zusatzhardware habe ich beim F40x auf die Schnelle 
keine Lösung gefunden, da der Analog Watchdog scheinbar nur in den NVIC 
läuft und nicht direkt an die Timer gehängt werden kann.

OHNE CPU und Zusatzhardware könnte so aussehen, dass Du Dir einen 
Komparator an einen Timer-Kontrollpin hängst. Triggerschwelle wird mit 
DAC oder PWM eingestellt, der Vergleichseingang hängt am Signal.

Cheerio,
 marcus

von Robin S. (der_r)


Lesenswert?

Danke an alle für die Antworten,

> Das langweilt deine CPU vermutlich nur.

Möglich, aber bei abertausenden von Interrupts/s sehe ich mich gerne um, 
ob bei diesen Hardware-Möglichkeiten nicht ne intelligentere Lösung 
denkbar ist.


W.S. schrieb:
> dann kommt nur in Frage, ohne
> DMA zu arbeiten, auch ohne Interrupts. Stattdessen in der Grundschleife
> in main mit so wenig Code wie möglich den ADC abzufragen, dessen Werte
> in den Ringpuffer zu schreiben und zu bewerten.

Das wäre mein letzter Ausweg, mal schauen.

Markus H. schrieb:
>welchen F103 setzt Du denn ein?
>OHNE CPU und ohne Zusatzhardware habe ich beim F40x auf die Schnelle
>keine Lösung gefunden, da der Analog Watchdog scheinbar nur in den NVIC
>läuft und nicht direkt an die Timer gehängt werden kann.

Es handelt sich um den STM32F103C8T6, den man bei Reichelt günstig 
bekommen kann (deshalb ;-) ).
Hmm, meine Vorstellung war schon, mit dem Analog Watchdog einen 
Interrupt auszulösen, in dem ich dann einen zweiten Timer aktiviere, der 
bei jedem Update-Event des ADC-Timers +1 hochzählt. Da ist eben das 
Problem der Latenz, wie auch beim von dir beschriebenen Vorgehen. Ich 
werde vielleicht einfach mal testen, wie gravierend das ist.

>OHNE CPU und Zusatzhardware könnte so aussehen, dass Du Dir einen
>Komparator an einen Timer-Kontrollpin hängst.
DAS ist eine sehr gute Idee! Die Möglichkeit halte ich mir auf der 
Platine in jedem Fall mal offen. Nur stellt sich da halt ebenfalls die 
Frage, wie man geschickt das Zählen beginnt. Wenn ich mit dem Pin wieder 
nur in eine ISR gehe, die dann einen Zähler aktiviert, der 
(hardwareseitig) mit dem ADC-Timer verbunden ist, sind wir wieder beim 
gleichen Problem wie beim Watchdog, oder?

Kann natürlich sein, ich übersehe da was, ich bin noch dabei, mir einen 
Überblick über die ganzen Möglichkeiten zu verschaffen.

von Marcus H. (Firma: www.harerod.de) (lungfish) Benutzerseite


Lesenswert?

Robin S. schrieb:
> Markus H. schrieb:
>>welchen F103 setzt Du denn ein?
>>OHNE CPU und ohne Zusatzhardware habe ich beim F40x auf die Schnelle
>>keine Lösung gefunden, da der Analog Watchdog scheinbar nur in den NVIC
>>läuft und nicht direkt an die Timer gehängt werden kann.
>
> Es handelt sich um den STM32F103C8T6, den man bei Reichelt günstig
> bekommen kann (deshalb ;-) ).
> Hmm, meine Vorstellung war schon, mit dem Analog Watchdog einen
> Interrupt auszulösen, in dem ich dann einen zweiten Timer aktiviere, der
> bei jedem Update-Event des ADC-Timers +1 hochzählt. Da ist eben das
> Problem der Latenz, wie auch beim von dir beschriebenen Vorgehen. Ich
> werde vielleicht einfach mal testen, wie gravierend das ist.

Schau mal in die entsprechende Doku und berichte, wieviel Taktzyklen der 
NVIC/ARM für den ISR Ansprung braucht. Wenn Deine MCU mit 72MHz läuft, 
kann Du den Jitter abschätzen.

>>OHNE CPU und Zusatzhardware könnte so aussehen, dass Du Dir einen
>>Komparator an einen Timer-Kontrollpin hängst.
> DAS ist eine sehr gute Idee! Die Möglichkeit halte ich mir auf der
> Platine in jedem Fall mal offen. Nur stellt sich da halt ebenfalls die
> Frage, wie man geschickt das Zählen beginnt. Wenn ich mit dem Pin wieder
> nur in eine ISR gehe, die dann einen Zähler aktiviert, der
> (hardwareseitig) mit dem ADC-Timer verbunden ist, sind wir wieder beim
> gleichen Problem wie beim Watchdog, oder?
>
> Kann natürlich sein, ich übersehe da was, ich bin noch dabei, mir einen
> Überblick über die ganzen Möglichkeiten zu verschaffen.
Ich schrieb "Timer-Kontrollpin" - sprich Du machst das direkt in 
Hardware.
Stichworte: Input-Capture oder ETR.

Insgesamt ist beim STM immer der Trick rauszufinden, wie man die 
Peripherie sinnvoll verwursten kann. Der NVIC ist mächtig, aber 
verhältnismäßig träge. Der ARM-Core bringt eine hohe mittlere 
Rechenleistung, hat aber, insbesondere mit GCC, hohe Latenzen bei 
Kontextwechseln.
Mit Assembler sähe das anders aus. ;)

von Robin S. (der_r)


Lesenswert?

Marcus H. schrieb:
> Schau mal in die entsprechende Doku und berichte, wieviel Taktzyklen der
> NVIC/ARM für den ISR Ansprung braucht. Wenn Deine MCU mit 72MHz läuft,
> kann Du den Jitter abschätzen.

Ich tue mich schwer, die spezifische Info bei ST zu finden, allerdings 
ist für den Cortex M3 bei ARM selbst zu lesen, dass nominell 12 Takte 
gebraucht werden, um eine ISR anzuspringen.

Angesichts dessen, dass meine Signale nur im kHz-Bereich liegen, werde 
ich der Einfachkeit halber mal ausprobieren, wirklich die Werte von der 
CPU überwachen zu lassen.


> Ich schrieb "Timer-Kontrollpin" - sprich Du machst das direkt in
> Hardware.
> Stichworte: Input-Capture oder ETR.

Darin werde ich mich ebenfalls mal einarbeiten, spätestens nachdem ich 
mal die Software-Lösung probiert habe. Danke!

von Marcus H. (Firma: www.harerod.de) (lungfish) Benutzerseite


Lesenswert?

Robin S. schrieb:
> Ich tue mich schwer, die spezifische Info bei ST zu finden, allerdings
> ist für den Cortex M3 bei ARM selbst zu lesen, dass nominell 12 Takte
> gebraucht werden, um eine ISR anzuspringen.

12 Takte Entry Latency, wenn der gewünschte Interrupt eine ausreichende 
Priorität hat.
Zuzüglich der Kram, den der Compiler noch macht.
Schließlich noch 10 Takte Exit Latency.
An dieser Stelle darfst Du auch mal ins Disassembly schauen.

Du kannst die kompletten ISR-Latenzzeiten testen, indem Du von extern 
triggerst und in der ISR einen GPIO setzt. Ohne groß aufzupassen sollten 
da Latenzzeiten unter 1us rauskommen - bei Verwendung der 
ST-Bibliotheken vor HAL.


Lektüre:
STM32F103x8 DocID13587 Datasheet
RM0008 Reference Manual
PM0056 Cortex M3
Sämtliche Peripheriedoku, inkl.  / NVIC

...

Die französische Originaldoku wurde bereits ins Englische übertragen und 
sehr übersichtlich in ca. 50 Dokumenten und auf ca. 10000 Seiten kurz 
zusammengefasst. ;)

von Vincent H. (vinci)


Lesenswert?

Für Fälle, wo der DMA kontinuierlich laufen und gleichzeitig auf die 
gelesenen/geschriebenen Daten zugegriffen werden muss gibt es den 
"Half-Transfer Interrupt".

Sobald dieser aktiv ist, kann gefahrlos die "erste Hälfte" der Daten 
bearbeitet werden.

Worauf natürlich weiterhin geachtet werden muss ist, dass die 
Bearbeitung der Daten beendet ist, bevor der DMA die besagte Hälfte 
wieder überschreibt...


Diverse F4-Derivate hatten soweit ich mich entsinne auch mal einen 
"Double Buffer" Mode. Damit dürften ähnliche Dinge machbar sein.

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.