Drive a Servo
Type an angle, watch it move. You’ll control a servo motor from the REPL, build a sweep, and wire a potentiometer for direct knob-to-motion control.
Servos are the most physically satisfying thing you can control from the REPL. Type a number and a thing moves. In Arduino you’d write code, compile, flash, and then watch it move. Here you type 90 servo and the arm swings.
Prerequisites
- Chapters 00–04 of the guide (the stack, word definitions, named values)
- The Blink an LED tutorial (GPIO basics)
- Hardware: ESP32 DevKit v1, a standard hobby servo (SG90, MG90S, or similar), jumper wires
- Optional: a potentiometer wired to GPIO 34
What you are building
Interactive servo control from the REPL, then automated sweeps and knob control. By the end you’ll have:
- Moved a servo to any angle by typing a number
- A sweep that pans smoothly from 0 to 180 degrees and back
- A configurable
patrolword that sweeps continuously - (Extension) A potentiometer that controls the servo angle directly
Hardware setup
Wiring the servo
A standard hobby servo has three wires:
| Wire color | Connection |
|---|---|
| Red (or brown) | 5V power (use the ESP32’s VIN or an external 5V supply) |
| Brown (or black) | GND |
| Orange (or yellow/white) | Signal to GPIO 13 |
Power note: Small servos (SG90) draw up to ~750mA under load. The ESP32’s USB power can handle one SG90 for light work. If the servo jitters, stutters, or the board resets, it’s drawing too much current. Use an external 5V supply for the servo’s power wire and keep GND shared with the ESP32.
Pin choice: GPIO 13 is used here. Any PWM-capable pin works. Avoid GPIO 0 (BOOT button), GPIO 1/3 (serial TX/RX), and input-only pins (34, 35, 36, 39).
Step 1 — Move to a position
froth> 13 'servo-pin def
froth> servo-pin 90 servo.write
The servo arm should move to 90 degrees (center position). Try other angles:
froth> servo-pin 0 servo.write \ full left
froth> servo-pin 180 servo.write \ full right
froth> servo-pin 45 servo.write \ halfway left
servo.write ( pin angle -- ) moves the servo on pin to angle degrees (0-180). The servo holds that position until told otherwise.
Type a number, the arm moves. Change the number, it moves again. No build step, no flash cycle.
Step 2 — Define a convenience word
froth> : servo ( angle -- )
... servo-pin swap servo.write ;
froth> 0 servo
froth> 90 servo
froth> 180 servo
Pick random angles. Watch the arm snap to each one.
Step 3 — Smooth sweep
A smooth sweep from 0 to 180 degrees:
froth> : sweep-up ( step-ms -- )
... 0
... [ dup 180 <= ] [
... dup servo
... 1 +
... over ms
... ] while
... drop drop ;
froth> : sweep-down ( step-ms -- )
... 180
... [ dup 0 >= ] [
... dup servo
... 1 -
... over ms
... ] while
... drop drop ;
froth> 10 sweep-up
froth> 10 sweep-down
The servo pans smoothly across its range. step-ms controls the speed: 5 is fast, 20 is slow and deliberate. The structure is identical to fade-up and fade-down from the Fade an LED
tutorial, just with a different range and output word.
Step 4 — Continuous patrol
froth> : patrol ( step-ms -- )
... [ true ] [
... dup sweep-up
... dup sweep-down
... ] while
... drop ;
froth> 10 patrol
The servo sweeps back and forth continuously.
Redefine with a pause at each end:
froth> : patrol ( step-ms -- )
... [ true ] [
... dup sweep-up 500 ms
... dup sweep-down 500 ms
... ] while
... drop ;
froth> 10 patrol
Half a second of stillness at each extreme. Redefine and call again.
Extension: potentiometer-controlled servo
Wire a potentiometer to GPIO 34 (same setup as Read a Sensor ). Map the ADC range (0-4095) to servo degrees (0-180):
froth> 34 'pot-pin def
froth> : read-angle ( -- degrees )
... pot-pin adc.read 180 * 4095 / ;
froth> : knob-servo ( -- )
... [ true ] [
... read-angle servo
... 20 ms
... ] while ;
froth> knob-servo
Turn the potentiometer. The servo arm tracks your hand. Left = 0 degrees, right = 180 degrees, everywhere in between.
The entire program is four words, each one line long.
Extension: named position presets
Define named positions and switch between them:
froth> 0 'pos-left def
froth> 90 'pos-center def
froth> 180 'pos-right def
froth> : left pos-left servo ;
froth> : center pos-center servo ;
froth> : right pos-right servo ;
froth> left
froth> center
froth> right
The REPL reads like English: left, center, right. Redefine the angles to fine-tune the positions for your specific mechanical setup.
What you learned
servo.write ( pin angle -- )moves a servo to a specific angle (0-180 degrees). The servo holds position.- Servos vs. DC motors: servos move to an angle and stay. DC motors spin continuously. Different tools for different jobs.
- Smooth sweeps: increment the angle by 1 in a loop with a delay between each step. Same pattern as
fade-up/fade-down. - Input-to-output mapping:
read-anglescales ADC counts to degrees. The same scaling pattern works any time you connect a sensor to an actuator. - Named presets with
def: give positions meaningful names. The REPL becomes a command vocabulary for your hardware. - Live redefinition: change
patrolbehavior by redefining the word. The servo responds immediately.