The controller code continually reads the 3 axes of the accelerometer and, based on those readings, sends the appropriate code via the IR transmitter.

Since accelerometers can detect gravity, they're great for calculating the tilt of your hand. But sometimes it hard to visualize what the motion translates to X-Y-Z values. For that, we recommend using the CircuitPython plotter

Check our our motion-plotting guide and video to see how you can read the x, y, and z accelerations and get values for use in detecting tilt.

There are three primary hand positions that correspond to stop, forward, and reverse:

  1. palm down: z is a high negative value,
  2. hand up with palm facing away from you: y has a high positive value, and
  3. hand down with palm facing toward you: y has a high negative value.

For each of these three hand positions, wrist rotation adds a turn to the basic stop/forward/reverse motion: rotating in place if the robot is stopped, or veering left/right if the robot is moving forward or reversing. The X component of the accelerometer reading indicates wrist rotation: a large negative value for a counterclockwise rotation, and a large positive value for clockwise rotation.

After configuring the hardware and libraries, the main loop reads the accelerometer and a 2 level conditional decides what should be sent to the robot.

Below is the code for the control glove. Save it to the Circuit Playground Express on the glove as code.py.

import time
import busio
import board
import pulseio
import adafruit_irremote
import adafruit_lis3dh

# Control debug output: it takes time so don't unless you're debugging
DEBUG_LOG = False

# Control codes
STOP = 0x01
ROTATE_LEFT = 0x02
ROTATE_RIGHT = 0x03
FORWARD = 0x04
FORWARD_LEFT = 0x05
FORWARD_RIGHT = 0x06
REVERSE = 0x07
REVERSE_LEFT = 0x08
REVERSE_RIGHT = 0x09

TRANSMIT_DELAY = 0.1

# Setup accelerometer
i2c = busio.I2C(board.ACCELEROMETER_SCL, board.ACCELEROMETER_SDA)
sensor = adafruit_lis3dh.LIS3DH_I2C(i2c, address=0x19)

# Create a 'pulseio' output, to send infrared signals on the IR transmitter @ 38KHz
pwm = pulseio.PWMOut(board.IR_TX, frequency=38000, duty_cycle=2 ** 15)
pulseout = pulseio.PulseOut(pwm)

# Create an encoder that will take numbers and turn them into IR pulses
encoder = adafruit_irremote.GenericTransmit(header=[9500, 4500],
                                            one=[550, 550],
                                            zero=[550, 1700],
                                            trail=0)

def log(s):
    """Optionally output some text.
    :param string s: test to output
    """
    if DEBUG_LOG:
        print(s)


while True:
    x, y, z = sensor.acceleration
    log("{0: 0.3f} {1: 0.3f} {2: 0.3f}".format(x, y, z))
    if z < -5.0 and abs(y) < 3.0:         # palm down
        if x < -5.0:                      # tipped counterclockwise
            log("ROTATE_LEFT")
            encoder.transmit(pulseout, [ROTATE_LEFT] * 4)
        elif x > 5.0:                     # tipped clockwise
            log("ROTATE_RIGHT")
            encoder.transmit(pulseout, [ROTATE_RIGHT] * 4)
        else:                             # level
            log("STOP")
            encoder.transmit(pulseout, [STOP] * 4)
    elif y > 5.0:                         # palm facing away
        if x < -5.0:                      # tipped counterclockwise
            log("FORWARD_LEFT")
            encoder.transmit(pulseout, [FORWARD_LEFT] * 4)
        elif x > 5.0:                     # tipped clockwise
            log("FORWARD_RIGHT")
            encoder.transmit(pulseout, [FORWARD_RIGHT] * 4)
        else:                             # straight up
            log("FORWARD")
            encoder.transmit(pulseout, [FORWARD] * 4)
    elif y < -5.0:                        # palm facing toward (hand down)
        if x < -5.0:                      # tipped counterclockwise
            log("REVERSE_RIGHT")
            encoder.transmit(pulseout, [REVERSE_RIGHT] * 4)
        elif x > 5.0:                     # tipped clockwise
            log("REVERSE_LEFT")
            encoder.transmit(pulseout, [REVERSE_LEFT] * 4)
        else:                             #straight down
            log("REVERSE")
            encoder.transmit(pulseout, [REVERSE] * 4)

    time.sleep(TRANSMIT_DELAY)

This guide was first published on Aug 08, 2018. It was last updated on Aug 08, 2018.

This page (Controller Code) was last updated on Nov 02, 2020.