jevstrudel.git / website / src / pages / workshop / motors.mdx
motors.mdx117 lines · 3.8 KB · raw
1---
2title: Movement with Strudel
3layout: ../../layouts/MainLayout.astro
4---
5
6import { MiniRepl } from '@src/docs/MiniRepl';
7import Box from '@components/Box.astro';
8import QA from '@components/QA';
9
10# Controlling motors with Strudel
11
12Strudel is mainly made for making music, but it's possible to pattern other things with it, including motors.
13
14We're going to use a microcontroller for this, called an "[Inventor 2040W](https://shop.pimoroni.com/products/inventor-2040-w)", which is
15a [Pico W](https://shop.pimoroni.com/products/inventor-2040-w?variant=40053063155795) with extra ports added including some for controlling motors.
16
17![image](https://shop.pimoroni.com/cdn/shop/products/Inventor2040_1of3_1500x1500_crop_center.jpg?v=1656927927)
18
19## Technical details
20
21Feel free to gloss over these!
22
23- The Inventor 2040W connects to the internet wirelessly, and it can power from a battery or USB. Hopefully the batteries last!
24- It's running [some code](https://github.com/patternclub/alpacalab/blob/main/course/main.py) that listens for messages using an "Internet of Things" network protocol (called MQTT). When it receives a message, it moves a motor.
25- It connects to a small server (running software called 'mosquitto') on Alex's laptop.
26- Strudel can send these messages instead of triggering sounds - that's how we use it to pattern movement.
27
28## First movement
29
30Let's get a motor running!
31
321. Note the letter drawn on a label on the back of the microcontroller.
33
342. Plug a battery into your microcontroller.
35
363. 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
37
384. Run the below to set up some values, changing the `x` in 'robot('x')` to the letter on your microcontroller.
39
40<MiniRepl
41  client:visible
42  tune={`
43   $: move("-60 80").motor("0").robot('x');
44  `}
45/>
46
47<Box>
48
49If you refresh the page, you'll need to change the letter to match your robot again.
50
51If your motor starts moving unexpectedly, someone else might have put your letter in by mistake!
52
53Note that in the above, we start counting motors from '0', so motor 1 on the board is motor 0 in the code.
54
55</Box>
56
57## Patterning movement
58
59Many strudel features for playing with sound patterns will work when
60playing with motor patterns. Try playing with the mininotation in the
61`move` command:
62
63<MiniRepl
64  client:visible
65  tune={`
66$: move("-10 0 10 [20 30]*2").motor("0").slow(2).robot('x')
67  `}
68/>
69
70The move instructions are in the range from -90 to 90.
71
72<box>
73  If your motors stop working at some point, and your code looks right, try pressing the 'reset' button on the
74  microcontroller.
75</box>
76
77It's possible to make smooth movements based on different 'waveforms', for example a smooth sinewave:
78
79<MiniRepl
80  client:visible
81  tune={`
82$: move(sine.range(-30, 30).segment(16)).motor("0").slow(2).robot('x');
83  `}
84/>
85
86The movement is still quite jerky, because the 'segment' command is
87only 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
88might get overwhelmed with a backlog of instructions!
89
90<box>
91  Try replacing `sine` with other waveforms: `saw` (sawtooth wave), `tri` (triangular wave) are good, and there is also
92  `rand` (random wave) and `perlin` (a kind of smoothed-out randomness).
93</box>
94
95## Patterning more than one motor
96
97You can pattern the `motor` command separately from the `move` one:
98
99<MiniRepl
100  client:visible
101  tune={`
102$: move("-10 0 10 [20 30]*2").motor("0 1").slow(2).robot('x');
103  `}
104/>
105
106Alternatively, you can pattern two motors in separate patterns. The below sends the same pattern for the first two motors, but with the second one running slower:
107
108<MiniRepl
109  client:visible
110  tune={`
111
112$: move("-10 0 10 [20 30]\*2").motor("0").slow(2).robot('x');
113
114$: move("-10 0 10 [20 30]\*2").motor("1").slow(3).robot('x');
115
116`}
117/>