Skip to content

Commit

Permalink
Merge pull request #134 from morganstanley/robot_build
Browse files Browse the repository at this point in the history
Add robot assembly and programming
  • Loading branch information
rmoriarty authored Apr 22, 2024
2 parents 46a1aab + 9432407 commit 0459b7c
Show file tree
Hide file tree
Showing 8 changed files with 186 additions and 0 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
61 changes: 61 additions & 0 deletions site/content/exercises/circuitpython/robotics/E13/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
---
template: exercise
title: Robot Assembly
level: 4
exercise: 13
category: Robotics
tags: ['CircuitPython']
---

In the last lesson we attached the Bluefruit board to the Crickit. Now let's build the rest of the robot.

# Assembly Video

[Assembly Walkthrough](https://video.morganstanley.com/#/videos/502f9fb8-00cc-4b84-950d-110df6d1edc4)

![](Lesson55.png)

**Supplies Needed:**

- Battery pack
- 3 AA batteries
- Bluefruit board
- Crickit
- 2 Motors
- 2 Wheels
- Robot Chassis
- 4 Long M3 Bolts + Nuts
- 4 Short M3 Bolts + Nuts
- 3 Black Nylon Spacers, Screws, and Nuts

![](Assembly0.jpg)

![](Assembly1.jpg)

# Attach Motors

- Attach one motor to each side
- Use M3 X 30 MM screws and M3 nuts \(Small box\)\.
- Thread Motor Wires up through chassis
- Attach caster wheels
- Attach caster wheels to each side
- Use M3 X 16 MM screws and M3 nuts \(Big box\)

![](Assembly2.jpg)

# Attach Bluefruit / Crickit to Robot Body

- Nylon spacers male to female \(M3X20 mm\)
- Nylon screws \(M3 X 12 mm\)
- Nylon nuts \(M3\)

![](Assembly4.jpg)

# Attach motor wires and power supply

- Attach motor wires and power supply to crickit
- Screw the motor wire leads into the ports\.
- Black\, Red\, Black\, Red
- Run the power supply under the body and up to the power supply port

![](Assembly5.jpg)
125 changes: 125 additions & 0 deletions site/content/exercises/circuitpython/robotics/E14/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
---
template: exercise
title: Robot Programming
level: 4
exercise: 14
category: Robotics
tags: ['CircuitPython']
---

Now let's program the robot!

# Bluetooth Code

Start with a basic program that listens for the three types of Bluetooth packets we've been using (`ColorPacket`, `AccelerometerPacket`, `ButtonPacket`) and prints the packet contents to the serial console. Start by running this program and sending each of the 3 packet types from your phone, confirming they're printed to the serial console. This will be the foundation of our robot program:

```python
from adafruit_ble import BLERadio
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from adafruit_ble.services.nordic import UARTService

from adafruit_bluefruit_connect.packet import Packet
from adafruit_bluefruit_connect.color_packet import ColorPacket
from adafruit_bluefruit_connect.accelerometer_packet import AccelerometerPacket
from adafruit_bluefruit_connect.button_packet import ButtonPacket

from adafruit_crickit import crickit

ble = BLERadio()
uart_service = UARTService()
advertisement = ProvideServicesAdvertisement(uart_service)

def handle_color_packet(packet):
print(f"Color={packet.color}")

def handle_accelerometer_packet(packet):
print(f"X={packet.x}, Y={packet.y}, Z={packet.z}")

def handle_button_packet(packet):
print(f"Button={packet.button}, Pressed={packet.pressed}")

while True:
# Keep advertising until another device connects
ble.start_advertising(advertisement)
while not ble.connected:
pass
ble.stop_advertising()

# Keep listening for packets while connected
while ble.connected:
if uart_service.in_waiting:
packet = Packet.from_stream(uart_service)
if isinstance(packet, ColorPacket):
handle_color_packet(packet)
if isinstance(packet, AccelerometerPacket):
handle_accelerometer_packet(packet)
if isinstance(packet, ButtonPacket):
handle_button_packet(packet)
```

# Accelerometer: Foward/Backward

We'll use the accelerometer measurement along the Z-axis to set forward/backward motor speed. Be sure the throttle doesn't go above 1.0 or below -1.0, otherwise an exception will be thrown:
```python
def compute_throttle(value):
if value > 1:
return 1
elif value < -1:
return -1
return value

def handle_accelerometer_packet(packet):
print(f"X={packet.x}, Y={packet.y}, Z={packet.z}")
throttle = compute_throttle(packet.z)
crickit.dc_motor_1.throttle = throttle
crickit.dc_motor_2.throttle = throttle
```

Try using your phone to make the robot move forward and backward, and notice how the speed changes based on the tilt of your phone. The wheel attachments probably won't be perfectly straight so you're likely to see the robot veer slightly to the left or right.

# Accelerometer: Left/Right

Now let's add the ability to turn left and right by changing the motor throttles to different values based on accelerometer measurement along the X-axis:
```python
def handle_accelerometer_packet(packet):
print(f"X={packet.x}, Y={packet.y}, Z={packet.z}")
throttle_1 = compute_throttle(packet.z + packet.x)
throttle_2 = compute_throttle(packet.z - packet.x)
crickit.dc_motor_1.throttle = throttle_1
crickit.dc_motor_2.throttle = throttle_2
```

# Servo: Turning Heads

Now let's attach the servo from the previous lesson and swivel the servo arm back and forth using the control pad on your phone app:
```python
# Start with arm at the halfway point
angle = 90
crickit.servo_1.angle = angle

def adjust_angle(amount):
global angle
angle = angle + amount
if angle > 180:
angle = 180
elif angle < 0:
angle = 0
crickit.servo_1.angle = angle

def handle_button_packet(packet):
print(f"Button={packet.button}, Pressed={packet.pressed}")
if packet.pressed:
if packet.button == ButtonPacket.LEFT:
adjust_angle(20)
elif packet.button == ButtonPacket.RIGHT:
adjust_angle(-20)
```

We can mount a paper cup "head" onto the servo arm, allowing us to turn the robot's head left and right using the control pad while it moves around based on the accelerometer readings.

# Customize It!

Now that we have the robot working let's add some bells and whistles! The left and right control pad buttons are used to adjust the servo angle, but currently the up and down buttons and the four number buttons are unused. Here are a few ideas:
- Play a tune (go back to the Sounds lesson for some musical samples).
- Blink LEDs in a pattern.
- Program the color picker to allow you to change LED colors.

0 comments on commit 0459b7c

Please sign in to comment.