> For the complete documentation index, see [llms.txt](https://rover-se.mantismc.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://rover-se.mantismc.com/man-in-the-loop-coding-exercise/pcep-python-prep.md).

# PCEP Python Prep

### Description

This flexible activity series is designed to help students learn foundational Python programming concepts while controlling a four-motor rover. Aligned with the **PCEP-30-02 Certified Entry-Level Python Programmer exam**, each self-contained activity focuses on a specific Python topic—such as variables, control flow, loops, data collections, and functions—while applying the concept to real rover movement. Students modify a single function in a provided rover control program to experiment with code and immediately observe the physical results on the robot. Each lesson pairs a clear programming objective with guided code examples, TODO challenges, and real-world rover testing. Instructors can mix and match activities or run them sequentially to fit different schedules, making the course adaptable for short workshops, multi-day camps, or full introductory Python classes.

<figure><img src="/files/Wthn4gT6GfHimorKHKSj" alt=""><figcaption></figcaption></figure>

### Overview

This guide covers:

* Generating PWM commands for the ROV.
* Understanding how PWM settings affect motor drive and direction.
* Running user-generated Python using LLM output based on guided input.

{% hint style="danger" %}
In order to run python, you will need to have an IDE and python compiler. If desired, you can use Visual Studio Code Code on your computer.

Follow this link <https://code.visualstudio.com/docs/setup/setup-overview> and use the steps related to your operating system.

Once you have the IDE installed,  follow these instructions to install python, <https://code.visualstudio.com/docs/python/python-tutorial>.
{% endhint %}

### Bleak library

* This library must be installed first <https://github.com/hbldh/bleak>
* From the command prompt run: Run “pip install bleak”

### RoverLLM.py

{% hint style="success" %}
The activities in this lesson are based on the contents of this file. When prompted below, you can use the copy feature to save a copy of the file to your device
{% endhint %}

<pre class="language-python" data-line-numbers><code class="lang-python">import asyncio
import gc
from bleak import BleakClient, BleakScanner

DEVICE_NAME = "ROV_7446B3EA794D"
MAILBOX_CHARACTERISTIC = "0000ffd1-0000-1000-8000-00805f9b34fb"
COMMAND_CHARACTERISTIC = "0000ffd2-0000-1000-8000-00805f9b34fb"

client = None  # Global client variable

async def find_device_by_exact_name(name):
    print("Scanning for BLE devices...")
    devices = await BleakScanner.discover(timeout=10.0)
    for d in devices:
        if d.name == name:
            print(f"Found device: {d.name} ({d.address})")
            return d.address
    print(f"No device found with name: {name}")
    return None
    
async def initialize():
    await MoveMotors(-1, -1, -1, -1)
    await MoveMotors(0, 0, 0, 0)
    
async def MoveMotors(m1, m2, m3, m4):
    motors = [max(-100, min(100, val)) &#x26; 0xFF for val in (m1, m2, m3, m4)]
    payload_mailbox = bytearray(motors)
    payload_command = bytearray([0x13, 0x00])

    await client.write_gatt_char(MAILBOX_CHARACTERISTIC, payload_mailbox, response=False)
    await client.write_gatt_char(COMMAND_CHARACTERISTIC, payload_command, response=False)
    print(f"Motors moved: [{m1} {m2} {m3} {m4}]")

async def StartProgram():
<strong>    print("Move Forward at 50% for 2 seconds")
</strong>    await MoveMotors(50, 50, 50, 50)
    await asyncio.sleep(2)
    print("Stop")
    await MoveMotors(0, 0, 0, 0)
    await asyncio.sleep(2)

async def main():
    global client
    address = await find_device_by_exact_name(DEVICE_NAME)
    if not address:
        return

    client = BleakClient(address)
    try:
        await client.connect()
        if not client.is_connected:
            print("Failed to connect.")
            return
        print(f"Connected to {DEVICE_NAME}")

        await initialize()
        await StartProgram()

    except Exception as e:
        print(f"Error: {e}")
    finally:
        try:
            print(f"Attempting disconnect... connected: {client.is_connected}")
            await client.disconnect()
            await asyncio.sleep(1)
            gc.collect()
            print("Disconnected and cleaned up.")
        except Exception as e:
            print(f"Error during disconnect: {e}")

if __name__ == "__main__":
    asyncio.run(main())
</code></pre>

Each activity aligns with topics from the **PCEP‑30‑02 Certified Entry‑Level Python Programmer exam**.

This course teaches Python programming while controlling a four‑motor rover.&#x20;

In every activity:

• Save the file as **activityX.py**\
• Run the program using **Visual Studio Code**\
• **Modify or debug the `StartProgram()` function**\
• Do NOT modify the rover Bluetooth code

You will fix bugs, complete missing code, and extend programs.

***

## Running Programs in Visual Studio Code

1. Open **Visual Studio Code**
2. Open your rover project folder
3. Create a new file (example: `activity1.py`)
4. Paste the rover base program into the file
5. Modify **StartProgram()**
6. Run the program

Open the terminal:

Terminal → New Terminal

Run:

```bash
python activity1.py
```

***

## Rover Motor Command

The rover moves using:

```python
await MoveMotors(m1, m2, m3, m4)
```

Values range **-100 to 100**

| Value | Meaning      |
| ----- | ------------ |
| 100   | Full Forward |
| 50    | Half Forward |
| 0     | Stop         |
| -50   | Reverse      |
| -100  | Full Reverse |

***

## SECTION 1 – Python Fundamentals

***

## Activity 1 – Instructions and Comments

### Objective

Learn:

• Python instructions\
• indentation\
• comments

### Save

```
activity1.py
```

### Starter Code

```python
async def StartProgram():

    # TODO move rover forward

    await MoveMotors(50,50,50,50)

    # TODO wait 2 seconds


    # TODO stop rover
```

### Student Task

Complete the program so the rover:

1. Moves forward **2 seconds**
2. Stops
3. Waits **1 second**

Add comments explaining the code.

***

## Activity 2 – Variables

### Objective

Learn:

• variables\
• integers\
• storing values

### Save

```
activity2.py
```

### Starter Code

```python
async def StartProgram():

    speed = 50

    await MoveMotors(speed,speed,speed,speed)
    await asyncio.sleep()

    await MoveMotors(0,0,0,0)
```

### Student Task

Fix the missing value so the rover moves forward **2 seconds**.

Add a variable called:

```
duration
```

***

## Activity 3 – Operators (Debugging)

### Objective

Learn:

• operators\
• modifying variable values

### Starter Code (Bug)

```python
async def StartProgram():

    speed = 10

    for i in range(5):

        await MoveMotors(speed,speed,speed,speed)
        await asyncio.sleep(1)

        speed + 10
```

### Student Task

Fix the bug so speed increases each loop.

Expected speeds:

10\
20\
30\
40\
50

***

## SECTION 2 – Control Flow

***

## Activity 4 – Conditional Statements

### Objective

Learn:

• if\
• elif\
• else

### Starter Code

```python
async def StartProgram():

    command = input("Enter command: ")

    if command == "forward":
        await MoveMotors(50,50,50,50)

    # TODO add backward command

    await asyncio.sleep(2)

    await MoveMotors(0,0,0,0)
```

### Student Task

Add commands:

```
backward
left
right
```

***

## Activity 5 – Loops

### Objective

Learn:

• for loops\
• repetition

### Starter Code

```python
async def StartProgram():

    for i in range(1):

        await MoveMotors(50,50,50,50)
        await asyncio.sleep(2)

        await MoveMotors(0,0,0,0)
```

### Student Task

Fix the loop so the rover repeats the movement **5 times**.

***

## Activity 6 – Movement Pattern

### Objective

Learn:

• combining loops with movement

### Starter Code

```python
async def StartProgram():

    for i in range(4):

        await MoveMotors(50,50,50,50)
        await asyncio.sleep(2)

        # TODO add right turn

    await MoveMotors(0,0,0,0)
```

### Student Task

Add turning code so the rover drives in a **square**.

***

## SECTION 3 – Data Collections

***

## Activity 7 – Lists

### Objective

Learn:

• lists\
• iterating through lists

### Starter Code

```python
async def StartProgram():

    speeds = [20,40,60]

    for s in speeds:

        await MoveMotors(s,s,s,s)
        await asyncio.sleep(1)
```

### Student Task

Add more speeds:

```
10
30
50
70
```

***

## Activity 8 – Movement Sequences (Debugging)

### Starter Code (Bug)

```python
async def StartProgram():

    moves = [
        (50,50,50,50),
        (50,-50,50,-50)
    ]

    for m in moves:

        await MoveMotors(m)
```

### Student Task

Fix the program so the rover executes the sequence.

Hint: `MoveMotors()` requires **4 arguments**.

***

## Activity 9 – Dictionaries

### Objective

Learn:

• dictionaries\
• key/value lookups

### Starter Code

```python
async def StartProgram():

    commands = {
        "forward": (50,50,50,50),
        "stop": (0,0,0,0)
    }

    cmd = input("Enter command: ")

    m = commands[cmd]

    await MoveMotors(m[0],m[1],m[2],m[3])
```

### Student Task

Add commands:

```
backward
left
right
```

***

## SECTION 4 – Functions

***

## Activity 10 – Functions

### Objective

Learn:

• defining functions\
• parameters

### Starter Code

```python
async def DriveForward(speed,time):

    # TODO complete function


async def StartProgram():

    await DriveForward(40,2)
```

### Student Task

Finish the function so the rover:

1. Moves forward
2. Waits
3. Stops

***

## Activity 11 – Exception Handling

### Objective

Learn:

• try\
• except\
• preventing program crashes

### Starter Code

```python
async def StartProgram():

    speed = int(input("Enter speed: "))

    await MoveMotors(speed,speed,speed,speed)
```

### Student Task

Add exception handling so the program does not crash if the user enters text.

***

## Activity 12 – Command Parser

### Objective

Learn:

• strings\
• text commands\
• program logic

### Starter Code

```python
async def StartProgram():

    command = input("Enter command: ").lower()

    if command == "forward":
        await MoveMotors(50,50,50,50)

    elif command == "backward":
        pass

    elif command == "left":
        pass

    elif command == "right":
        pass
```

### Student Task

Complete the commands so the rover responds correctly.

Add a command:

```
spin
```

***

## Final Challenge – Rover Patrol

Create a new file:

```
final_mission.py
```

Write a program that:

1. Drives in a square
2. Spins in place
3. Returns to the starting point
4. Stops

Use:

• loops\
• functions\
• conditionals\
• lists


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://rover-se.mantismc.com/man-in-the-loop-coding-exercise/pcep-python-prep.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
