Wenn Dinge schiefgehen, obwohl die Programmlogik korrekt zu sein scheint, ist es an der Zeit, die Signale zu untersuchen, die in die MCU eingehen und aus der MCU herauskommen. Das beste Werkzeug dafür ist ein Logikanalysator.

Einleitung

Ein Logikanalysator (LA) zeichnet Signale auf und zeigt sie ähnlich wie ein Oszilloskop an. Im Gegensatz zu einem Oszilloskop wird nur der logische Pegel abgetastet, d. h. ob das Signal über oder unter einer bestimmten Schwellenspannung liegt. Was ihm an Auflösung fehlt, macht er in der Regel durch die Anzahl der Eingangskanäle wett, die 4 bis 136 statt 2 bis 4 wie bei einem Oszilloskop betragen.

Die große Anzahl von Kanälen ist vor allem dann wichtig, wenn man mit parallelen Bussystemen arbeiten will. Heutzutage befinden sich die parallelen Bussysteme jedoch meist nur innerhalb der MCU. Der Großteil der Kommunikation erfolgt seriell über I2C, SPI oder asynchrone Kommunikation. Nichtsdestotrotz ist es oft sehr nützlich, eine große Anzahl von GPIOs zu überwachen, um die zeitliche Koordination verschiedener Signale zu verstehen. Insbesondere bei der Suche nach zeit- oder ereignisreihenbezogenen Fehlern kann diese Art der Messung äußerst hilfreich sein.

Ein weiterer Vorteil von Logikanalysatoren ist, dass sie sogenannte Protokolldecoder besitzen, die den Bitstrom einer seriellen Kommunikation in sinnvolle Symbole übersetzen. Ein Beispiel dafür ist im Titelbild dieses Beitrags zu sehen. Der Bitstrom wird als I2C-Operationen interpretiert. Darüber hinaus werden diese I2C-Operationen als Befehle zum Lesen einer Echtzeituhr interpretiert.

Der beste Weg, den Umgang mit einem Logikanalysator zu lernen, ist, ihn einzusetzen. Zu diesem Zweck werde ich ein kleines Beispiel vorstellen. Wir werden dann drei verschiedene Logikanalysatoren betrachten:

  • Einen Arduino Uno, der in einen Logikanalysator verwandelt wurde,
  • einen sehr preiswerten (10 €) Logikanalysator, den man unter dem Namen 24MHz 8ch Logic Analyzer bei eBay und Amazon findet,
  • und der Saleae Logic Pro 8, ein High-End-Analysator.

Beispiel

Ein Freund bittet um einen Gefallen, nämlich ihm ein kleines Gerät zu bauen, das seriell gesendete Dezimalzahlen im ASCII-Code (bei 19200 Baud, 1 Startbit, 8 Datenbits, 1 Stopbit, keine Parität) in eine parallele Darstellung (mit 4 Ausgangsleitungen) umwandelt. Ohne viel Aufhebens tippt man das folgende Programm in einen Computer, lädt es auf einen Arduino Uno hoch und gibt ihm dem Freund, wobei man ihm noch verraten sollte, wo er welche Drähte anschließen muss.

// Receive decinmal digits on serial line and
// set data lines 8/9/10/11 to corresponding value 

// output pins 
byte outpin[4] = { 8, 9, 10, 11 };

void setup()
{
  Serial.begin(19200);
  for (byte i = 0; i < sizeof(outpin); i++) 
    pinMode(outpin[i], OUTPUT); // init output pins
}

void loop()
{
  char inp;
  byte out;

  while (Serial.available()) {
    out = -1;
    inp = toupper(Serial.read());
    if (inp >= '0' && inp <= '9') out = inp - '0';
    if (out >= 0) setoutpin(out);
  }
}

// set output pin corresponding to decimal digit received
void setoutpin(byte val)
{
  for (byte i = 0; i < sizeof(outpin); i++) {
    if (val&1) digitalWrite(outpin[i], HIGH);
    else digitalWrite(outpin[i], LOW);
    val = val >> 1;
  }
}

Am nächsten Tag bringt der (inzwischen ehemalige) Freund den Uno zurück und beklagt sich bitterlich, dass das Board an den Ausgangspins manchmal Werte zeigte, die viel höher als 9 waren. Mit anderen Worten, es wird Zeit, das Ding zu debuggen. Zu diesem Zweck fügt man eine Zeile vor der while-Schleife ein:

Serial.write(random(20) + '0');

Damit kann man eingehende serielle Kommunikation simulieren. Danach lädt man das Programm erneut hoch und verbindet Arduino Pin 0 (RX) mit Pin 1 (TX). Jetzt wird während jedes Schleifendurchlaufs ein serielles Byte gesendet und empfangen und man kann überprüfen, was mit den Ausgangspins passiert (man merke sich an dieser Stelle, dass die TX-RX-Verbindung entfernt werden muss, wenn man das nächste Mal ein Programm hoch laden will).

Ein in einen Logikanalysator verwandelter Uno

Jetzt wollen wir einen zweiten Uno (oder Nano, Pro Mini oder etwas Ähnliches) in einen Logikanalysator mit 6 Eingangskanälen, nämlich den Arduino-Pins 8 bis 13 verwandeln. Zu diesem Zweck muss man zunächst das Logikanalysator-Programm von gillham herunterladen. Eigentlich sollte man besser meinen Fork dieses Programms herunterladen, da die Reihenfolge der Abtastwerte im Originalprogramm nicht dem entspricht, was PulseView, die GUI für den Logikanalysator, erwartet. Außerdem habe ich einige Verbesserungen vorgenommen, wie z.B. das Triggern wieder zum Laufen gebracht, das Timing genauer gemacht und den Capture-Buffer vergrößert.

Jetzt benötigt man noch PulseView, das man sich von der sigrok-Download-Seite herunterladen kann. Nun kann man den Uno-LA und das zu prüfende Gerät (DUT) so einrichten, wie im folgenden Fritzing-Sketch gezeigt. Da PulseView eine direkte Antwort erwartet, nachdem es eine Verbindung zu dem Uno-LA aufgebaut hat, muss die Auto-Reset-Funktion des Arduino deaktiviert werden. Am einfachsten geht das, indem man einen Elektrolytkondensator von 10 µF oder mehr zwischen RESET und GND legt. Der markierte negative Draht muss an den GND Pin und der andere in den RESET-Pin.

Logikanalysator-Mess-Aufbau

Nun muss der USB-Stecker in den LA-Uno gesteckt werden, das Logikanalysator-Programm hochgeladen und PulseView gestartet werden. Dann muss die Verbindung zum LA aufgebaut werden. Dazu klickt man auf das kleine Dreieck neben dem Werkzeugsymbol.

Verbindungsaufbau zum Arduino-LA

Nun muss alles so wie oben eingestellt werden und der richtige seriellen Anschluss ausgewählt werden. Wenn man jetzt auf Scan for devices using driver above klickt, dann erscheint in der unteren Box AGLArevV1 with 6 channels, und man kann eine Verbindung herstellen, indem man auf OK klickt. AGLA steht für Arduino Generic Logic Analyzer, ein Name, der vom ursprünglichen Autor gillham geprägt wurde, und rev bedeutet, dass die Daten in umgekehrter Reihenfolge zurückgegeben werden.

Nun kann man oben rechts die Abtastfrequenz einstellen (100 kHz ist ein guter Wert). Dies ist die Frequenz, mit der der Logikanalysator Abtastungen vornimmt. 100 kHz bedeutet, dass alle 10 µs ein Wert abgetastet wird. Links neben dem Feld für die Abtastfrequenz befindet sich das Feld für die Speichertiefe. Hier kann man wählen, wie viele aufeinanderfolgende Abtastungen man vornehmen möchte. In unserem Fall ist der höchste Wert für unseren Uno-Analyzer, nämlich 1,536 k Abtastwerte, bereits ausgewählt. Das bedeutet, dass man bei jedem Erfassungslauf mit 100 kHz 15 ms lang Signale aufzeichnen kann. Schließlich wählt man die aktiven Kanäle aus (indem man auf das Messspitzensymbol klickt und dann die aktiven Kanäle auswählt). Nachdem alles eingerichtet wurde, lässt man den Logikanalysator starten, indem man auf Run (oben links) klickt. Dann könnte man z.B. folgendes Ergebnis erhalten:

Mit AGLA aufgenommene Signalverläufe

In Zeile 0 sieht man die seriellen Leitungsdaten. In Zeile 1 bis 4 werden die parallelen Ausgangswerte visualisiert. Es wäre gut, wenn alle diese Werte bereits interpretiert werden würden. Aber dafür gibt es ja Protokolldecoder! Wenn man auf das gelb/grüne Wellensymbol oben rechts klickt, erhält man eine Liste von Decodern, von denen man Parallel und UART (durch Doppelklick) auswählen sollte. Beide Decoder können konfiguriert werden, indem man auf die entsprechenden Symbole auf der linken Seite klickt, wie unten gezeigt.

Nach der Konfiguration sehen die aufgenommen und interpretierten Daten wie folgt aus:

Aufgenommene Daten durch Protolldekoder interpretiert

In diesem Fall sehen alle seriellen Signale vernünftig aus. Es kann vorkommen, dass die ersten seriellen Bytes komisch aussehen, da der Decoder einige Zeit braucht, um sich zu synchronisieren. Interessant ist in jedem Fall, dass es in der parallelen Dekodierzeile kleine Teile gibt, die merkwürdig aussehen. Wen man sich den Teil zwischen 2 und 1 ansieht, stellt man fest, dass dort ein anderer Wert stehen könnte. Man kann den Bereich vergrößern (mit der Plus-Taste oder dem Mausrad), danach den Cursor aktivieren (die beiden blauen Fähnchen) und dann die Zeit messen, die der Teil zwischen 2 und 1 aktiv ist (durch Ziehen der Fähnchen). Sie beträgt 10 µs.

Gezoomte Ansicht mit aktiviertem Cursor

Der Logikanalysator scheint darauf hinzudeuten, dass wir beim Wechsel von einem Wert zu einem anderen einen Übergangszustand von 10 µs durchlaufen könnten, der nicht beabsichtigt ist. Da 10 µs jedoch die Abtastzeit ist, könnte man sich fragen, ob es sich hier um ein Messartefakt handelt.

Erhöhen wir also die Abtastfrequenz auf 500 kHz, was bedeutet, dass wir nun nur noch 3 ms lang aufzeichnen können. Um sich auf den wichtigen Teil zu konzentrieren, kann man einen sogenannten Trigger verwenden. Dabei handelt es sich um eine Bedingung, auf die der Logikanalysator wartet und erst mit der Aufzeichnung beginnt, wenn die Bedingung erfüllt ist. Der Trigger kann durch Klicken auf die farbigen Kanalanzeigen auf der linken Seite konfiguriert werden.

Normalerweise kann man Trigger auf der Basis des Pegels eines Signals oder auf der Basis von Flanken definieren. Unser Uno-Logikanalysator unterstützt nur Pegel-Trigger. Um einen der Zustände abzufangen, wenn ein ungewöhnlich hoher Wert ausgegeben wird, setzen wir den Trigger für Zeile 2 und Zeile 4 auf High. Dann werden wir Ausgaben von 10 oder höher abfangen. Danach werden die Triggersymbole auf der rechten Seite der Kanalanzeige angezeigt.

Außerdem klicken wir noch auf das Werkzeugsymbol links neben dem Messspitzensymbol. Hier kann man einstellen, wie viel von der Aufzeichnung vor dem Auslösen angezeigt werden soll. Ein guter Wert ist 20 %. Startet man jetzt die Datenerfassung erneut, indem man auf Run klickt, könnte das Ergebnis wie folgt aussehen:

Datenaufnahme mit Trigger

Die vertikale, gestrichelte Linie zeigt den Auslösezeitpunkt. Die seriellen Daten sehen merkwürdig aus, wahrscheinlich weil der Decoder nicht synchronisieren konnte. Interessant ist jedoch, dass wir nun definitiv einen Fall mit einem Wert außerhalb des Bereichs haben. Wie oben zoomen wir heran und benutzen den Cursor.

Das Problem

Dieser Zustand lässt sich nicht als Messartefakt erklären. Es gibt jetzt tatsächlich zwei Abtastungen und die Überlappzeit scheint 4 µs zu betragen. Vielleicht könnte man mit einer höheren Abtastfrequenz mehr herausfinden. Man kann bis zu einer Frequenz von 5 MHz abtasten. Allerdings werden bei einer Frequenz von über 1 MHz die Abtastwerte vor dem Trigger nicht angezeigt. Der Grund dafür ist, dass es bei solch hohen Abtastraten nicht möglich ist, die Abtastwerte in einem Ringspeicher abzulegen.

Auf jeden Fall ist unser derzeitiges Messgerät für die tägliche Arbeit nur mäßig geeignet:

  • 1536 Abtastwerte sind nicht sehr viel;
  • es sind nur einfache Triggerbedingungen möglich;
  • bei Abtastfrequenzen, die höher als 1 MHz sind, sieht man keine Abtastwerte vor dem Trigger;
  • die höchste Abtastfrequenz beträgt 5 MHz.

Ich den Uno-Logikanalysator tatsächlich auch nur vorgestellt, um den Appetit auf einen echten Logikanalysator zu wecken. Es ist aber auf jeden Fall hilfreich, PulseView kennengelernt zu haben, da diese Open-Source-Software auf fast allen Logikanalysatoren läuft. Wer an weiteren Funktionen von PulseView interessiert ist, kann einen Blick in das Handbuch werfen.

24MHz 8ch Logikanalysatoren

Für rund10 € erhält man einen Logikanalysator, der um viele Größenordnungen leistungsfähiger ist als der Uno-Logikanalysator. Wie bereits erwähnt, gibt es diese Geräte unter anderem bei eBay und Amazon. Sie basieren alle auf dem Cypress FX2-Mikrocontroller. Die gute Nachricht ist: Sie werden alle von PulseView unterstützt und funktionieren einwandfrei.

Ein 24 MHz 8ch Logikanalysator

Die technischen Daten sind: 8 Kanäle mit bis zu 24 MHz Abtastfrequenz und die Speichertiefe ist praktisch unbegrenzt, da alle erfassten Daten über USB gestreamt werden. Aber Vorsicht: 24 MHz funktioniert nur dann, wenn die Kommunikation auf dem USB-Bus nicht durch andere Geräte behindert wird. Außerdem ist das mitgelieferte USB-Kabel oft von sehr schlechter Qualität und sollte sofort in den Mülleimer geworfen werden!

Vergleicht man die technischen Daten mit unserem Uno (6 Kanäle, maximal 1 MHz mit Trigger, 1,5K Speichertiefe), so haben wir hier einen klaren Sieger. Schließen wir also den Logikanalysator an den Prüfling an. Wenn man regelmäßig mit dem Logikanalysator arbeiten will, dann ist das Messkabel vermutlich das Erste, was man ersetzen möchte. Es gibt z. B. für den Buspiraten Messkabel, die den richtigen 10-poligen Stecker für den Logikanalysator und Prüfspitzen am anderen Ende besitzen. Das kostet allerdings weitere 10 €. Allerdings sind High-End-Tastköpfe nochmal erheblich teurer. Diese kosten rund 10 € pro Stück! Auf der sigrok-Website findet man einen interessanten Vergleich verschiedener Messspitzen.

Der Anschluss von PulseView an den Logikanalysator ist einfach zu bewerkstelligen. Hier muss man den fx2lafw-Treiber und das USB interface auswählen. Wenn man nun die Scan-Taste drücken, sollte Saleae Logic with 8 channels oder etwas Ähnlichem auftauchen und man kann eine Verbindung herstellen, indem man OK drückt.

Wiederholen wir nun die Messung von oben, wählen aber 24 MHz Abtastfrequenz und 1 M Abtastwerte. Außerdem wählen wir den Trigger so, dass alle Datenleitungen D1-D4 auf High liegen (was dem Wert hexadezimal 0x0F entspricht), und stellen Pre-trigger capture ratio auf 20 %. Schließlich muss man noch den UART– und den Parallel-Decoder wie oben beschrieben einstellen. Das Ergebnis könnte wie in der folgenden Abbildung aussehen.

Der „Bösewicht“

Es ist deutlich zu sehen, dass die Situation, in der die Auslösebedingung erfüllt ist, eintritt, wenn wir von 9 auf 7 umschalten. Wenn man jetzt heranzoomt, kann man messen, wie viel Zeit es dauert, den Ausgang einer Ausgangsleitung zu ändern.

Zoomen und Messen

Wie man sehen kann, dauert es 5 µs, bis die Leitung D3 von High auf Low umgeschaltet wird. 5 µs scheint also die Ausführungszeit des Funktionsaufrufs digitalWrite(i, LOW) zu sein (aber siehe weiter unten!). Dies wirft zwei interessante Fragen auf. Erstens: Welche Abtastfrequenz ist angemessen? Zweitens: Wie können wir den Entwurf unseres Seriell-Parallel-Wandlers verbessern?

Nach dem Nyquist-Shannon-Abtasttheorem braucht man eine Abtastfrequenz, die mindestens doppelt so hoch wie die höchste Frequenz ist, wenn man ein analoges Signal perfekt diskretisieren will. In unserem Fall wollen wir kein analoges Signal diskretisieren, sondern ein digitales Signal erfassen. Wenn wir also ein Taktsignal (z. B. von einem SPI-Bus) mit einem Tastverhältnis von 50 % haben, dann bedeutet die Abtastung mit einer Rate, die dem Zweifachen der Taktfrequenz entspricht, zwei Abtastpunkte pro Periode, idealerweise einen für jeden Zustand. Es besteht jedoch eine hohe Wahrscheinlichkeit, dass ein hoher oder niedriger Zustand verpasst wird. Saleae empfiehlt aus diesem Grund eine Abtastfrequenz, die mindestens das Vierfache der Bandbreite des digitalen Signals beträgt, in unserem Fall also das Vierfache der SPI-Taktfrequenz. Andere empfehlen das Sechsfache der Bandbreite. Wenn man nun Zeitintervalle messen will, sollte man sich darüber im Klaren sein, dass der Fehler im schlimmsten Fall immer ein Abtastintervall beträgt. Im Falle der obigen Messung beträgt die Zeit also 4,995 ± 0,041 µs, d. h. der Fehler ist vernachlässigbar.

Was kann man nun gegen unseren fehlerhaften Entwurf des Seriell-Parallel-Wandlers tun? In unserem Fall haben wir zwei Möglichkeiten. Erstens könnten wir die Ausgänge mithilfe von PORTB, dem Ausgangsregister des Arduino, setzen. Dann würden alle Leitungen ihren Wert genau zur gleichen Zeit ändern. Der Code könnte dann wie folgt aussehen:

void setoutpin(byte val)
{
  PORTB = (PORTB & 0xF0) | (val & 0x0F);
}

Wir lesen den aktuellen Wert der Ausgangspins und wählen die höherwertigen 4 Bits aus (weil wir sie nicht ändern wollen). Dann wird dieser Wert mit den niederwertigen 4 Bits der Variablen val bitweise verodert und an die Ausgangspins gesendet. Wie könnte das Umschalten jetzt aussehen?

Wenn man denselben Trigger wie zuvor verwendet, kann man u.U. sehr schnell ein Ergebnis wie oben dargestellt erhalten. Man sieht, dass sich jetzt alle Signale genau zur gleichen Zeit ändern (soweit man das messen kann), aber jetzt sieht man ein Übersprechen, d.h. eine elektromagnetische Störungen, auf Leitung D4. Diese wird wahrscheinlich durch das gleichzeitige Abschalten von drei Leitungen und der Benutzung von Messkabeln verursacht. Nun, das kann man vermutlich vernachlässigen, denn ohne die Messkabel würde das Übersprechen nicht auftreten.

Dieses Phänomen deutet jedoch auf ein allgemeines Problem hin. Wenn die parallelen Leitungen umgeschaltet werden, dann ist der Bus in dieser Übergangsphase generell instabil. Es ist also ratsam, einige Zeit zu warten, bis sich alle Signale stabilisiert haben. Parallele Bussysteme haben in der Regel ein zusätzliches Taktsignal, bei dem eine Flanke signalisiert, dass sich alle Leitungen in einem stabilen Zustand befinden. Und das ist es, was wir wahrscheinlich in das System einbauen sollten (auch auf der Empfangsseite!).

Schließlich stellt sich noch die Frage, ob wir einen leistungsfähigeren Logikanalysator brauchen. Wie bereits erwähnt, sollte die Abtastrate mindestens viermal so hoch sein wie die Bandbreite des Systems. In unserem Fall würde das bedeuten, dass 6 MHz das Maximum ist. In der Tat sind die Taktraten der Busse, die ein Bastler verwendet, meistens niedriger. Ich schätze, dass 90 % aller Anwendungsfälle für Bastler mit dem El Cheapo Logikanalysator abgedeckt werden. Und für einige der übrigen, z.B. schnelle SPI-Busse, könnte man die Busfrequenz zum Debuggen reduzieren. Trotzdem kann man sich natürlich fragen, was man mit einem leistungsfähigeren Logikanalysator alles anstellen könnte.

Saleae Logic Pro 8

Saleae ist das Unternehmen, das USB-Logikanalysatoren populär gemacht hat. Anfangs (in den 70er Jahren) waren Logik-Analysatoren schweres Geschütz, etwas, das nur Forschungs- und Entwicklungslabors kaufen konnten. Durch die Übertragung aller Daten über USB an einen PC konnte die erforderliche Elektronik auf ein Minimum reduziert werden, und genau das war Saleaes Innovation. Tatsächlich war die Elektronik in den ersten Saleae-Logikanalysatoren nicht mehr als ein Entwicklungsboard des Cypress FX2-Mikrocontrollers (plus Puffer). Und genau das ist es, was man erhält, wenn man einen der 24-MHz-8-Kanal-Analysatoren kauft. Dies sind Klone der ersten Generation der Saleae-Logikanalysatoren und arbeiten auch noch mit der ersten Generation der Saleae-Software, genannt Logic. Die Verwendung der Saleae-Software auf diesen Klonen verstößt jedoch gegen die Lizenzbedingungen der Software. Aber dann gibt es ja heutzutage PulseView.

Saleae hat die USB-Streaming-Logikanalysatoren im Laufe der Jahre weiterentwickelt, und die aktuellen High-End-Modelle verwenden USB 3.0. Sie haben einstellbare Logikpegel, eine maximale Abtastfrequenz von 500 MHz, analoge Eingänge (mit einer Bandbreite von 5 MHz) und bis zu 16 Kanäle. Dies sind die Modelle Logic Pro 8 und Logic Pro 16. Es gibt auch ein abgespecktes Modell namens Logic 8, das nur USB 2.0 verwendet. Und es ist möglich, für dieses Modell einen Rabatt zu bekommen, wenn man Student oder Elektronik-Enthusiast ist (d.h. kein Geld mit der Bastelei verdient).

Zusätzlich zu den Verbesserungen auf der Hardwareseite hat sich auch die Software im Laufe der Jahre verbessert. In der Tat ist es die Software, die den Unterschied ausmacht. Und Saleae hat von Anfang an alle drei Plattformen unterstützt, was man als Mac-Benutzer sehr zu schätzen weiß. Logic 2, die aktuelle Software, ist sehr vielseitig und einfach zu bedienen. Wenn ich es mit PulseView vergleiche, würde ich Logic 2 den Vorzug geben, aber das ist natürlich eine Frage des persönlichen Geschmacks. Die Anzahl der Decoder ist definitiv ein Pluspunkt für PulseView, während die einfache Bedienung für Logic 2 spricht. Und das Beste ist, dass man die rohen Erfassungsdaten aus Logic 2 exportieren und in PulseView importieren kann (falls man einen Decoder benötigt, der nicht von Logic 2 unterstützt wird). Laut der sigrok-Website ist es möglich, Logic Pro 8 mit PulseView zu verwenden. Allerdings wird der analoge Teil noch nicht unterstützt.

Nun wollen wir einige Messungen am Arduino durchzuführen.

Saleae Pro 8 in Aktion

Um die Stärken der verschiedenen Logikanalysatoren (und GUIs) zu demonstrieren, wollen wir die Zeit zu bestimmen, die benötigt wird, um das Ausgangssignal eines Arduino zu ändern. Wir werden messen, wie lange es dauert, ein Bit mithilfe der Portmanipulation zu ändern (das sollte zwei Zyklen oder 125 ns dauern), ein gesamtes Portbyte zu ändern (1 Zyklus oder 67,5 ns) und einen Arduinopin mithilfe des digitalWrite-Aufruf zu ändern. Dazu benutzen wir das folgende kleine Arduino-Programm.

void setup ()
{
  DDRB = 0x3F; // all PORTB pins are output (Arduino pins 8-13)
}

void loop ()
{
  PORTB |= 0x01; // switch on bit 0
  PORTB |= 0x02; // switch on bit 1
  PORTB &= ~0x02; // switch off bit 1
  PORTB = 0x0F;  // switch on all 4 low bits
  PORTB = 0x00;  // switch off all 4 low bits
  digitalWrite(8, HIGH); // switch on lowest bit again
  PORTB = 0; // and everything off again
  delayMicroseconds(20); // wait 20 µsec
}

Und was macht der Logic Pro 8 daraus?

E/A-Zeitmessung mit dem Saleae Logic Pro 8

Wenn man die Maus über eine Wellenform bewegt, werden Zeit und Frequenz automatisch gemessen und angezeigt. Wie man sieht, dauert der digitalWrite-Vorgang 2,246 µs. Darüber hinaus kann man auch explizite Messungen vornehmen, um beispielsweise die Flanken verschiedener Kanäle in Beziehung zu setzen, wie man in der folgenden Abbildung sieht.

Explizite Messung

Die Messergebnisse sind höchst unüberraschend. Das Ändern eines Bits dauert 126 ns, das Ändern des gesamten Bytes 66 ns, was mehr oder weniger den Erwartungen entspricht. Bei einer Abtastfrequenz von 500 MHz haben wir einen Worst-Case-Fehler von 2 ns, was die Abweichungen von den theoretischen Werten erklärt.

Wie schaut es aus, wenn wir den 10 € Logikanalysator einsetzen?

Der 24 MHz 8 Ch Analysator in Aktion
Ändern eines Ausgabebits

Bei einer Abtastfrequenz von 24 MHz ist es nicht verwunderlich, dass wir nur 42 ns (das Abtastintervall) für die Änderung des gesamten Ausgangsbytes messen, was in Wirklichkeit 67,5 ns sind. Die Änderung eines Bits dauert 125 ns, was der Wahrheit eher nahe kommt, aber die Messung hat natürlich einen Fehler von ± 42 ns. Für die Ausführung der digitalWrite-Funktion messen wir wiederum 2,246 µs. Hier müssen wir für jede Messung den Cursor verwenden.

Zum Schluss probieren wir noch unseren Uno-Logikanalysator aus. Selbst bei einer Abtastfrequenz von 5 MHz (was ein Abtastintervall von 200 ns bedeutet) wissen wir, dass wahrscheinlich einige Signale verpasst werden. Aber wie schlecht läuft tatsächlich?

Abtastfrequenz 5 MHz auf dem Uno-Logikanalysator

Wie man deutlich sieht, verpasst man tatsächlich viele der kurzen Impulse. Das ist aber nicht weiter verwunderlich ist, da die Impulse kürzer sind als das Abtastintervall. Wenn man die Zeit misst, die für die Ausführung von digitalWrite benötigt wird, sind es wiederum 2,2 µs.

Das einzige Rätsel, das wir noch lösen müssen, ist, warum wir hier 2,2 µs gemessen haben und im vorherigen Abschnitt 5 µs für die Ausführungszeit von digitalWrite. Hierfür gibt es mehrere Gründe. Erstens haben wir hier den Arduino-Pin 8 gemessen, der kein PWM-Pin ist. Wenn man das Gleiche für Pin 11 macht, erhält man 3 µs. Zweitens haben wir hier von der Flanke, die durch eine Portmanipulationsanweisung verursacht wurde, bis zur Flanke, die durch digitalWrite verursacht wurde, gemessen. Weiter oben hatten wir zwischen zwei Flanken gemessen, die beide durch digitalWrite verursacht wurden. Wenn man das mit zwei einfachen digitalWrite-Aufrufen macht, erhält man in der Tat 4 µs, was bedeutet, dass digitalWrite auch nach dem Ändern des Ausgangspins noch Code ausführt. Drittens, hatte das erste Programm eine Schleife, in der Indexberechnungen usw. ausgeführt wurden, was vermutlich zu weiteren 8-10 Maschineninstruktionen geführt hat, die sich zu einer weiteren Mikrosekunde aufaddieren. Und dann ist man bei den 5 µs, die wir oben gemessen hatten.

Zusammenfassung

Ich würde meinen Logikanalysator nicht mehr hergeben. Er ist ein unverzichtbares Werkzeug bei der Entwicklung eingebetteter Systeme. Bei der Verbesserung des Arduino Generic Logic Analyzer Programms war der „echte“ Logikanalysator zum Beispiel sehr hilfreich bei der Suche nach einigen Fehlern (verursacht durch Inkompatibilitäten zwischen PulseView und AGLA).

Welcher Logikanalysator ist also der richtige? Würde ich empfehlen, den Arduino Generic Logic Analyzer für die tägliche Arbeit zu verwenden? Definitiv nicht! Wenn das Budget knapp ist, hat die 24-MHz-8-Kanal-Variante das beste Preis-Leistungs-Verhältnis. Und es wird wahrscheinlich fast alle Fälle abdecken, die einen interessieren. Hat man mehr Geld zur Verfügung, könnte der Saleae Logic 8 mit einem Rabatt eine Option sein. Es gibt jedoch jede Menge Alternativen, und die meisten von ihnen werden von PulseView unterstützt, was ich als wichtiges Kriterium für die Auswahl eines Logikanalysators ansehen würde.

Abschließend möchte ich noch auf das interessante YouTube-Video des ursprünglichen Autors von PulseView hinweisen, in dem man alles über sigrok und Logikanalysatoren erfährt. Und wer es auf einen High-End-Logikanalysator abgesehen hat, sollte sich den KEYSIGHT 16803A 102-Kanal Portable Logic Analyzer ansehen, der zum Schnäppchenpreis von 14.500 US$ angeboten wird.