Oszillopskop "Stresstest" mit Arduino

Ich wollte heute mal mein Oszilloskop einen Stresstest unterziehen bzw. schauen, welche Frequenzen es noch erkennbar darstellen kann.
Mir ist klar, dass mit einem 16MHz IC das Oszilloskop normalerweise nicht ausgereizt werden sollte, aber das könnte ich dann eventuell noch später mit meinem stm32F103CBT6 Board/Maple Mini (72 MHz Takt) noch ausreizen.

Bei dem Oszilloskop handelt sich dabei um ein Hantek DSO5102P.
Es ist ein preiswertes 2 Kanal DSO mit 100MHz Bandbreite, 1GSa/s und leider nur 40K Speichertiefe.
Das Gute and dem Oszi ist, dass es für rund 200€ zu haben ist und per Software und auslöten von 2 Kondensatoren auf 200MHz Bandbreite gebracht werden kann und es dazu einige Beiträge zu Verbesserungen (z.B. zum reduzieren von Überschwingen, verbesserung der Flankensteilheit etc.) gibt.

Was ich nun (erstmal) versucht habe, ist ein paar Impulse unterschiedlicher Länge auszugeben:

void setup() 
{
  pinMode(6, OUTPUT);
}


void loop() 
{
      delayMicroseconds(100);

      // 100 kHz
      PORTD = B01000000; // D6 HIGH.
      delayMicroseconds(10);
      PORTD = B00000000;  // D6 HIGH LOW
      delayMicroseconds(10);

      // 200 kHz
      PORTD = B01000000; // D6 HIGH.
      delayMicroseconds(5);
      PORTD = B00000000;  // D6 HIGH LOW
      delayMicroseconds(5);

      // 1 MHz
      PORTD = B01000000; // D6 HIGH.
      delayMicroseconds(1);
      PORTD = B00000000;  // D6 HIGH LOW
      delayMicroseconds(1);
}

Ich habe verschiedene Nanos und Unos mit Quarzoszillator mit Keramikresonator getestet und alle sind ähnlich "danaben" von der Impulsdauer.

Die delayMicroseconds(10) dauert 8,8µs (113KHz statt 100KHz)
delayMicroseconds(5) dauert 3,81µs (262KHz statt 200KHz)
und delayMicroseconds(1) dauert 70nS (~14,3MHz statt 1MHz)

Letzteres kann eigentlich schon nicht mehr sein, weil das ja quasi schon Geschwindigkeitsgrenze des Arduinos ist.

Außerdem ist da irgendwas sehr ungenau (entweder das delayMicroseconds, die Taktgeber oder mein Oszilloskop).

Kann das mal jemand verifizieren oder was dazu sagen?

Vielleicht solltest du mal die Doku zu den Funktionen lesen, welche du verwendest.....

Caveats and Known Issues

This function works very accurately in the range 3 microseconds and up. We cannot assure that delayMicroseconds will perform precisely for smaller delay-times.

Eine Fehlpeilung von 3µs ist also zu erwarten.
Und da bist du voll drin.

So kurze Impulszeiten kannst Du nicht zuverlässig per Software erzeugen.
Nutze einen Timer (1 oder 2) und erzeuge die Impulse per HW. Das geht wesentlich genauer, und da kannst Du auch noch kürzere Pulse als 1µs ziemlich genau generieren.
Die 70ns sind exakt das, wenn Du direkt per Port-Befehl den Ausgang Ein- und direkt danach wieder ausschaltest. Wenn das stimmt, hat dir der Compiler den delay wegoptimiert, denn allein der Unterprogrammaufruf dauert schon länger ( Bei delayMicroseconds(1) macht der Aufruf auch nichts anderes als direkt wieder zurückzuspringen).

Ich hatte das so verstanden, dass ab 3µs die Werte sehr präziese sein sollen, nicht, dass die Abweichung 3µs beträgt.

Aber mal davon abgesehen, dass ich es immernoch anders verstehe, frage ich mich, wie das Arduino die 14,3MHz pulse schafft :smiley:

EDIT:
@MicroBahner: Im Anhang ist ein Sceenshot… sollte also wirklich stimmen :wink:
Aber gut zu wissen. Wobei es mit dem Timer und per Hardware nur genauer, aber nicht schneller geht oder?
Also bei 1MHz ist schluss, wenn ich das hier richtig verstehe:
Timer1

Leon333:
Wobei es mit dem Timer und per Hardware nur genauer, aber nicht schneller geht oder?

Rein von der HW her geht es schon schneller, aber offensichtlich unterstützt die Library das nicht - da musst Du dann selbst an die Timerregister ran.
Wobei - wenn ich das richtig verstehe - die 1µs die Wiederholfrequenz ist, Die PWM-Pulse am Ausgang müssten dann schon kürzer machbar sein.
Ich kenne die Lib aber nicht, da ich den Timer gegebenenfalls lieber selbst einrichte.

tjoa…

Also aus wissenschaftlichem Interesse hab ich einfach nochmal das hier getestet:

void setup() 
{
  pinMode(6, OUTPUT);
}
void loop() 
{
  while(1)
  {
    PORTD = B01000000; // D6 HIGH.
    PORTD = B00000000;  // D6 HIGH LOW
    PORTD = B01000000; // D6 HIGH.
    PORTD = B00000000;  // D6 HIGH LOW
  }     
}

Ergebnis:
Das Arduino kann einen HIGH Impuls mit einer Frequenz von ~16,5MHz ausgeben (60,5ns).
(siehe Anhang 0001)
Dabei ist das setzen von HIGH zu LOW in einem Takt (16MHz) möglich.
(siehe Anhang 0002)
Ein zurückspringen in einer while-Schleife dauert ~125ns.
(siehe Anhang 0003 und rechne die 60ns takt für das LOW setzen weg)

Das dürfte dann das Ende der Fahnenstange gewesen sein :wink:

Danke an alle, war ein interessanter Test!

void setup()
{
  pinMode(6, OUTPUT);
}
void loop()
{
  while(1)
  {
    PIND = B01000000; // toggle D6
    PIND = B01000000; // toggle D6
    PIND = B01000000; // toggle D6
    PIND = B01000000; // toggle D6
  }     
}

Das sollte deutlich schneller sein.

Bei der Bandbreite des Scopes kommt es nicht auf die Pulsdauer oder -Frequenz an, sondern auf die Steilheit der Flanken. Jede Flanke eines Rechtecks wird verschliffen, wenn nur die maximal mögliche Abtastrate eingestellt wird. Dann kann man feststellen, wieviele Samples das angezeigte Signal tatsächlich braucht, um von Null auf die volle Amplitude des Signals zu kommen.

Das setzt aber voraus, daß das Signal wirklich steile Flanken hat, und das hängt mehr von der der Ausgangsstufe des Generators und der Verkabelung ab, als von der Frequenz des Testsignals. Deshalb reicht ja auch ein 1kHz Signal, um einen Tastkopf zu kalibrieren. Dabei würde ich diesem eingebauten Kalibriersignal-Generator steilere Flanken zutrauen als jedem Eigenbau.

Whandall:

void setup()

{
  pinMode(6, OUTPUT);
}
void loop()
{
  while(1)
  {
    PIND = B01000000; // toggle D6
    PIND = B01000000; // toggle D6
    PIND = B01000000; // toggle D6
    PIND = B01000000; // toggle D6
  }   
}



Das sollte deutlich schneller sein.

Habs ausgetestet, ändert and der Ausgabegeschwindigkeit nichts… nicht mal im ns-Bereich.

Aber wie “deutlich” schneller sollte es denn sein?
Wir sind ja eh schon bei 16MHz angekommen :smiley:

Stimmt, bei genauer Betrachtung ist es genau gleich schnell.

Bei meiner Methode wird allerdings nicht das gesamte Register zermatscht,
sondern nur das eine Bit gekippt, mach das mal mit deiner Methode, dann bist du halb so schnell.