Hallo, momentan versuche ich, ein externes PWM Signal eines SMT172 Temperatursensor an einem ESP32 Pin zu lesen. Ich würde das gerne mit Micropython hinbekommen, es klappt aber leider nicht. Hat jemand Erfahrung, wie man ein PWM Signal in Micropython ausliest? Ein Teilproblem, welches ich nicht verstehe, ist folgendes: Wenn ich ein Callback für eine ansteigende Flanke des externen Pins setze und dann im Callback nur den Wert des Pins ausgebe, dann ist er mal 0 und mal 1. Sollte bei einer ansteigenden Flanke nicht immer der Pinwert im Interruptcode 1 sein? Viele Grüße Felix
Hm. Mal drei andere Fragen: 1. Wenn die Callback-Funktion für einen steigende Flanke ausgelöst wird, welchen anderen Wert als '1' kann der Pin, während einer gewissen Zeit nach der Flanke haben? 2. Wie auch immer, Du Frage 1. beantwortest: Welchen Zweck hat es, den Wert nach dem Interrupt der steigenden Flanke, den Portpin zu lesen, wenn per Definition einer steigenden Flanke der Wert '1' sein muss ? Jedenfalls, wenn Du unbedingt darauf bestehst, den Zusammenhang zwischen dem Wechsel von '0' und '1' und einer steigenden Flanke programmatisch zu überprüfen: 3. Für wie lange Zeit ist nach einer steigenden Flanke der Wert '1' und wie lange braucht im Vergleich der Code um den Portpin auszulesen?
Hallo Theor, den Wert direkt danach auszulesen ist erstmal ein kleiner Sanity-Check gedacht. Ein Problem was bei Micropython nach meinem Verständnis besteht ist, dass du nur eine Interruptfunktion pro Pin haben kannst. D. h. mit dem Wert muss gechecked werden, ob es gerade durch eine steigende Flanke oder fallende Flanke getriggert wurde. Die einzulesende PWM-Frequenz ist maximal 7kHz, d. h. das auslesen des Pins sollte nach meinem Verständnis nicht zu lange dauern. Gruß Felix
> den Wert direkt danach auszulesen ist erstmal ein kleiner Sanity-Check gedacht. Beantworte bitte Frage 1 und 2 von oben. Was soll der Sanity-Check, wenn die Definition gesund ist? Oder siehst Du in der Definition einen Fehler? Oder hast Du konkreten Anlass zu vermuten, dass der ESP diese Definition nicht korrekt realisiert? > Ein Problem was bei Micropython nach *meinem Verständnis* > [Hervorhebung durch mich] besteht ist, dass du nur eine > Interruptfunktion pro Pin haben kannst. > D. h. mit dem Wert muss gechecked werden, ob es gerade durch > eine steigende Flanke oder fallende Flanke getriggert wurde. Das ist eine problematische Aussage, denn der erste Satz hat keinen inneren Zusammenhang mit dem zweiten. Was den ersten Satz betrifft: Falls ich nur genau einen Interrupt pro Pin haben kann, dann weist das auftreten des Interrupts auch darauf hin, das genau dieser Pin den Interrupt ausgelöst hat. Das Gegenteil wäre der Fall, wenn ein Interrupt durch mehrere Quellen ausgelöst werden kann und der Interrupt-Mechanismus keine eigenen Mittel bereitstellt, die Quelle zu unterscheiden. Der Doku von micropython entnehem ich nicht, dass der Interrupt unspezifisch bzgl. der Pins ist. http://docs.micropython.org/en/v1.9.3/esp8266/esp8266/tutorial/pins.html Das ist (zugegeben) manchmal ein Versäumnis des Autors. Deswegen könntest Du im Datenblatt des Controller nachprüfen, ob das beim ESP... so ist oder nicht. (Ich kenne den leider nicht). Aber hast Du eigentlich einen Anlass anzunehmen, dass die Doku von micropython in der Hinsicht zu lakonisch ist? Beim AVR, z.B. dem ATMega48, 88, 168 gibt es so einen Fall durchaus. Der Pin Change Interrupt ist in Grenzen (und abhängig von der Konfiguration) unspezifisch. Man kann z.B. nicht ohne weiteres sagen ob und welcher Pin zwischen 23 und 16 den Interrupt ausgelöst hat. Meinst Du das ist beim ESP auch so und warum konkret meinst Du das? Was den zweiten Satz betrifft: Was lässt Dich davon ausgehen, dass der ESP nicht ausschliesslich bei einer steigenden Flanke den Interrupt auslöst? Was den Zusammenhang betrifft: Angenommen, der ESP hätte wie Du sagst nur einen Intterupt, der bei einer beliebigen Flanke auslöst. Das heisst noch nicht, dass er das nicht spezifisch für einen Pin tut. Umgekehrt geht die Schlussfolgerung auch nicht. > Die einzulesende PWM-Frequenz ist maximal 7kHz, d. h. das auslesen > des Pins sollte nach meinem Verständnis nicht zu lange dauern. Das sollte auch 1mHz und bei 1GHz nicht zu lange dauern. Wichtig ist doch die Relation zwischen CPU-Frequenz und PWM-Frequenz, wenn Du das abfragst. Also Frage 3. Und die wird ja nur relevant, falls Du Frage 1 und 2 so beantwortest, dass die Definition nicht realisiert wird, oder das der ESP den Interrupt unspezifisch bzgl. der Ursache auslöst, oder das der ESP den Interrupt unspezifisch oder für mehrere Pins gleichermaßen auslöst. Denk darüber mal in Ruhe nach. Das ist alles recht einfach. Wenn ich Dir raten darf, wonach Du nicht gefragt hast: Hüte Dich vor unbegründeten Annahmen und analysiere Deine Fragen, wenn die Antwort Dich nicht befriedigt. Häufig stellt man nur die falschen Fragen oder man stellt sie zu ungenau.
Um die Diskussion wieder etwas stärker auf die Frage zu fokussieren: Ich habe folgenden Code auf einem ESP32 Dev Board mit an Pin4 angeschlossenen SMT172 Temperatursensor ausgeführt:
1 | >>> import machine |
2 | >>> p4 = machine.Pin(4, machine.Pin.IN) |
3 | >>> def callback(p): |
4 | ... print("{} {}".format(p, p.value())) |
5 | ...
|
6 | >>> p4.irq(trigger=machine.Pin.IRQ_RISING, handler=callback) |
7 | <IRQ> |
8 | >>> Pin(4) 0 |
9 | Pin(4) 0 |
10 | Pin(4) 0 |
11 | Pin(4) 0 |
12 | Pin(4) 0 |
13 | Pin(4) 1 |
14 | Pin(4) 1 |
15 | Pin(4) 1 |
16 | Pin(4) 1 |
17 | Pin(4) 0 |
18 | Pin(4) 0 |
19 | Pin(4) 0 |
20 | Pin(4) 0 |
21 | Pin(4) 1 |
22 | Pin(4) 1 |
23 | Pin(4) 1 |
24 | Pin(4) 1 |
25 | Pin(4) 0 |
26 | Pin(4) 0 |
27 | Pin(4) 0 |
28 | Pin(4) 0 |
Nach meinem Verständnis müsste IRQ_RISING dafür sorgen, dass der Callback nur bei einer steigenden Flanke ausgeführt wird und damit die Ausgabe nur 1 anzeigt. Die Frequenz von 7kHz des SMT172 ist deutlich niedriger als die 240Mhz Frequenz des ESP32. Leider weiß ich nicht, wielange das Interpretieren des Python Codes genau braucht, hat da jemand einen Hinweis bzw wo bei mir der Denkfehler ist?
Felix schrieb: > Um die Diskussion wieder etwas stärker auf die Frage zu fokussieren: Ich > habe folgenden Code auf einem ESP32 Dev Board mit an Pin4 > angeschlossenen SMT172 Temperatursensor ausgeführt: > >
1 | >>>> import machine |
2 | > ... |
3 | >
|
> > Nach meinem Verständnis müsste IRQ_RISING dafür sorgen, dass der > Callback nur bei einer steigenden Flanke ausgeführt wird und damit die > Ausgabe nur 1 anzeigt. richtig > Die Frequenz von 7kHz des SMT172 ist deutlich > niedriger als die 240Mhz Frequenz des ESP32. Wie lang soll denn die H-Time des Sensors sein - von den 143μs Periodendauer? > Leider weiß ich nicht, > wielange das Interpretieren des Python Codes genau braucht, hat da > jemand einen Hinweis bzw wo bei mir der Denkfehler ist? Auf jeden Fall solltest du dich bei so zeitkritischen Funktionen davon verabschieden so aufwendige Sachen wie Print im Interrupt zu machen. Lies den Zustand des Pins in eine Variable und setze ein Flag. In der loop kannst du des Zustand ausgeben. Was die Verarbeitungsgeschwindigkeit angeht - toggle mal einen Pin in der loop und schau dann welche Frequenz dann am Pin rauskommt. Im übrigen willst du ja die Zeit deines PWM-Signals messen, wenn du 100 Stufen auflösen willst darf die Verarbeitung auch nur weniger als 1/100 der zu messenden Zeitspanne betragen. Ich hab zwar noch nicht mit μPython gearbeitet, aber ich denken das wird nichts. Sascha
Hallo Sascha, vielen Dank für den Input. Ich habe das Print Statement herausgenommen und tatsächlich, jetzt passt das Verhalten zur Theorie:
1 | from machine import Pin |
2 | |
3 | elements = 100 |
4 | buf = bytearray(elements) |
5 | counter = 0 |
6 | |
7 | def callback(p): |
8 | global buf, counter, elements |
9 | |
10 | if counter >= elements: |
11 | return
|
12 | |
13 | buf[counter] = p.value() |
14 | counter += 1 |
15 | |
16 | pwmPin = Pin(4, Pin.IN) |
17 | pwmPin.irq(trigger=Pin.IRQ_RISING, handler=callback) |
18 | |
19 | while counter < elements: |
20 | pass
|
21 | |
22 | pwmPin.irq(None) |
23 | |
24 | print(buf) |
Output:
1 | bytearray(b'\x00\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01') |
Als kleines Fragezeichen bleibt noch, warum die ersten zwei Werte nicht 1 sind. Ich habe gecheckt, dass es nicht an der Initialisierung liegt, die ersten zwei Aufrufe schreiben wirklich ne 0 rein. Die maximale Frequenz rauszufinden wäre spannend. Leider kann ich momentan das Timing des Outputs nicht messen.
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.