Roboter
Informationen und Anleitungen zu den Bauteilen und den Zusammenbau des SMARS-Roboters
- Allgemeine Hinweise
- Elektronische Bauteile für den Roboterbau
- Die LED
- Der Widerstand
- Der Raspberry Pi Pico
- Der Transistor
- Der Motortreiber
- Der Spannungswandler
- Das Wukong 2040 Board
- Programmierung des Raspberry Pi Pico mit Micropython
- LEDs schalten
- Ampelschaltung mit LEDs
- Der Motor
- Der Ultraschallsensor
- Der Infrarotsensor
- Codebeispiele
- Zusammenbau des SMARS-Roboters
- Das Steckbrett mit Raspberry Pi Pico und Abdeckplatte
- Gehäuse und Räder
- Anschluss der Motoren
- Der Ultraschallsensor
- Der komplette Roboter
- Der Kettenantrieb
- Der Zusammenbau Crawlys
- Zusammenbau von Walky
- Bibliotheken für die Roboter
- Motorsteuerung
- Ultraschallsensor
- Infrarotsteuerung
- Servosteuerung
- Das komplette Modul "robotlibrary"
- Dokumentation
- Fehlerbehebung
- 3D-Konstruktionsdateien für die Roboter
Allgemeine Hinweise
Umgang mit Elektronikteilen
Die hier veröffentlichten Anleitungen sind nicht als alleinige Anleitung gedacht, sondern sollen immer zusammen mit dem Unterricht benutzt werden. Sie dienen als Gedächtnisstütze oder für diejenigen, die einzelne Stunden verpasst haben, als Möglichkeit, beim Aufbau aufzuholen.
Grundsätzlich gilt, dass alle verbauten elektronischen Teile sehr empfindlich gegen Verpolung und zu hohe Spannungen sind. Daher sollte man sich nach dem Hinzufügen eines Bauteils immer vergewissern, dass alles richtig angeschlossen ist. Am besten zeigt man die Anschlüsse immer noch jemand anderem.
Hier einige Beispiele für explodierende Elektronikteile:
Allgemeine Tipps für die Programmierung
- Python und Micropython definieren Programmierblöcke über Einrückungen. Es ist also wichtig, dass von Anfang an darauf geachtet wird, Einrückungen immer sauber und vor allem einheitlich zu machen. Bei einer falschen Einrückung taucht in der Fehlermeldung das Wort
Indent
auf. - Auch dürfen Blöcke nicht leer sein, da sonst die Einrückung nicht erkannt werden kann. Wenn man also Code schreibt und erst einmal etwas anderes implementieren möchte, dann schreibt man den Platzhalter
pass
in den Code. - Bevor man Code auf den Roboter lädt, muss dieser getestet werden. Dazu muss das Programm in Thonny gestartet werden, damit man Fehlermeldungen und Debug-Nachrichten lesen kann. Wer ungetesteten Code hochlädt und dann erwartet, dass der Roboter funktioniert, ist selbst schuld.
- Eine Python-Datei wird auf dem Pico automatisch gestartet, wenn sie
main.py
heißt. Das bedeutet aber auch, dass das Programm gestartet wird, wenn man den Pico am Rechner über USB einsteckt. Das kann beim Testen zeitraubend sein, da man immer erst das Programm beenden muss. In der Testphase bietet es sich also an, einen anderen Namen für die Startdatei zu wählen.
Elektronische Bauteile für den Roboterbau
Die LED
Die LED oder Leuchtdiode hat heute die Glühlampe fast vollständig verdrängt. Und das hat auch gute Gründe. Der Wirkungsgrad einer LED liegt bei 30–40 %. Der Wirkungsgrad einer Glühlampe liegt bei ca. 5 % ¹. Das heißt, dass eine LED 30–40 % der eingesetzten Energie in Licht umwandelt. Eine normale Glühlampe ist damit zu 95 % eine Heizung und nur zu 5 % ein Leuchtmittel. Die LED ist damit immer noch nicht perfekt, aber das Beste, das es zurzeit für die Lichterzeugung gibt. Außerdem lebt sie länger als die Glühlampe, die aufgrund ihrer Konstruktion schnell altert.
Die Polung der LED
Eine LED muss richtig gepolt werden, um zu leuchten. Wird sie verpolt, kann sie dabei kaputtgehen. Das lange Beinchen heißt Anode und ist die positive Seite. Die kurze Seite ist die Kathode und die negative Seite oder Masse. Eine LED muss immer zusammen mit einem Widerstand geschaltet werden.
Wie eine LED mit dem Pico an- und ausgeschaltet werden kann, steht hier
Der Widerstand
Der Widerstand ist dafür da, andere elektronische Bauteile vor Überlastung zu schützen. Es gibt ihn in mit sehr vielen verschiedenen Widerstandswerten. Diese sind mit einem Farbcode angegeben.
Der Raspberry Pi Pico
Der Pico ist das Herzstück des Roboters, denn er führt den Code aus, der den Roboter steuert. Der Pico wird mit Micropython programmiert, das eine kleinere Ausgabe des großen Pythons ist.
Der Pico ist, wie die meisten elektronischen Teile, sehr empfindlich gegen Verpolung oder Überlastung oder Kurzschlüsse. Daher muss man immer sehr sorgfältig alle Verbindungen überprüfen, bevor eine Spannung angelegt wird.
Detaillierter Pinout-Plan des Pico zum Download
Er wird über einen Mikro-USB-Anschluss an den Computer angeschlossen. Als Entwicklungsumgebung benutzen wir Thonny.
Um die Pin-Anschlüsse ansteuern zu können, muss zunächst aus der Bibliothek machine Pin importiert werden:
from machine import Pin
Nicht alle Pins haben dieselben Fähigkeiten. Welcher Pin was kann, steht im detaillierten Pinout-Plan. Generell sollten für den Roboterbau die angegebenen Pins verwendet werden. Diese sind auf jeden Fall geeignet für die benötigte Funktion und die Fehlersuche wird erleichtert, wenn man nicht jedes Mal auch die Zuordnung der Pins überprüfen muss.
Der Transistor
Das Schaltzeichen
Transistoren gibt es in vielen verschiedenen Ausfertigungen. Dies ist ein Beispiel.
Das heißt, mit einem Transistor kann man mit einer niedrigen Spannung eine größere Spannung regulieren. Das kann ein einfacher Schaltvorgang sein oder die relative Regelung einer Spannung. Damit ist der Transistor in seiner Grundfunktion ein Verstärker. In einer digitalen Schaltung wird der Transistor auch wieder nur an- oder ausgeschaltet. Die Regelung der Helligkeit einer LED oder der Geschwindigkeit eines Motors erfolgt genauso wie ohne Transistor.
Für den Roboterbau werden wir nicht direkt mit einem Transistor arbeiten. Sie sind aber Teil fast aller Bauteile, die verwendet werden.
Der Transistor ist die Grundvoraussetzung, dass es moderne Computer gibt.
Ein Transistor ist ein elektronisches Halbleiter-Bauelement zum Steuern oder Verstärken meistens niedriger elektrischer Spannungen und Ströme. Er ist der weitaus wichtigste „aktive“ Bestandteil elektronischer Schaltungen, der beispielsweise in der Nachrichtentechnik, der Leistungselektronik und in Computersystemen eingesetzt wird. Besondere Bedeutung haben Transistoren – zumeist als Ein/Aus-Schalter – in integrierten Schaltkreisen, was die weit verbreitete Mikroelektronik ermöglicht.
Die Bezeichnung „Transistor“ ist ein Kofferwort des englischen transfer resistor, was in der Funktion einem durch eine angelegte elektrische Spannung oder einen elektrischen Strom steuerbaren elektrischen Widerstand entspricht. Die Wirkungsweise ähnelt der einer entsprechenden Elektronenröhre, nämlich der Triode.
Quelle: Wikipedia: https://de.wikipedia.org/wiki/Transistor
Der Motortreiber
Aktuelle Variante
Dieser Motortreiber beinhaltet gleichzeitig einen Spannungswandler, der genau 5V Gleichspannung liefert.
Vorherige Variante
Dieser Typ Motortreiber ist häufiger mal durchgebrannt. Daher wurde er durch ein stärkeres Modell ersetzt.
Der Spannungswandler
Der Spannungswandler wird mittlerweile nicht mehr benötigt, da dieser im neuen Motortreiber integriert ist.
Mit dem Spannungswandler können wir eine Gleichspannung in eine niedrigere Spannung umwandeln. Da wir für die Motoren 6-9V benötigen, der Pico und die elektronischen Komponentenn aber nur 3,3V - 5 V vertragen, betreiben wir den Roboter mit einer 9V Batterie und nutzen den Spannungswandler für den Pico. Der Pico wiederum stellt 3,3V für den Betrieb der anderen Teile bereit.
Der Spannungswandler muss vor dem Anschluss an den Pico auf die richtige Spannung eingestellt werden. Dafür haben wir Spannungsmessgeräte.
Das Wukong 2040 Board
Das Wukong 2040 Board wird für die Roboter „Walky“ und „Crawly“ benötigt. Es bietet praktische Anschlüsse für bis zu 12 Servomotoren und 4 Motoren. Außerdem bietet es zwei farbige LEDs, zwei Druckknöpfe und einen Buzzer. Die Stromversorgung läuft über einen 3,7V-Akku, der in dem Board aufladbar ist.
Als Gehirn dient natürlich wieder ein Raspberry Pi Pico.
Programmierung des Raspberry Pi Pico mit Micropython
Schritt-für-Schritt-Anleitung, um einige der vielen Möglichkeiten des Picos kennenzulernen.
LEDs schalten
Die interne LED
Der Pico hat eine interne LED, die folgendermaßen angesteuert werden kann:
import time
from machine import Pin
#led=Pin("LED", Pin.OUT) # Für den Pico mit eingebautem WLAN
led=Pin(25, Pin.OUT) # Für den Pico ohne WLAN
led.value(1)
time.sleep(1)
led.value(0)
Soll die LED unabhängig vom Programmablauf blinken, dann kann man das mit einem Timer realisieren.
from machine import Pin,Timer
# led=Pin("LED", Pin.OUT) # Für den Pico mit eingebautem WLAN
led=Pin(25, Pin.OUT) # Für den Pico ohne WLAN
timer = Timer()
timer.init(freq=2, mode=Timer.PERIODIC, callback=lambda t: led.toggle())
Soll der Timer beendet werden, so kann man das mit dem Befehl timer.deinit()
erreicht werden.
Möchte man mehr Kontrolle haben oder komplexere Funktionen einbauen, dann geht das so:
import time
from machine import Pin,Timer
# led=Pin("LED", Pin.OUT) # Für den Pico mit eingebautem WLAN
led=Pin(25, Pin.OUT) # Für den Pico ohne WLAN
led.value(1)
time.sleep(1)
led.value(0)
def blink(timer):
led.toggle()
timer = Timer()
Timer().init(freq=2, mode=Timer.PERIODIC, callback=blink)
Ein Timer läuft auch nach dem Ende des Programms weiter. Also nicht wundern, wenn es weiter blinkt.
Aufgabe: Die LED zum Blinken bringen.
Eine externe LED
Das war zwar schon spannend, aber nun wollen wir eine externe LED an den Pico anschließen. Dazu benötigen wir eine LED, einen 100 Ω Widerstand sowie zwei Kabel. Stecke die Schaltung genau so zusammen, wie abgebildet. Achte vor allem darauf, dass die LED richtig herum ist.
Hier ist der dazugehörige Schaltplan:
Externe LED mit Transistor
Der Pico liefert an den Pins nur eine Spannung von 3,3 Volt und die Stromstärke ist auch nicht sehr hoch. Es ist leicht möglich, die Anschlüsse zu überlasten, zwar nicht mit nur einer LED, jedoch bleibt es dabei ja nicht. Daher müssen Transistoren verwendet werden.
Es gibt zwei mögliche Schaltungen für die LED mit Transistor. Der Unterschied ist nur, ob die Schaltung auf Anoden- oder auf Kathodenseite geschieht.
Regelung der Helligkeit
Egal, ob du die LED mit oder ohne Transistor betreibst, so ist die Helligkeit bislang immer die gleiche. Glühlampen lassen sich sehr einfach dimmen, indem man die Spannung regelt. Bei der LED funktioniert das nicht, da die Spannung an der LED immer dieselbe ist. Die LED ist nämlich kein ohmsches Bauteil. Außerdem haben wir mit dem Pico die Schwierigkeit, dass er ein digitales Gerät ist und bekanntermaßen kennen digitale Geräte nur 1 und 0 oder an und aus. Wie lässt sich damit also die Helligkeit regulieren?
Ampelschaltung mit LEDs
Ampelschaltung
Verwende die LED-Ampel, um eine Ampelschaltung zu programmieren. Schaltet dann mehrere Ampeln zu einer Kreuzung zusammen, indem ihr die Picos miteinander kommunizieren lasst. Dazu müsst ihr einen Pin auf dem Pico, der Befehle erhält, als Eingangspin definieren.
Empfange Daten auf Pin 16 und blinke mit der internen LED
from machine import Pin
sensor=Pin(16, Pin.IN, Pin.PULL_UP)
led=Pin(25, Pin.OUT)
while True:
while sensor.value():
led.value(1)
led.value(0)
Sende Daten mit Pin 15 und blinke mit der internen LED
import time
from machine import Pin
#led=Pin("LED", Pin.OUT) # Für den Pico mit eingebautem WLAN
led=Pin(25, Pin.OUT) # Für den Pico ohne WLAN
sender=Pin(15,Pin.OUT)
while True:
led.value(1)
sender.value(1)
time.sleep(1)
led.value(0)
sender.value(0)
time.sleep(1)
Nur einer der beiden Picos muss über USB an Strom angeschlossen werden. Beide Programme werden unter dem Namen "main.py" auf dem Pico abgespeichert, dann laufen die Programme automatisch, sobald die Picos Strom bekommen.
Knopfsteuerung der Ampel
Für die Programmierung eines Ampelknopfes, muss man den Knopf entprellen, damit keine Geisterbewegungen registriert werden. Ein minimales Codebeispiel ist dieses:
from machine import Pin
import time
button = Pin(15, Pin.IN, Pin.PULL_DOWN)
pressed = False
num_pressed = 0
last_pressed = 0
DEBOUNCE_WAIT = 100
def button_handler(pin):
global pressed, num_pressed, last_pressed #mit dem Befehl global teilt man Python mit, dass man die Variabel verwenden möchte, die außerhalb der Funktion initialisiert wurde.
while utime.ticks_diff(utime.ticks_ms(), last_pressed) < DEBOUNCE_WAIT: # Hier wird verhindert,dass mehrere Auslösungen hintereinander registriert werden.
pass
last_pressed = utime.ticks_ms()
if not pressed:
while time.ticks_diff(time.ticks_ms(), last_pressed) < DEBOUNCE_WAIT:
pass
if pin.value() == 1:
pressed=True #Damit kann im Programmablauf der Knopfdruck registriert werden.
num_pressed +=1
print(pin.value(), "number presses: ", num_pressed)
last_pressed = time.ticks_ms()
pressed=False # Dies hier eher im weiteren Programmablauf verwenden.
button.irq(trigger=Pin.IRQ_RISING, handler=button_handler)
# Hier weiterer Programmablauf
while True:
pass
Programmiergrundkurs in Python
Der Motor
Ein Motor wird genauso gesteuert wie eine LED. Man kann ihn entweder einfach an- und ausschalten, oder mithilfe der Pulsweitenmodulation die Geschwindigkeit regeln. Probiert es einfach einmal aus. Da ein Motor deutlich mehr Leistung hat als eine LED, kann man den Raspberry Pi Pico schnell überlasten. Daher betreiben wir den Motor nur über einen Transistor. Es sorgt dafür, dass das Steuersignal des Picos verstärkt von der 9V Batterie an den Motor geleitet wird. Aber Achtung: Der Motor ist für dauerhaft 6V ausgerichtet und sollte daher nicht zu lange mit 9V betrieben werden.
Für diese Schaltung könnt ihr die Schaltung der LED mit Transistor ohne den Widerstand verwenden.
Der Code für diese Steuerung ist genauso wie für eine LED. In dem Schaltbild wird der Pin 15 benutzt.
Richtungssteuerung
Wie könnte man nun die Drehrichtung des Motors ändern, ohne die Kabel umzustecken?
Überlegt erst einmal und dann schaut ihr euch das nächste Bauteil an:
Der Ultraschallsensor
Schließt den Ultraschallsensor an den Pico an:
Die Softwarebibliothek für den Ultraschallsensor
Der Infrarotsensor
Der IR-Sensor wird folgendermaßen an den Pico angeschlossen. Der OUT-Pin kann natürlich auch geändert werden.
So wird der Infrarotsensor ausgelesen:
from machine import *
import time
# Der Pin für den Infrarotsensor wird initialisiert.
ir=Pin(16,Pin.IN,Pin.PULL_UP)
while True:
print(ir.value()) #Es wird einmal der Wert ausgegeben, der am Pin anliegt.
while ir.value() == 0: # Solange der Wert 0 bleibt, ändert sich die Anzeige nicht.
time.sleep_ms(50)
print(ir.value()) # Ist/Wird der Wert 1, wird erneut auf der Konsole ausgegeben.
while ir.value() == 1:
time.sleep_ms(50) # Solange der Wert 1 bleibt, ändert sich die Anzeige nicht.
Codebeispiele
Theo III
Best Practise
Ausschalten der Motoren bei Unterbrechung des Programms
Anfangs wird man sehr viel an dem Roboterprogramm testen müssen. Dabei wird das Programm dann häufig abstürzen. Damit die Motoren nicht weiter in dem Zustand laufen, in dem sie dabei geschaltet waren, kann man mit einem try/except
arbeiten:
try:
# Hier läuft das Programm
except Exception as err:
print(err) # Nötig, um Fehlermeldungen angezeigt zu bekommen.
r.emergency_stop() # Roboter anhalten, hier ein Beispiel mit der robotlibrary.
print("Robot stopped") # Damit es ganz deutlich ist.
except KeyboardInterrupt:
r.emergency_stop()
print("Keyboard interrupt")
Effizienter Code
Auch wenn die Rechenleistung der Picos ausreichen sollte, ergibt es Sinn, sich über Effizienz Gedanken zu machen, da schwer zu erkennen ist, ob manche Probleme durch Überlastung des Prozessors hervorgerufen werden.
while True:
robot.drive()
if us.get_dist() > min_distance:
# stop or turn
robot.stop()
In diesem Beispiel wird in der Schleife der Befehl drive()
mit jedem Durchlauf aufgerufen, was nicht sonderlich effizient ist, da die Motoren weiterfahren, auch wenn das Programm gerade andere Befehle ausführt. Eine bessere Variante wäre diese:
robot.drive()
while us.get_dist() > min_distance:
pass
robot.turn()
Hier wird nur die Entfernung zum nächsten Hindernis überprüft. Sobald der Roboter zu nahe gekommen ist, wird die Schleife beendet und der Code wird weiter ausgeführt.
Fehlertoleranter Code
Die Sensoren, die wir benutzen, liefern nicht immer zuverlässige und korrekte Ergebnisse. Daher kann man sich nicht darauf verlassen, dass eine Messung ausreicht. Ist man auf genauere Ergebnisse angewiesen, kann es sinnvoll sein, die Ergebnisse von Sensormessungen (insbesondere des Ultraschallsensors) zu filtern. Dazu kann gehören, Extremwerte, die im vorliegenden Fall unwahrscheinlich sind, zu ignorieren oder Mittelwerte von mehreren Messungen zu bilden. Ein Beispiel für die Glättung der Entfernungswerte aus dem Ultraschallsensor:
us = Ultra(16)
dist_values = deque([0,0,0,0,0],5)
while True:
d = us.get_dist()
dist_values.append(d)
d = sum(dist_values)/len(dist_values)
print(f"Entfernung: {d} cm")
Eine andere Methode muss für das Auslesen des Infrarotsensors gefunden werden. Hier könnte man z.B. eine kurze Wartezeit einbauen und dann abfragen, ob der Sensor immer noch denselben Wert liefert wie bei Auslösung der Reaktion.
Überschreiben von Methoden aus der Bibliothek
Möchte man die Funktion einer Methode aus der Roboterbibliothek (robotlibrary) verändern, kann man die Methode überschreiben (Fachbegriff aus der objektorientierten Programmierung). Dafür wird die Klasse Robot
vererbt, wie in dem Codebeispiel angegeben. Möchte man nun z.B. die Methode set_speed()
verändern, dann definiert man sie einfach neu. Ist eine Methode nicht in der abgeleiteten Klasse (in diesem Fall MyRobot
definiert, dann wird die Methode der Elternklasse (Robot
) genommen. Probiere es aus, indem du das vorliegende Programm einmal mit und einmal ohne die Definition von set_speed()
aufrufst.
from robotlibrary.robot import Robot
from time import sleep, sleep_ms
class MyRobot(Robot):
def __init__(self):
super().__init__(False,None)
print("start")
def set_speed(self,x):
print(f"Child method set_speed. Value: {x}")
def main():
try:
robot = MyRobot()
robot.set_speed(90)
while True:
sleep(1)
except KeyboardInterrupt:
robot.emergency_stop()
if __name__ == "__main__":
# execute only if run as a script
main()
Verändern der Funktion der Fernbedienung
Eine Ableitung funktioniert nicht, wenn man die Methode read()
verändern möchte, da von der Bibliothek immer die Elternklasse aufgerufen würde. Man kann aber vor der Initialisierung der Klasse Robot
eine neue Methode definieren und diese als Parameter übergeben. Hier ist ein Beispiel, wie es geht.
# Example for how to override the read() method that gets input from the remote control.
# Define your own method.
def my_read(buffer: memoryview):
print("my_read called.")
def main():
try:
# Use the name of your method as a parameter when initialising the robot object.
r = Robot(True,my_read)
r.set_speed(100)
while True:
sleep(1)
except KeyboardInterrupt:
r.emergency_stop()
if __name__ == "__main__":
# execute only if run as a script
main()
Den Ultraschallsensor im Hintergrund laufen lassen
In komplexeren Programmen kann es lästig werden, immer wieder die Entfernung zum nächsten Hindernis zu überpüfen. Dieses Beispiel erläutert, wie man das Problem löst, indem man die Entfernungsmessung in den Hintergrund verlegt.
from robotlibrary.robot import Robot
from time import sleep, sleep_ms
import uasyncio as asyncio
################################## Your class definition
class MyRobot(Robot):
def __init__(self):
super().__init__(False,None) # Call the original constructor.
print("start")
# With this method defined here, the robot will not drive as the speed is not set in this function.
def set_speed(self,x):
print(f"Child method set_speed. Value: {x}")
################################# End of class definition
# Define functions for your program
async def monitor_dist():
global distance
while True:
if robot.get_dist() < distance:
react_to_obstacle()
await asyncio.sleep_ms(100)
def react_to_obstacle():
global distance
print("danger")
robot.random_spin(300)
robot.set_forward(True)
robot.set_speed(80)
async def my_program():
robot.set_speed(90)
while True:
print("driving")
await asyncio.sleep_ms(100)
async def main():
asyncio.create_task(monitor_dist())
await my_program()
################################# Initialize the robot and start the program.
robot = MyRobot()
distance = 20
if __name__ == "__main__":
# execute only if run as a script
try:
asyncio.run(main())
except KeyboardInterrupt:
print("Emergency stop")
robot.emergency_stop()
Beschleunigung mit Entfernungsmessung
Diese Methode ist nur nötig, wenn man nicht asyncio benutzt.
Beschleunigt man den Roboter langsam mit der Methode set_speed
, dann kann er in der Zeit bis zum Erreichen der Geschwindigkeit keine Entfernungsmessung durchführen. Dies ist ein Beispiel, wie man beides erreichen kann:
obstacle_detected = False
new_speed = 100
speed_now = 0
min_distance = 15
while speed_now <= new_speed and not obstacle_detected:
#Set the speed for the motors, f. ex. motor.set_speed(speed_now)
utime.sleep_ms(10+int(speed_now/2))
speed_now += 1
if us.get_dist() < min_distance: # Adjust the code to your needs.
obstacle_detected = True
if obstacle_detected:
# Stop or turn or whatever
obstacle_detected = False
else:
# keep going
pass
Zusammenbau des SMARS-Roboters
In diesem Kapitel werden die mechanischen Aufbauschritte erklärt.
Das Steckbrett mit Raspberry Pi Pico und Abdeckplatte
Es gibt verschiedene Varianten von Platten, auf denen das Steckbrett aufgeklebt ist.
Aktuelle Variante
Diese Variante ist für den „Theo III“!!
In dieser Variante wird das Steckbrett quer aufgeklebt. Die Abdeckplatte wir von hinten in den Roboter eingeschoben.
Ältere Varianten
älteste Variante
Die ältere Variante wird von oben auf das Gehäuse gesteckt.
neuere Variante
Die neuere Variante wird von hinten in das Gehäuse eingeschoben.
Gehäuse und Räder
Es gibt mehrere Varianten von Gehäusen für die SMARS-Roboter. Das aktuellste ist der „Theo III“.
Theo III
Ein neu gedrucktes Gehäuse enthält noch einige Stützstrukturen um die Halterungen für die passiven Räder und in dem Schlitz für den Schalter. Diese müssen zunächst entfernt werden. Das Gehäuse wird mit den passiven Rädern montiert ausgeteilt. Diese sollten nicht mehr entfernt werden, da das Gehäuse dabei brechen kann. Generell ist darauf zu achten, dass die Seitenwände nicht belastet werden, da sie schnell abbrechen können.
Es gibt bei dem Gehäuse ein vorne und hinten. Hinter erkennt man an der Einprägung „Theo III“. Dort befindet sich auch der Schalter. Beim Einsetzen der Motoren ist darauf zu achten, dass der Motor mit den längeren Kabeln nach vorne kommt.
Für die aktiven Räder müssen zunächst die Motoren eingesetzt werden. Im Idealfall rasten die Motoren ein und sind dann schon fest. Wenn der 3D-Druck ungenau war, kann es sein, dass die Motoren nur sehr schwer einrasten oder gar nicht. Die Löcher an den Rädern, in die die Motorwellen eingesteckt werden, haben, genau wie die Motorwellen, eine abgeflachte Seite. Diese müssen zusammengebracht werden. Es kann sein, dass die Motorwelle nicht passt. In diesem Fall muss das Loch vorsichtig erweitert werden. Hier kann es schnell passieren, dass das Loch zu groß wird. Dann hilft nur noch Klebstoff.
Ältere Versionen
Gehäuse für Kettenfahrzeug
Das Gehäuse kann direkt nach dem Druck noch einige Rückstände der Stützstrukturen enthalten. Das bedeutet vor allem, dass die Löcher für die Motorwellen zu sind und dass die Aufnahme für die passiven Räder noch gesäubert werden müssen. Grundsätzlich muss man beim Entfernen von Material sehr vorsichtig sein, da man schnell zu viel weggenommen hat.
Als Erstes sollten die passiven Räder aufgesteckt werden. Dazu wird das Gehäuse hochkant flach auf die Tischfläche gelegt und dann werden die Räder aufgesteckt. Dies kann sehr schwer sein. Da die Gehäuse leicht brechen können, muss man darauf achten, keinen Druck auf die oberen Ränder auszuüben. Sind die Räder erst einmal aufgesteckt, sollten sie nicht mehr entfernt werden.
Gehäuse für Gummireifenfahrzeug
Diese Gehäuse sollten sofort einsatzbereit sein. Dennoch sollte man vorher schauen, ob es noch irgendwo Überbleibsel von Stützstrukturen gibt, die vorher entfernt werden sollten.
Die passiven Räder haben keine Gummireifen und werden mithilfe von kurzen Stiften auf den Achsen befestigt.
Aktive Räder an beiden Gehäusetypen
Die 9V-Batterie wird zwischen die Motoren gelegt. Der Clip sollte auch schon befestigt werden. Dabei ist darauf zu achten, dass sich die blanken Kabelenden nicht berühren können (Isolierband). Die Kabel der Motoren sollten durch die Halterungen für die 9V-Batterie geführt werden. Damit kann der SMARS Roboter schon auf eigenen Rädern stehen.
Anschluss der Motoren
Folgende Verbindungen werden benötigt, um die Motoren zum Laufen zu bringen:
Die 9V Batterie versorgt die Motoren mit Strom. Die vier Datenkabel IN1, IN2, IN3, IN4 steuern den Motor. Dabei sind IN1 und IN2 für den einen und IN3 und IN$ für den anderen Motor zuständig. Diese steuern die Brückenschaltung im Motortreiber. Die Richtungssteuerung erfolgt, indem die Signale an den Pins vertauscht werden. Ein Pin muss aus sein, der andere ist an. Wird dieser mithilfe der PWM-Modulation gesteuert, lässt sich auch die Geschwindigkeit regulieren. Hierfür kann dann die Bibliothek für die Motorsteuerung benutzt werden.
Der Ultraschallsensor
Der Ultraschallsensor wird von oben in die Halterung geschoben und danach wird das Gehäuse von vorne aufgesteckt. Die beiden Augen des Sensor schließen dann bündig mit dem Gehäuse ab. Die Halterung wird dann von oben auf das Gehäuse vorne oder hinten aufgeschoben und die Anschlüsse für die Kabel müssen nach oben geführt werden. Für den Betrieb des Ultraschallsensors verwendet man eine Bibliothek.
Für die neueste Version des Roboters (Theo III) gibt es verschiedene Varianten von Halterungen, die ein Verstellen und alternative Befestigungen ermöglichen.
Der komplette Roboter
Komplett zusammengebaut sollte der Roboter dann so aussehen (schematische Darstellung):
Neueste Version (Theo III)
Grundsätzlich müssen alle Bauteile auf die richtige Polung überprüft werden. Es reicht nicht, alles so zu stecken, wie es auf dem Schaubild steht, da es beim Steckbrett und den Bauteilen Abweichungen geben kann. Beim Verpolen gehen die Bauteile schnell kaputt und die Batterie läuft leer.
Deshalb lohnt es sich, alles gut zu überprüfen!
Ältere Version des Roboters (v1 und v2)
Der Kettenantrieb
Die Kette ist das mechanisch komplizierteste Element des SMARS-Roboters. Die einzelnen Kettenglieder (16 Stück pro Seite) werden mit Stücken von Filament zusammengesetzt. Dabei ist darauf zu achten, dass die Stücke nicht seitlich herausgucken und am Gehäuse hängenbleiben können. Eines könnte ein Stück heraus stehen bleiben, um die Kette einfacher aufmachen zu können.
Die Kette darf weder zu stramm noch zu locker sein. Eine zu kurze Kette zieht die Räder zusammen und der Motor kann diese Reibung nicht überwinden. Eine zu lockere Kette spurt leicht aus und setzt sich dann auf die Rauten auf den Rädern. Dann wird die Spannung auch zu stark. Es kann eine ganze Weile dauern, bis man eine gut funktionierende Kette zusammengebaut hat.
Außerdem werden sich die beiden Ketten nicht gleich schnell drehen, da die Motoren nicht miteinander synchronisiert sind. Hier kann man versuchen, die beiden Seiten mit unterschiedlichen Geschwindigkeiten zu betreiben, bis der Roboter möglichst geradeaus fährt.
Unterschiedlich lange Kettenglieder
Um die Kettenlänge anzupassen, gibt es unterschiedlich lange Kettenglieder. Diese sollten eins nach dem anderen in die Kette eingefügt werden, bis die richtige Länge erreicht ist. Zuviele Kettenglieder, die nicht die Standardlänge haben, können auch zu Problemen führen, da sie nicht mehr passgenau auf den Rädern sitzen.
Normale Länge
Die normal langen Kettenglieder sind an der vorderen Kante rechtwinklig geschnitten.
kürzere Länge
Die etwas kürzeren Kettenglieder haben auf der linken Seite eine Fase.
längere Länge
Und die längeren Kettenglieder sind rechts gefast.
Elastische Kette
Alternativ gibt es auch Ketten aus TPU, die elastisch sind.
Der Zusammenbau Crawlys
Crawly ist ein Roboter, der ähnlich wie eine Krabbe kriecht, aber mit nur vier statt acht Beinen.
Die Herausforderung liegt bei Crawly in der Gestaltung eines natürlichen Gangs.
Der komplette Crawly
Komplett zusammengebaut sieht Crawly so aus.
Der Prototyp des Bewegungsablaufs sieht so aus:
Zusammenbau der Beine
An den Beinen muss eventuell die Unterstützungsstruktur des 3D-Drucks noch entfernt werden. Das Bild oben zeigt, wie die Teile zusammengesetzt werden müssen.
2 Beine am Gehäuse befestigen
Der Schenkel muss wie eine Klammer auf den Servomotor gesetzt werden. Dabei aufpassen, dass nicht zu viel Druck ausgeübt wird.
3 Anschlüsse und Software
Es ist sinnvoll, die Servomotoren in einer vernünftigen Reihenfolge anzuschließen. Ich habe mit dem Bein links hinten angefangen (Pin 0) und bin dann im Uhrzeigersinn vorgegangen. Dabei kam der Hüftmotor immer vor dem Kniemotor.
Bibliotheken für die verschiedenen Teile des Roboters mit Beispielcode für eine Vorwärtsbewegung sind in der robotlibrary
integriert.
Zusammenbau von Walky
Der komplette Walky
Komplett zusammengebaut sieht Walky so aus:
Der Prototype des Bewegunsablaufs sieht so aus:
1 Zusammenbau der Beine
2 Beine am Gehäuse befestigen
3 Anschlüsse und Software
Bibliotheken für die Roboter
Micropython Software-Bibliotheken für den Betrieb der Roboter.
Motorsteuerung
Speichere diesen Code auf dem Pico unter dem Namen "motor.py".
Motorbibliothek
from machine import Pin, PWM
import utime
MIN_DUTY = 0
MAX_DUTY = 60000
MAX_SPEED = 100
MIN_SPEED = 30
class Motor:
'''This class manages the motor. Don't edit!'''
def __init__(self, pinNo):
self.gpio = pinNo
self.speed=0
self.forward=True
self.pwm1=PWM(Pin(pinNo))
self.pwm1.freq(50000)
self.pwm1.duty_u16(0)
self.pwm2=PWM(Pin(pinNo+1))
self.pwm2.freq(50000)
self.pwm2.duty_u16(0)
self.speed_offset = 0
def set_speed(self,s):
'''Sets the speed of the motor. Checks for sensible input.'''
if s + self.speed_offset <= MIN_SPEED:
s = 0
self.reset_offset()
elif s + self.speed_offset >= MAX_SPEED:
s = MAX_SPEED
self.pwm1.duty_u16(int(MAX_DUTY*(s+self.speed_offset)/100))
self.speed=s
def change_speed(self,sc):
'''This defines an offset to the speed in motor. It is used with the remote control to turn the robot.'''
if self.speed + sc > MIN_SPEED and self.speed + sc < MAX_SPEED:
self.speed_offset += sc
self.set_speed(self.speed)
def reset_offset(self):
self.speed_offset = 0
def off(self):
self.pwm1.duty_u16(0)
self.speed = 0
def set_forward(self,forward):
'''Sets the motor to forward or backward without changing the speed. '''
if self.forward==forward:
return
self.pwm1.duty_u16(0)
self.pwm1,self.pwm2=self.pwm2,self.pwm1
self.forward=forward
self.set_speed(self.speed)
Beispiel für die Anwendung dieser Bibliothek
Kopiere diesen Code in eine andere Datei auf dem Pico, z. B. „motortest.py“.
from motor import Motor
from utime import sleep, sleep_ms
motor = Motor(12)
motor.set_speed(70)
motor.set_forward(True)
sleep(1)
motor.off()
Ultraschallsensor
Ultraschallbibliothek
Speichere diesen Code auf dem Pico unter dem Namen "ultrasonic.py".
from machine import Pin
from time import sleep
import utime
class Ultra:
'''This class manages the ultrasonic sensor. It returns the distance to an obstacle in cm. '''
def __init__(self, pinNo):
self.trigger = Pin(pinNo, Pin.OUT) # to trigger a sound impulse
self.echo = Pin(pinNo+1, Pin.IN) # records the echo of the trigger pulse
def get_dist(self):
'''This returns the measured distance in cm. (float)'''
timepassed = 0
signalon = 0
signaloff = 0
self.trigger.low()
utime.sleep_us(2)
self.trigger.high()
utime.sleep_us(5)
self.trigger.low()
while self.echo.value() == 0:
signaloff = utime.ticks_us()
while self.echo.value() == 1:
signalon = utime.ticks_us()
timepassed = signalon - signaloff
distance = round((timepassed * 0.0343) / 2, 2)
# print("The distance from object is ", distance, "cm.") # for debugging purposes uncomment the line.
utime.sleep_ms(10) # Wait necessary or program halts
return distance
Beispiel für die Anwendung dieser Bibliothek
Kopiere diesen Code in eine andere Datei auf dem Pico, z. B. „ultratest.py“.
from ultrasonic import Ultra
from utime import sleep, sleep_ms
us = Ultra(16)
while True:
print(f"gemessene Entfernung: {us.get_dist()} cm.")
sleep(1)
Zum Fahren siehe Motorsteuerung.
Infrarotsteuerung
Ein Infrarotsensor kann zum Erkennen von Hindernissen oder der Verfolgung einer schwarzen Linie genutzt werden. Die folgende Klasse steuert den Sensor.
from machine import Pin,Timer
import micropython
micropython.alloc_emergency_exception_buf(100)
class IR:
'''This class manages the IR-sensor. Write your code in Robot.ir_detected()'''
def __init__(self, pinNo,callback_func):
self.out = pinNo
self.ir_detected = callback_func
self.ir = Pin(pinNo, Pin.IN, Pin.PULL_UP)
self.ir.irq(trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING, handler=self.obstacle)
self.detected=False
self.timer = Timer()
def reset_detected(self,t):
self.detected = False
def obstacle(self, pin):
'''This is called on any change in the IR-sensor. '''
if not self.detected:
self.ir_detected(pin,self.out)
self.detected = True
self.timer.init(mode=Timer.ONE_SHOT, period=100, callback=self.reset_detected)
Der Code muss unter dem Dateinamen „infrared.py“ auf dem Pico gespeichert werden.
Der Infrarotsensor wird folgendermaßen im eigenen Programm eingebunden. Das Beispiel ist für zwei Infrarotsensoren.
from infrared import IR
IR_PIN_LEFT=0
IR_PIN_RIGHT=1
def ir_detected(pin, pinno):
print(f"Pin: {pin}, pin number: {pinno}")
if pinno == IR_PIN_LEFT:
print("links")
elif pinno == IR_PIN_RIGHT:
print("right")
ir_left = IR(0, ir_detected)
ir_right = IR(1, ir_detected)
Servosteuerung
Der Ultraschallsensor kann auch mit einem Servomotor drehbar gemacht werden. Die folgende Klasse steuert den Servomotor:
from machine import Pin, PWM
import utime
class Servo:
'''This class manages the servo motor that turns the ultrasonic sensor. You need a servo motor installed to get use out of this.
Don't use directly or edit.'''
def __init__(self,pin):
self.pin=PWM(Pin(pin))
self.pin.freq(50)
self.min=1350
self.max=8100
self.angle=0
def set_angle(self,a):
'''If installed, the servor motor will set the angle of the ultrasonic sensor. 90° ist straight ahead.'''
if a > self.angle:
for i in range(self._get_duty(self.angle),self._get_duty(a)):
self.pin.duty_u16(i)
elif a < self.angle:
for i in range(self._get_duty(self.angle), self._get_duty(a),-1):
self.pin.duty_u16(i)
self.angle = a
utime.sleep_ms(4)
def _get_duty(self,angle):
'''Internal function. Calculates the PWM duty for the given angle.'''
return round((self.max-self.min)/180*angle+self.min)
Dieser Code muss unter dem Dateinamen „servo.py“ auf dem Pico gespeichert werden.
Das komplette Modul "robotlibrary"
Dieses Modul, das von Github heruntergeladen werden kann, steuert die Roboter mit allen Peripheriegeräten (Motoren, Sensoren). Dazu muss das Paket heruntergeladen und entpackt werden. Das Verzeichnis „robotlibrary“ muss dann auf den Pico hochgeladen werden.
SMARS Roboter "Theo III"
Um das Modul zu benutzen, muss nur folgender Import gemacht werden: from robotlibrary.robot import Robot
.
Ein kurzes Codebeispiel, wie der Roboter funktioniert, ist in der Quelldatei zu finden.
Oder hier ein Beispiel für die Benutzung des Servomotors.
from robotlibrary.robot import Robot
from time import sleep,sleep_ms
try:
r = Robot(False)
r.set_angle(0)
sleep_ms(500)
r.set_angle(180)
sleep_ms(500)
r.set_angle(90)
r.set_speed(80)
while True:
while r.get_dist() > 15:
pass
r.emergency_stop()
sleep_ms(400)
r.set_speed_instantly(80)
r.spin_before_obstacle(20)
r.set_forward(True)
r.set_speed(80)
except:
r.emergency_stop()
print("Robot stopped")
Crawly
Crawly ist ein Roboter, der, ähnlich wie eine Schildkröte auf vier Beinen kriechen kann. Um Crawly zu steuern, muss nur folgender Import gemacht werden: from robotlibrary.crawly import Crawly
Ein kurzes Codebeispiel, wie der Roboter funktioniert, ist in der Quelldatei zu finden.
Under construction:
Walky
Walky ist ein Roboter, der, ähnlich wie ein Hund, auf vier Beinen laufen kann. Um Walky zu steuern, muss nur folgender Import gemacht werden: from robotlibrary.walky import Walky
Ein kurzes Codebeispiel, wie der Roboter funktioniert, ist in der Quelldatei zu finden.
Die Dokumentation für die Bibliothek ist unter docs
zu finden oder kann hier heruntergeladen werden: robotlibrary.pdf
Dokumentation
Documentation for robotlibrary/robot.py
Robot
This is the central class which manages and uses all the other components of the robot. The parameters are defined in config.py
_drive
This abstracted driving function is only called locally by the other functions with better names. It accelerates and decelerates to make driving more natural. Do not call directly!
_drive_instantly
This abstracted driving function is only called locally by the other functions with better names. It sets the speed immediately. Do not call directly!
set_speed_instantly
Sets the new speed immediately. Doesn't change the driving mode of the robot. :param s: the speed you want to set.
set_speed
Sets the new speed and accelerates and decelerates. Doesn't change the driving mode of the robot. :param s: the speed you want to set.
set_forward
Sets the direction of the robot. True means forward. :param f: True for forwards and False for backwards.
spin_right
Spin right indefinitely.
spin_left
Spin left indefinitely.
turn_right
This turns the robot to the right without it spinning on the spot. Each call makes the turn steeper.
turn_left
This turns the robot to the right without it spinning on the spot. Each call makes the turn steeper.
go_left
With Meccanum wheels the robot goes sideways to the left.
go_right
With Meccanum wheels the robot goes sideways to the right.
turn
This turns the robot right or left. Is mostly used by the remote control. :param turn: positive or negative value. Higher values mean steeper turn.
go_straight
Lets the robot go straight on. Usually called when a turn shall end.
spin_before_obstacle
This spins until the distance to an obstacle is greater than the given parameter distance. :param distance: The distance
toggle_spin
Toggle turn for the given duration. With each call the opposite direction(clockwise / anti-clockwise) is used. :param d: The duration for the turn in milliseconds.
random_spin
Randomly turn for the given duration. :param d: The duration for the turn in milliseconds.
stop
Stop the robot slowly by deceleration.
emergency_stop
Stop the robot immediately.
ir_detected
If implemented this method is called when the IR-sensor has detected a change. Fill in your code accordingly.
get_dist
Get the distance from the ultrasonic sensor.
set_angle
If implemented, turn the servo motor with the ultrasonic sensor to the given angle. :param a: The angle that is to be set.
get_smallest_distance
This returns the angle of the ultrasonic sensor where it measured the smallest distance
get_longest_distance
This returns the angle of the ultrasonic sensor where it measured the longest distance
Documentation for robotlibrary/config.py
Module
This defines the parameters for the motors.
MAX_DUTY: Set to lower than the maximum not to overload the motors. Absolute maximum is 65535. MIN_DUTY: Set this to the minimum duty cycle that the motor needs to start moving. MIN_SPEED: Only 0 is making sense here but if you want you can change that. Must be above 0 though. MAX_SPEED: If you want another scale than 0-100, set the maximum here.
DEBOUNCE_WAIT: This defines the waiting time for the debouncing of the buttons. Leave as it is if you don't know what it means.
WHITE_DETECTED: Use these constants to check for white or black with the IR-sensor. Don't change! BLACK_DETECTED: Use these constants to check for white or black with the IR-sensor. Don't change!
Motors and ultrasonic sensor must use consecutive pins. so, f. ex. the left motor uses pins 12 and 13. Use >None< if you don't use the device. MLF and LRF are for four wheel drive. ML: pin number for left motor (or left rear motor for four wheel drive). MR: pin number for right motor (or right rear motor for four wheel drive). MLF: pin number for left motor (or left front motor for four wheel drive). Use None if not used. MRF: pin number for right motor (or right front motor for four wheel drive). Use None if not used. US: pin number for the ultrasonic sensor. Use None if not used. IR: pin number for the infrared sensor. Use None if not used. SERVO: pin number for the servo motor. Use None if not used.
JS_X_MEDIAN JS_Y_MEDIAN JS_MAX_DUTY JS_MIN_DUTY: These define the parameters for the joystick. You need to calibrate the numbers. Look at joystick.py for details.
ROBOT_NAME: You need to set a custom name if you use a remote control.
SERVO_MIN_DUTY: Only change if the servo doesn't move the required 180°. SERVO_MAX_DUTY: Only change if the servo doesn't move the required 180°.
Fehlerbehebung
Motoren
Motoren drehen sich nicht oder nur sehr schwer
Bei Kettenrobotern: Die Ketten sind zu stramm oder zu locker
Wenn die Ketten zu stramm sind, dann hat der Motor nicht genügend Kraft sich zu drehen. Ein Anzeichen dafür ist, wenn die Räder von der Ketten zusammengezogen werden, sodass die Achsen auf einer Seite nicht parallel sind. In diesem Fall sollten längere Kettenglieder eingefügt werden, bis die Kette gut sitzt.
Sind die Ketten zu locker, kann die Kette aus der Führung springen und auf den Führungsknubbeln aufsitzen. Dann muss die Kette wieder strammer gemacht werden.
Die Motoren drehen sich auch ohne Kette nicht
- Drehen sich beide Motoren nicht, kann es sein, dass die Stromversorgung nicht richtig angeschlossen ist. Es ist unbedingt darauf zu achten, dass der Motortreiber nicht falsch herum gepolt wird.
- Dreht sich nur ein Motor nicht, ist zunächst zu überprüfen, ob die Steuerpins auch korrekt mit dem Motortreiber verbunden sind.
- Ist dies der Fall, dann sollte überprüft werden, ob an den Anschlüssen für den Motor auch eine Spannung anliegt.
- Ist dies nicht der Fall, ist der Motortreiber eventuell kaputt.
Ein Motor dreht sich immer falsch herum
- Die Steuerpins sind verpolt
- Der Motor ist am Motortreiber verpolt.
- Es ist ein Fehler im Code
Es ist grundsätzlich sinnvoll, die Verkabelung der Steuerpins zu vertauschen, da man hierfür nicht mit dem Schraubendreher arbeiten muss. Das Ergebnis ist dasselbe.
Sobald der Pico Strom bekommt, dreht sich ein Motor und hört auch nicht mehr auf
- Der Pico ist womöglich beschädigt. Diesen mit dem Testprogramm und der Testplatine auf korrekte Funktion überprüfen.
Testprogramm
from machine import Pin, PWM
import utime
# Bestimme, welche Pins getestet werden sollen. Die Platine hat sieben LEDs. Somit können 7 Pins gleichzeitig getestet werden.
p_start = 11
p_end = 16
pins = list()
for i in range(p_start,p_end):
pins.append(PWM(Pin(i)))
# Die LEDs werden initialisiert. Hier nichts ändern.
#leds=[PWM(Pin(pins[0], Pin.OUT)), PWM(Pin(pins[1], Pin.OUT)), PWM(Pin(pins[2], Pin.OUT)), PWM(Pin(pins[3], Pin.OUT)), PWM(Pin(pins[4], Pin.OUT)), PWM(Pin(pins[5], Pin.OUT)), PWM(Pin(pins[6], Pin.OUT))]
# PWM Frequenz wird eingerichtet.
print("Der Test beginnt.")
for p in pins:
p.freq(2000)
# Zu Beginn werden alle LEDs ausgeschaltet.
for p in pins:
p.duty_u16(0)
# Die LEDs werden einzeln langsam aufgeblendet und abgeblendet. Gehen Sie ruckartig an und aus, dann ist PWM defekt.
for p in pins:
for i in range (65535):
p.duty_u16(i)
for i in range (65535, 0, -1):
p.duty_u16(i)
utime.sleep_ms(800)
# Alle LEDs blinken dreimal schnell hintereinander
for x in range(3):
for p in pins:
p.duty_u16(65535)
utime.sleep_ms(100)
for p in pins:
p.duty_u16(0)
utime.sleep_ms(100)
# Alle LEDs werden auf einer niedrigen Helligkeitsstufe angeschaltet und bleiben an.
for p in pins:
p.duty_u16(10000)
print("Der Test ist fertig.")
Der Ultraschallsensor funktioniert nicht
- Der Ultraschallsensor funktioniert am besten, wenn das Hindernis aus einem harten Material besteht, dass den Schall gut reflektieren kann. Ebenso kann es sein, dass das Hindernis sehr schräg steht und damit den Schall in eine andere Richtung reflektiert.
- Der SMARS reagiert nicht auf Hindernisse. In diesem Fall ist zunächst zu prüfen, ob auf Softwareseite alles in Ordnung ist. Zum Beispiel könnte der Code einer anderen Gruppe getestet werden, bei denen es funktioniert.
- Im nächsten Schritt sollte der Ultraschallsensor getestet werden. Dazu muss das Messprogramm von Thonny aus gestartet werden, damit die Messergebnisse angezeigt werden. Werden keine Messergebnisse gezeigt, dann zum nächsten Schritt.
- Es muss überprüft werden, ob die Pins für Trigger und Echo auch nicht vertauscht sind. Die beiden Pins lassen sich ohne Gefahr für den Pico vertauschen, sie funktionieren aber natürlich nur, wenn sie richtig herum sind.
- Funktioniert der Ultraschallsensor bei Start des Programms über Thonny aber nicht beim autonomen Start, dann muss überprüft werden, ob der Kondensator auch an der richtigen Stelle steckt.
- Wird das Programm als main.py ohne Thonny ausgeführt, kann es sein, dass der Code Fehler enthält, wenn er nicht vorher gut getestet war. Dann stürzt das Programm natürlich ab und es sieht nur so aus, als ob der Ultraschallsensor nicht funktionieren würde.
- In einigen Fällen hat der Ultraschallsensor auch Funktionsstörungen, die nach einigen Minuten Pause wieder behoben sind.
3D-Konstruktionsdateien für die Roboter
Die Dateien für "Theo III" sind nicht mit der originalen Version des SMARS-Roboters kompatibel, da das Gehäuse leicht verändert wurde. Die Dateien (.FCSTD) sind mit dem Programm "Freecad" zu bearbeiten.
Die Halterungen für "Theo III" sind mit den anderen Robotern "Crawly" und "Walky" kompatibel.
STL-Dateien können direkt in einem Slicer für den Druck auf einem 3D-Drucker vorbereitet werden.
Gute Tutorials für die Benutzung des Programms Freecad gibt es z.B. hier: https://www.youtube.com/@stolz3d
Das Chassis
Das Chassis (Theo III)
Das Modell enthält die nötigen Stützstrukturen und muss daher ohne weitere Stützstrukturen gedruckt werden.
Diese Version des Roboters hat etwas stärkere Vorder- und Rückseiten und einen Schlitz für einen Schalter.
Des Weiteren stehen die Räder 2 mm näher zusammen, was reichen sollte, um die Kettenspannung genügend zu reduzieren, damit sich die Motoren frei drehen können. Es könnte eher das Problem sein, dass die Ketten zu locker sind.
Die Steckbrettplatte
Die Steckbrettplatte für den Theo III
Auf der Steckbrettplatte wird das Steckbrett und der Motortreiber befestigt. Der Druck erfolgt ohne Stützstrukturen.
Diverse Halterungen
Konstruktionsdatei für den Ultraschallsensor-Halter
Der Druck erfolgt ohne Stützstrukturen.
Gehäuse für den Ultraschallsensor (Theo III) | druckbare Datei
Halterung für den Ultraschallsensor (Theo III) | druckbare Datei
Ultraschallhalter für allgemeinen Halter
Konstruktionsdatei für den IR-Sensor-Halter:
Der Druck erfolgt ohne Stützstrukturen. Die beiden Teile müssen korrekt auf der Druckplatte ausgerichtet werden. Dazu wird der allgemeine Halter benötigt.
IR sensor - Druckdatei mit richtiger Ausrichtung: IR-sensor.stl
Für diejenigen, die den IR-Halter selber konstruieren wollen, hier ist eine Konstruktionsskizze, die man benutzen kann:
Konstruktionsdatei für den Motor- und Batteriehalter
Motor- und Batteriehalter | druckbare Datei
Bemaßungen für Motor- und Batteriehalter
Allgemeine Halter
Allgemeiner Halter - Druckdatei: SMARS_v3_general_holder.stl
Allgemeiner Halter hoch - Druckdatei: SMARS_v3_general_holder_high.stl
Allgemeiner Halter hinten - Druckdatei: SMARS_v3_holder_rear.stl
Allgemeiner Halter für 2 IR-Sensoren
Allgemeiner Halter für 3 IR-Sensoren
Bemaßung der Halterung für eigene Designs.
Antrieb
Original Bauteile
Die folgenden Bauteile sind unverändert vom Original übernommen worden.