5µs LED pulse/ zwei Frequenzen

Hi

ich möchte mit einem Arduino Uno 5µs pulse erzeugen um zwei LEDs anzusteuern. Die LEDs sollen mit unterschiedlichen Frequenzen Pulsen (500Hz und 1KHz). Also im Prinzip ein Funktionsgenerator bei dem die Pulslänge auf 5µs begrenzt ist. Kennt jemand ein paar Beispiel sketches? Ist das überhaupt realisierbar mit dem Arduino?

Wenn die optische anzeige LEDs sind, wirst du keinen unterschied sehen.

Arbeite dich in die Arduino Basics ein!

void loop()
{
static unsigned long last_micros;
static byte i = 0;



if(micros() - last_micros >= 5)
{
last_micros = micros();
i++;
}

if(i%2==0) // toggle led 500Hz
else // toggle led 1kHz

}

Dank für die Antwort. Stimmt, der Unterschied ist optisch nicht sichtbar. Ich will die Pulse verwenden um Lichtdetektoren (PMTs) auszumessen.

toka11: ich möchte mit einem Arduino Uno 5µs pulse erzeugen um zwei LEDs anzusteuern. Die LEDs sollen mit unterschiedlichen Frequenzen Pulsen (500Hz und 1KHz). Also im Prinzip ein Funktionsgenerator bei dem die Pulslänge auf 5µs begrenzt ist. Kennt jemand ein paar Beispiel sketches? Ist das überhaupt realisierbar mit dem Arduino?

Das ist natürlich möglich.

Da ein einziges "digitalWrite" allerdings schon 4 bis 5 µs dauert, müßtest Du zur recht genauen Einhaltung von einstelligen Mikrosekundenzeiten aber wohl eher die Register des Atmega-Controllers direkt programmieren als Arduino-Komfortfunktionen aus der Arduino Core-Library zu verwenden.

Soll das Arduino-Programm denn noch etwas anderes machen? Oder nur das, was Du beschrieben hast?

Die 5µs Impulsdauer sollen recht genau eingehalten werden, so wie ich es verstanden habe.

Was ist mit den Abständen zwischen den 1 kHz Impulsen: Sollen auch die möglichst bis auf die Microsekunde eingehalten werden, oder können die statt alle 1000 µs auch mal nach 1004 µs und dann wieder nach 996 µs wiederholt werden?

Ich befürchte das funktioniert so nicht. Die IF Anweisung und die digitalWrite() verbrauchen zuviel Zeit um 5µS genau zu timen.

Meines Erachtens muß man mit delayMicroseconds() und direktes setzen des Ports oder mit Timer arbeiten.

siehe http://forum.arduino.cc/index.php?topic=282580.msg1982688#msg1982688

Viele Grüße Uwe

Fuer die direkte AVR Portmaipulation gibt es eine Klasse in FastLED.

fastpin.h und fastpin_avr.h

Es gibt auch eine Library namens DigitalWriteFast

Und exakte, kurze Delays kann man mit inline Assembler machen wenn man mit delayMicroSeconds() nicht hinkommt. Wobei es für 5µs reichen sollte.

Ansonsten sind wie schon erwähnt noch die Timer eine Option. Das ist dann aber kompliziert wenn man damit noch nichts gemacht hat.

Vielen Dank für die vielen ANtworten. Im Arduino cookbook habe ich eine Beispiel basierend auf Timer1 gfunden. Damit lassen sich 5µs Pulse sehr gut erzeugen. Allerdings kann ich nur eine LED mit einer Frequenz ansteuern.

Die Frequenzen sind für meine Anwendung nicht festgelegt. Es geht nur darum zwei LEDs synchron einzuschalten und danach dann nur eine einzuschalten. Also: on/on, off/on, on/on.... usw.

Ob die Frequenz dann 1KHz/500Hz oder 200Hz/400Hz beträgt, ist eigentlich egal. Wichtig ist, dass die Pulse synchron laufen.

Gibt es denn eine Möglichkeit mit Timer1 zwei LEDs anzusteuern?

Ja, in dem du im Compare Interrupt Handler die 2. Led nur jedes 2. mal schaltest.

Sry, das ich mich einklinke, aber braucht man für 1kHz Toggle Frequenz nicht ein Delay von 500 µs?

Die Frequenz gibt doch an, wie viele Schwingungen pro Sekunde. Bei 1kHz sind das 1000 Schwingungen in einer Sekunde. Das heißt eine Schwingung pro (1/1000)s = 1ms.

Um jetzt mit 1kHz zu toggln braucht man doch eine Frequenz von 2kHz daher ein Delay von 500µs, oder sehe ich da was Falsch? :(

Ja, solange die duty time 50% ist. Ich will aber das die LED nur für 5µs leuchtet.

Also bei 1KHz 995µs off und 5µs on usw.

Bei 500Hz dann 1995 off und 5µs on usw.

Vorgehensweise:

  1. 1 kHz IRQs erzeugen, z.B. die Taktquelle von hier übernehmen: http://blog.blinkenlight.net/experiments/dcf77/phase-detection/
  2. im Interrupt aus einer statischen Variable die gewünschte Portmaske direkt in den Port schreiben.
  3. 5*16-1 = 79 assembler nop statements einfügen
  4. 0 direkt in den Port schreiben
  5. die Portmaske für den nächsten Durchlauf berechnen und in der statischen Variable speichern, dh. das 500 Hz Bit per Exklusiv OR mit 1 verknüpfen
  6. WICHTIG: entweder per Oszi nachmessen und ggf. NOPs wegnehmen, oder per avr-objdump nachschauen ob der Compiler das alles so kompiliert wie man sich das vorstellt
  7. Alternativ zu 5 und 6: die Portmanipulation vollständig in Assembler programmieren damit die Zeiten wirklich garantiert korrekt eingehalten werden

[quote author=Udo Klein link=msg=1988010 date=1417711902] dh. das 500 Hz Bit per Exklusiv OR mit 1 verknüpfen [/quote] Einen Pin invertieren geht am schnellsten und einfachsten wenn man eine 1 auf das Pin-Eingangsregister PINn schreibt.

Vielen Dank für die Informatioen. Scheint nicht nicht trivial zu sein wie ich dachte (jedenfalls für mich).
Eigentlich arbeite ich an einem anderen Projekt und benötige nur eine schnelle Lösung für einen Testaufbau.

Hat zufällig jemand ein sketch den ich nur anpassen muss?

@Serenify, den Trick kenne ich, aber der wäre hier falsch. Er soll ja nicht den Pin invertieren sondern die Portmaske modulieren. Das wirkt dann wie ein Frequenzhalbierer.