Skip to content

12. Output devices

For this week’s assignment I connected and programmed a stepper motor through an arduino and motor driver, all on a bread board.

Main components:

  • Stepper: Mercury Motor SM-42BYG011-25
  • Barduino ESP32
  • Driver Motor: Pololu md09b/ A4988

I will walk through the basic set/ connections and logic behind everything.

Overview: The stepper motor’s precision motion is due to the alternative switching between two electromagnets which are connected by two collies/ circuits within the motor. In this case we have a bipolar motor, where each coil controls a ‘control channel’. By alternating the coils we are able to make precision steps.

Important note:

It’s important to check each stepper motor’s power needs and limits. For the current version, it moves on 12V and has a current limit to 0.33A. This will be important later when we set the ‘trimmer’ on the motor driver to ensure that the current going through the motor does not exceed that current limit.

Motor Driver: The motor driver is the component needed to communicate the alternating on/off with the stepper coils. In this case it acts as 2 H-bridges that reverse polarity of the coils. This would not be possible through an Barduino because first it can not handle the load 12V and would burn out. The drive acts as a power amplifier taking low-current signals from the Barduino and translating them to control the high-current transistors. For this reason the driver is connected to 2 power supplies. The low voltage through the VDD is to power the board. And the higher VMOT is for powering the stepper.

![](../../docs/images/Week (10) - Output/Screenshot 2026-04-06 at 8.46.04 PM.png

Setting the current limit:

We set the current limit through the delicate operation of adjusting the trimmer - the circular component on the bottom of the driver. As stated above this is to ensure that the stepper is receiving the current current and voltage - nothing that can damage it.

First we need to know what the current limit of the stepper, in this case its 0.33A.

Now based on the equation V= I.R

Connecting motor driver to Barduino:

Control pins:

The motor driver has three main controls that are responsible for communicating with the Stepper through the Board.

Enable_PIN: Is a pin the simply activates of deactivates the motor driver, by sending a simple High/Low voltage. Connect Enable_Pin on board to the low/ground in the bus DIR_PIN: Is responsible for deciding on direction of rotation. High = CW, Low = CCW. Or the opposite. This pin is controlled by number of steps. Ie. for a full rotation is either direction we can program for 200/ the full rotation of the Stepper model Connect DIR_PIN to pin 11 in the board STEP_Pin: Is responsible for the speed of rotation and is programed by time. Ie. 5000ms to make a full rotation. Connect Step_PIN to pin 10 in the board

Sleep/Rest Pin

Connect the Sleep and Rest pins in the board to each other. (I’m not yet sure what this does!?)

Power up the Barduino and Driver:

The Barduino will be powered through the USB connection with supplies of 5V. This 5V runs through a built in voltage regulator which reduced the voltage to 3.3V which is the voltage that will be powering the signal side of the board.

Connect the ground_PIN of the Barduino to the - of the bus Connect the V3.3_PIN of the Barduino to the + of the bus Connect the VDD_PIN of the driver to the + of the bus Connect the Ground_PIN of the driver (next to the VDD) to the - of the bus

Now the chip is supplied by 3.3V and can communicate with the Board

Powering up the Driver

Using a 12V wall charger we will supply a separate power to the stepper through the driver.

Connect the 12V power supply to an external connection and two jumper wires. Ground/ Power. Connect the Ground to the - of the bus and the Power to the + of the bus Connect a capacitor to the circuit (100uF) Connect the grounds across the buses with a jumper cable. Connect the Vmot_PIN in the driver to the + of the bus Connect the Groundmot_PIN in the driver to the - of the bus

Now the driver has a 12V power supply, able to move the stepper.

Connecting the Stepper

The last step is to properly connect the stepper. The stepper has two coils each with a High/low so 4 in total. To test which two wires belong to the same coil we do a simple touch and spin test. Touch two tips of the coil together and manually spin the Stepper. If the resistance increases that means the two wires belong to the same circuit. After defining the two coils:

Connect the first coil in 1A_PIN & 1B_PIN in the driver Connect the second coil in the 2A_PIN & 2B_PIN in the driver

Finally, add a heat dissipator to the driver. Ensure it is small enough and does not touch the pins on the board.

The connections are complete. Now we can connect the Board through the USB and program the desired rotational movement.

Programing the Stepper: Playing around with differnt Motions

I wanted to program different rotational movements to reflect the rotation of waves. Rather than finding movements that reflect the motion of waves in linear terms, I’d like to imagine the movement that interacts with/ dances with the sound. This is a much freer relationship to sound and the interpretation of waves.

Observation of waves: Three questions.

Does a wave slow down or speed up when approaching the shore? As a swell approaches the shore line it slows down - it moves faster in deeper waters and slows as the waters become more shallow. This is not so apparent when seen from the shore line! The crash of the waves, its unraveling and the compression of energy, gives the opposite feeling somehow (at least for me) - that the wave speeds up during the crash. Why does a wave crash? As the water becomes shallow, the lower part of the wave encounters more friction, while the top part closer to the surface continues at speed. The disparity of speed causes the wave to break, as if to shear apart.

Where does a wave end? The wave is a pulse of energy moving through the medium of water. As it hits the shore and crashes, the energy is absorbed by the earth. So in a sense the wave continues infinitely into the earth’s crust and does work on the cliff edge making the grains of sand. That is one way of looking at it. Another way is to think of the movement of water animated by the wave. The wave is in a process of deceleration, reaching zero speed at the moment the water slides back the other way, switching direction. This could be seen as the end of the water wave, when the speed of water hits 0.00 and recedes back the other way.

Based on these observations I’ve designed three sets of code that start to play around with motion inspired by the movement of waves.

CODE (1): DigitalWrite

#define STEP_PIN 10 #define DIR_PIN 11

void setup() {

Serial.begin(115200); pinMode(STEP_PIN, OUTPUT); pinMode(DIR_PIN, OUTPUT); }

void loop() {

Serial.println(“HIGH!”); digitalWrite(DIR_PIN, HIGH);

for (int i = 0; i < 600; i++) { digitalWrite(STEP_PIN, HIGH); delayMicroseconds(1000); digitalWrite(STEP_PIN, LOW); delayMicroseconds(1000); }

Serial.println(“LOW!”); digitalWrite(DIR_PIN, LOW);

for (int i = 0; i < 100; i++) { digitalWrite(STEP_PIN, HIGH); delayMicroseconds(2500); digitalWrite(STEP_PIN, LOW); delayMicroseconds(2500); } }

Reflection: The code is designed to switch directions of rotation. When the DIR_PIN is set High the motor rotates clockwise for the number of steps defined here: for (int i = 0; i < 600; i++) {/ in this case clock wise for 3 full rotations/ each rotation is 200 Steps.

The speed of rotation is set by the next line of code:
digitalWrite(STEP_PIN, HIGH); delayMicroseconds(1000); digitalWrite(STEP_PIN, LOW); delayMicroseconds(1000);

The higher the number the longer it will take to complete the rotations and the slower the motor. This was a good exercise to start to understand how the stepper received information from. I played around with the numbers and observed the changes in rotational direction, number of rotations and speed.

CODE (2): Abrupt Switch in Speed (digitalWrite)

This code simply rotates the stepper in unidirection and switches between two speeds (Slow/Fast) after 180 degrees are pasted.

#define STEP_PIN 10 #define DIR_PIN 11

const int SLOW_DELAY = 6000; // microseconds - slow half const int FAST_DELAY = 800; // microseconds - fast half

void setup() { Serial.begin(115200); pinMode(STEP_PIN, OUTPUT); pinMode(DIR_PIN, OUTPUT); digitalWrite(DIR_PIN, HIGH); }

void loop() {

// FIRST HALF: 0-180 degrees, SLOW
for (int i = 0; i < 100; i++) {
doStep(SLOW_DELAY);

}

// SECOND HALF: 180-360 degrees, FAST
for (int i = 0; i < 100; i++) {
doStep(FAST_DELAY);
}

}

void doStep(int delayTime) { digitalWrite(STEP_PIN, HIGH); delayMicroseconds(delayTime); digitalWrite(STEP_PIN, LOW); delayMicroseconds(delayTime); }

Understanding the code:

I’m trying to understand the time delay in its relationship with the steps. In the case of Slow_Delay it is set to 6000 Microseconds. But when we break this down to the actually singles from the STEP_PIN we see that the its DOUBLED. Meaning that for each step when set at Slow_Delay its 6000µs on HIGH and 6000µs on LOW: making the time for a single step 12,000µs . Which means that the half rotation is a total equals 12,000 * 100 = 1,200,000 = 1.2 seconds?

void doStep(int delayTime) {` digitalWrite(STEP_PIN, HIGH); delayMicroseconds(delayTime); // wait 6000µs digitalWrite(STEP_PIN, LOW); delayMicroseconds(delayTime); // wait 6000µs AGAIN }

CODE (3):Smoother Switch across 2 Speeds (AccelStepper)

For ease, I installed AccelStepper by Mike McCauley library to help move the stepper. This makes things easier by handling the complex pulse generation. Enabling us to control the stepper precisely, through acceleration and deceleration without having to write low level code.

  • The AccelStepper library used Steps per second, rather than the Delay in microseconds. Its calculated through the following formula: steps per second = 1,000,000 / (delay in microseconds x 2) The x 2 is because each step has two delays — one after HIGH and one after LOW, exactly like in the raw code. This its a method of coding were a maximum (FAST) and minimum (SLOW) values are placed and the rotation is set to move smoothly from one value to the other through the mapFloat. Here is a how it works: As i goes from 0 to 99, mapFloat smoothly moves currentSpeed from FAST to SLOW. So: i = 0 → currentSpeed = 277 steps/sec (fast) i = 50 → currentSpeed = 221 steps/sec (medium) i = 99 → currentSpeed = 166 steps/sec (slow)

Code: #include <AccelStepper.h #define STEP_PIN 10 #define DIR_PIN 11 AccelStepper stepper(AccelStepper::DRIVER, STEP_PIN, DIR_PIN); const float SLOW_SPEED = 400; const float FAST_SPEED = 450; void setup() { Serial.begin(115200); stepper.setMaxSpeed(FAST_SPEED); stepper.setAcceleration(500); } void loop() { // FIRST HALF: fast to slow for (int i = 0; i < 100; i++) { float currentSpeed = mapFloat(i, 0, 99, FAST_SPEED, SLOW_SPEED); stepper.setSpeed(currentSpeed); // wait here until this one step actually executes while (!stepper.runSpeed()) {} }

// SECOND HALF: slow to fast for (int i = 0; i < 100; i++) { float currentSpeed = mapFloat(i, 0, 99, SLOW_SPEED, FAST_SPEED); stepper.setSpeed(currentSpeed); // wait here until this one step actually executes while (!stepper.runSpeed()) {} } } float mapFloat(int x, int inMin, int inMax, float outMin, float outMax) { return outMin + (float)(x - inMin) * (outMax - outMin) / (inMax - inMin); }