Demo - teuler/robotling GitHub Wiki

"robotling"-Code hochladen ...

Nachdem MicroPython auf dem HUZZAH32 installiert wurde, kann man die Demo-Software entweder mit ampy oder der pymakr-Erweiterung von Atom hochladen (siehe Installation). Im folgenden wird die pymakr-Option beschrieben.

Vorbereiten, ...

  1. WICHTIG: Zusätzlich zu den Dateien in code/robotling wird eine aktuelle Version der Treiberbibliothek robotling_lib benötigt. Diese lädt man am einfachsten als .zip-Datei von der Repository-Seite und entpackt sie im Ordner code/robotling auf dem Entwicklungs-PC (-> code/robotling/robotling_lib).

  2. Die Demo sollte mit allen Platinenversion funktionieren, empfohlen wird die Neuste. Die Version muss man der Demo mitteilen (in robotling_board_version.py):

    [...]
    # Robotling board version
    BOARD_VER = const(130)
    
  3. Die Datei hexbug_config.py enthält Parameter, die man an den eigenen HexBug-Roboter anpassen muss. Diese befinden sich im Bereich USER SECTION. Am wichtigsten sind die folgenden Einstellungen, da sie von der verbauten Hardware abhängen:

    • IR_SCAN_BIAS_F - Da der "Kopf" des Roboters beim Laufen hin und her schwenkt, aber sich dabei nicht notwendigerweise in beiden Richtungen gleich schnell dreht, kann es sein, dass der Roboter anstatt geradeaus eine Kurve läuft. Mit IR_SCAN_BIAS_F kann man versuchen, dies zu kompensieren. Zum Beispiel bewirkt ein Wert von -0.1, dass der Kopf kürzer (90%) in positiver und länger (110%) in negativer Richtung gedreht wird.
    • MIN_US_SERVO, MAX_US_SERVO - Diese Werte hängen vom verwendeten Servo ab. Die Werte müssen so eingestellt werden, dass der Sensorarm bei MIN_US_SERVO in einem 45°-Winkel nach schräg oben bzw. bei MAX_US_SERVO 45° nach schräg unten zeigt.
    • MORE_DEVICES - Hier muss man z.B. angeben, mit welchem Kompass das Board bestückt ist. Diese "Geräteliste" wird dann an die Instanz des Roboters (HexBug-Klasse) übergeben, so dass diese die entsprechenden Funktionen initialisiert. Hier ein Beispiel:
      MORE_DEVICES     = ["compass_cmps12"]
      
      ... wenn das CMPS12-Kompassmodul auf das Board gesteckt wurde, oder ...
      MORE_DEVICES    = ["lsm303", "dotstar_feather"]
      
      ... wenn das Flora LSM303-Kompassmodul auf das Board gelötet und auf den HUZZAH32 ein DotStar-Feathermodul gesteckt wurde. Auch die WLAN-Netzverbindung - falls vom Mikrocontrollermodul unterstützt - kann hier durch Hinzufügen des Strings "wlan" aktiviert werden.

    Hier der komplette Ausschnitt von hexbug_config.py mit den vom Benutzer modifizierbaren Parametern:

    [...]
    # ---------------------------------------------------------------------
    # USER SECTION
    # ==>
    #
    # Tilt-sensing
    PIRO_MAX_ANGLE   = const(25)   # Maximal tilt (i.e. pitch/roll) allowed
                                   # .. before robot responds
    
    # Obstacle/cliff detection
    #
    # Scan positions as list of head turn durations in [ms] and as a list
    # of approx. angular positions ([°]).
    IR_SCAN_POS      = [-300, 300, 300, -300]
    IR_SCAN_POS_DEG  = [-35, 0, 35, 0]
    IR_SCAN_BIAS_F   = -0.0        # To account for bias in turning motor:
                                   # .. pos > 0 --> pos*(1+IR_SCAN_BIAS_F)
                                   # .. pos < 0 --> pos*(1-IR_SCAN_BIAS_F)
    IR_SCAN_CONE_DEG = const(30)   # Angular width of scan cone (only for GUI)
    IR_SCAN_SENSOR   = const(0)    # 0=GP2Y0A41SK0F (4-30 cm)
                                   # 1=GP2Y0AF15X (1.5-15 cm)
    AI_CH_IR_RANGING = const(0)    # Analog-In channel for IR distance sensor
    DIST_OBST_CM     = const(9)    # Lower distances are considered obstacles
    DIST_CLIFF_CM    = const(25)   # Farer distances are considered cliffs
    DIST_SMOOTH      = const(0)
    
    # Light intensity measurements
    AI_CH_LIGHT_R    = const(3)
    AI_CH_LIGHT_L    = const(2)
    
    # Servo settings
    DO_CH_DIST_SERVO = DIO0        # Digital-Out channel for distance sensor servo
    MIN_DIST_SERVO   = const(45)   # Limits of servo that holds the arm with the
    MAX_DIST_SERVO   = const(-45)  # .. IR distance sensor in [°]
    MIN_US_SERVO     = const(1172) # Minimum timing of servo in [us]
    MAX_US_SERVO     = const(2033) # Maximum timing of servo in [us]
    SCAN_DIST_SERVO  = const(-25)  # Angle of IR distance sensor arm
    
    # Period of timer that keeps sensor values updated, the NeoPixel pulsing,
    # and checks for tilt (in [ms])
    TM_PERIOD        = const(50)
    
    # Default motor speeds ..
    SPEED_WALK       = const(-55)  # -70 .. for walking forwards
    SPEED_TURN       = const(35)   # +30 .. for turning head when changing direction
    SPEED_SCAN       = const(40)   # .. for turning head when scanning
    SPEED_TURN_DELAY = const(500)  # Duration for turning in new direction
    SPEED_BACK_DELAY = const(600)  # Duration for backing up (cliff)
    
    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    # Options, depending on board and sensor complement
    USE_LOAD_SENSING = const(0)    # Use AI channels #6,7 for load-sensing (> v1.1)
    USE_POWER_SHD    = const(0)    # Use ENAB_5V (voltage regulator off)   (> v1.1)
    SEND_TELEMETRY   = const(1)    # only w/ESP32
    
    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    # "Behaviours" and their parameters
    #
    # Look around
    DO_LOOK_AROUND   = const(30)   # =probabilty ([‰]) to activate behaviour
    
    # Take a nap
    # If activated, the roboter falls asleep from time to time. When this happens,
    # the processor and all on-board electronics go to deep sleep or are turned
    # off. The roboter wakes up after a random number of seconds.
    # (only with ESP32, needs `USE_POWER_SHD` enabled)
    DO_TAKE_NAPS     = const(0)    # =probability, [‰]to activate behaviour
    NAP_FROM_S       = const(5)    # range of random numbers to sleep ...
    NAP_TO_S         = const(20)   # ... in [s]
    
    # Find light source
    # Uses a photodiode pair to home in on a light source. Give pins that connect
    # to the photodiodes in `AI_CH_LIGHT_R` and `AI_CH_LIGHT_L` (above)
    # (obviously, does not work together `DO_WALK_STRAIGHT`)
    DO_FIND_LIGHT    = const(0)    # 1=enabled
    
    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    # "Behaviors", not yet fully implemented/tested
    #
    # Use the compass to walk straight ahead
    DO_WALK_STRAIGHT = const(0)
    HEAD_ADJUST_FACT = const(-1)   #
    HEAD_ADJUST_THR  = const(5)    # [°]
    
    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    # Additional devices plugged into the robotling board
    # Possible devices:
    # - Compass modules     : "compass_cmps12", "lsm303", "lsm9ds0"
    # - ToF distance sensor : "vl6180x"
    # - Display             : "dotstar_feather"
    # - WLAN                : "wlan"
    # - Cameras             : "amg88xx"
    MORE_DEVICES     = ["lsm303", "wlan"]
    
    # <==
    # ----------------------------------------------------------------------------
    
  4. Die Demo verwendet in den Standardeinstellungen kein WLAN. Man kann eine WLAN-Verbindung einfach aktivieren, indem man "wlan" zur Liste MORE_DEVICES in hexbug_config.py hinzufügt (siehe oben). Wenn sich das HUZZAH32-Modul mit dem WLAN zu verbinden versucht, wird dies durch ein rasches Blinken der roten LED auf dem Modul angezeigt.

    Falls man die experimentelle, drahtlose webrepl -Schnittstelle verwenden möchte, um mit MicroPython zu interagieren, muss man die folgenden drei Zeilen in boot.py aktivieren.

    # REPL via WLAN
    """
    do_connect()
    import webrepl
    webrepl.start()
    """
    

    In jedem Fall muss man die entsprechenden WLAN-Zugangsdaten in NETWORK.py definieren:

    my_ssid     = "YOUR-NETWORK-SSID"
    my_wp2_pwd  = "YOUR-PASSWORD"
    

... anschließen ...

Nun schließt man das HUZZAH32-Modul (mit dem ESP32) über ein USB-Kabel an den PC an; die gelbe LED auf dem HUZZAH32-Modul sollte je nach Ladezustand des Akkus aufleuchten. Dauerhaftes Leuchten bedeutet, dass der Akku geladen wird; flickert die LED, ist der Akku voll und die Ladung wird erhalten. In der pymakr-Erweiterung setzt man die richtige USB-Schnittstelle (den virtuellen COM-Port) und das Verzeichnis mit der Demo-Software (d.h. den kompletten Pfad zu \code\robotling).

Hinweis: Das Verzeichnis mit der Robotling-Software hat sich geändert; die Dateien, die in den Roboter hochgeladen werden, sind nun in \code\robotling anstatt wie früher direkt in \code.

Hinweis: Da die Demo sofort startet und der Roboter eher nicht mit dem Kabel losrennen sollte, empfiehlt es sich, ihn vor dem Laden der Demo-Software auf die Seite legen. Der Demo-Code liest den Lagesensor ("accelerometer") im Kompass aus und wenn der Roboter nicht aufrecht ist, werden alle Motoren abgeschaltet - er hört auf zu zappeln - und der NeoPixel pulsiert blau.

... und Code hochladen

Erst schaltet man das "robotling"-Board an (Schalter neben dem Akku-Anschluß), um die 5V-Versorgung zu aktivieren.

Nun drückt man den upload-Knopf in der pymakr-GUI, damit werden vorhandene Dateien im FLASH des ESP32 gelöscht und der Inhalt des gesetzten Verzeichnisses (also code\robotling) inklusive aller Unterordner in den FLASH geschrieben. Anschließend bootet der ESP32 und MicroPython führt zunächst boot.py und dann main.py aus. Wenn alles korrekt installiert und angeschlossen ist, sollten Bootmeldungen den erfolgreichen Start der Demo anzeigen, z.B.:

Robotling (board v1.20, software v0.1.8.0) w/ MicroPython 1.11.0 (esp32)
Initializing ...
[        GUID] robotling_30aea413e508
[     mcp3208] 8-channel A/D converter             (0.1.1.0): ok
[     drv8835] 2-channel DC motor driver           (0.1.1.0): ok
[    Neopixel] ready
I2C bus frequency is 400.0 kHz
Scanning I2C bus ...
... 2 device(s) found ([25, 30])
[      lsm303] Magnetometer/accelerometer          (0.1.0.0): ok
[      lsm303] Compass, calibrated                 (0.1.1.1): ok
Connecting to network...
I (4314) phy: phy_version: 4100, 2a5dd04, Jan 23 2019, 21:00:07, 0, 0
[     network] ('192.168.178.54', '255.255.255.0', '192.168.178.1', '192.168.178.1')
... done.
[GP2Y0A41SK0F] IR ranging (Sharp), A/D channel #0  (0.1.1.0): ok
Using 1x IR ranging (Sharp) as ranging sensor(s)
Servo is ready.
DC motor A is ready.
DC motor B is ready.
Initializing telemetry via MQTT ...
[       topic] b'robotling_30aea413e508/'
... done.
Entering loop ...

... und die Demo starten

Der NeoPixel sollte nun anfangen blau zu pulsieren. Jetzt kann man das USB-Kabel abziehen.

Sobald man den Roboter aufrecht stellt, beginnt er zu laufen. Der IR-Distanzsensor richtet sich schräg auf den Boden vor dem Roboter; so können halbwegs zuverlässig Hindernisse (gemessene Entfernung näher als der Boden, d.h. < ~8 cm) und "Klippen" (z.B. Tischkanten, > ~20 cm) detektiert werden.

Solange nichts im Weg ist, läuft der Roboter mehr oder weniger gerade aus und der NeoPixel pulsiert grün. Der Sensor wird dabei etwas hin und her bewegt, um einen breiteren Bereich vor dem Roboter zu überwachen. Wird ein Hindernis erkannt, pulsiert die LED orange, der Roboter stoppt und dreht sich solange, bis ein freier Weg gefunden ist. Erkennt der Roboter eine Kante, so pulsiert der NeoPixel violet, der Roboter bewegt sich einen Schritt rückwärts und dreht sich, bis weder ein Hindernis noch eine Kante detektiert wird. Kippt der Roboter um mehr als ~25°, wird der NeoPixel blau und alle Motoren stoppen.

Hier der Roboter mit der Platinenversion v1.0:

Hier der Roboter mit der Platinenversion v1.2:

Troubleshooting

  • Erkennt der Roboter zu oft Hindernisse oder Klippen, wo keine sind, so muss man im Code die Schwellenwerte für die Erkennung in main.py anpassen. Um die richtigen Werte zu finden, kann man eine Hilfsfuntion verwenden. Dazu muss der Roboter aber per USB-Kabel an den PC angeschlossen und die Ausführung der Demo mit "Ctr-C" unterbrochen werden:
    Loop stopped.
    Memory     : 37% of 117kB heap RAM used.
    Battery    : 4.1V, ~99% charged
    Performance: spin:  9.615ms @ 20.0Hz ~19%
    ---
    MicroPython v1.11-126-g7c2e83324 on 2019-07-07; ESP32 module with ESP32
    Type "help()" for more information.
    >>>  
    
    Nun hat man eine REPL-Verbindung zu MicroPython und ruft die Hilfsroutine auf. Dabei gibt angle den Winkel für den Servomotor mit dem Distanzsensor an; trials die Anzahl der Messungen. Die Ergebnisse werden ständig ausgegeben, so dass man nun die Entfernung des Bodens vor dem Roboer ohne Hindernis oder Klippe bestimmen kann.
    >>> r.getDist(angle=-25, trials=100)
    11.2496 cm
    11.29977 cm
    10.94253 cm
    11.29977 cm
    11.2496 cm
    10.91124 cm
    10.91124 cm
    11.02159 cm
    [...]
    
    Nun ändert man den Erkenungsbereich entsprechend in main.py:
    DIST_OBST_CM     = const(7)    # Lower distances are considered obstacles
    DIST_CLIFF_CM    = const(13)   # Farer distances are considered cliffs
    

Weiter zu "Verhalten"

⚠️ **GitHub.com Fallback** ⚠️