[RPi3] Entfernung über Ultraschallsensor messen

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
robin_
User
Beiträge: 48
Registriert: Montag 3. August 2020, 17:59

Alles klar, ich werde es mit Pin_IRQs (muss erstmal gucken was das meinst) probieren. Oszillator ist nicht vorhanden.

Ich habe, wie gesagt, mehrere Beispiele im Netz gesehen, wo das Messen recht präzise mit dem im Ausgangspost genannten Code funktioniert. Mit Pico + HC-SR04. Hatte es ebenfalls mit nem Pi3B+ probiert.
Da das nicht gefruchtet hat vermute ich, dass irgendwas am Setup nicht stimmt. Also falsche Pins oder so... benutze GPIO 6 und 7 (Pin 9 und 10).

Gibt es GPIO's die eher verwendet werden sollten als andere?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Oszilloskop. Nicht Oszillator. Meines Wissens Nacht gibt es keine Pins, die bevorzugt sind. Du kannst aber erstmal die prinzipielle Funktionsfähigkeit testen, indem du mit einem Kabel oder gar Schalter prüfst, ob eine LOW/HIGH/LOW Sequenz erkannt wird. Auch wenn die händisch natürlich unpräzise und langsam ist, erkennst du daran, ob die Programmierung überhaupt tut.
robin_
User
Beiträge: 48
Registriert: Montag 3. August 2020, 17:59

So, hier nun meine aktuelle Version, die vom Prinzip her funktioniert.

Code: Alles auswählen

from machine import Pin
import utime
import micropython


micropython.alloc_emergency_exception_buf(100)

# Pin 9 / 10
TRIGGER_GPIO = 6
ECHO_GPIO = 7

SOUND_VELOCITY_M_S = 343


class Measurement:

    def __init__(self):
        self.trigger = Pin(TRIGGER_GPIO, Pin.OUT)
        self.echo = Pin(ECHO_GPIO, Pin.IN, Pin.PULL_DOWN)

        self.echo_start = utime.ticks_us()
        self.echo_end = utime.ticks_us()
        self.finished_measurement = False

    def loop(self):
        print("=== loop()")
        self.measure()

        while self.finished_measurement == False:
            print("... waiting for finish...")
            utime.sleep(1)
        
        diff = utime.ticks_diff(self.echo_end, self.echo_start)
        delay_s = diff / 1e6


        print("Signal was high for ", delay_s, " seconds.")
        self.finished_measurement = False


    def measure(self):
        print("=== measure()", self.echo.value(), " is current echo status")
        self.trigger.high()
        utime.sleep(2)
        self.trigger.low()

        while self.echo.value() == 0:
            print("low...")
            utime.sleep_us(1)
        
        print("WE ARE HIGH")
        self.echo_start = utime.ticks_us()
        self.echo.irq(self.irq_callback, self.echo.IRQ_FALLING, hard=True)

    def irq_callback(self, _):
        print("--- irq_callback()")
        self.echo_end = utime.ticks_us()
        self.finished_measurement = True


if __name__ == "__main__":
    print("starting up ...")

    m = Measurement()
    m.loop()
Und zwar:
Ich habe als Trigger eine LED genommen und diese 2 Sekunden lang leuchten lassen, die geht schonmal an.
Um das Echo zu testen hab ich einfach am Steckbrett auf den GPIO 7 (Echo) mit nem Kabel 3,3V vom Pin 36 angelegt.
Ich konnte damit die Zeit in Sekunden messen, die die Reihe im Steckbrett dann mit 3,3V versorgt war (durchs Kabel einstecken).

2. Variante: Um den Spannungswandler zu testen, wollte ich das ganze wiederholen, nur dass ich das Kabel, welches mein Schalter simulieren soll, mit 5V (Pin40) verbunden ist. Da das ja so nicht an die GPIO's darf, hab ich dass durch den Y-Anschluss vom Wandler gejagt (und die A-Seite liegt am GPIO an). Also eigentlich das gleiche, nur dass mein 'Schalter' (in Form des Kabels) 5V hat und erst durch den Wandler geht, so wie beim Sensor halt auch.
Und das klappt nicht.

Entweder passiert gar nichts, als wäre nichts gesteckt, oder es wird dauerhaft die irq_callback() aufgerufen. Klingt mir mich als Laie danach, dass die Spannung entweder gar nicht anliegt oder zu gering ist. Also sprich, das Wandeln von 5V -> 3V klappt anscheinend nicht.

Nun muss ich sehen wie ich das Problem gelöst kriege...
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Da sind ein paar Fehler drin. IRQs nur einmal registrieren, und die sollten so wenig wie möglich machen - vor allem nix ausgeben. Und das warten auf das Echo sollte auch keine print Ausgabe noch Wartezeit beinhalten. Auf einem Micro ist ein tighter poll loop schon ok, alternativ sollte der IRQ beide Richtungen beherrschen. Aber dann muss man ja auch Pollen, bis der Abbruch kommt.

Was die Elektronik angeht - ja, das sieht nach einem elektronischen Problem aus. Die Komponente kann kaputt sein. Wenn du öfter sowas machen willst, lohnt sich wirklich ein Oszi. . Billige analoge bekommt man zum Preis von 2 Kästen Bier. Und spart sich Stunden an Probiererei. Vielleicht habt ihr auch ein repair Café oder Ähnliches, wo man sowas mal benutzen oder sich helfen lassen kann.
robin_
User
Beiträge: 48
Registriert: Montag 3. August 2020, 17:59

__deets__ hat geschrieben: Mittwoch 9. August 2023, 22:22 Da sind ein paar Fehler drin. IRQs nur einmal registrieren, und die sollten so wenig wie möglich machen
Ja stimmt, dass hatte ich vergessen, im ersten Draft hatte ich im Callback die IRQ auf IRQ_FALLING gesetzt, also quasi ein callback für HIGH und dann einen für LOW. Das war aber nicht so stabil, zumindest mit meiner "Ich steck das Kabel ins Steckbrett" - Variante.

Das mit dem Prints weiß ich, musste nur irgendwie debuggen.
Auf einem Micro ist ein tighter poll loop schon ok, alternativ sollte der IRQ beide Richtungen beherrschen. Aber dann muss man ja auch Pollen, bis der Abbruch kommt.
Genau, das mit dem IRQ in beide Richtungen funktioniert vielleicht mit dem Sensor, aber nicht mit meiner Ausprobiererei. Beim Reinstecken ins Board gabs anscheinend paar mal Kontakt - Kein Kontakt wodurch das ja dann direkt ausgelöst wurde.

Mit "Tighter poll loop" meinst du das hier dann?

Code: Alles auswählen

while self.echo.value() == 0:
    pass
Wenn du öfter sowas machen willst, lohnt sich wirklich ein Oszi. . Billige analoge bekommt man zum Preis von 2 Kästen Bier. Und spart sich Stunden an Probiererei. Vielleicht habt ihr auch ein repair Café oder Ähnliches, wo man sowas mal benutzen oder sich helfen lassen kann.
Danke für den Tipp, ich schau mal in der Uni + Ebay ;)
robin_
User
Beiträge: 48
Registriert: Montag 3. August 2020, 17:59

So,

Ich hab den Sensor jetzt zufriedenstellend ans laufen bekommen - vielen Dank!
Lösung war, wie schon im letzten Post vermutet, dass das Echo Signal nicht durch kam.

Ich habe das jetzt mit 2 in Reihe geschalteten Wiederständen gemacht, 10kOhm und 22kOhm: Das Echo Signal geht durch beide in GND, nach dem ersten (10kOhm) greife ich mir das ab und das ist dann die Verbindung zum Pico GPIO.
Sollte dann so bei 3.4V liegen, also im Rahmen.

Hier nun die zwischenfertige Lösung:

Code: Alles auswählen

from machine import Pin
import utime
import micropython

micropython.alloc_emergency_exception_buf(100)

TOGGLE_GREEN_LT = 0.1
TOGGLE_RED_GT = 0.2
THRESHOLD = 0.02

# Pin 1,2,4
RED_GPIO = 0
YELLOW_GPIO = 1
GREEN_GPIO = 2


# Pin 9 / 10
TRIGGER_GPIO = 6
ECHO_GPIO = 7

SOUND_VELOCITY_M_S = 343

class Measurement:

    def __init__(self, freq_hz = 5):
        self.freq_hz = freq_hz

        self.trigger = Pin(TRIGGER_GPIO, Pin.OUT)
        self.echo = Pin(ECHO_GPIO, Pin.IN, Pin.PULL_DOWN)
        self.echo.irq(self.irq_callback, self.echo.IRQ_FALLING, hard=True)
        
        self.echo_start = utime.ticks_us()
        self.echo_end = utime.ticks_us()
        self.finished_measurement = False

        self.red = Pin(RED_GPIO, Pin.OUT)
        self.yellow = Pin(YELLOW_GPIO, Pin.OUT)
        self.green = Pin(GREEN_GPIO, Pin.OUT)
        self.current_light = None
        
        self.lights_off = {RED_GPIO: [self.yellow, self.green], YELLOW_GPIO: [self.green, self.red], GREEN_GPIO: [self.yellow, self.red]}
        self.lights = {RED_GPIO: self.red, YELLOW_GPIO: self.yellow, GREEN_GPIO: self.green}


    def off(self):
        for p in self.lights.values():
            p.low()


    def signal_length_to_distance_m(self, diff_us):
        diff_s = diff_us / 1e6
        distance_m = SOUND_VELOCITY_M_S * diff_s / 2
        return distance_m


    def toggle(self, gpio):
        self.lights[gpio].high()
        for p in self.lights_off[gpio]:
            p.low()


    def control_lights(self, distance_m):
        TOGGLE_GREEN_COND = distance_m < TOGGLE_GREEN_LT
        TOGGLE_YELLOW_COND = TOGGLE_GREEN_LT + THRESHOLD < distance_m < TOGGLE_RED_GT - THRESHOLD
        TOGGLE_RED_COND = distance_m > TOGGLE_RED_GT
        
        if TOGGLE_GREEN_COND and self.current_light != GREEN_GPIO:
            self.toggle(GREEN_GPIO)
        
        elif TOGGLE_YELLOW_COND and self.current_light != YELLOW_GPIO:
            self.toggle(YELLOW_GPIO)
        
        elif TOGGLE_RED_COND and self.current_light != RED_GPIO:
            self.toggle(RED_GPIO)
            

    def loop(self):
        while True:
            self.measure()
            while self.finished_measurement == False:
                utime.sleep(1 / self.freq_hz)
            
            diff = utime.ticks_diff(self.echo_end, self.echo_start)
            self.finished_measurement = False
            distance_m = self.signal_length_to_distance_m(diff)
            self.control_lights(distance_m)


    def measure(self):
        self.trigger.high()
        utime.sleep_us(10)
        self.trigger.low()

        while self.echo.value() == 0:
            pass
        
        self.echo_start = utime.ticks_us()
       

    def irq_callback(self, _):
        self.echo_end = utime.ticks_us()
        self.finished_measurement = True


if __name__ == "__main__":
    m = Measurement()
    try:
        m.loop()
    except KeyboardInterrupt:
        m.off()
Ich werde das zukünftig erweitern und vmtl. mittels MQTT die Daten an nen Server schicken.

Vermutlich ist die Variante mit den Widerständen nicht so schön, eig. wäre dafür ja der Spannungswandler gewesen... vielleicht krieg ich das zukünftig dann mal hin.

Danke:)
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

So ein spannungsteiler ist völlig ok. Kannst du lassen. Den Echo Puls reicht eigentlich ja auch ein Transistor. Aber Hauptsache es tut.
Benutzeravatar
__blackjack__
User
Beiträge: 13117
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Anmerkungen zum Quelltext: Das Hauptprogramm sollte in einer Funktion stehen. Momentan ist `m` (kein guter Name!) eine globale Variable.

`Measurement` ist auch kein guter Name für die Klasse. Die enthält auch zu viel. Letztlich ist das eine Gott-Klasse die *alles* macht.

Der `off()`-Aufruf sollte nicht nur passieren wenn der Benutzer das mit Strg+C abbricht, sondern *immer*, nehme ich mal an. Dann gehört das in einen ``finally``-Zweig.

Das `current_light`-Attribut wird nicht benutzt.

`lights_off` ist überflüssig und fehleranfällig wenn man so etwas manuell mit den ”invertierten” Werten füllt. Und bei `lights` ist die Abbildung überflüssig und das der Code über die Pin-Nummern-Konstanten geht, statt direkt die `Pin`-Objekte zu verwenden.

`high()` und `low()` sind nicht auf allen Portierungen vorhanden, `on()` und `off()` dagegen schon.

`freq_hz` macht eigentlich nicht wirklich Sinn. Man verzögert damit letztlich nur die Erkennung des Ereignisses.

In `control_lights()` sind lokale Namen wie Konstanten benannt. Und warum werden die ganzen Bedingungen überhaupt vor dem ``if``/``elif`` ausgewertet? Da ist doch noch gar nicht klar ob überhaupt alle Ergebnisse benötigt werden.

`toggle()` ist ein extrem irreführender Name. Eine Methode die so heisst und den Wert für eine LED übergeben bekommt, schaltet diese eine LED in den Zustand in dem sie gerade nicht ist. Wenn die was anderes macht, ist das total überraschend, denn alle anderen Methoden die so heissen machen genau das.

Ungetestet:

Code: Alles auswählen

import micropython
import utime
from machine import Pin

micropython.alloc_emergency_exception_buf(100)

TOGGLE_GREEN_LT = 0.1
TOGGLE_RED_GT = 0.2
THRESHOLD = 0.02

# Pin 1,2,4
RED_GPIO = 0
YELLOW_GPIO = 1
GREEN_GPIO = 2

# Pin 9 / 10
TRIGGER_GPIO = 6
ECHO_GPIO = 7

SOUND_VELOCITY_M_S = 343


class Instrument:
    def __init__(self):
        self.process_echo = self._process_echo
        self.trigger = Pin(TRIGGER_GPIO, Pin.OUT)
        self.echo = Pin(ECHO_GPIO, Pin.IN, Pin.PULL_DOWN)
        self.echo_start = None
        self.distance_m = None
        self.echo.irq(
            self.irq_callback, Pin.IRQ_RAISING | Pin.IRQ_FALLING, hard=True
        )
        self.red = Pin(RED_GPIO, Pin.OUT)
        self.yellow = Pin(YELLOW_GPIO, Pin.OUT)
        self.green = Pin(GREEN_GPIO, Pin.OUT)
        self.lights = [self.red, self.yellow, self.green]

    def _process_echo(self, echo_end):
        diff = utime.ticks_diff(echo_end, self.echo_start)
        self.distance_m = SOUND_VELOCITY_M_S * (diff / 1e6) / 2

    def irq_callback(self, pin):
        if pin.value():
            self.echo_start = utime.ticks_us()
        else:
            micropython.shedule(self.process_echo, utime.ticks_us())

    def switch_to(self, target_light):
        for light in self.lights:
            light.value(light == target_light)

    def update_lights(self):
        if self.distance_m < TOGGLE_GREEN_LT:
            self.switch_to(self.green)

        elif (
            TOGGLE_GREEN_LT + THRESHOLD
            < self.distance_m
            < TOGGLE_RED_GT - THRESHOLD
        ):
            self.switch_to(self.yellow)

        elif self.distance_m > TOGGLE_RED_GT:
            self.switch_to(self.red)

    def start_measurement(self):
        self.distance_m = None
        self.trigger.on()
        utime.sleep_us(10)
        self.trigger.off()

    def off(self):
        self.switch_to(None)


def main():
    instrument = Instrument()
    try:
        while True:
            instrument.start_measurement()
            while instrument.distance_m is None:
                pass
            instrument.update_lights()
    except KeyboardInterrupt:
        pass
    finally:
        instrument.off()


if __name__ == "__main__":
    main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
hyle
User
Beiträge: 96
Registriert: Sonntag 22. Dezember 2019, 23:19
Wohnort: Leipzig

Könnte evtl. *jemand* mal der Titel anpassen? Es geht ja schon länger nicht mehr um einen RPi3 oder/und "normales" Python. 🙊

//Edit: Sorry, ich hatte ein "Bitte!" vergessen
Alles was wir sind ist Sand im Wind Hoschi.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Solche Muehe gebt ihr euch vielleicht im Raspberry Pi Forum - dafuer streicht ihr da ja auch die dicke Werbekohle ein! Hier, im bescheidenen Python-Forum, das grau und frei von "dieser eine komische Trick, dein Bauchfett zu verlieren" ist, obwohl ich den wirklich dringend braeuchte, ist mir das zu aufwendig 😬
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

So, ich habe das ganze mal in Rust durchimplementiert. Die PIO Statemachine zaehlt munter die verflossenen Ticks, und die Ergebnisse sind meistens plausibel - ich vermute bei Abweichungen eher den Sensor als Problemquelle. Und im Oszilloskop sieht auch alles tippi toppi aus, es wackelt halt gerade bei kleinen Abstaenden.

https://github.com/deets/pico-experiments
robin_
User
Beiträge: 48
Registriert: Montag 3. August 2020, 17:59

__deets__ hat geschrieben: Donnerstag 17. August 2023, 16:52 So, ich habe das ganze mal in Rust durchimplementiert. Die PIO Statemachine zaehlt munter die verflossenen Ticks, und die Ergebnisse sind meistens plausibel - ich vermute bei Abweichungen eher den Sensor als Problemquelle. Und im Oszilloskop sieht auch alles tippi toppi aus, es wackelt halt gerade bei kleinen Abstaenden.

https://github.com/deets/pico-experiments
Danke für den Link, ich bin leider nen Monat zu gar nichts mehr gekommen :S

Ich versuche gerade deine Implementierung von Rust auf uPython zu übertragen:

Code: Alles auswählen

TRIGGER_GPIO = 28
ECHO_GPIO = 22
SOUND_VELOCITY_M_S = 343

micropython.alloc_emergency_exception_buf(100)

@rp2.asm_pio(autopush=True)
def measure_distance():
    wrap_target()

    set(pins, 1) [9]     # lasts 10 us
    set(pins, 0)
    mov(y, 31)           # y's value is: 4_294_967_295
    wait(1, pins, 0)        # wait until input pin at location 0 is HIGH
    
    
    label("count")
    jmp(y_dec, "decrement")
    label("decrement")
    jmp(pins, "count")
    mov(isr, y)
    push()

    wrap()


def main(sm:rp2.StateMachine):
    """Read the output FIFO."""

    while True:
        print(sm.get())


if __name__ == "__main__":
    rp2.PIO(0).remove_program()
    sm = rp2.StateMachine(0, measure_distance, freq=1_000_000, set_base=Pin(TRIGGER_GPIO), in_base=Pin(ECHO_GPIO))
    sm.active(1)
    main(sm)
Es hängt an der Zeile fest:

Code: Alles auswählen

wait(1, pins, 0) 
heißt also, dass entweder der pico auf ein high eines falschen pins wartet oder dass der echo-pin nie high wird, weil der trigger nicht klappt.
'TRIGGER_GPIO' und 'ECHO_GPIO' sind definitiv richtig, wenn ich die Pulse direkt mit Python mache, funktioniert alles.

Hab jetzt 3h lang alles mögliche ausprobiert, komm da nicht mehr weiter. Vielleicht hat ja noch jemand eine Idee.

Gruß Robin
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Also was ich sofort sehe: du hast ja nur einen Wert von 31 fuer den Counter, das wird auch Probleme machen. Und ich sehe nicht, wo du den Echo-Pin in Python auf Eingabe stellst, und Trigger auf Ausgabe. Und hast du ein Oszi? Denn damit solltest du beobachten koennen, was da passiert. Die Frequenz ist auch falsch.
robin_
User
Beiträge: 48
Registriert: Montag 3. August 2020, 17:59

Also erstmal zum Counter:

Bei folgenden Code ist der output immer 4286578687, also 2^32 -1. Daher nehme ich an, dass es das selbe ist bzw. mit !null funktioniert es nicht und ~null war manchmal inkonsistent, häufig war dann der output auch 0 womit der counter ja nicht mehr funktioniert.

Code: Alles auswählen

    mov(y, 31)
    mov(isr, y)
    push()
Und ich sehe nicht, wo du den Echo-Pin in Python auf Eingabe stellst, und Trigger auf Ausgabe
Muss man das? In den offiziellen Beispielen hab ich das bspw. nie gesehen...

Bsp. LED mit 1Hz

Code: Alles auswählen

@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW)
def blink_1hz():
    # Cycles: 1 + 7 + 32 * (30 + 1) = 1000
    set(pins, 1)
    set(x, 31)                  [6]
    label("delay_high")
    nop()                       [29]
    jmp(x_dec, "delay_high")

    # Cycles: 1 + 7 + 32 * (30 + 1) = 1000
    set(pins, 0)
    set(x, 31)                  [6]
    label("delay_low")
    nop()                       [29]
    jmp(x_dec, "delay_low")



# Create and start a StateMachine with blink_1hz, outputting on Pin(25)
rp2.PIO(0).remove_program()
sm = rp2.StateMachine(0, blink_1hz, freq=2000, set_base=Pin(2))
sm.active(1)

time.sleep(2.2)
print("End")
sm.active(0)
sm.exec('set(pins, 0)')
Ich hab das aber mal ausprobiert, keine Änderung:

Code: Alles auswählen

sm = rp2.StateMachine(0, measure_distance, freq=1_000_000, set_base=Pin(TRIGGER_GPIO, Pin.OUT), in_base=Pin(ECHO_GPIO, Pin.IN))
Und hast du ein Oszi? Denn damit solltest du beobachten koennen, was da passiert.
Leider nein.
Die Frequenz ist auch falsch.
Warum ist die Frequenz falsch? Ich dachte man kann diese halbwegs frei wählen mit min. 2kHz (ca.). Ich hab sie auf 1MHz gesetzt, damit ist jeder cycle genau 1us lang. Der Trigger soll genau 10us high sein (laut Datenblatt) und das passiert doch genau hiermit:

Code: Alles auswählen

    set(pins, 1) [9]
    set(pins, 0)
Was überseh' ich?
Danke dir!
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ok, falsche Frequenz war vielleicht ein bisschen scharf formuliert, ich hatte halt eine bestimmte Berechnungsgrundlage, und die habe ich erstmal nicht wiedergefunden. Zu probieren etwas nachzumachen, waehrend man es gleichzeitig veraendert, ist halt eine Einladung fuer ggf. subtile Probleme. Aehnliches auch bezueglich der Pin-Outputs: ich habe die drin, das habe ich so aus meinen Beispielen, auf denen ich das basiert habe, genommen. Ob das jetzt strenggenommen notwendig ist oder nicht, kann ich gar nicht sagen, ohne selbst in experimente einzusteigen. Aber es ist halt ein offensichtlicher Unterschied. Den zu eliminieren, haette ggf. geholfen. Ob das so geht, wie du das da machst, weiss ich aber zB auch nicht, weil du da das einfach nur in die Argumente kippst. Aber es haengt dann von der Implementierung innendrin ab, ob diese Einstellung uebernommen wird, ober nicht. Ich wuerde mindestens mal probieren, die mal explizit davor zu definieren, und nur als Namen reinzugeben.

Ohne Oszi ist in meinen Augen Entwicklung von Elektronik frueher oder spaeter unmoeglich. Billige gebrauchte analoge 2-Kanaeler kosten viellecht 30-50 Euro. Das solltest du ggf. mal erwaegen.

In der Zwischenzeit kannst du vielleicht einfach mas ne Drahtbruecke zu einem anderen Pin schlagen, und auf dein einen Input-IRQ legen, unnd schauen, ob da was getriggert wird.
robin_
User
Beiträge: 48
Registriert: Montag 3. August 2020, 17:59

Jo verständlich, hatte es auch ehrlich gesagt probiert so nah wie an deinem Beispiel zu machen. Lässt sich halt nicht alles 1:1 übernehmen, bspw. hab in uPython auch keine definition von jmp_pins gesehen; Die Frequenz bestimmst du glaub ich über

Code: Alles auswählen

    let freq = clocks.system_clock.freq().raw();
    let div = (16 * freq / 1000_000 / 31 / 2) as u16;


das dürften dann wohl die 125 MHz sein.

Oszi hatte ich schonmal geschaut, gibts leider nicht so richtig was bei mir in Aachen
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

In unmittelbarer Naehe der RWTH gibt es keine gebrauchten Oszis? Ich bin geschockt! Da haette ich schon gedacht. Und finde da zB https://www.kleinanzeigen.de/s-anzeige/ ... 5-168-1706 oder sowas. Wie gesagt, ich kann's nur waermstens empfehlen, man tappt sonst schlicht sprichwoertlich im Dunkeln. Ein preiswerter DSLogic LogicAnalyzer ist auch vie Wert (und kostet 8 Kanal glaube ich 70 oder so), aber das Oszi ist in meinen Augen wichtiger. Weil manchmal Signale schlecht sein koennen, und da kann der LA nix zu sagen.

Ich bin was micropython und die PIOs angeht nicht kompetent im Moment. Ich hab's ja bewusst mit Rust gemacht. Vielleicht findet sich da noch wer anderes, denn zumindest unmittelbar habe ich nicht die Zeit, mich da an einem Port zu probieren.
robin_
User
Beiträge: 48
Registriert: Montag 3. August 2020, 17:59

Jo, danke, ich halt die Augen offen:)

Code: Alles auswählen

@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW, out_init=rp2.PIO.OUT_LOW)
def measure_distance():
    wrap_target()

    set(pins, 1) [19]     # lasts 10 us
    set(pins, 0)
    mov(y, ~null)           # y's value is: 4_294_967_295
    wait(1, pin, 0)        # wait until input pin at location 0 is HIGH
    label("count")
    jmp(y_dec, "decrement")
    label("decrement")
    jmp(pin, "count")
    mov(isr, y)
    push()
    wrap()

def main(sm:rp2.StateMachine):
    """Read the output FIFO."""

    while True:
        print(sm.get())
        time.sleep(0.1)

if __name__ == "__main__":
    rp2.PIO(0).remove_program()
    sm = rp2.StateMachine(0, measure_distance, freq=2_000_000, set_base=Pin(TRIGGER_GPIO, Pin.OUT), in_base=Pin(ECHO_GPIO, Pin.IN))
    sm.active(1)
    main(sm)
Komme der Sache näher. Bei Wait steht pin anstelle pins. Anscheinend ist bei

Code: Alles auswählen

   jmp(pin, "count")
aber die Bedingung 'pin' immer false, sodass er direkt y ins isr pusht.
Der Output ist damit dann:

Code: Alles auswählen

4286302472
4286302471
4286302470
4286302469
4286302468
4286302467
4286302466
...
Hätte eig. vermutet immer den gleichen Wert zu sehen, weil

Code: Alles auswählen

mov(y, ~null)
y eig. immer auf den Ausgangswert gehen sollte... dachte ich zumindest :D
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ja, ich haette auch erwartet, dass er hochspringt, und wieder die 32 gesetzten Bits bekommt. Du kannst ja mal probieren mit einem extern per Kabel hochgezogenen Pin nur die Zaehlschleife zum laufen zu bekommen, bei deutlich reduzierter Geschwindigkeit. Also das Trigger-gedoens weglassen, und nur ein positives Level abzaehlen.
robin_
User
Beiträge: 48
Registriert: Montag 3. August 2020, 17:59

Btw: Mit

Code: Alles auswählen

mov(y, 31)
ist der output

Code: Alles auswählen

4294967294
4294967294
4294967294
4294967294
4294967294
4294967294
4294967294
...
Antworten