# data[].attributes.body
Zwei Wochen bevor Praktikumsbeginn, darf ich das Mindstorms Robot Inventor Kit bereits nach Hause nehmen, um mich etwas darin einzuarbeiten.

# data[].attributes.body
Seine ersten Gehversuche macht mein Tricky bereits am Empfang der Stiftung Weizenkorn.

# data[].attributes.body
Nach seinen ersten Schritten lernt Tricky einer grünen Linie zu folgen. Ist die Linie dick genug, macht er das dann auch, wenn auch etwas im zick zack Kurs. Das lernt er später noch besser!

# data[].attributes.body
Am Abend Zuhause angekommen gehts weiter. Tricky muss aber noch lernen nicht vom Tisch zu stürzen.

# data[].attributes.body
Ich stelle Florian vor was mein Tricky alles schon so für Tricks gelernt hat.

# data[].attributes.body
Wir einigen uns darauf, dass ich mich in meinem Tutorial auf das programmieren in Python beschränke, und nicht auf die visuelle Programmierung eingehe.

# data[].attributes.body
Der Roboter fährt geradeaus auf ein Hinderniss zu, bis er ihm zu Nahe kommt, dann legt er den Rückwertsgang ein,

# data[].attributes.body
Jetzt kann Tricky auch einer dünneren schwarzen Linie folgen, ohne zick zack kurs, und schafft sogar enge Kurven (meistens).

# data[].attributes.body
Sobald ich einen Arbeits Laptop bekomme, kann ich anfangen in Word mein Tutorial, dass ich bis jetzt nur in einem Online Texteditor auf dem Surface Tablet angefangen habe zu schreiben, schön zu designen und strukturieren.

Bis dahin, bringe ich Tricky die Basketball Challenge bei.

# data[].attributes.body
Tricky kann jetzt Basketball spielen!

Etwas frustrierend war lange einen Fehler im Code zu suchen, nur um dann festzustellen, nach gut 30 Minuten, dass eine Klammer doppelt vorhanden war. Aber Ende Gut Alles Gut, Tricky kann jetzt Basketball!

# data[].attributes.body
Mithilfe des Gyroskops und nur einer einzigen Funktion für links sowie Rechtskurven, kann Tricky jetzt auf die Grad genaue Drehungen vollziehen.

# data[].attributes.body
Jetzt da ich Laptop und zwei grosse Bildschirme habe, kann ich voll loslegen mit dem Tutorial schreiben.

Das bisher geschriebene habe ich nun in ein besseres Layout gepackt, wodurch das ganze gleich übersichtlicher wirkt.

# data[].attributes.body
Heute habe ich den Roboter dazu programmiert, Basketball zu spielen, genaue Kurven zu fahren, und Hindernissen auszuweichen.¨

Morgen versuche ich das heute programmierte im Tutorial zu beschreiben, sowie das bereits geschriebene weiter auszubauen.

# data[].attributes.body
Ich konnte mein Tutorial etwas ausbauen, sowie zusätzlich das Basketball sowie das Kurven mit Funktionen fahren, erklären.

Beim Hindernis ausweichen habe ich gemerkt, dass der Roboter manchmal abstürzt, ich aber noch nicht herausgefunden habe wieso dies passiert. Sicher etwas dass ich mir morgen genauer anschaue.

# data[].attributes.body
Mein Tutorial weiter ausbauen. Die einzelnen Denk und Programmierschritte noch besser erklären, auch das Layout noch etwas verbessern.

Dann auch das Programm für Hindernisse ausweichen auf vordermann bringen, damit dieses nicht mehr abstürzt. Falls möglich.

# data[].attributes.body
Da ich heute einen guten Teil der Zeit mit der Fehlersuche im Programm verbracht habe, wäre es wahrscheinlich sinnvoll ein Kapitel im Tutorial genau dem zu widmen: Was tun bei Fehlern? /Fehlerbehebung.

# data[].attributes.body
Mit der Struktur und Umfang des Tutorials bin ich zufrieden. Ich denke mir die Struktur macht so Sinn, und auch vom Umfang her denke ich ist es ganz gut so als erster Einstieg in die Robotik/Python Programmierung.

So habe ich meine Arbeit in diesem zweiwöchigen Praktikum etwas abgesteckt, habe jetzt einen guten Überblick wie mein Tutorial von Struktur, Inhalt, und Umfang aussehen wird.

Inhaltlich hoffe ich kann man den einzelnen Programmierschritten soweit folgen, allerdings sollte ich das ganze noch verständlicher und detailierter herüberbringen.
Gerade jemand der kein Englisch kann, und nicht auf die Dokumentation in der Lego Entwicklungsumgebung zurückgreifen kann, und zusätzlich noch gar nie mit Programmierung in Kontakt getreten ist, dürfte es so noch schwer haben dem Tutorial zu folgen. Ich hoffe dies noch besser hinzukriegen,.

# data[].attributes.body
Um besser erklären zu können um was es sich bei z.B: einer While Schlaufe, oder einer If Bedingung, handelt, habe ich das Tutorial um ein paar grafische Abbildungen erweitert. Ich hoffe das hilft dem Verständnis.

# data[].attributes.body
Ich komme immer noch nicht draus wieso mir der Roboter manchmal abstürzt. Ich habe einen Verdacht an was es liegen könnte, kann den Fehler aber nicht beheben momentan.

Zuerst versuche ich nun noch die letzte Aufgabe für den Roboter zu meistern, das Noten lesen und musizieren.

# data[].attributes.body
Tricky kann jetzt farblich codierte Noten lesen, und diese wiedergeben.

Ich versuche jetzt das im Tutorial zu beschreiben.

# data[].attributes.body
Jetzt habe ich mir den Code zum Hindernis ausweichen noch mal gut angeschaut. Bis auf einen Fehler der aus irgendeinem Grund entsteht sobald eine Kurve von 180 Grad gemacht wird, wobei sich der Roboter einfach ewigs im Kreis dreht (was für mich keinen Sinn ergibt)
läuft das Programm jetzt.

Zur Umgehung von diesem Fehler macht der Roboter halt jetzt einfach nur eine 179 Grad Drehung.

Keine elegante Lösung, aber durchaus praktikabel für auf weiteres.

# data[].attributes.body
Jedes Kapitel in meinem Tutorial kommt mit entsprechendem Quellcode der Programmieraufgabe.

Da ich ja schon einiges auf Video dokumentiert habe, lege ich auch jedem Kapitel ein kleines Video bei, das den Roboter in Aktion zeigt, denke ich mir.

Frage aber nächste Woche noch Luca und Florian, ob sie dies auch für eine gute Idee halten.

# data[].attributes.body
Ich bin ganz gut vorangekommen diese Woche, und Tricky hat viel neues gelernt.

Auch das Tutorial ist jetzt so in seiner Rohfassung "fertig", aber sicher noch stark verbesserungs und ausbaufähig,

Nächste Woche würde ich mir hierzu gerne Feedback einholen, und dann verbessern und ausbauen.

# data[].attributes.body
Gerne würde ich mir zu meinem Tutorial ein kleines Feedback einholen.

# data[].attributes.body
Heute habe ich für jede Aufgabe im Tutorial ein kurzes Video aufgenommen, welches den Roboter in Aktion zeigt.

Dann habe ich das Tutorial weiter ausbauen können. Ich hoffe, dass die ersten Kapitel die ich heute bearbeitet habe so auch für Programmier Neulinge verständlicher sind.

# data[].attributes.headline
Was behandelt mein Tutorial, und vorallem; Was nicht?

# data[].attributes.subject
Was behandelt mein Tutorial, und vorallem; Was nicht?

# data[].attributes.body
Ein paar Gedanken/Notizen dazu:

Mein Tutorial kann kein klassisches programmier Tutorial sein, sondern ist ganz darauf fokusiert: wie programmiere ich einfach handelnden lego roboter?

Also kein Einstieg mit viel Mathe und genauen Erklärungen zu was ist eine Variable, was ist eine Schleife, etc.

Tutorial kann als Auffrischung dienen, kann aber von mir als Programmier-Anfänger keine umfassende Einführung in Python Programmierung allgemein sein.
.
Das Tutorial dient dazu einen Einblick in die Python Programmierung der Lego Roboter zu bieten, ein total Anfänger im Programmieren sollte zumindest fähig sein den Code damit nachzuvollziehen.

Um programmieren richtig zu lernen wäre ein richtiges Python Tutorial von Vorteil (z.b. von codecademy.com), sowie Beschäftigung mit der in Lego Mindstorms Entwicklungsumgebung integrierten Dokumentation.

# data[].attributes.headline
Idee für komplexere Aufgabe mit 2 Robotern

# data[].attributes.subject
Idee für komplexere Aufgabe mit 2 Robotern

# data[].attributes.body
Roboter soll Ball nach Farbe sortieren.

Falls man zwei Roboter für die Aufgabe zur Verfügung hat, könnte der einte als „Ball Ausgabe Maschine“ funktionieren. Der zweite Roboter als Ball Transporteur und nach Farbe Sortierer.

Roboter 1 gibt beliebigen Ball aus, sobald Roboter 2 in davor steht.

Roboter 2 fährt bis zur grünen Linie, Ball wird ausgegeben.

Roboter misst Farbwert des Balles, und folgt schwarzer Linie bis zu entsprechender Farbe von Körben zum Sortieren, wo er den Ball entsprechend seiner Farbe Ablegt.

# data[].attributes.body
Inspiriert von Luca recherchiere ich ein wenig wie man zwei Roboter miteinander verbinden würde, sprich über Bluetooth miteinander kommunizieren lassen würde.

# data[].attributes.attachment_link.readable_text
The hub2hub library is not part of the original firmware of either the Robot Inventor hub or the SPIKE Prime hub. In the official SPIKE Prime firmware, a low-level ubluetooth library is available to be able to directly communicate between hubs. The documentation of this module can be found here: ubluetooth documentation.

The main goal of the hub2hub library is to simplify the python code required to setup and maintain a BLE connection between hubs in contrast to the low-level ubluetooth library available in the official firmware. Installation of the library and writing programs that use it are both possible via the official LEGO Education SPIKE Prime app, as explained below.

The following steps guide you through the process to install the hub2hub library. These steps should be repeated for each of the hubs that will be used in the BLE network.

Step 1:

If you did not update your SPIKE Prime software yet, install one of the latest versions of the SPIKE Prime app (1.3.4 or 1.3.3) and connect your device. If the app asks for a hub update, perform the hub update.

Warning

This library does not work when using the MINDSTORMS Robot Inventor app. Due to a firmware difference, the Bluetooth module is not available when using the MINDSTORMS Robot Inventor App and corresponding firmware. Luckily you can just connect your MINDSTORMS hub to the SPIKE Prime app and update the SPIKE PRIME Firmware on the hub.

Step 2:

Download and open the project: Install_hub2hub_v003.llsp.

Step 3:

Set the SPIKE Prime execution mode in download mode, and select an unused project slot.

Step 4:

Run the project by pressing the play button and wait until the hub is powered down. (if you use a USB cable to connect the hub, the hub will probably restart automatically)

Step 5:

Installation is successful. The hub2hub library is now installed on your hub. You can now safely use the slot you used for this installation for a new project.

Warning

Firmware updates of the hub are likely to remove the library from the filesystem of the hub. Hence, this procedure should be repeated if a firmware update removed the library from the hub.

Step 6: (optional)

To test if the library is functioning properly try the example projects: parent_example.llsp and child_example.llsp on two seperate hubs.

This library is still actively developed. There are still some known issues:

The hubs do not automatically disconnect when a program is stopped. To disconnect the hubs you need to restart the hubs. In other words: after each time you run the project restart the hubs before you run the program again

It might take a few tries to get a hub connected to a large BLE network.

If you run in any additional issues you can report them here.

Before introducing the commands from the hub2hub library first some background information on the communication protocol used by the hub2hub library is required.

In a typical BLE network there exist one parent device and one or more child devices. This parent device can send a request to all child devices in the network. An example of a request could be: Set left motor speed to 50. After sending this request the parent will wait on a response from the child device if the message was successfully received. The child device could respond with for example motor speed set to 50. After this, the parent can send a new request to the same hub or any other hub. This protocol ensures only one hub is sending messages, thereby not overloading the BLE network with messages. This protocol also allows for bidirectional communication, since the child hub can respond with any message to the root, with the only limitation that the root always has to send a request first.

The MINDSTORMS Robot Inventor and SPIKE Prime hubs are only able to connect to 3 child devices and 1 parent device. For different projects with different numbers of hubs, this will lead to different BLE network structures. Below the star network topology is explained for connecting up to 4 hubs. An extension of this network is the Tree network which does not limit the number of hubs connected to the parent. (At the moment the Tree network structure is still in an experimental phase, the reliability of connections in this type of networks is not at the desired level yet)

Star network

In a star network there is one parent hub and a maximum of three child hubs, with an address as given in the Figure below.

Tree network

The tree network is an extension of the star network. In this network structure, the child hubs can act as both a child and as a parent hub to three other child hubs. See the figures below for example networks.
Example of a tree network with one intermediate level: Example of a tree network with two intermediate levels:
This network can be viewed as a family tree, where the oldest grandfather (root parent) can send requests to his complete offspring. Requests to a child not directly connected to the root parent will be routed to the child, via the parents in the intermediate levels. Similarly, the response of the child is routed via the same path.

In a tree network different levels can be distinguished:

Level 0: one root parent, this is the parent that can send request to all other child hubs.

Level 1, ..., N-1 intermediate levels: the hubs are both a child and a parent or only a child

Level N: The highest level where the hubs are only a child

The addresses of the hubs follow the following rules:

* Level 0: 000.., the number of zeros is the number of layers except the root layer
Level 1: 100..., 200..., or 300...

Level 2: the child hubs connected to one of the hubs from Level 1: copy the first digit of the parent hub, and add 1, 2, or 3 behind this one. For the hubs connected to the hub with address 100..., its child hub addressess are 110..., 120..., and 130....

Level 3: similarly to level 2 copy the first 2 digits of the parent and add 1, 2, or 3.

Setup the BLE network

import hub2hub

The only thing necessary from the hub2hub library is the BLEnetwork, this can be imported using
Example code:
from hub2hub import BLEnetwork

Define network

A network can be defined as a dictionary with key value pairs representing the name of the hub (string) as key and its address in the network (string) as the value.
Example code:
network = { ## Name: Address 'A': '0', 'B': '1', 'C': '2', 'D': '3', }

BLEnetwork()
BLEnetwork(name, network, state=initial_state)
Initiate the hub as part of the BLE network.
Parameters:

name (str): name of this hub in the BLE network

network (dict): the BLE network this hub operates in

state (optional): the state value can be of any type, and represents a variable that can be changed anywhere, including the on_requestand on_response methods, in the program using ble.state.

Sample code:
from hub2hub import BLEnetwork network = { ## Name: Address 'A': '0', 'B': '1', 'C': '2', 'D': '3', } ble = BLEnetwork('A', network, state=0)

connect()

Establish connection with the BLE network. First the children are connected, afterwards the parent is connected.
Sample code:
ble.connect()

is_connected()
is_connected() Returns:

bool: True if all children and parent are connected; False if one of the children or parent is not connected.
Example code:
while ble.is_connected(): print('connected to the BLE network') sleep_ms(100)

Root methods

Next the methods that can be used by the root parent are introduced

request_child
request_child(child,message,wait_for_response=True)
Send a request to a child in the network
Parameters:

message: the message that is send along with the request. The value can be of any type.

child: name of the child to which the request is send

wait_for_response: True if you expect a response message from the child, the parent cannot send new messages untill it received the response; False if the child will not respond with a message after receiving the request, the parent can send a new message directly.

Sample code:
### from the example project: parent.llsp (step 6 of installation instructions) # Create message based on button presses message = 0 if buttonL.was_pressed(): message -=1 if buttonR.was_pressed(): message +=1 # Send request to child B ble.request_child('B', message, wait_for_response=True)

set_on_response()
set_on_response(callback)
Set the function that will be executed when a response from a child is received.

Parameters:

Callback: a user defined function with the arguments: message, and the child from which the reponse originates.
Sample code:
### on_response from the example project: parent.llsp (step 6 of installation instructions) def on_response(message,child): # if response is from child 'B' if child is 'B': # update BLE state ble.state = (ble.state + message) % 12 # update Display display.show(Image.ALL_CLOCKS[ble.state]) return ble.set_on_response(on_response)

Child methods

Next the methods that can be used by all children are introduced

set_on_request()
set_on_request()
set the function that will be executed when a request from the root is received by a child.
Parameters:

callback function: this function will be executed if a request is received from the root. The parameters of this function is the message send by the parent. The callback can return a message to the parent or None (Returning None is only adviced if the parent does not require a response).
Sample code:
### on_request from the example project: child.llsp (step 6 of installation instructions) def on_request(message): # update BLE state ble.state = (ble.state + message) % 12 # Update display display.show(Image.ALL_CLOCKS[ble.state]) # Define response message response_message = 0 if buttonL.was_pressed(): response_message -=1 if buttonR.was_pressed(): response_message +=1 # respond with response_message return response_message ble.set_on_request(on_request)

Note

It is important to keep the execution time of the on_request function as short as possible. The response message to the root parent will be send after completion of the callback. Hence, during the execution of this method no other messages can be send in the BLE network.

# data[].attributes.attachment_link.title
hub2hub - Unofficial LEGO MINDSTORMS and SPIKE Prime low-level hub module documentation

# data[].attributes.attachment_link.description
The hub2hub library is not part of the original firmware of either the Robot Inventor hub or the SPIKE Prime hub. In the official SPIKE Prime firmware, a low-level ubluetooth library is available to be able to directly communicate between hubs. The documentation of this module can be found here: ubluetooth documentation.

# data[].attributes.body
sehr interessant wäre eine app programmieren zu können, die den Roboter über eine über bloothooth verbundene handy cam steuert.

Bis jetzt habe ich aber nur herausgefunden das dies möglich ist, aber noch keine gute Anleitung dafür gefunden oder Hinweise darauf wie das gelöst wurde.

# data[].attributes.body
Ich verusche mich gerade am programmieren eines Radars für Tricky. Er soll nahe Objekte wie  einen Ball erkennen können, und dann auf das nächstgelegene Objekt zufahren.

# data[].attributes.body
Das Grundprinzip hat Tricky jetzt verstanden, er dreht sich im Kreis in  kleinen Intervallen und misst nach jedem Intervall die Entfernung und speichert diese in einer Liste.

Dann wird in der Liste geschaut an welcher Stelle der niedrigster Wert ist. Tricky dreht sich dann in Intervallen an die Stelle wo der niedrigste Wert gemessen wurde, und fährt auf das Hindernis zu.

So könnten sich auch zwei Roboter im Raum "treffen", einander erkennen und aufeinander zu fahren.

Ich versuche jetzt das Konzept weiter auszubauen, bezweifle aber dass es dieses in das Tutorial schafft.

# data[].attributes.body
erklären wieso die eine 180 grad kurve zwei 90 grad kurven sind im code von funktion für genaue kurven.
nach 180 kommt eben nicht 181 sondern -179 als wert vom gyro. Zudem kommt dass sich der Roboter etwa 2-3 grad gedreht hat pro Schleifen Durchgang. So kann es passieren dass der Roboter sich einfach auf immer im Kreis dreht.  Deshalb wichtig mit dieser Funktion nicht mehr als +/- 175 Grad zu drehen. 