Controlling motors with Strudel

Strudel is made for making music, but it’s possible to pattern other things with it, including motors.

We’re going to use a microcontroller for this, called an “Inventor 2040W”, which is a Pico W with extra ports added including some for controlling motors.

image

Technical details

Feel free to gloss over these!

  • The Inventor 2040W connects to the internet wirelessly. It’s powered via USB but you don’t have to plug it into a laptop, and you can even power it from a battery.
  • It’s running some code that listens for messages using an “Internet of Things” network protocol (called MQTT). When it receives a message, it moves a motor.
  • It connects to a small server (running software called ‘mosquitto’) in our studio. You can also configure it to connect to another server if you want to use it outside out the studio - it’s a bit fiddly, but I can show you how.
  • Strudel can send these messages instead of triggering sounds - that’s how we use it to pattern movement!

First movement

Let’s get a motor running!

  1. Note the letter drawn on a label on the back of the microcontroller.

  2. Plug your microcontroller into USB power

  3. Plug a motor into ‘servo’ (not motor) plug numbered 1, with the yellow (lightest) cable closest to the ‘1’, and the brown (darkest) cable outward

  4. Run the below to set up some values, changing the x in /move/x to the letter on your microcontroller. Nothing will happen yet!


// Change 'x' in /move/x to the letter on the back of your microcontroller
window.path = '/move/x';

// This adds the 'move' and 'motor' commands to strudel
const {move, motor} = createParams('move', 'motor'); window.move = move; window.motor = motor;
// This adds the 'robot' command
Pattern.prototype.robot = function()  {return this.mqtt('alpaca', undefined, path, 'wss://things.patternclub.org:443/mqtt')};
silence;

If you refresh the page, you’ll need to change and run the above again before the following patterns work.

If your motor starts moving unexpectedly, someone else might have put your letter in the /move/ line by mistake!!

  1. Now, run the below. It will ask for a password, which is set to be the same as the alpacalab wifi password. Hopefully your motor will then start to move!

move("-10 0 10").motor("0").slow(2).robot();  

Note that in the above, we start counting motors from ‘0’, so motor 1 on the board is motor 0 in the code.

Using the main strudel interface

If you want to work in the main strudel ‘repl’, click here for a starting point with the set-up code and movement code together.

Patterning movement

Many strudel features for playing with sound patterns will work when playing with motor patterns! Try playing with the mininotation in the move command:


move("-10 0 10 [20 30]*2").motor("0").slow(2).robot()

The move instructions are in the range from -90 to 90.

If your motors stop working at some point, and your code looks right, try pressing the ‘reset’ button on the microcontroller.

It’s possible to make smooth movements based on different ‘waveforms’, for example a smooth sinewave:


move(sine.range(-30, 30).segment(16)).motor("0").slow(2).robot();

The movement is still quite jerky, because the ‘segment’ command is only taking 16 positions from the sinewave. Try increasing it to 32 or 64. It’s best not too much higher than that, as the microcontroller might get overwhelmed with a backlog of instructions!

Try replacing sine with other waveforms: saw (sawtooth wave), tri (triangular wave) are good, and there is also rand (random wave) and perlin (a kind of smoothed-out randomness).

Patterning more than one motor

You can pattern the motor command separately from the move one:


move("-10 0 10 [20 30]*2").motor("0 1").slow(2).robot();

Alternatively, you can pattern two motors independently, using the stack command. The below sends the same pattern for the first two motors, but with the second one running slower:


stack(
move("-10 0 10 [20 30]*2").motor("0").slow(2),
move("-10 0 10 [20 30]*2").motor("1").slow(3)
).robot();

Patterns of patterns!

Once you have three patterns you like, you can give them names like ‘a’, ‘b’ and ‘c’, and then pattern them with the `pick command.

let a = move("20 [-10 10] 30 35 40").motor(0).off(0.25, x => x.motor(1));

let b = stack(
  move(sine.segment(64).range(30, -30)).motor(0),
  move(sine.segment(64).range(40, -40).slow(1.5)
).motor(1)
)

let c = move(perlin.range(20,-20).fast(2).segment(64)).motor("0,1");

$: "<a a a b b b b b c c c c>".pick({a,b,c}).robot();

You can click here to start patterning your patterns in the main strudel interface.