Lesson 1. A servo: an angle by number
In picturesAfter this lesson the canvas has a servo — a small motor with a horn that goes to a set angle and holds it. You set the angle with a number on four switches: 0 — the horn at 0°, 8 — at 90°, 15 — almost at 170°. In the next lesson we build an arm from such servos.
1.1. Idea: the angle is the pulse length
A servo listens to one pin, PWM. Short pulses come to it, one after another. The servo measures how long each pulse lasts and turns the horn:
- a 0.5 ms pulse — 0°;
- a 1.5 ms pulse — 90°;
- a 2.5 ms pulse — 180°.
Between the pulses there is a pause; its length does not matter, as long as the pulses keep coming. This is how servos are driven in model planes, robots and 3D printers: one wire, and any angle.
1.2. Idea: cut time into windows
We measure the pulse length in windows. An 8 kHz clock ticks every 0.125 ms — that is one window. Two CD4029 counters in a chain count windows from 0 to 255 and start again. 256 windows make a frame 32 ms long: one pulse in each frame.
What we want. The pulse is on at the start of the frame, while the count is still small, and goes off at the right window:
PWM1= 1 while the count is less than the pulse length in windows.
The CD4585, a 4-bit comparator, tells “less — greater” for two numbers. Our count has 8 bits, so there are two comparators in a chain: the low one compares the low 4 bits and passes “less” and “equal” to the high one, and the high one decides by its own bits, or, if they are equal, by the answer of the low one. That is how you compare long numbers on paper too: the high digits first, the low ones when the high ones are equal.
1.3. Idea: “number + 4”
The number on the switches is 0 to 15, but the pulse must start at 4 windows (0.5 ms = 0°). So the pulse length is number + 4 windows:
- 0 → 4 windows = 0.5 ms = 0°;
- each next unit adds one window, 0.125 ms, which is 11.25°;
- 15 → 19 windows = 2.375 ms ≈ 169°.
Adding 4 means adding one to bit 2. Bits 0 and 1 do not change, and bit 2 with the carry is worked out like column addition:
| A3 A2 | W2 | W3 | W4 | Example |
|---|---|---|---|---|
| 0 0 | 1 | 0 | 0 | 0 + 4 = 4 |
| 0 1 | 0 | 1 | 0 | 4 + 4 = 8 |
| 1 0 | 1 | 1 | 0 | 8 + 4 = 12 |
| 1 1 | 0 | 0 | 1 | 12 + 4 = 16 |
W2=NOT A2— bit 2 flips: an inverter, CD4069.W3=A3XORA2— bit 3 changes when a carry comes from bit 2: CD4070.W4=A3ANDA2— the carry onwards, into bit 4: CD4081.
We get the number W4 W3 W2 A1 A0 — it goes to the comparators. Three gates instead of a whole adder: we always add the same number, so only the part of the adder needed for the four is left.
1.4. Build
A new project. The chips are ready-made, from the kit file arm-chips.json; their pins get labels (double-click a pin). Build and run in Fast (the engine button at the top).
Step 0. The chips into the library
If the library has no Arm folder yet: the import button in the library → the file arm-chips.json. The Arm folder appears — ten chips for the whole kit (and the parts they are built of inside).
Step 1. Sources
| Part | Setting | Label |
|---|---|---|
| Power | VCC | |
| Ground | GND | |
| Clock | 8kHz | CK |
| Button | RESET | |
| Input (switch) | A0 | |
| Input (switch) | A1 | |
| Input (switch) | A2 | |
| Input (switch) | A3 |
Step 2. The window counter: two CD4029
Clock — click its body until 8kHz. The PE pins of both counters go to RESET: the button sets them to 0.
| Part | Pin | Label |
|---|---|---|
| TI CD4029B | CLOCK CI BD UD PE J1 J2 J3 J4 Q1 Q2 Q3 Q4 CO | CK GND VCC VCC RESET GND GND GND GND C0 C1 C2 C3 CY |
| TI CD4029B | CLOCK CI BD UD PE J1 J2 J3 J4 Q1 Q2 Q3 Q4 | CK CY VCC VCC RESET GND GND GND GND C4 C5 C6 C7 |
Step 3. Number + 4: three gates
One gate of each chip is used; the inputs of the other gates go to GND (in lesson 2 the elbow takes them).
| Part | Pin | Label |
|---|---|---|
| TI CD4069UB | A G B C D E F | A2 W2 GND GND GND GND GND |
| TI CD4070B | A B J C D E F G H | A3 A2 W3 GND GND GND GND GND GND |
| TI CD4081B | A B J C D E F G H | A3 A2 W4 GND GND GND GND GND GND |
Step 4. Compare: two CD4585 → the PWM1 pulse
| Part | Pin | Label |
|---|---|---|
| TI CD4585B | A0 A1 A2 A3 B0 B1 B2 B3 LTIN EQIN GTIN LT EQ | C0 C1 C2 C3 A0 A1 W2 W3 GND VCC VCC LL LE |
| TI CD4585B | A0 A1 A2 A3 B0 B1 B2 B3 LTIN EQIN GTIN LT | C4 C5 C6 C7 W4 GND GND GND LL LE VCC PWM1 |
Step 5. The servo
Menu Mechanics → Servo.
| Part | Pin | Label |
|---|---|---|
| Servo | PWM | PWM1 |
Loose, do not group into a chip: in lesson 2 the second servo shares the clock, the counter and RESET with the first.
1.5. Check
- Turn the power on and press RESET once — the counters go to 0, the servo starts getting pulses.
- Switches
A3 A2 A1 A0=0000— the servo horn is at 0°. - Set the numbers from the table — the horn turns: 11.25° for each unit of the number.
| Number | Switches A3 A2 A1 A0 | Pulse | Angle |
|---|---|---|---|
| 0 | 0 0 0 0 | 0,5 ms | 0° |
| 4 | 0 1 0 0 | 1,0 ms | 45° |
| 8 | 1 0 0 0 | 1,5 ms | 90° |
| 12 | 1 1 0 0 | 2,0 ms | 135° |
| 15 | 1 1 1 1 | 2,375 ms | 169° |
Lesson 1 paste (Cmd+I)
Paste into a new project. The chips from arm-chips.json are needed.
# Lesson 1 - a servo turned by a number: switches A3..A0, the servo goes to number x 11.25 degrees.# Paste into a new project. Chips: arm-chips.json. After power on press RESET once.# ---------- power ----------power(VCC)ground(GND)# ---------- clock 8 kHz, RESET ----------clock{hz=1}(CK)button(RESET)# ---------- shoulder number ----------input(A0)input(A1)input(A2)input(A3)# ---------- window counter: two CD4029, 0..255 ----------"TI CD4029B"(CLOCK=CK, CI=GND, BD=VCC, UD=VCC, PE=RESET, J1=GND, J2=GND, J3=GND, J4=GND, Q1=C0, Q2=C1, Q3=C2, Q4=C3, CO=CY)"TI CD4029B"(CLOCK=CK, CI=CY, BD=VCC, UD=VCC, PE=RESET, J1=GND, J2=GND, J3=GND, J4=GND, Q1=C4, Q2=C5, Q3=C6, Q4=C7)# ---------- +4 for the shoulder: one gate of CD4069, CD4070, CD4081 ----------"TI CD4069UB"(A=A2, G=W2, B=GND, C=GND, D=GND, E=GND, F=GND)"TI CD4070B"(A=A3, B=A2, J=W3, C=GND, D=GND, E=GND, F=GND, G=GND, H=GND)"TI CD4081B"(A=A3, B=A2, J=W4, C=GND, D=GND, E=GND, F=GND, G=GND, H=GND)# ---------- shoulder pulse: two CD4585, count < number + 4 -> PWM1 ----------"TI CD4585B"(A0=C0, A1=C1, A2=C2, A3=C3, B0=A0, B1=A1, B2=W2, B3=W3, LTIN=GND, EQIN=VCC, GTIN=VCC, LT=LL, EQ=LE)"TI CD4585B"(A0=C4, A1=C5, A2=C6, A3=C7, B0=W4, B1=GND, B2=GND, B3=GND, LTIN=LL, EQIN=LE, GTIN=VCC, LT=PWM1)# ---------- servo ----------mservo sh{rot=90}(PWM=PWM1)Stuck? Something doesn't work →