Vorstellung und Anleitung zu Spurfolger Exzessen am TX-Pi mit Python3

Hallo Kids, hier ist eine Ecke extra für euch!
Ihr könnt hier Fragen aller Art stellen, die wir euch gerne so schnell wie möglich beantworten.
Ihr dürft hier aber auch gerne eure Modelle einfach mal anderen Fischertechnikern vorstellen.
Antworten
Mahlzeit
Beiträge: 20
Registriert: 06 Sep 2020, 10:40

Vorstellung und Anleitung zu Spurfolger Exzessen am TX-Pi mit Python3

Beitrag von Mahlzeit » 04 Dez 2020, 13:01

Moin Moin!

Ich möchte gerne einen neuen Spurfolger bauen mit dem TX-Pi. Da das etwas anders läuft als auf dem ftTXT möchte ich die Schritte dazu inkl. Beispielcode hier aufzeigen, zum Nachbauen für andere oder einfach nur so.

Vor ein paar Wochen hat wohl jemand versehentlich meinen ftTXT mit seinem/ihrem verwechselt. Echt schade. Nachdem ich das jetzt erstmal eine Weile verdauen musste, habe ich aber auf diese Weise Gelegenheit mich mehr mit dem TX-Pi zu beschäftigen.

Ich könnte mir vorstellen, dass Spurfolger auch für andere Einsteiger interessant sind, daher wollte ich das gerne wie ein Anfängertutorial gestalten, wem das an der Stelle zu viel Info ist, der kann natürlich auch einfach nur die Bilder anschauen oder in den Code gucken!

Da mein IR-Sensor weg ist, bin ich auf diese IR Sensoren von Pololu gestoßen:

Bild

"Man weiß nie, was genug ist, wenn man nicht weiß, was mehr als genug ist." --(nicht von mir, aber auch nicht von Karl Dall)

Okay, aber ob die obigen 31 IR LEDs in einer Reihe mehr als genug sind? :D Ich vermute es stark und zumindest hat der Raspberry PI glaube ich auch nur 17 GPIOs mit schaltbaren Widerständen, sodass ich mich für die Variante QTR-HD-09RC mit 9 LEDs entschieden habe. (Im Rückblick hätte ich vermutlich übrigens lieber eine MD statt HD Variante nehmen sollen, die hat größere Abstände zwischen den Leds)

Vorweg: Die Sensoren funktionieren sehr gut am Pi, man braucht keinen ADC. Man schließt jede einzelne Lampe an einen GPIO, zieht dann den Widerstand hoch, indem man den GPIO auf Ausgang stellt, lässt die Lampe kurz aufladen, stellt den GPIO von Ausgang auf Eingang (= Widerstand runter) und misst dann wie lange es dauert bis die Spannung 0 ist.

Sehen kann man da übrigens nix. (IR Licht). Die Lampen brauchen bei mir auch weniger als 0.00001s zum Aufladen und der Pi4 schafft dann etwa 250 loops/s meines kompletten PID Spurfolgerprogramms inkl der 250x9 Messwerte der LED. Zu schnell zum gucken, aber gut für unser Programm.

Leider stellt der Hersteller ausschließlich Beispielcode für den Arduino zur Verfügung und der Link auf ein Pythonprojekt im Netz verweist ins Nichts. Daher müssen wir das oben gesagte an der Stelle selber in Python formulieren und zwar am besten in einer Funktion, die wir bei Bedarf aufrufen.

Code: Alles auswählen

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)

def ir_sensor(pin, puls_dur):  # pin = gpio (bcm) pin number, puls_dur (in ms) = previously determined calibration value
    pulse_end = time.perf_counter()  # this will make invalid results negative so we can spot them easily and prevent puls_end from throwing an error
    GPIO.setup(pin, GPIO.OUT)  # define which pin to measure
    GPIO.output(pin, GPIO.HIGH)  # turn on 5v on relevant pin
    time.sleep(0.0001)  # wait for the led to charge up
    pulse_start = time.perf_counter()  # start counting
    GPIO.setup(pin, GPIO.IN)  # set pin to input in order to pull down resistor
    while GPIO.input(pin) > 0:
        pass  # waiting for voltage to become zero
    if GPIO.input(pin) == 0:
        pulse_end = time.perf_counter()  # stop counter and measure elapsed time
    pulse_duration = pulse_end - pulse_start
#    print("duration:", round((pulse_duration * 1000),2), "ms") #print the time of voltage decay if you want to get calibration data
    if pulse_duration > puls_dur * 1000:
        colour_seen = 1  # 1 is black
    elif pulse_duration > 0:
        colour_seen = 0  # 0 is white
    else:
        colour_seen = -33  # this is basically an identifier for an unsuccessful reading
    return colour_seen
	
	

Die LEDs entladen sich nicht alle gleich schnell, und die Werte hängen außerdem noch vom Abstand zum Boden ab, sodass ich sie alle einzeln "kalibriert" habe und die individuelle Schwelle die den Übergang zwischen Schwarz und Weiß anzeigt (meist ca. 0.00030s) dann für jeden Pin einzeln an die Funktion übergebe.


Speichert man die Pins und Kalibrierungswerte als Paare in einem python dictionary und nutzt dann list comprehension um die Messwerte zu generieren, können wir unsere Anwendung später problemlos auf den Spurfolger mit 31 Leds skalieren, ohne das Programm ändern zu müssen.

Code: Alles auswählen

pins_calib = {
    5:0.31,
    6:0.25,
    13:0.50,
    19:0.30,
    26:0.20,
    12:0.45,
    16:0.50,
    20:0.45,
    21:0.25
}

def measurements():
    error_list = []
    for i in range(len(pins_calib)):
        error_list.append(ir_sensor(([key for key in pins_calib.keys()][i]), ([value for value in pins_calib.values()][i])))
    return error_list

So kann jetzt in jedem loop unseres PID Spurfolgerprogramms eine neue Liste mit Messwerten angelegt und dann blitzschnell entscheiden werden was zu tun ist.

Man beachte jedoch, dass dies so erst ab Python 3.7 klappt (Python Docs: "Changed in version 3.7: Dictionary order is guaranteed to be insertion order."), daher könnt ihr an der Stelle einmal "python3 -V" im Terminal eingeben um euch eurer Version zu vergewissern.


Bevor es weiter gehen kann mit der eigentlichen PID Steuerung, Verkabelung usw. muss ich mir wohl erstmal über mein Fahrzeug Gedanken machen.

Wir brauchen 2-4 Räder, 2 Motoren und der Spursensor muss irgendwie ca. 5mm bis 30mm über dem Boden angebracht sein. Rest erstmal egal.

Also so sah mein erster Entwurf aus: Man baue eine rollende Plattform mit einer Wanne und werfe alles oben rein. Der Spursensor lässt sich durchaus auch irgendwie bodennah festklemmen zwischen ein paar Steinen.

wagen1.jpg
wagen1.jpg (89.37 KiB) 2451 mal betrachtet

Ich bin manchmal etwas ungeduldig und im Prinzip würde mir das jetzt für den Anfang auch so reichen. Aber die Konstruktion wird wohl die erste Kurve nicht heil überstehen und der Spursensor wird auch nicht halten. 8-)


Zweite Idee für den Spursensor und den Pi:
wagen2.jpg
wagen2.jpg (31.56 KiB) 2451 mal betrachtet
Das klappt auf diese Weise eigentlich ganz gut und ich würde euch jetzt auch mein ft_Kartonauto zeigen allerdings hat kürzlich jemand unsere Heißklebepistole nach dem Weihnachtsdekobasteln über Nacht angelassen (!) und die geht jetzt nicht mehr. Anders kriege ich den IR Sensor aber nicht im Karton sicher befestigt.

Also Idee Nummer drei: zufällig war ich letztens auf den 3d Druck Faden hier im Forum aufmerksam geworden und habe dann in der Folge bei https://www.thingiverse.com/phabermehl/designs und https://www.thingiverse.com/harbaum/designs im Prinzip alles gefunden was man so brauchen könnte.

Daher lieber gut geklaut als schlecht geklebt.

Noch ein paar Löcher in der Software reingebohrt und voilá.
wtfus.jpg
wtfus.jpg (46.57 KiB) 2451 mal betrachtet
Okay, das Ergebnis haut hier wahrscheinlich auch keinen vom Hocker, aber dafür geht es wirklich ganz leicht mit dem Autodesk Fusion360 (kostenlos) i.V.m. 10 Minuten Youtube Tutorial (kostenlos), denn so langsam möchte ich das Auto gerne auch mal fahren lassen...

Zum Glück ist das Thema 3d Druck ja stark im Kommen, sodass nach etwas rumfragen auch jemand gefunden wurde der mir meine kleinen Sensorhalter und PI4 Adapter in Goldglitter Seiden-PLA drucken konnte. Leider kommt der Glitter Effekt auf dem Bild nicht richtig durch.

pacman_mit_zahnspange.jpg
pacman_mit_zahnspange.jpg (36.23 KiB) 2451 mal betrachtet

Und mit diesem Zwischenstand mache ich jetzt auch erstmal Schluss mit Teil 1. Nächste Woche geht es dann weiter mit 5V für den Pi, i2c für die Motoren, dem neuen Fahrzeugaufbau, dem PID Loop für den Spurfolger und so weiter..
zwischenstand_teil1.jpg
zwischenstand_teil1.jpg (71.61 KiB) 2451 mal betrachtet

Viele Grüße
Dennis

Benutzeravatar
MasterOfGizmo
Beiträge: 2720
Registriert: 30 Nov 2014, 07:44

Re: Vorstellung und Anleitung zu Spurfolger Exzessen am TX-Pi mit Python3

Beitrag von MasterOfGizmo » 04 Dez 2020, 14:03

Wow, sehr cool. Endlich ein PI in einem Roboter.

Wegen des Dicts: Macht das so Sinn? Du nutzt das Dict imho nur als Liste, über die Du gehst. Wäre da sowas (Achtung ungetestet) nicht näher an dem, was Du machen willst?

Code: Alles auswählen

pins_calib = [
    (5, 0.31),
    (6, 0.25),
...
]

def measurements():
    error_list = []
    for i in pins_calib:
        error_list.append(ir_sensor(i[0], i[1]))
    return error_list
Welchen Sensor nimmst Du denn da? Du scheinst einen mit neun LEDs zu verwenden, den gibt es auf dem oberen Bild aber nicht. Oder wie?

Ein wenig schmerzlich klingt aber die Verwendung von 9 IOs am Pi. Der hat doch schon so wenig und man braucht die ständig ... so einer kleiner Arduino in der Mitte, der sich um die ganzen LEDs mit voller Aufmerksamkeit kümmert und dann dem Pi nur per USB oder I²C von seinen Beobachtungen erzählt wäre doch auch schick ....
Arduino für fischertechnik: ftDuino http://ftduino.de, ftDuino32 http://ftduino.de/32

Benutzeravatar
PHabermehl
Beiträge: 2429
Registriert: 20 Dez 2014, 22:59
Wohnort: Bad Hersfeld

Re: Vorstellung und Anleitung zu Spurfolger Exzessen am TX-Pi mit Python3

Beitrag von PHabermehl » 04 Dez 2020, 14:16

@Dennis:

GROSSARTIG!!!!

@Till:

Den 9-LED-Sensor hat er doch im Text genannt. Passt.
https://www.MINTronics.de -- der ftDuino & TX-Pi Shop!

viele Grüße
Peter

Antworten