# 2. Servos

Servos are motors that adjusts to certain angles following certain PWM pulses.
[![](https://learn.digilabdte.com/uploads/images/gallery/2026-04/scaled-1680-/image-1775439129336.png)](https://learn.digilabdte.com/uploads/images/gallery/2026-04/image-1775439129336.png)

## Servo Signal Operation
Servo operates with 20 ms PWM periods.

[![](https://learn.digilabdte.com/uploads/images/gallery/2026-04/scaled-1680-/image-1775438797003.png)](https://learn.digilabdte.com/uploads/images/gallery/2026-04/image-1775438797003.png)

![](https://cdn.getmidnight.com/84f7b02a8128f5f5775611244c24b941/2023/02/ServoGif.gif)

| Parameter   | Typical Value  |
| ----------- | -------------- |
| PWM Period  | ≈ 20 ms        |
| Pulse Width | ≈ 1 – 2 ms     |

Servo operates with 20 ms PWM periods. This can hardly be achieved with Timer0 since Timer0 is an **8-bit timer**.

This means its maximum counter value is:

```
2^8 - 1 = 255
```
20 ms period is hardly achievable with this which requires a **16-bit timer** is preferred.

---

[![](https://learn.digilabdte.com/uploads/images/gallery/2026-04/scaled-1680-/image-1775439744377.png)](https://learn.digilabdte.com/uploads/images/gallery/2026-04/image-1775439744377.png)


This allows precise generation of long PWM periods.

Using a prescaler of 8:

[![](https://learn.digilabdte.com/uploads/images/gallery/2026-04/scaled-1680-/image-1775439774296.png)](https://learn.digilabdte.com/uploads/images/gallery/2026-04/image-1775439774296.png)

Timer tick duration:

[![](https://learn.digilabdte.com/uploads/images/gallery/2026-04/scaled-1680-/image-1775439802013.png)](https://learn.digilabdte.com/uploads/images/gallery/2026-04/image-1775439802013.png)

Required servo period: 20 ms

Number of timer counts required:

[![](https://learn.digilabdte.com/uploads/images/gallery/2026-04/scaled-1680-/image-1775439866000.png)](https://learn.digilabdte.com/uploads/images/gallery/2026-04/image-1775439866000.png)

---

### Servo Initialization Code Example

```asm
  SBI DDRB, 1
```

Configure **OC1A pin** as output.
Timer1 will control this pin automatically.

---

```asm
LDI R22, (1<<COM1A1) | (1<<WGM11)
STS TCCR1A, R22
```

TCCR1A configuration:

| Bit        | Purpose                         |
| ---------- | ------------------------------- |
| COM1A1 = 1 | Enable PWM output on OC1A       |
| WGM11 = 1  | Part of Fast PWM mode selection |

This connects Timer1 to the output pin.

---

```asm
LDI R22, hi8(40000)
STS ICR1H, R22
LDI R22, lo8(40000)
STS ICR1L, R22
```

Set **ICR1 = 40000**.

This is to make the Timer 1 count to 40 000 following the previous calculations.

```asm
LDI R22, (1<<WGM13) | (1<<WGM12) | (1<<CS11)
STS TCCR1B, R22
```

TCCR1B configuration:

| Bit           | Purpose                   |
| ------------- | ------------------------- |
| WGM13 + WGM12 | Complete Fast PWM Mode 14 |
| CS11 = 1      | Prescaler = 8             |

This starts Timer1 in Fast PWM mode.

### Servo Initialization
```asm
; Sets Timer1 PWM in PB1 to use period of 20ms by using Fast PWM.
; Timer1 counts until ICR1
SERVO_init:
  SBI DDRB, 1

  LDI R22, (1<<COM1A1) | (1<<WGM11)
  STS TCCR1A, R22

  LDI R22, hi8(40000)
  STS ICR1H, R22
  LDI R22, lo8(40000)
  STS ICR1L, R22

  LDI R22, (1<<WGM13) | (1<<WGM12) | (1<<CS11)
  STS TCCR1B, R22

  RET
```
### Servo Usage
```asm
  .EQU LEFT, 2400  ; Generates a 2400/40000 % duty cycle. 

  LDI R16, hi8(LEFT)
  STS OCR1AH, R16
  LDI R16, lo8(LEFT)
  STS OCR1AL, R16
```

This code makes the PWM generate compare match at count `2400` this allows it to produce a 2400/40000 * 20 ms = ~1.2 ms pulse which is around 0 degrees.