Guten Tag, ich habe an meinem Arduino Leonardo eine Infrarot-LED angeschlossen, die über den PWM Pin (490Hz) alle 2ms für ca. 80µs eingeschaltet wird. Nun möchte ich die Lichtintensität mittels einer Photodiode messen. Dafür habe ich eine Verstärkerschaltung, die ca. 40µs nach einschalten der LED eine konstante Spannung für die nächsten 30 µs ausgibt (siehe Bild). Am Oszilloskop sieht das alles soweit gut aus. Nun möchte ich die Spannung aber auch am Arduino messen können. Laut der analogRead() Funktion dauert der Vorgang allerdings ca. 100µs. Ich müsste die Spannung innerhalb dieser 30-40µs messen können, da ich die LED nicht länger als 100µs bei 1A Strom betreiben darf. Meine Frage ist nun, ob bzw. wie ich ausgehend vom PWM Signal zu einer bestimmten Zeit den Analogen Input am Arduino auslesen kann. Oder ist der ATmega32u4 dafür ungeeignet? So wie ich das verstanden habe, kann man den analogen Eingang ohne die analogRead() Funktion deutlich schneller auslesen, indem man den Vorteiler am Arduino kleiner macht. Nun habe noch nicht genau verstanden, wie das genau funktioniert, bzw. ob man den Zeitpunkt des einlesens überhaupt am PWM Signal ausrichten kann. Für jede Hilfe bin ich sehr dankbar. Viele Grüße Nader
Nader N. schrieb: > So wie ich das verstanden habe, kann man den analogen Eingang ohne die > analogRead() Funktion deutlich schneller auslesen, indem man den > Vorteiler am Arduino kleiner macht. Dann musst du halt 40µs nach dem Impuls dem ADC ein Start Signal geben. Siehe https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7766-8-bit-AVR-ATmega16U4-32U4_Datasheet.pdf Kapitel 24 Nun steht da "65 - 260µs Conversion Time", was viel mehr ist als die von dir genannten 30µs. Das ist aber nicht schlimm, denn der ADC nimmt beim Start ein "Sample" von der Spannung und kann dieses dann in aller Ruhe auswerten. Insofern sollte das sogar mit analogRead() noch klappen. Die Funktion macht ja nun nicht viel mehr, als den Channel auszwählen und dann das Startsignal zu geben. Um die 40µs genau genug einzuhalten, wirst du vermutlich Interrupts sperren müssen, damit die nicht dazwischen "funken". > ob man den Zeitpunkt des Einlesens überhaupt am PWM Signal > ausrichten kann. Das kann man vermutlich irgendwie in einem Timer-Interrupt in Kombination mit delayMicroseconds() unterbringen. Auf jeden fall hat das schon eine Komplexität, für die das Arduino Framework nicht gedacht war. Du wirst nicht umhin kommen, den Chip zumindest teilweise "zu Fuß" zu programmieren. Und damit das mit dem Arduino Framework harmoniert, wirst du auch in dessen Quelltexte schauen müssen. Willst du dir das wirklich antun?
Stefan ⛄ F. schrieb: > Nun steht da "65 - 260µs Conversion Time". Das ist nicht schlimm, denn > für deinen Fall genügt es ja, während des Impulse die Spannung zu > erfassen (samplen). Wie lange die darauf folgende Messung dauert, ist > ziemlich egal, denn sie basiert auf dem Sample. Ah Gut zu wissen. Ich dachte, die Spannung muss über die gesamte Zeit am ADC anliegen. > > Dann musst du halt 40µs nach dem Impuls dem ADC ein Start Signal geben. > > > Insofern sollte das sogar mit analogRead() noch klappen. Die Funktion > macht ja nun nicht viel mehr, als den Channel auszwählen und dann das > Startsignal zu geben. > > Um die 40µs genau genug einzuhalten, wirst du vermutlich Interrupts > sperren müssen, damit die nicht dazwischen "funken". Genau, aber woher weiß ich, zu welcher Zeit mein PWM-Signal auf HIGH springt? Würde man sowas mit einem Interrupt Pin implementieren und dann einfach mit delayMicroseconds() 30µs warten, bis man analogRead() aufruft? Bzw was meinst du mit "Interrupts sperren"? Trotzdem schon mal vielen Dank!
Schau dir mal in Kapitel 24.6 die "Auto-Trigger" Sources an. Richtig eingestellt übernimmt dir komplett die Hardware das Triggern des ADC. Bei ADC-End-Conversion kannst du dann bestimmt einen ISR auslösen lassen oder den letzten Wert pollen (Achtung falls das kein atomarer Zugriff sein sollte!). Ich kenne die Controller nicht richtig, das ist aber in vielen Anwendungsfällen ein Standardfall dass man an einer gewissen Stelle der PWM messen möchte. Wahrscheinlich kann man von einem Timer einen Compare Match Value dafür verwenden oder man muss halt einen zweiten synchronen Timer dafür verwenden.
Stefan ⛄ F. schrieb: > Das kann man vermutlich irgendwie in einem Timer-Interrupt in > Kombination mit delayMicroseconds() unterbringen. Auf jeden fall hat das > schon eine Komplexität, für die das Arduino Framework nicht gedacht war. > Du wirst nicht umhin kommen, den Chip zumindest teilweise "zu Fuß" zu > programmieren. Und damit das mit dem Arduino Framework harmoniert, wirst > du auch in dessen Quelltexte schauen müssen. > > Willst du dir das wirklich antun? Okay das klingt für mich schon etwas komplizierter. Wenn das Arduino Framework für sowas nicht gedacht ist, womit würde man eine solche Messung sonst realisieren?
Ich habe den text aus meinem Beitrag nochmal überarbeitet und dabei
ergänzt, dass du vermutlich einen Interrupt vom PWM Timer nutzen musst.
Und ja, innerhalb des Interrupthandlers würde ich mit
delayMicroseconds() die 40µs abwarten, dann den ADC starten.
Da fällt mir etwas ein: analogRead() würde aber nicht nur den ADC
starten, sondern auch auf das Ergebnis warten. Und da könnte länger
dauern, als bis zum nächsten Interrupt. Dann hängt alles.
Vergiss den Ansatz, das kann nicht klappen.
Du könntest aber in deiner Hauptschleife den Status vom PWM Pin
einlesen. Sobald er auf High geht, wartest du die 40µs ab und rufst dann
analogRead() auf.
> was meinst du mit "Interrupts sperren"?
Etwa so:
1 | void loop() |
2 | {
|
3 | if (digitalRead(PWM_PIN)==HIGH) |
4 | {
|
5 | cli(); // Interrupts sperren |
6 | delayMicroseconds(40); |
7 | a = analogRead(ANALOG_PIN); |
8 | sei(); // Interrupts erlauben |
9 | |
10 | // warte bis der PWM Pin wieder auf Low geht
|
11 | while (digitalRead(PWM_PIN)==HIGH) { |
12 | yield() |
13 | };
|
14 | }
|
15 | }
|
Das kann man mit Zustandsautomaten eleganter machen, aber ich will dich nicht überfordern. Auf diese Weise ist sicher gestellt, dass während der zeitkritischen Phase keine Timer und auch nicht das USB Interface stören. Ich bin allerdings nicht sicher, ob die PWM noch funktioniert, wenn man Interrupts sperrt. Vielleicht kann der liebe Arduino Fanboy etwas dazu sagen.
Kannst du nicht einfach mit dem 2. Compare Register des Timers ein Interrupt auslösen und mit dem dann den ADC starten. Must du einmalig mit Timer-Frequenz und Duty Cycle ausrechnen mit welchen Wert du den Belegen must, damit der 30µs später kommt. Meine Empfehlung es, das Ganze ohne das Arduino-(Framework/API/HAL oder wie man es nennen möchte) zu machen. Bei Zeitkritischen Sachen macht es zu viel Overhead.
ck schrieb: > Kannst du nicht einfach mit dem 2. Compare Register des Timers ein > Interrupt auslösen und mit dem dann den ADC starten. Dazu muss man wohl den PWM Timer auch am Arduino Framework vorbei programmieren. > Meine Empfehlung es, das Ganze ohne das Arduino-(Framework/API/HAL > oder wie man es nennen möchte) zu machen. Bei Zeitkritischen Sachen > macht es zu viel Overhead. Ich fürchte auch, dass das Umgehen des Frameworks hier mehr Probleme bereitet, als den Chip gleich ganz "zu Fuß" zu programmieren.
MaNi schrieb: > Schau dir mal in Kapitel 24.6 die "Auto-Trigger" Sources an. > Richtig eingestellt übernimmt dir komplett die Hardware das Triggern des > ADC. > Bei ADC-End-Conversion kannst du dann bestimmt einen ISR auslösen lassen > oder den letzten Wert pollen (Achtung falls das kein atomarer Zugriff > sein sollte!). > > Ich kenne die Controller nicht richtig, das ist aber in vielen > Anwendungsfällen ein Standardfall dass man an einer gewissen Stelle der > PWM messen möchte. > > Wahrscheinlich kann man von einem Timer einen Compare Match Value dafür > verwenden oder man muss halt einen zweiten synchronen Timer dafür > verwenden. Okay Vielen Dank, das werde ich mir mal anschauen. Stefan ⛄ F. schrieb: > > Du könntest aber in deiner Hauptschleife den Status vom PWM Pin > einlesen. Sobald er auf High geht, wartest du die 40µs ab und rufst dann > analogRead() auf. Das werde ich dann gleich mal ausprobieren. ck schrieb: > Meine Empfehlung es, das Ganze ohne das Arduino-(Framework/API/HAL oder > wie man es nennen möchte) zu machen. Bei Zeitkritischen Sachen macht es > zu viel Overhead. Hier fürchte ich, reichen meine Kenntnisse nicht annähernd aus. Ich habe bisher nur mit der ArduinoIDE gearbeitet.
Warte doch 1.92 ms +- und miss halt den nächsten Implus. Richtige Vorgehensweise (Auto-Trigger) wurde schon genannt. Man lässt den ADC über n Timer laufen. Kann man mit der API nicht so einfach abbilden. Müsste man die Register händisch setzen. Bin jetzt auch nicht zu 100% informiert, welcher Timer die PWM macht und ob da "nochwas frei" ist, wo man dranhängen kann. Müsste man in die analogWrite() reinsehen. Dort wird ja sicher der Timer initialisiert usw. Die Sensorlosen Brushless-Controller machen das ja auch: Messen der EMK im laufenden Betrieb.
Eines, was sicher ist: der Controller an sich kann das, er ist schnell genug. Und jetzt muss man nur noch herausfinden, wie man ihn mit der Programmiersprache und -umgebung und -API seiner Wahl dazu bringt, effizient und schnell das zu tun, was man braucht. Wenn sich herausstellt, dass ein Teil der Toolchain davon nicht hinreichend taugt, dann muss eine andere Entwicklungsumgebung her. Nader N. schrieb: > Laut der analogRead() Funktion dauert der Vorgang allerdings ca. 100µs. Dann sieh dir doch mal an, was da gemacht wird. Und sieh im Datenblatt zum µC nach, ob es besser ginge. Und dann schreib deine eigene Funktion, die es besser macht. ck schrieb: > Meine Empfehlung es, das Ganze ohne das Arduino-(Framework/API/HAL oder > wie man es nennen möchte) zu machen. So ist es.
Wieso will man die Helligkeit einer IR-LED, die voll eingeschaltet ist, messen? wendelsberg
wendelsberg schrieb: > Wieso will man die Helligkeit einer IR-LED, die voll eingeschaltet ist, > messen? Ich vermute mal, dass nicht die LED selbst ausgemessen werden soll, sondern irgend etwas dass diese beleuchtet.
Okay vielen Dank erstmal für eure Antworten. Ich habe jetzt erstmal wie Stefan gesagt hat, das PWM Signal als Interrupt genutzt und mit delayMicrosenconds() herumprobiert, bis das Ergebnis mit den Messungen am Oszilloskop übereinstimmte. Das hat überraschenderweise ganz gut funktioniert. Ich werde mit aber trotzdem mal den AutoTrigger aus dem Datenblatt anschauen. Wenn der Arduino noch mehr zu tun hat, als nur die Spannung zu messen, kommt der vermutlich auch an seine Grenzen. Da werde ich mich wohl auch erstmal einlesen müssen, damit kenne ich mich noch nicht aus. ck schrieb: > Meine Empfehlung es, das Ganze ohne das Arduino-(Framework/API/HAL oder > wie man es nennen möchte) zu machen. Bei Zeitkritischen Sachen macht es > zu viel Overhead. Ich habe auch bisher immer nur mit der Arduino IDE gearbeitet. Was gibt es denn sonst für Optionen für die Programmierung? Dann könnte ich mich damit noch auseinandersetzten. Stefan ⛄ F. schrieb: > wendelsberg schrieb: >> Wieso will man die Helligkeit einer IR-LED, die voll eingeschaltet ist, >> messen? > > Ich vermute mal, dass nicht die LED selbst ausgemessen werden soll, > sondern irgend etwas dass diese beleuchtet. Genau ich möchte das Streulicht in einer Wasserprobe messen um daraus die Wassertrübung zu bestimmen.
Nader N. schrieb: > Ich habe auch bisher immer nur mit der Arduino IDE gearbeitet. Was gibt > es denn sonst für Optionen für die Programmierung? Dann könnte ich mich > damit noch auseinandersetzten. Die naheliegendste Option ist, mit dem Atmel Studio ohne das Arduino Framework zu arbeiten. Aber dann fehlt dir vermutlich der Code zur Unterstützung der USB Schnittstelle. Dabei kann ich dir nicht helfen. Wegen genau diesem Punkt bevorzuge ich AVR Mikrocontroller Module mit separatem USB-UART Chip, die den Arduino Nano.
Nader N. schrieb: > Ich werde mit aber trotzdem mal den AutoTrigger aus dem Datenblatt > anschauen. Wenn der Arduino noch mehr zu tun hat, als nur die Spannung > zu messen, kommt der vermutlich auch an seine Grenzen. Nö. Aber deine Programmierkünste.
Nader N. schrieb: > Genau ich möchte das Streulicht in einer Wasserprobe messen um daraus > die Wassertrübung zu bestimmen. Dann solltest du auch mal den Photoempfänger besser kompensieren, der schwingt wie wild. https://www.mikrocontroller.net/articles/Lichtsensor_/_Helligkeitssensor#Konstantstromquelle_mit_Transimpedanzverst.C3.A4rker
Stefan ⛄ F. schrieb: > Die naheliegendste Option ist, mit dem Atmel Studio ohne das Arduino > Framework zu arbeiten. Aber dann fehlt dir vermutlich der Code zur > Unterstützung der USB Schnittstelle. Dabei kann ich dir nicht helfen. > > Wegen genau diesem Punkt bevorzuge ich AVR Mikrocontroller Module mit > separatem USB-UART Chip, die den Arduino Nano. Okay schau ich mir mal an. Ich kann ja sonst auch einen Nano nehmen. Falk B. schrieb: > Nö. Aber deine Programmierkünste. Ja vermutlich. Aber da kann ich ja noch dazulernen :) Falk B. schrieb: > Dann solltest du auch mal den Photoempfänger besser kompensieren, der > schwingt wie wild. Die Verstärkerschaltung hatte auch schon besser funktioniert. Ich musste die aber nochmal umdimensionieren und hatte keine passende Kapazität zur Hand. Das wird noch gemacht.
Du kannst dir auch das ganze Softwaregedöns sparen, wenn du einen externen Sample&Hold-IC verwendest, z.B. LF398. Dessen Logikeingang musst du nur für die beschriebenen 30 µs nach dem PWM-Impuls einschalten. Messen kannst du dann wenn du lustig bist. Georg
Hallo, - in einer Pin ISR auf Flanke triggern - darin Timer mit 40µs starten - wenn Timer seiner Interrupt auslöst sich selbst stoppen und ADC starten - wenn ADC sich ready meldet Wert auslesen Kann und sollte man ausbauen indem man die nächste Flankenerkennung erst wieder scharf schaltet wenn man den ADC ausgelesen hat. Der ADC kommt wohl ansonsten eh nicht hinterher.
Wäre es möglich, den ADC auf die negative Flanke des IR-lED Signals zu triggern? Dermüsste doch sofort in dem Moment Sample&Hold machen und sich den Wert vor dem Abfallen zur Wandlung dadurch merken
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.