Skip to content

Kommentare zum MMBasic Programm

Thomas Euler edited this page Apr 2, 2023 · 47 revisions

Das Hauptprogramm

In diesem Abschnitt wird das Hauptprogramm ausschnittweise erklärt. Das komplette Programm findet man hier. Eine detaillierte Beschreibung der Programmierschnittstelle (API) für die Roboterfunktionen findet man unter Robotling-API (MMBasic).

Drawing Hinweis: Hier wird eine ältere Version des Programms (v1.01) beschrieben, aber grundsätzlich sind Funktionen und Aufbau bei den aktuellen Programmversionen (v1.1x) sehr ähnlich.

1. Definitionen

Nach den Versionsinformationen folgen Angaben über die Optionen, die gesetzt sein sollten, damit das Programm Geräte (wie z.B. das Display) an den erwarteten Pins findet.

[...]
' Assumed options:
'   OPTION COLOURCODE ON
'   OPTION DISPLAY 64, 80
'   OPTION CPUSPEED 133000
' With PicoDisplay:
'   OPTION SYSTEM SPI GP18,GP19,GP20
'   OPTION LCDPANEL ST7789_135, RLANDSCAPE, GP16,GP22,GP17
'   OPTION GUI CONTROLS 10

Arrays beginnen mit dem Index 0 und alle Variablen müssen explizit deklariert werden.

Option Base 0
Option Explicit

Drawing

Es folgt die Definition, wie auf welchen Pin vom Sensorport vorne am Roboter zugegriffen werden kann ...

Const R.TX        = 6  ' COM2
Const R.RX        = 7  '
Const R.SDA       = 1  ' I2C
Const R.SCL       = 2
Const R.A0        = 31 ' ADC0
Const R.A1        = 32 ' ADC1
Const R.A2        = 34 ' ADC2
Const R.D0        = 5

... und ein paar Konstanten, die das Verhalten des Programms generell regeln.

Const R.SERVOS_ON = 1  ' 0=Servos stay off (for testing purposes)
Const R.DISPLAY   = 1  ' 0=PicoDisplay not used
Const R.VERBOSE   = 0  ' 0=No logging to the console

Drawing

Der Roboter besitzt drei vorne montierte Abstandssensoren, die Distanzen bis 50 cm erfassen und als gepulstes Signal zurückliefern.

Sie sind schräg nach unten ausgerichtet und messen den Abstand zum Boden. Durch diese Anordnung können nicht nur Hindernisse erkannt werden, sondern auch Tischkanten. Hier werden die relevanten Abstände definiert: Alles was im Bereich 5-20 cm gemessen wird, ist "freie Fläche", kleinere Abstände werden als Hindernisse interpretiert, größere als Kanten.

Const R.D_CLIFF   = 20 ' Distance threshold (cm) for cliff
Const R.D_OBJECT  = 5  ' Distance threshold (cm) for obstacle
Const R.D_MAX     = 30 ' Max. displayed distance (cm)

2. Initialisierung

Da es in dieser Implementierung von MMBasic keine Funktionsbibliotheken in getrennten Dateien gibt, muss der gesammte Code in eine Programmdatei. Um nicht immer durch jede Menge Code scrollen zu müssen, um ans Hauptprogramm zu kommen, sind alle Funktionen des Roboters inklusive der Initialisierung weiter hinten. Um in den Initialisierungsbereich zu kommen, wird hier ein verpöntes GoToverwendet; die Initialisierungsroutine springt anschließend nach RobotMain, und das Hauptprogramm kann beginnen.

' Initialize hardware
GoTo InitRobot

' Start of main program
RobotMain:
  Dim integer n, running = 0, ev = 0

3. Sensoren verbinden und Anzeige starten

Nun werden die drei oben genannten Distanzsensoren initialisiert und mit den Pins am Sensorport verbunden. Anschließend wird ein Splash-Screen gezeigt, die GUI des TFT-Display initialisiert und das Pulsieren der RGB-LED gestartet. Diese zeigt über die Farbe an, in welchem Zustand sich der Roboter gerade befindet - grün freier Weg und vorwärts laufen, gelb Hinderniss entdeckt, rot Abgrund detektiert.

  ' Initialize sensors
  R.CreateSensor 0, R.TX, POLOLU_TOF_50, 3, USE_PULSIN
  R.CreateSensor 1, R.RX, POLOLU_TOF_50, 3, USE_PULSIN
  R.CreateSensor 2, R.D0, POLOLU_TOF_50, 3, USE_PULSIN

  ' Create GUI controls (if display is enabled)
  R.Splash 2000
  R.CreateGUI

  ' Start heartbeat
  R.SetRGBLED C_READY, START_BEAT

4. Tasten für Programmstart und -abbruch festlegen

Der folgende Code verbindet zwei der Tasten auf dem TFT-Display-Breakout mit Interrupt-Routinen, die das Programm starten (A) oder beenden (X).

  ' Set key A to start and key X to stop robot
  Dim integer abort_requested = 0
  Sub StartProg
    running = 1
  End Sub
  Sub AbortProg
    R.Log INFO, "User pressed key A"
    abort_requested = 1
  End Sub
  R.OnKey R.KEY_A, "StartProg"
  R.OnKey R.KEY_X, "AbortProg"

5. Mögliche Ereignisse definieren

Hier werden Ereignisse definiert, die der Roboter mit seinen Sensoren erkennen kann. Die Bitmuster stellen da, wo im "Sichtfeld" ein Hindernis bzw. eine Kante erscheint.

  ' Possible events
  Const EV_NONE   = 0
  Const EV_OBJ_R  = &B000001
  Const EV_OBJ_C  = &B000010
  Const EV_OBJ_L  = &B000100
  Const EV_OBJ    = &B000111
  Const EV_CLF_R  = &B001000
  Const EV_CLF_C  = &B010000
  Const EV_CLF_L  = &B100000
  Const EV_CLF    = &B111000

6. Hauptschleife

Nun wird darauf gewartet, dass der Benutzer A drückt und den Roboter loslaufen lässt.

  ' Wait for key A to start program
  Do While Not(running): R.Spin 100: Loop

Die Hauptschleife:

  1. R.Spin 100 (anstatt Pause 100) wartet für 100 ms und sorgt dafür, dass Sensoren ausgelesen werden und die LED weiter pulsiert.
  2. Die Werte der Distanzsensoren werden in ev als Bitmuster kodiert.
  3. Je nach Ereignis (ev) dreht sich der Roboter vom Hindernis oder der Kante weg; wenn nichts detektiert wird, läuft der Roboter gerade aus.
  4. Am Ende der Schleife wird überprüft, ob der Benutzer die X Taste auf dem Display-Breakout gedrückt hat.
  ' Start moving
  Do While running
    R.Spin 100

    ' Check for object and/or cliff
    ev = 0
    ev = ev Or Choice(R.Sensor(2) < R.D_OBJECT, EV_OBJ_R, 0)
    ev = ev Or Choice(R.Sensor(2) > R.D_CLIFF, EV_CLF_R, 0)
    ev = ev Or Choice(R.Sensor(1) < R.D_OBJECT, EV_OBJ_C, 0)
    ev = ev Or Choice(R.Sensor(1) > R.D_CLIFF, EV_CLF_C, 0)
    ev = ev Or Choice(R.Sensor(0) < R.D_OBJECT, EV_OBJ_L, 0)
    ev = ev Or Choice(R.Sensor(0) > R.D_CLIFF, EV_CLF_L, 0)

    ' Respond to event
    If ev = 0 Then
      ' Nothing detected, just walk ahead
      R.SetRGBLED C_READY
      R.Move FORWARD, 200
    ElseIf ev And EV_CLF Then
      ' Some cliff detected
      R.SetRGBLED C_DETECT_CLIFF
      R.Move BACKWARD, 100
      R.Spin 2000
      R.Move Choice(Rnd() > 0.5, TURN_LEFT, TURN_RIGHT), 100
      R.Spin 2000
    ElseIf ev And EV_OBJ Then
      ' Some object detected
      R.SetRGBLED C_DETECT_OBJ
      If ev And EV_OBJ_R Then
        R.Move TURN_LEFT, 150
        R.Spin 2000
      ElseIf ev And EV_OBJ_L Then
        R.Move TURN_RIGHT, 150
        R.Spin 2000
      EndIf
    EndIf

    ' Check if still running
    running = Not(abort_requested)
  Loop

Wenn die Hauptschleife verlassen wurde, hält der Roboter an und schaltet ab. Das Programm endet.

  ' Shutting down
  R.Stop
  R.Spin 2000, END_OF_MOVE
  R.Shutdown
  Print "Done"
End

Home

  1. Werkzeuge und Material (DE | EN)
  2. Aufbau
    2.1 Mechanik (DE | EN)
    2.2 Aufbau und Hinweise (DE | EN)
    2.3 Elektronik und Platine (DE | EN)
  3. Sensoren (DE | EN)
  4. Demo (DE | EN)
  5. Erweiterungen & Modifikationen
    5.1 Alternatives Display (DE | EN)
    5.2 CO2-Wächter (DE | EN)
  6. Galerie (DE | EN)
  7. Software - MMBasic
    7.1 MMBasic zum Laufen bringen (DE | EN)
    7.2 Kommentare zum Programm (DE | EN)
    7.3 Robotling API (DE | EN)
    7.4 Building PicoMite MMBasic (DE | EN)
  8. Software - MicroPython
    8.1 Running MicroPython (DE | EN)
    8.2 Building MicroPython (DE | EN)
Clone this wiki locally