We want to use motion to change some settings on our little creature friend Spoka. In this case, we're going to use rotating the lamp to the left and to the right as two separate inputs. We plan to use shake as an input, so we need to make sure that our rotation motion isn't mistaken for a shake motion. There are various ways we could use orientation as a limiting factor, but many of them make using the actual input difficult and inconsistent. We want our lamp to work easily every time!

So, we're going to require a series of events to occur in a particular order for the input to be accepted.  How will we accomplish this? We're going to create a state machine.

## State Machines

Put simply, a state machine looks for a series of inputs. When it reads an input, it changes state. Each step specifies the next state. When all of the required steps have been completed, in the correct order, it returns the desired result.

Consider purchasing a soda from a vending machine. First, you are required to insert the correct amount of money. If you only insert half, nothing happens. The correct input here is the full cost of the soda. Once you've inserted that, the next step is to choose which soda you want. The soda machine waits for this input before continuing. If you choose a cola, the machine will then proceed to dispense a cola. Once that is complete, the machine returns to it's original state: waiting for the correct amount of money to be inserted so it can repeat the steps once again.

How does this apply to code? If you would like to require a series of inputs in a certain order, instead of a single input, you'll want to create a state machine. For example, if you wanted to use rotating your Circuit Playground Express as an input, you could set it so any time it is rotated to the left, it recognises that as an input and spams the result anytime it's in that position. However, if you wanted to have it see rotating left as an input once, and require it be rotated back before allowing the left rotation input to work again, you'd need a state machine. That's what we're going to do!

## The State of Spoka

The first thing we need to do is decide what we want our state machine to look like. First, we want our code to first require a rotation of approximately 90 degrees to the left or right of the upright position. Next, it should require the lamp to be held in that rotated state for one second. Last, it should require the lamp to be placed in either the opposite rotation state or the upright state before the next rotation input in the same direction can be started.

Here is a list of the steps for using the left rotation as an input:

1. Begin upright or rotated to the right.
2. Rotate 90 degrees to the left of the upright position.
3. Hold for one second.
4. Rotate upright or to the right.

The right rotation will be the same steps, with right swapped for left.

```# SPDX-FileCopyrightText: 2018 Kattni Rembor for Adafruit Industries
#

import time

# pylint: disable=redefined-outer-name

def upright(x, y, z):
x_up = abs(x) < accel_threshold
y_up = abs(y) < accel_threshold
z_up = abs(9.8 - z) < accel_threshold
return x_up and y_up and z_up

def left_side(x, y, z):
x_side = abs(9.8 - x) < accel_threshold
y_side = abs(y) < accel_threshold
z_side = abs(z) < accel_threshold

return x_side and y_side and z_side

state = None
hold_end = None

accel_threshold = 2
hold_time = 1

while True:
x, y, z = cpx.acceleration
if left_side(x, y, z):
if state is None or not state.startswith("left"):
hold_end = time.monotonic() + hold_time
state = "left"
print("Entering state 'left'")
elif (state == "left"
and hold_end is not None
and time.monotonic() >= hold_end):
state = "left-done"
print("Entering state 'left-done'")
elif upright(x, y, z):
if state != "upright":
hold_end = None
state = "upright"
print("Entering state 'upright'")
```

Let's check this out! Connect to the REPL so you can view the `print` statements. Begin with the board flat, facing upright. You may see "Entering state 'upright'". Rotate the board 90 degrees to the left. You should see "Entering state 'left'". Hold for 1 second, or until you see "Entering state 'left-done'". Then rotate back to facing upright, and look for "Entering state 'upright'". Now you've used our state machine!

So let's take a look at the code.

### Functions

First, we create the functions that define what "left" and "upright" mean.

```def upright(x, y, z):
return abs(x) < accel_threshold and abs(y) < accel_threshold and abs(9.8 - z) < accel_threshold

def left_side(x, y, z):
return abs(9.8 - x) < accel_threshold and abs(y) < accel_threshold and abs(z) < accel_threshold```

To identify the orientation of the board, we're using the accelerometer. The accelerometer provides an `(x, y, z)` tuple, which is the acceleration value, in meters per second squared (m/s2), currently applied to the x, y and z axes. We can use this to determine what direction the board is pointing. When the board is flat with the front facing upright, acceleration returns `(0, 0, 9.8)`. This is because there is 0 acceleration on the x and y axes, and 9.8m/s2 (gravity!) on the z axis. So, the first function uses this information to tell the code that `upright` means when the board is flat and facing up. The same concept applies to `left_side`, with the values altered to match the values when the board is pointed to the left. As gravity is -9.8m/s2, we take the absolute value of `(x, y, z)` using `abs()` to avoid dealing with negative numbers in our math.

### Variables

Next, we create some variables for use later: `state` and `hold_end`. Then, we set `hold_time` to `1`, and `accel_threshold` to `2`.

```state = None
hold_end = None

accel_threshold = 2
hold_time = 1```

`hold_time` is the amount of time you must hold the board in the rotated state to continue to the next step in the state machine. `accel_threshold` is the number used to determine how close to exactly-rotated you must have the board to activate the input. If the `accel_threshold` is 0, then it must be rotated to exactly the right spot to activate it. Experimentation led us to use 2, which provides a range for the orientation that successfully activates the input. If you find you're having trouble finding the correct angle to hold the board, you can increase this number. `accel_threshold` must be between `0` and `9.8`. Be aware that the higher the number, the easier it is to activate the input, so you may mistakenly activate it if you set the number too high. At `9.8`, any movement registers as a rotation. It is not recommended to set it that high.

### The Loop

Next we begin our loop. The first thing we do is call and assign acceleration. Next, we begin our state machine. At any given point in time, the code is looking to see whether the board is pointing to the `left_side` or `upright`. Within that, we begin to use that information to work through the steps of our input.

If we rotate to the left side, it checks to make sure that the `state` is either `None` (as we assigned on startup), or doesn't start with `"left"`.

```if left_side(x, y, z):
if state is None or not state.startswith("left"):
hold_end = time.monotonic() + hold_time
state = "left"
print("Entering state 'left'")```

If either one of these conditions is met, it assigns `hold_end = time.monotonic() + hold_time`, and the code enters the `"left"` state. This meaning `hold_end` is equal to the current time plus the `hold_time` and `state = "left"`.

If neither of the first two conditions is true, it checks for three other conditions.

```        elif (state == "left"
and hold_end is not None
and time.monotonic() >= hold_end):
state = "left-done"
print("Entering state 'left-done'")```

Is the `state` equal to `"left"`, is `hold_end` not equal to `None`, and is the current time greater than or equal to `hold_end`. If all of these conditions is met, it begins to check whether or not the hold time has passed. Once it has, it enters the `"left-done"` state. At this point, we must return the lamp to the upright state to begin the left rotation part of our state machine again.

The last section checks to see if the board is upright.

```    elif upright(x, y, z):
if state != "upright":
hold_end = None
state = "upright"
print("Entering state 'upright'")
```

If so, it checks to see if the state is not already upright before setting `hold_end = None` and `state = "upright"`. The reason for verifying that the state is not already upright is to avoid spamming the upright position, since the lamp spends most of its time upright.

And now our state machine can begin again!

This guide was first published on Feb 20, 2018. It was last updated on Feb 20, 2018.