Electronics From Zero Search/

Embedded systems · Intermediate

Microcontrollers: pins, inputs and outputs

A microcontroller is a small computer that senses the world through its input pins and acts on it through its output pins. This lesson connects everything from the course to the way real projects are built.

Builds on: dividers, logic, transistor switch, PWM

What is inside a microcontroller?

One chip holds a processor, flash memory for your program, RAM for data, and a set of peripherals wired to its pins. The ones you will use first are:

  • GPIO (general-purpose input/output): pins you can set high or low, or read as high or low.
  • ADC (analogue-to-digital converter): measures a voltage and turns it into a number.
  • Timers and PWM: produce precise timing and the pulse-width modulation you met in the PWM explainer.
  • Serial interfaces such as UART, I²C and SPI, for talking to sensors, displays and computers.

Boards such as the Arduino Uno (5 V logic), Raspberry Pi Pico (3.3 V) and ESP32 boards (3.3 V) put a microcontroller on a board with a USB connection so you can program it easily. The examples below use the Arduino language because it is widely documented.

Know your logic voltage

A 5 V board drives its pins to about 5 V when high; a 3.3 V board drives them to about 3.3 V. Many 3.3 V chips are damaged by 5 V on their pins. Check before connecting two boards or a 5 V sensor to a 3.3 V board.

Digital outputs: blinking an LED

An output pin acts like a switch to the supply (HIGH) or to ground (LOW). Connect an LED with a series resistor between the pin and ground, and the program decides when it lights. The resistor is chosen exactly as in the Circuit lab, using the board’s logic voltage as the supply.

const int LED_PIN = 13;   // the Uno's built-in LED is on pin 13

void setup() {
  pinMode(LED_PIN, OUTPUT);
}

void loop() {
  digitalWrite(LED_PIN, HIGH);
  delay(500);               // wait 500 milliseconds
  digitalWrite(LED_PIN, LOW);
  delay(500);
}
Pin current is limited

Each pin, and the chip as a whole, can only supply a small current, and the limits differ between chips. Look up both in your microcontroller’s datasheet. An LED with a sensible resistor is fine; motors, relays and lamps are not.

Digital inputs: reading a button

An input pin reads whether the voltage on it is high or low. If nothing is connected, the pin floats and picks up electrical noise, reading random values. A pull-up resistor to the supply holds it high until a button connects it to ground. Many microcontrollers have built-in pull-ups you can switch on in code.

const int BUTTON_PIN = 2;

void setup() {
  pinMode(BUTTON_PIN, INPUT_PULLUP);  // internal pull-up: reads HIGH when not pressed
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  bool pressed = (digitalRead(BUTTON_PIN) == LOW);  // the button connects pin 2 to GND
  digitalWrite(LED_BUILTIN, pressed ? HIGH : LOW);
}

Mechanical buttons bounce: for a few milliseconds the contacts make and break several times. If you count presses, ignore changes that happen within a short time of the last one (often 20–50 ms) or add a small RC filter.

Analogue inputs: measuring a voltage

The ADC compares the pin voltage with a reference voltage and returns a whole number. A 10-bit ADC has 2¹⁰ = 1024 steps, so with a 5 V reference each step is about 4.9 mV. Sensors such as LDRs and thermistors are read by placing them in a voltage divider and measuring the middle point. Circuit lab 02 lets you try this with an LDR and a thermistor.

Bench · ideal ADCcode = floor(Vin ÷ Vref × 2ⁿ)
ADC code—
Step size—
Code × step—

void setup() {
  Serial.begin(9600);
}

void loop() {
  int raw = analogRead(A0);            // 0 to 1023 on an Uno (10-bit)
  float volts = raw * (5.0 / 1024.0);  // Arduino's own example divides by 1023; the difference is under 0.1%
  Serial.println(volts);
  delay(200);
}
Model

This is an ideal converter. Real ADCs have small offset, gain and noise errors, and the exact formula and reference options are in each chip’s datasheet. Never apply more than the chip’s allowed voltage to an analogue pin.

“Analogue” outputs with PWM

Most microcontrollers cannot output a true in-between voltage on a normal pin. Instead they use PWM. On an Arduino Uno, analogWrite(pin, value) takes a value from 0 (always off) to 255 (always on) and works on the pins marked with a ~ symbol (3, 5, 6, 9, 10 and 11).

analogWrite(9, 64);   // 64 / 255 ≈ 25% duty: average ≈ 1.25 V on a 5 V board

Open the PWM explainer

Driving bigger loads safely

Motors, relays, LED strips and solenoids need more current than a pin can give. The pin drives a transistor or logic-level MOSFET, which switches the load from its own supply.

  • Connect the grounds of the microcontroller and the load supply together, or the control signal has no reference.
  • Fit a flyback diode across any motor, relay or solenoid.
  • Add a resistor in series with the base (BJT), or a pull-down on the gate (MOSFET) so the load stays off while the board starts up.
  • Motors cause electrical noise and supply dips that can reset the board; capacitors across the supply and separate supplies help.
Safety

Use low-voltage supplies while learning. Lithium batteries can deliver very high currents if shorted and can catch fire if damaged or charged incorrectly; use proper chargers and protection. Never connect a microcontroller project to mains without an enclosed, certified power supply.

Knowledge check

Next steps

Build the automatic night light project Or build a 555 Blinky (no code) Connect a real Arduino: Hardware lab

Try these circuits in a free browser simulator such as Wokwi before buying parts, then build them on a breadboard with a real board. Look up every part in the Component explorer and check its datasheet.