Arduino Ladder · Bozoma Innovation Hub

Band 6  ·  Things That Move

Swap  The stepper dial

A pointer that moves an exact number of steps and can turn for ever. It has no idea where it is, so you have to remember for it.

Time
85 min
You need
28BYJ-48 stepper, ULN2003 driver board, potentiometer, button, battery pack, 12 jumper wires
At once
One per stepper
Before this
Finish Band 6 Part 7 first. The shared-ground rule matters here exactly as much as it does for the servo.

Sketches for this project

Every file opens with a plain-English header saying what it does and how to wire it, hole by hole.

Why

What a stepper does that a servo cannot

The gate in Band 6 uses a servo. You tell it an angle and it goes there. It can only reach 180 degrees, and it always knows where it is.

A stepper is the other way round in both respects.

  • It can turn for ever, in either direction, all the way round and round again. A servo cannot.
  • It has no idea where it is. You tell it a number of steps and it takes exactly that many. Ask it where it is pointing and it cannot tell you, because nothing inside it is looking.

That second one is the whole difficulty and the whole lesson. If the pointer's position matters, you have to remember it yourself, in a variable, and keep that variable honest every single time you move.

This is the same shape as lastAngle in the servo gate, and it is not optional here. There the deadband was a comfort. Here the remembering is the mechanism.

Build

Wire it

30 min
+ − − + j i h g f e d c b a 1 5 10 15 20 USB ARDUINO UNO ULN2003 driver board ULN2003 driver board IN1 IN1 IN2 IN2 IN3 IN3 IN4 IN4 - - + + knob knob button button 6 V battery pack 6 V battery pack a21 a21 e19 e19 e21 e21 f19 f19 f21 f21 f5 f5 f6 f6 f7 f7 j19 j19 j5 j5 j6 j6 j7 j7 SCL SCL SDA SDA AREF AREF GND GND 13 13 12 12 11 11 10 10 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0 0 IOR IOR RST RST 3V3 3V3 5V 5V GND GND GND GND VIN VIN A0 A0 A1 A1 A2 A2 A3 A3 A4 A4 A5 A5
The driver board and the battery are the only things on the + rail. Four wires on the two rails before you add anything else.
Before you startUSB unplugged, battery switched off. Clear the servo and its wires off the board.
Which rails, before you plug anything inYour board has two + rails and two − rails, one pair along each long edge, and on most boards the top pair and the bottom pair are not joined to each other. On this page, the + rail and the − rail always mean the pair along the top edge, the ones nearest row j, the same pair Band 6 used. The button's a21 wire starts down in the bottom block and still runs the long way round to the top − rail.

The check two steps below counts seven wires on those rails. It will count seven even if some of them are on the wrong strip, so count them on one strip.

The motor end is easy

The blue cylinder has a white plug on a short lead. It goes into the white socket on the driver board and it only fits one way. That end cannot be got wrong.

The Arduino end has one trap in it

Driver boardArduino pinNote
IN18
IN210Not 9. Read the box below.
IN39Not 10.
IN411
−—The breadboard − rail
+—The breadboard + rail
8, 10, 9, 11. The middle two are crossed on purpose.The Stepper library treats the first two pins you give it as the two ends of one coil, and the last two as the two ends of the other. Inside a 28BYJ-48 the two ends of one coil are IN1 and IN3, not IN1 and IN2. So IN3 has to land on pin 9, where the library is expecting pin 8's partner. Crossing the two middle wires is how you hand the library the pairs it thinks it has.

Wire them 8, 9, 10, 11 in the obvious order and the motor will buzz, shake, and go nowhere at all. It is not broken and neither are you. This is the single most common way this build fails, and now it cannot catch you.

The rest

Battery pack red to the + rail, black to the − rail. Then check it before any power: two reds on the + rail, two blacks on the − rail, nothing else on either yet.

You should seeExactly four wires on the two rails at this moment. The driver board's two, and the battery's two. Three more will join the − rail in the next steps: the ground link, the knob's j5 wire and the button's a21 wire. Nothing else ever will.

One wire from the − rail to an Arduino GND pin.

Same wire, same reason, same band. A stepper on its own battery needs the shared ground exactly as much as the servo did. Leave it out and you get the buzzing again, from a different cause, which is why you check the pin order and this wire before suspecting anything else.

The knob. Legs in f5, f6, f7. Wire j5 to the − rail, j6 to A0, and j7 straight to the Arduino's 5V pin.

Not to the + railThe + rail is battery power, about six volts. An Arduino pin must never see more than five. The knob takes its power from the Arduino's own 5V pin, on its own wire.

The button. Four legs into e19, e21, f19, f21, body over the middle channel. Wire j19 to pin 2 and a21 to the − rail.

Make the pointer and the dial. Tape a strip of card to the motor's shaft so it sticks out like a hand. Then draw a dial on another piece of card, tape the motor to the middle of it, and mark where the pointer starts.

You should seeThe pointer swinging clear of the card all the way round, and the motor held down firmly enough that it does not walk when it turns.
Mark the starting positionDraw a line on the dial where the pointer is sitting right now, before you power anything. The sketch assumes the pointer starts at step 0, and if you ever get confused about where it is, switching off and turning it back to that line by hand is how you start again.

Plug in the USB, switch the battery on, and upload b6_06_stepper_dial.ino. Open the serial monitor at 9600.

You should seeThe pointer moving to wherever the knob is set, slowly and smoothly, and holding there. Turn the knob and it follows. Press the button and it goes all the way round once and comes back to the knob's position.
If it buzzes and shakes but does not turnThe pin order. 8, 10, 9, 11. This is the fault four times out of five.
If nothing happens at allThe shared ground wire, or the battery is off. To test, turn the knob a long way from one end to the other and watch the four little lights on the driver board. They should flicker while it steps, and two of them stay lit when it stops. If they never light at all, even with the knob right round, the board has no power. Dark lights on their own are not proof of anything: if the pointer is already where the knob is asking for, the sketch is not stepping and the lights have nothing to show.
If it turns but the wrong waySwap the two wires on Arduino pins 8 and 9, so that IN1 goes to 9 and IN3 goes to 8. That reverses the order of the first pair, which reverses the direction. Do not swap 8 and 11: that gives you the buzzing instead. Or leave it and remember which way is which, since nothing in this build cares.
The button makes the sketch stop listening for six secondsAt the speed this sketch uses, one full turn takes about six seconds, and dial.step() does not return until the turn is finished. During those six seconds the knob is ignored and a second press of the button is not noticed. That is not a fault, but it is a real limit, and it is the same lesson delay() taught you in Band 5: while one thing is happening, nothing else is.
If it gets hot when standing stillThat is normal for a stepper and it is one of their real costs. A stepper holds its position by pushing constantly, whether anything is resisting it or not, so it draws its full current even when nothing is moving. A servo is different: it only pushes when something is pushing back, which is why it goes quiet once it has arrived, and why Band 6 Part 7 offers detach() as a way of saving battery rather than as a necessity. Neither is happy left powered for hours, but the stepper is the greedier of the two.
Look closer

The number you have to keep honest

25 min

Find these lines in the sketch:

long atStep = 0;            // where we believe the pointer is

void goToStep(long target) {
  long move = target - atStep;
  if (move == 0) {
    return;
  }
  dial.step(move);
  atStep = target;
}

Read the comment on the first line again. Where we believe the pointer is. Not where it is. Nothing in this circuit can tell you where it actually is.

dial.step(move) takes a number of steps and a direction, worked out by subtracting. Then atStep = target updates the belief. Those two lines must always happen together, and the moment they stop matching reality, everything after it is wrong and nothing complains.

Break it, and watch the belief go wrong
  1. Delete the line atStep = target;. Predict what will happen, then upload.
  2. Put it back. Now, while it is running, take hold of the pointer and turn it by hand about a quarter turn. Let go. Turn the knob a little.
What happens, after you have tried both

Without the update: atStep stays at 0 for ever, so every move is calculated from 0 rather than from where it is. Turn the knob a little and the pointer flies off much further than you asked. It gets worse the further round you go, and it never recovers.

Turning it by hand: the pointer is now a quarter turn away from where the sketch believes it to be, and the sketch has no way of finding out. Every future move is off by that quarter turn, permanently, until you restart. The gears will also have complained; do not make a habit of it.

Both faults have the same shape: a variable and the world stopped agreeing, and nothing in the system noticed. That is what “open loop” means, and almost every cheap moving thing you will ever meet is open loop.

The number 2048

STEPS_PER_TURN is 2048, and that is not a round number by accident. The motor itself takes 32 steps per turn. A gearbox inside divides that down by about 64, which is why it is slow, and why it is far stronger than a motor that size has any right to be. 32 times 64 is 2048.

2048 is a rounding, and you can see itThe gearbox is not exactly 64 to 1. It is closer to 63.68, which makes a true full turn about 2038 steps. Ask for one turn and you will not see the difference. Ask for twenty turns in a row and the pointer will end up noticeably past your starting line. Try it, count how far past, and work out what number would have been right. Cheap parts have specifications that are approximately true, and knowing which of your numbers is approximate is a real engineering skill.

Why the deadband is in steps here

In the servo gate the deadband was 3 degrees. Here it is 20 steps, which is only about three and a half degrees of the pointer, because 2048 steps make a whole turn.

Same idea, different units. Compare the two sketches side by side and check you can say why the numbers are so different for the same amount of movement.

Change it

Make it yours

30 min
Bronze
Make the button turn it anticlockwise instead, and then make a second button that turns it clockwise. Then say in one sentence why atStep does not need updating for either.
Silver
Turn the dial into a gauge for something real: the light sensor from Band 4, or the distance sensor from Band 7. Mark the card with the numbers you measure, not with numbers you assumed. That measuring step is the whole of Band 4 arriving in a new place. Read the box under this list before you wire it.
Gold
Give it a home position. Add a button that returns the pointer to step 0 whatever it currently believes, and use it to fix the by-hand problem above. Then think about what would have to change for the device to find home by itself at switch-on, and write down what extra part you would need. Real machines have that part.
Any sensor you swap in takes its power from the Arduino's 5V pin, never from the + railBand 4 told you to run the light sensor's top leg to “the + rail”, and in Band 4 the + rail was five volts from the Arduino. In this band the + rail is about six volts from the battery. Feed a sensor from that and its middle leg can hand your analog pin nearly six volts. That is over the limit, and it does its damage quietly, with nothing to tell you. The knob's own 5V wire already goes to the right place, so take the knob out and put the sensor's power leg on that same wire. Its bottom leg goes to the − rail as before. A DHT11 is worse again: it is a five-and-a-half volt part, so six volts damages the sensor as well as the pin. The rule has not changed since Part 7: anything the Arduino reads is powered by the Arduino. The + rail is only for things that push.
The answer to the Gold question, if you want to check yourselfA switch at the home position that the pointer presses when it reaches it. Switch on, turn slowly one way until the switch closes, and now you know where you are. Printers, scanners and 3D printers all do this every time you switch them on, and the noise they make while doing it is exactly this.
Done

You still owe Band 6 the same evidence

This Swap replaces the gate, not the band. To claim Band 6 you still need:

  • A video of your dial responding to something, and a photo showing the ground link between the − rail and the Arduino
  • Your notes from the loaded-card activity in Part 1
  • The deadband table from Part 9b, done with your stepper's numbers
  • Your build log, including which way round the pin order caught you, if it did
  • The three deadband values you tried in Part 9c, and which you would choose for a gate and which for a dial
  • Five or six correct answers in Part 12, the Check yourself questions, including question 2

Part 12 asks about a servo sketch you have not built. Answer it anyway. Every idea in it is one you have used here: the deadband, the remembered position, and what happens when a reading is acted on too eagerly. If you can answer it having built the dial, you have understood the band rather than the build, which is the point.

Ship it

One video under sixty seconds, and one post of five lines. You built something different from the person next to you, so your video is the one nobody else in the room can post. Say in the post which build you chose and why — that choice is itself worth a line.

The four shots: three seconds of the thing still, fifteen of you doing something to it, fifteen of it responding all the way to the end, and ten of your measurement or the thing that went wrong first.

Show your work has the template and the three checks to make before anything goes public. Tag it #BozomaBuilds.