TinySkiff ESP32-S3 Lab · Day 22 of 30

Make a motor
answer the knob

Today the board moves something. A knob sets the plan, three small signals carry it to the L293D driver chip, and the chip switches a 9V battery's current through a DC motor. Sweep the knob and the shaft speeds up, slows, stops at centre, and spins the other way.

About 30 minutesArduino firstMicroPython optionalBring a 9V battery
Agent assist code TSK-DAY22-MOTOR

Hand this to an agent so it can pull the lesson packet and coach you step by step.

01 First, know the pieces

What you need

Six pictured parts plus one you supply yourself — a 9V battery. Freenove leaves the battery out of the box, so have a fresh one ready along with the kit's battery line (the clip-on lead that reaches the extension board). Tap Define on any part you haven't met — the answer opens as a field note you can read and dismiss without losing your place.

Official manual photo of the ESP32-S3 development board.
Manual photo

ESP32-S3 board

The brain that runs your uploaded sketch.

Official manual image of the ESP32-S3 GPIO extension board.
Manual photo

GPIO extension board

Spreads the pins into rows — and carries the battery's power today.

Official manual photo of a small DC motor with two terminals and a metal shaft.
Manual photo

DC motor

The part that moves — current through its two terminals spins the shaft.

Official manual photo of the L293D motor driver chip, a sixteen-pin integrated circuit.
Manual photo

L293D driver chip

Takes the board's small signals and switches the battery's current.

Official manual illustration of a rotary potentiometer with rotation arrows and its three pins labelled 1, 3, and 2.
Manual illustration

Rotary potentiometer

The knob — one sweep sets both speed and direction.

Official manual image of a jumper wire.
Manual photo

Jumper wires (M/M)

Temporary, solder-free connections.

02 Make the physical circuit

Chart the circuit

The official Freenove diagram is your chart — schematic on top, the same circuit built on a breadboard below. Click it to enlarge. More wires than usual today, so take the connections one row at a time.

Official Freenove circuit — C Tutorial, Chapter 16 (Relay & Motor), page 147. The crop keeps Freenove's note about powering the motor from a 9V battery — that note is the heart of today's safety rule.
L293D In1 GPIO 13 First direction signal — HIGH here drives the motor one way.
L293D In2 GPIO 14 Second direction signal — always set opposite to In1.
L293D Enable1 GPIO 12 The speed signal — PWM here sets how hard the motor drives.
Pot outer pins 3.3V and GND Feed the knob's track so the wiper can sweep between them.
Pot middle pin GPIO 1 The knob's voltage lands here — the pin the code reads as A0.
Motor terminals L293D Out1 and Out2 Where the chip feeds the battery's current to the motor.
9V battery line Extension board power terminal Supplies the motor's current so the USB port never carries it.

Power the motor from the battery only. Freenove's warning is direct — powering the motor from the ESP32-S3 directly "may cause permanent damage to your ESP32-S3". Even spinning free, this motor draws about 0.2–0.3 A, far past what the board can supply. Connect the 9V battery to the extension board's power terminal and let it carry the motor.

Share one ground. An external supply must share a common ground with the board — the extension board's power terminal does this for you when it's wired as charted. Unplug USB before you move any wire.

03 One action at a time

Build it

This is the main path — you can finish the day without opening a single field note. Tap each step as you go to keep your place.

0 / 10 done
  1. Keep USB unplugged, seat the ESP32-S3 on the GPIO extension board, and set the 9V battery aside until the wiring is checked.

  2. Press the L293D into the breadboard so its notch faces the same way as the chart — the chip only works one way round.

  3. Wire the direction pins — In1 → GPIO 13 and In2 → GPIO 14.

  4. Wire the speed pin — Enable1 → GPIO 12.

  5. Connect the motor's two terminals to the chip's Out1 and Out2.

  6. Wire the potentiometer — outer pins to 3.3V and GND, middle pin to GPIO 1.

  7. Clip the battery line onto the 9V battery and connect it to the extension board's power terminal, minding + and −.

  8. Compare every wire to the chart — this is the day to be fussy about it — then plug in USB.

  9. Open Sketch_16.1_Control_Motor_by_L293D.ino in Arduino IDE and upload it.

  10. Switch on the extension board's power and sweep the knob slowly from end to end.

The board moves the world.

A knob in your hand is now steering a spinning shaft. Head to Test & debug to confirm the centre-stop and the reverse.

04 Read just enough code

Read the code

One sketch, three jobs — read the knob, work out speed and direction from the centre point, and hand both to the driver chip. Switch to MicroPython if you'd rather see the same idea in Python — the wiring never changes.

Sketch_16.1_Control_Motor_by_L293D.ino
int in1Pin = 13;      // Define L293D channel 1 pin
int in2Pin = 14;      // Define L293D channel 2 pin
int enable1Pin = 12;  // Define L293D enable 1 pin
int channel = 0;

boolean rotationDir;  // Define a variable to save the motor's rotation direction
int rotationSpeed;    // Define a variable to save the motor rotation speed

void setup() {
  Serial.begin(115200);
  pinMode(in1Pin, OUTPUT);
  pinMode(in2Pin, OUTPUT);
  pinMode(enable1Pin, OUTPUT);

  ledcAttachChannel(enable1Pin, 1000, 11, channel);//Set PWM to 11 bits, range is 0-2047
}

void loop() {
  int potenVal = analogRead(A0);      // Convert the voltage of rotary potentiometer into digital
  if (potenVal > 2048)
    rotationDir = true;
  else
    rotationDir = false;
  // Calculate the motor speed
  rotationSpeed = abs(potenVal - 2048);
  Serial.println(rotationSpeed);
  delay(100);
  driveMotor(rotationDir, constrain(rotationSpeed,0,2048));
}

void driveMotor(boolean dir, int spd) {
  // Control motor rotation direction
  if (dir) {
    digitalWrite(in1Pin, HIGH);
    digitalWrite(in2Pin, LOW);
  }
  else {
    digitalWrite(in1Pin, LOW);
    digitalWrite(in2Pin, HIGH);
  }
  // Control motor rotation speed
  ledcWrite(enable1Pin, spd);
}
analogRead(A0)Reads the knob. A0 is this board's alias for GPIO 1 — the same pin your wire lands on.
ledcAttachChannel(enable1Pin, 1000, 11, channel)Sets up PWM on the enable pin at 11 bits, so speed runs from 0 to 2047.
rotationSpeed = abs(potenVal - 2048)Speed is the knob's distance from centre; which side of 2048 it sits on picks the direction.
ledcWrite(enable1Pin, spd)Hands the speed to the chip — more on-time on Enable1 means more push through the motor.

05 Understand, don't memorise

Small signals, borrowed muscle

A GPIO pin is a messenger. It can say a lot, and it can carry almost nothing. Today's chip is the porter that carries the load the message describes.

Read

Knob to number

The ADC turns the pot's voltage into a number from 0 to 4095.

Decide

Centre is zero

Distance from 2048 is the speed and its side is the direction.

Signal

Three small wires

In1 and In2 set direction while Enable1 carries the PWM speed.

Deliver

Chip switches battery

The L293D feeds the 9V battery's current through the motor.

The model speed = distance from 2048 · direction = side of 2048

Why the chip is here

A GPIO pin can offer a few milliamps, and this motor draws around 0.2–0.3 A before it even does any work. The L293D takes the pin's small signal and switches the battery's heavy current — the board decides, the chip delivers.

Two power worlds, one ground

The 9V battery moves the motor; USB feeds the board. The two supplies only agree on what HIGH and LOW mean because they share a ground on the extension board — that shared wire is what makes the chip's inputs readable.

06 Know it worked

Test & debug

The proof today is the spinning shaft in front of you — Serial Monitor backs it up with a live speed number.

What you should see
Motor
  • Knob at centre — the motor sits still.
  • Turn one way — the shaft spins up, faster the further you go.
  • Sweep back through centre — it slows, stops, then spins the other way.
  • Serial Monitor at 115200 baud prints the speed number — 0 at centre, up to 2047 at the ends.

Expect a small still zone either side of centre — a motor needs a push of current before it beats its own friction, so the first sliver of knob travel does nothing. Today's challenge puts a number on exactly that.

If it doesn't
  • Motor never spins? Check the 9V battery on the extension board — its switch and its wiring — then the L293D's orientation by the notch.
  • Spins one direction only? A direction wire is loose or swapped — recheck In1 on GPIO 13 and In2 on GPIO 14.
  • Board resets or USB drops out? You're powering the motor from USB — stop and connect the 9V battery so the extension board carries the load.
  • Speed number stuck in Serial Monitor? Check the pot's middle wire on GPIO 1 — the pin the code reads as A0.

07 Make the idea yours

Try this: find the starting push

Same working circuit, two experiments with the numbers on your screen. It fits inside today's 30 minutes.

Find the breakaway number

Creep the knob out from centre while watching Serial Monitor. Note the number on screen the moment the shaft first turns — that's the push this motor needs to beat its own friction. Try it in both directions.

Print a signed speed

Change the sketch so Serial prints potenVal - 2048 in place of the abs() value. Now one direction reads positive and the other negative — a single number that tells the whole story of the shaft.

Logbook

08 Learn it with a hand on the tiller

Coach me through it

Every lesson ships with a code and a machine-readable packet, so an agent can guide you with full context.

Lesson code

TSK-DAY22-MOTOR

How the agent should behave: guide one physical connection at a time, wait for you to confirm, keep the 9V-battery rule front and centre, and always check wiring, power, board, and port before changing code.

Field note

Shortcut

Prompt copied