Skip to content

Week 9 - Input Devices


Assignment Overview

Group Assignment: - Probe an input device's analog levels and digital signals

Individual Assignment: - Measure something: add a sensor to a microcontroller board that you have designed and read it


Group Assignment

Introduction

For this week's group assignment, we probed both the analog and digital signals of an input device. We decided to test the SEN-14262 Sound Sensor and observe its signals using an oscilloscope.


The SEN-14262 Sound Sensor

The SEN-14262 is a small sound sensor module that detects sound in the environment. It works with a 3.3–5V power supply and has five pins:

Pin Function
VCC Power supply
GND Ground
AUDIO Raw sound signal
ENVELOPE Smoothed signal showing sound intensity
GATE Goes HIGH when sound crosses a set threshold

Since the sensor outputs both analog (envelope) and digital (gate) signals, we used a single program to read both values and observe the waveforms on the oscilloscope.


Setup

Here is the code we used to read both signals:

const int digitalPin = 2; // Gate output
const int analogPin = A0; // Envelope or Audio output

void setup() {
  Serial.begin(115200);
  pinMode(digitalPin, INPUT);
  Serial.println("Reading SparkFun Sound Detector...");
  Serial.println("Format: DigitalValue , AnalogValue");
  Serial.println("------------------------------------");
}

void loop() {
  int digitalVal = digitalRead(digitalPin);
  int analogVal = analogRead(analogPin);

  Serial.print(digitalVal);
  Serial.print(" , ");
  Serial.println(analogVal);

  delay(10);
}

Analog Signal

An analog signal changes smoothly and continuously over time, and can represent any value within a range — like the continuous variation in sound volume.

The AUDIO/ENVELOPE pin was connected to the analog pin A0 of the microcontroller. The oscilloscope probe tip was placed on this same pin, with the ground clip connected to GND. This allowed us to visualize the continuous voltage changes produced by the microphone as a smooth waveform on the oscilloscope.


Digital Signal

A digital signal only switches between two fixed values — HIGH or LOW. It doesn't change smoothly like an analog signal, which makes it very clear and reliable for detecting simple on/off states.

The GATE pin was connected to digital pin D2 of the microcontroller. The oscilloscope probe tip was placed on this pin, with the ground clip on GND. When sound exceeded the sensor's threshold, the GATE signal jumped between its two fixed voltage levels, appearing as a square wave on the oscilloscope.


Conclusion

Through this group assignment, we were able to clearly observe the difference between analog and digital signals using the SEN-14262 sound sensor and an oscilloscope. The analog signal showed a smooth, continuous waveform representing sound intensity, while the digital signal produced a clean square wave switching between HIGH and LOW whenever sound was detected.

For more details, check out the full group assignment page here.


Individual Assignment

This week I got to explore a bunch of different sensors and input devices using my XIAO ESP32 DEV Board. The main goal was simple — get each sensor connected, write the code, and see the readings come through on the Serial Monitor. I used Claude AI to help me write all the code, and honestly it made the whole process so much smoother. I'll include the code for each sensor and explain what's going on.


Creating the XIAO ESP32 DEV Board

Extra thing that I did this week was I designed a XIAO ESP32 DEV Board and milled it. The board was heavily inspired from Mr. Adrián Torres's fabxiao

Thank you Mr. Torres for the inspiration!

I will briefly explain the process of making the board because the process is the same as the previous week.

First I made the schematics for the board in KiCad:

Then I routed all the traces and I didn't use any 0 Ohms resistors!!

After that I made the RML file using MODS CE.

I milled the design in Roland SRM-20 milling machine:

After that I soldered the components to the board I just milled.

Here is my XIAO ESP32 DEV Board:


Sensors Tested This Week

All the sensors I tested this week:

  1. DHT11 Temperature & Humidity Sensor
  2. MPU6050 Accelerometer & Gyroscope
  3. SparkFun Sound Detector
  4. IR Obstacle Sensor
  5. Rotary Encoder
  6. Tactile Button
  7. HC-SR04 Ultrasonic Sensor
  8. Flex Sensor

DHT11 Temperature & Humidity Sensor

The DHT11 is a basic digital temperature and humidity sensor. It's cheap, easy to wire, and works great for reading the ambient conditions in a room. I used the module version which already has a pull-up resistor built in, so it's literally just 3 wires.

Wiring Configuration

DHT11 Module XIAO ESP32-C3
VCC 3.3V
GND GND
DATA D2 (GPIO4)

Required Library

I installed the DHT sensor library by Adafruit and Adafruit Unified Sensor through the Library Manager in Arduino IDE.

Code Implementation

I generated this code using Claude AI with the following prompt:

"Write an Arduino program for a DHT11 temperature and humidity sensor. I will give you the pins I used — DATA is connected to D2 (GPIO4) on the XIAO ESP32-C3. Factcheck the code before you answer me."

What does the code do?

This code reads temperature and humidity data from a DHT11 sensor connected to a XIAO ESP32-C3 microcontroller. Every 2 seconds, it measures the humidity as a percentage, and the temperature in both Celsius and Fahrenheit. If the sensor fails to return valid data, it prints an error message in the Serial Monitor warning the user to check the wiring. If the readings are valid, it displays all three values neatly in the Serial Monitor with a separator line. It repeats this process continuously, allowing the system to monitor environmental conditions in real time.

#include <DHT.h>

#define DHT_PIN  4        // D2 = GPIO4 on XIAO ESP32-C3
#define DHT_TYPE DHT11

DHT dht(DHT_PIN, DHT_TYPE);

void setup() {
  Serial.begin(115200);
  dht.begin();
  Serial.println("DHT11 Ready!");
}

void loop() {
  delay(2000);

  float humidity    = dht.readHumidity();
  float tempC       = dht.readTemperature();
  float tempF       = dht.readTemperature(true);

  if (isnan(humidity) || isnan(tempC)) {
    Serial.println("Failed to read from DHT11! Check wiring.");
    return;
  }

  Serial.print("Humidity:    ");
  Serial.print(humidity);
  Serial.println(" %");

  Serial.print("Temperature: ");
  Serial.print(tempC);
  Serial.print(" °C  |  ");
  Serial.print(tempF);
  Serial.println(" °F");

  Serial.println("-------------------");
}

Test Results

It worked on the first try which was great! The temperature was reading around 23°C and humidity around 47–53% which is pretty normal for an indoor room.


MPU6050 Accelerometer & Gyroscope

The MPU6050 is a 6-axis motion sensor — it measures acceleration on 3 axes and rotation on 3 axes, plus it has a built-in temperature sensor. It uses I2C which means only 4 wires are needed. I wanted to test this one because motion sensing is super useful for interactive projects.

Wiring Configuration

MPU6050 XIAO ESP32-C3
VCC 3.3V
GND GND
SDA D4 (GPIO6)
SCL D5 (GPIO7)
XDA, XCL, AD0, INT Not connected

Required Library

I installed Adafruit MPU6050, Adafruit Unified Sensor, and Adafruit BusIO from the Library Manager.

Code Implementation

I generated this code using Claude AI with the following prompt:

"Write an Arduino program for the MPU6050 accelerometer and gyroscope module. I will give you the pins I used — SDA is connected to D4 (GPIO6) and SCL to D5 (GPIO7) on the XIAO ESP32-C3. Factcheck the code before you answer me."

What does the code do?

This code reads motion and temperature data from an MPU6050 sensor connected to a XIAO ESP32-C3. At startup, it checks if the sensor is connected and configures the accelerometer, gyroscope, and filter settings. Every 500 milliseconds, it prints the acceleration (m/s²), rotation speed (rad/s) on all three axes, and the sensor's internal temperature in Celsius to the Serial Monitor. It repeats this continuously, allowing the system to track movement and orientation in real time.

#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>

Adafruit_MPU6050 mpu;

void setup() {
  Serial.begin(115200);
  Wire.begin(6, 7); // SDA=GPIO6, SCL=GPIO7 for XIAO ESP32-C3

  if (!mpu.begin()) {
    Serial.println("MPU6050 not found! Check wiring.");
    while (1) delay(10);
  }
  Serial.println("MPU6050 Ready!");

  mpu.setAccelerometerRange(MPU6050_RANGE_8_G);
  mpu.setGyroRange(MPU6050_RANGE_500_DEG);
  mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);

  delay(100);
}

void loop() {
  sensors_event_t a, g, temp;
  mpu.getEvent(&a, &g, &temp);

  Serial.println("---- MPU6050 Reading ----");

  Serial.print("Accel X: "); Serial.print(a.acceleration.x);
  Serial.print("  Y: ");     Serial.print(a.acceleration.y);
  Serial.print("  Z: ");     Serial.print(a.acceleration.z);
  Serial.println(" m/s²");

  Serial.print("Gyro  X: "); Serial.print(g.gyro.x);
  Serial.print("  Y: ");     Serial.print(g.gyro.y);
  Serial.print("  Z: ");     Serial.print(g.gyro.z);
  Serial.println(" rad/s");

  Serial.print("Temp:     ");
  Serial.print(temp.temperature);
  Serial.println(" °C");

  Serial.println("-------------------------");
  delay(500);
}

Test Results

The accelerometer X axis was reading around 10 m/s² when the sensor was lying flat — that's just gravity, which means it's working correctly! The gyro values were close to 0 when the sensor wasn't moving, which is also exactly what you'd expect.


SparkFun Sound Detector

The SparkFun Sound Detector is a really cool module. Unlike a simple microphone, it has three separate outputs — a digital GATE pin that tells you when sound is detected, an ENVELOPE pin that gives you the volume level as an analog value, and an AUDIO pin for the raw signal. I used the GATE and ENVELOPE pins for this test.

One thing to note — this module needs at least 3.5V to work properly, so I powered it from the 5V pin on the XIAO-DEV (from USB) instead of 3.3V.

Wiring Configuration

Sound Detector XIAO ESP32-C3
VCC 5V
GND GND
GATE D3 (GPIO5)
ENVELOPE A0 (GPIO2)
AUDIO Not connected

Code Implementation

I generated this code using Claude AI with the following prompt:

"Write an Arduino program for the SparkFun Sound Detector. I will give you the pins I used — GATE is connected to D3 (GPIO5) and ENVELOPE to A0 (GPIO2) on the XIAO ESP32-C3. Factcheck the code before you answer me."

What does the code do?

This code reads sound data from a SparkFun Sound Detector sensor connected to a XIAO ESP32-C3. It continuously checks two things: the Gate pin to detect whether sound is present or not, and the Envelope pin to measure the loudness as an analog value. It then maps that loudness into a visual bar made of | characters and prints everything to the Serial Monitor every 50 milliseconds, allowing the system to detect and visualize sound levels in real time.

#define GATE_PIN     5   // D3 = GPIO5
#define ENVELOPE_PIN A0  // GPIO2

void setup() {
  Serial.begin(115200);
  pinMode(GATE_PIN, INPUT);
  pinMode(ENVELOPE_PIN, INPUT);
  Serial.println("SparkFun Sound Detector Ready!");
}

void loop() {
  int gate     = digitalRead(GATE_PIN);
  int envelope = analogRead(ENVELOPE_PIN);

  int bars = map(envelope, 0, 4095, 0, 20);
  String bar = "";
  for (int i = 0; i < bars; i++) bar += "|";

  Serial.print("GATE: ");
  Serial.print(gate ? "SOUND " : "quiet ");
  Serial.print(" | Envelope: ");
  Serial.print(envelope);
  Serial.print(" | ");
  Serial.println(bar);

  delay(50);
}

Test Results

Clapping near the sensor shot the envelope value up to around 1700 and the bar filled up nicely. A quiet room kept values below 200. The GATE was flipping between "SOUND" and "quiet" responsively which was satisfying to watch.


IR Obstacle Sensor

The IR obstacle sensor is a really simple sensor that detects when an object is close in front of it by bouncing an infrared beam off it. Super useful for detecting presence or obstacles. The wiring is only 3 pins and it works directly on 3.3V.

One important thing — the output logic is inverted. The OUT pin goes LOW when it detects something, and stays HIGH when nothing is there. This confused me at first but the code handles it correctly.

Wiring Configuration

IR Module XIAO ESP32-C3
VCC 3.3V
GND GND
OUT D2 (GPIO4)

Code Implementation

I generated this code using Claude AI with the following prompt:

"Write an Arduino program for an IR obstacle sensor module. I will give you the pins I used — OUT is connected to D2 (GPIO4) on the XIAO ESP32-C3. Factcheck the code before you answer me."

What does the code do?

This code reads data from an IR obstacle sensor connected to a XIAO ESP32-C3. It continuously checks whether an obstacle is detected or not, and only prints a message to the Serial Monitor when the state changes — either from clear to detected, or detected to clear.

#define IR_PIN 4   // D2 = GPIO4 on XIAO ESP32-C3

int lastState = -1;

void setup() {
  Serial.begin(115200);
  pinMode(IR_PIN, INPUT);
  Serial.println("IR Sensor Ready!");
}

void loop() {
  int state = digitalRead(IR_PIN);

  if (state != lastState) {
    if (state == LOW) {
      Serial.println(">>> OBSTACLE DETECTED!");
    } else {
      Serial.println("    Clear — no obstacle");
    }
    lastState = state;
  }

  delay(20);
}

Test Results

Waving my hand in front of the sensor triggered it instantly. The state-change only printing made the output super clean to read. You can also adjust the detection range using the blue potentiometer on the board.


Rotary Encoder

A rotary encoder is basically a knob that you can turn infinitely in either direction and it tracks how many steps you've rotated and which way. It also has a push button built in when you press the knob down. Really useful for menus, volume controls, or any kind of user input.

Wiring Configuration

Encoder XIAO ESP32-C3
CLK D1 (GPIO3)
DT D2 (GPIO4)
SW D3 (GPIO5)
VCC 3.3V
GND GND

Code Implementation

I generated this code using Claude AI with the following prompt:

"Write an Arduino program for a rotary encoder module. I will give you the pins I used — CLK is connected to D1 (GPIO3), DT to D2 (GPIO4), and SW to D3 (GPIO5) on the XIAO ESP32-C3. Factcheck the code before you answer me."

What does the code do?

This code reads input from a rotary encoder connected to a XIAO ESP32-C3. It tracks the rotation direction by comparing the CLK and DT pins — incrementing a counter when turned clockwise and decrementing it when turned counterclockwise, printing the updated count to the Serial Monitor each time. It also detects when the built-in encoder button is pressed, with a 50ms debounce to avoid false triggers. This allows the system to track rotational position and button presses in real time.

const int clkPin = 3; // XIAO D1 = GPIO3
const int dtPin  = 4; // XIAO D2 = GPIO4
const int swPin  = 5; // XIAO D3 = GPIO5

int counter = 0;
int currentStateCLK;
int lastStateCLK;
unsigned long lastButtonPress = 0;

void setup() {
  pinMode(clkPin, INPUT);
  pinMode(dtPin, INPUT);
  pinMode(swPin, INPUT_PULLUP);

  Serial.begin(115200);
  lastStateCLK = digitalRead(clkPin);
}

void loop() {
  currentStateCLK = digitalRead(clkPin);

  if (currentStateCLK != lastStateCLK && currentStateCLK == 1) {
    if (digitalRead(dtPin) != currentStateCLK) {
      counter--;
    } else {
      counter++;
    }
    Serial.print("Counter: ");
    Serial.println(counter);
  }

  lastStateCLK = currentStateCLK;

  if (digitalRead(swPin) == LOW) {
    if (millis() - lastButtonPress > 50) {
      Serial.println("Button pressed!");
    }
    lastButtonPress = millis();
  }

  delay(1);
}

Test Results

Rotating the knob clockwise incremented the counter and counterclockwise decremented it. Pressing the knob down printed "Button pressed!" cleanly. The debouncing worked well — no false triggers.


Tactile Button

A tactile button is about as simple as it gets for input devices. Press it and something happens. For this test I wired it up with an LED so you can actually see the response — the LED turns on when the button is pressed.

Wiring Configuration

Component XIAO ESP32-C3
Button D7 (one leg to pin, other to GND)
LED D6 (with resistor to GND)

Code Implementation

I generated this code using Claude AI with the following prompt:

"Write an Arduino program for a tactile button with an LED. I will give you the pins I used — the button is connected to D7 and the LED to D6 on the XIAO ESP32-C3. Factcheck the code before you answer me."

What does the code do?

This code controls an LED using a button connected to a XIAO ESP32-C3. When the button is not pressed, the LED turns OFF, and when the button is pressed, the LED turns ON. It continuously checks the button state and updates the LED accordingly in real time.

const int LED_PIN    = D6;
const int BUTTON_PIN = D7;

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

void loop() {
  int buttonState = digitalRead(BUTTON_PIN);

  if (buttonState == HIGH) {
    digitalWrite(LED_PIN, LOW);
  } else {
    digitalWrite(LED_PIN, HIGH);
  }
}

Test Results

Pressing the button turned the LED on immediately and releasing it turned it off. Clean and responsive. Simple but satisfying!


HC-SR04 Ultrasonic Sensor

The HC-SR04 measures distance by sending out an ultrasonic pulse and timing how long it takes to bounce back. It's the classic distance sensor you see in basically every robotics and electronics project. I actually used one of these before in a motion sensor lamp project, so it was cool to revisit it.

Wiring Configuration

HC-SR04 XIAO ESP32-C3
VCC 5V
GND GND
TRIG D2 (GPIO4)
ECHO D3 (GPIO5)

⚠️ Note: The ECHO pin outputs 5V logic but the XIAO only accepts 3.3V. Ideally use a voltage divider on the ECHO line to protect the pin. For quick testing it may work, but for long-term use add the voltage divider.

Code Implementation

I generated this code using Claude AI with the following prompt:

"Write an Arduino program for the HC-SR04 ultrasonic distance sensor. I will give you the pins I used — TRIG is connected to D2 (GPIO4) and ECHO to D3 (GPIO5) on the XIAO ESP32-C3. Factcheck the code before you answer me."

What does the code do?

This code measures distance using an HC-SR04 ultrasonic sensor connected to a XIAO ESP32-C3. It sends a short ultrasonic pulse through the trigger pin, then measures how long it takes for the echo to return. It converts that duration into a distance in centimeters and prints it to the Serial Monitor every 500 milliseconds. If no echo is received, it prints an out of range warning instead.

const int trigPin = D2;
const int echoPin = D3;

void setup() {
  Serial.begin(115200);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
}

void loop() {
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);

  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  long duration = pulseIn(echoPin, HIGH);

  float distanceCm = duration * 0.034 / 2;

  if (duration > 0) {
    Serial.print("Distance: ");
    Serial.print(distanceCm);
    Serial.println(" cm");
  } else {
    Serial.println("Out of range / No echo");
  }

  delay(500);
}

The distance formula works like this — sound travels at ~0.034 cm per microsecond. We divide by 2 because the pulse travels to the object and back, so the total distance is half the total travel time.

Test Results

Moving my hand closer to the sensor decreased the distance reading and moving it away increased it. The readings were stable and updated every 500ms. Range is roughly 2cm to 400cm.


Flex Sensor

This week I also tried to get inputs from my flex sensor but it didn't work out as I planned. The main problem was that the flex sensor is not firmly connected to the XIAO ESP32-C3. I wanted to make it work but I wasn't able to get time so I will try again next week and update in my project development.


Reflection

This was honestly one of the most fun weeks for me. Getting all these different sensors talking to my XIAO ESP32 DEV Board and seeing real data come through the Serial Monitor was super satisfying. I feel a lot more comfortable with wiring and reading datasheets now.

Using Claude AI to generate the code made the whole process way faster, and I made sure to actually read through each line so I understood what was going on rather than just blindly copy-pasting.


Thank you for reading! See you next week!