Two programs: an assembly version driving a servo from pushbuttons, and a C version that reads an LM34 temperature sensor through the ADC and positions the servo accordingly.
lab8_part2_pwm_servo.asm— Fast PWM on Timer0/OC0 (PB3). SW0–SW6 on PORTD jump the servo to 0/30/60/90/120/150/180°.lab8_part6_adc_servo.c— Free-running ADC on the LM34, temperature shown on PORTD LEDs, servo positioned by temperature band. (Microchip Studio GCC C Executable project.)
PWM period = 256 × 64 / 1e6 = 16.4 ms (~61 Hz, close enough for hobby servos)
High time = (OCR0 + 1) × 64 µs
OCR0 values were calibrated in-lab against the actual servo (the datasheet values did not match the motor). Theoretical pulse widths at 1 MHz / prescaler 64:
| OCR0 | Pulse (theoretical) | Angle |
|---|---|---|
| 8 | 0.58 ms | 0° |
| 12 | 0.83 ms | 30° |
| 17 | 1.15 ms | 60° |
| 21 | 1.41 ms | 90° |
| 26 | 1.73 ms | 120° |
| 30 | 1.98 ms | 150° |
| 34 | 2.24 ms | 180° |
The angles were verified empirically — re-tune OCR0 for your specific servo if the positions are off.
LM34 = 10 mV/°F. With left-adjusted result and the 2.56 V internal
reference, ADCH reads ≈ °F directly, used both for the LED display and as the
servo band index:
<=31°F -> 0° <51 -> 60° <71 -> 120° <81 -> 150°
<41 -> 30° <61 -> 90° else-> 180°
Part 2 (assembly):
- Pushbuttons → PORTD (ribbon cable), pull-ups enabled in firmware.
- Servo signal → PB3 (OC0), plus servo VTG and GND.
Part 6 (C):
- LM34 output → PA0 (ADC0), sensor VTG and GND.
- LEDs → PORTD, servo → PB3 as above. Disconnect the pushbuttons first.
- Use solid, seated jumpers on the sensor line — loose PA0 wiring causes the LEDs to flicker erratically (the exact failure seen in the original lab).
Assembly part: AVR Assembler Project, device ATmega32, add the .asm.
C part: GCC C Executable Project, device ATmega32. Add lab8_part6_adc_servo.c.
Set the symbol F_CPU=1000000UL (Project → Properties → Toolchain → AVR/GNU C
Compiler → Symbols) or rely on the #ifndef default in the source. Program with
the JTAGICE mkII.
- C source uses
<avr/io.h>and a definedF_CPU(original used<xc.h>, which is for Microchip XC compilers, not avr-gcc). - ADC configured explicitly for free-running auto-trigger;
ADIFis cleared correctly by writing 1. - Bit positions written with named macros (
REFS1,ADLAR,ADEN, …) instead of raw hex.