Week 09 — Input Devices / Sensor Testing with My Custom Board

Group assignment

Individual assignment

Documentation

During Week 8 Electronic Design, I designed and fabricated my own board based on the Seeed Studio XIAO ESP32-C3 microcontroller. After milling, cleaning, and soldering the microcontroller and other components, the final board looked like this:

Custom Yaro board with XIAO ESP32-C3
My custom fabricated board based on XIAO ESP32-C3.

The circuit diagram is shown below:

Yaro board circuit layout and traces
Board layout used for the fabricated board.

I also used the pinout diagram of the XIAO ESP32-C3 to understand how to connect and test the different sensors and actuators.

XIAO ESP32-C3 pinout diagram
XIAO ESP32-C3 pinout reference.

For this week, I tested several input devices and checked how they interacted with the LED on my custom board.

Working with Pins on the XIAO ESP32-C3

At the beginning, I had a problem addressing the pins in Arduino code. I first tried using numeric values such as 1, 2, and 6, but this did not work as expected. After checking documentation and debugging tutorials, I understood that in Arduino IDE for the XIAO ESP32-C3, pins should be addressed with names such as D6, D7, and D10.

This solved the issue, and after that my LED and sensors started working correctly.

Reference materials


1. Embedded LED Blink

My first test was a simple LED blinking program using the LED connected to pin D6 on my custom board.

Code


      
void setup() {          // the setup function runs once when you press reset or power the board
  pinMode(D6, OUTPUT);   // initialize digital pin D6 as an output.
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(D6, HIGH);  // turn the LED on
  delay(1000);             // wait for a second
  digitalWrite(D6, LOW);   // turn the LED off
  delay(1000);             // wait for a second
}

Result

LED blink test on custom board
Embedded LED blink validation on the board.

Video - Ebbedded LED blinking test

Embedded LED blink test.

I also tested the same logic with an external LED. In that case, I only needed to change the pin number from D6 to D10, depending on where the external LED was connected.


2. Embedded Button and LED

Next, I tested the onboard button together with the LED. Every button press toggled the LED state.

How the button works

A push button is a digital input device with only two states: pressed and not pressed. I used INPUT_PULLUP, so the pin reads HIGH when idle and LOW when pressed to ground.

Code

const int ledPin = D6;
const int buttonPin = D7;

bool ledState = false;
bool lastButtonState = HIGH;
bool currentButtonState = HIGH;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);  // button to GND
  digitalWrite(ledPin, LOW);
}

void loop() {
  currentButtonState = digitalRead(buttonPin);

  // detect button press (HIGH -> LOW)
  if (lastButtonState == HIGH && currentButtonState == LOW) {
    ledState = !ledState;
    digitalWrite(ledPin, ledState);
    delay(200);   // simple debounce
  }

  lastButtonState = currentButtonState;
}

Result

The embedded button successfully toggled the LED on and off.

Video - Embedded button and LED test

Button toggling LED state.

The same logic also worked for an external button by changing to const int buttonPin = D10;.

Button test setup with custom board
Button-to-LED test setup.

3. External Vibration Sensor

After testing a basic digital button, I moved on to a vibration sensor.

How the vibration sensor works

A vibration sensor is typically a digital input. In my test, the sensor output became LOW when vibration was detected, so the logic had to match this behavior.

Code

const int ledPin = D6;
const int vibrationPin = D10;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(vibrationPin, INPUT_PULLUP);
  digitalWrite(ledPin, LOW);
}

void loop() {
  int vibrationState = digitalRead(vibrationPin);

  if (vibrationState == LOW) {    // shaking detected
    digitalWrite(ledPin, HIGH);
    delay(50);
    digitalWrite(ledPin, LOW);
    delay(50);
  } else {
    digitalWrite(ledPin, LOW);
  }
}

Result

When the sensor was shaken, the LED blinked quickly. With no vibration, the LED stayed off.

Video - External vibration sensor test

Vibration-triggered LED response.

4. External Analog Sound Sensor

Then I tested an analog sound sensor.

How the sound sensor works

Unlike the vibration sensor, the sound sensor returns an analog value based on sound intensity. I moved the output to an analog pin and used analogRead() instead of digitalRead(). I connected it to A0.

Vibration sensor wired to custom board
External vibration sensor wiring setup.

Code

const int ledPin = D6;
const int soundPin = A0;      // sound sensor connected to A0
const int threshold = 500;    // adjust this value after testing

void setup() {
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
  Serial.begin(115200);
}

void loop() {
  int soundValue = analogRead(soundPin);
  Serial.println(soundValue);

  if (soundValue > threshold) {
    digitalWrite(ledPin, HIGH);
    delay(50);
    digitalWrite(ledPin, LOW);
    delay(50);
  } else {
    digitalWrite(ledPin, LOW);
  }
}

Result

When sound intensity was above the threshold, the LED blinked. Below the threshold, it stayed off. This helped me understand the practical difference between digital and analog sensor behavior.


5. External Analog Ambient Light Sensor

I also tested an ambient light sensor as another analog input device.

How the ambient light sensor works

The sensor measures light intensity as a continuous analog signal. I used the same workflow as the sound sensor: read with analogRead(), compare to a threshold, and react when crossing the threshold.

Ambient light sensor connected to board
Ambient light sensor testing setup.

At first, the threshold was too low and the LED blinked too easily, so I increased it to const int threshold = 2000;.

Observation

With a higher threshold, the LED remained off under normal room light. When I moved my iPhone camera close to the sensor while recording, the LED started blinking again. This suggests the camera light or IR system affected the reading.


6. PIR Motion Sensor

Next, I tested a PIR motion sensor.

How a PIR sensor works

A PIR (Passive Infrared) sensor detects changes in infrared radiation, not camera-like image motion. It responds to heat-pattern changes, such as a person crossing its field of view.

The sensor also needed a warm-up time of around 10 to 30 seconds before stable output.

I experienced some issues with the initial setup, so to better understand how the sensor was behaving, I used the Serial Monitor to observe its input signal in real time.

In my kit, the PIR sensor is a digital sensor, so I had to reconnect it to a digital input pin instead of using an analog input.

Debugging code using Serial Monitor

const int pirPin = D10;

void setup() {
  pinMode(pirPin, INPUT);
  Serial.begin(115200);
}

void loop() {
  Serial.println(digitalRead(pirPin));
  delay(200);
}
Arduino IDE serial monitor for PIR sensor debug
Serial monitor output while validating PIR signal states.

Code for LED blinking on motion

const int ledPin = D6;
const int pirPin = D10;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(pirPin, INPUT);
  digitalWrite(ledPin, LOW);
}

void loop() {
  int motion = digitalRead(pirPin);

  if (motion == HIGH) {
    digitalWrite(ledPin, HIGH);
    delay(60);
    digitalWrite(ledPin, LOW);
    delay(60);
  } else {
    digitalWrite(ledPin, LOW);
  }
}

Result

When motion was detected, the LED blinked rapidly; otherwise it stayed off.

Video - PIR motion sensor test

PIR motion sensor triggering LED blink.

7. Potentiometer (Rotation Sensor)

Finally, I tested a potentiometer (rotation sensor).

How the potentiometer works

A potentiometer is an analog input. Rotating the knob changes resistance and output voltage, which the MCU reads as an analog value. I connected it to A0 and used the reading to control LED blink speed.

Goal

Code

const int ledPin = D6;
const int rotationPin = A0;

void setup() {
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
  Serial.begin(115200);
}

void loop() {
  int sensorValue = analogRead(rotationPin);

  int level = map(sensorValue, 0, 4095, 0, 10);
  level = constrain(level, 0, 10);

  Serial.print("Value: ");
  Serial.print(sensorValue);
  Serial.print("  Level: ");
  Serial.println(level);

  if (level == 0) {
    digitalWrite(ledPin, LOW);
    delay(30);
    return;
  }

  int blinkDelay = 550 - (level * 50);

  if (blinkDelay < 20) {
    blinkDelay = 20;
  }

  digitalWrite(ledPin, HIGH);
  delay(blinkDelay);
  digitalWrite(ledPin, LOW);
  delay(blinkDelay);
}

Result

The potentiometer successfully controlled LED blinking speed, creating around ten visible levels from no blinking to very fast blinking.

Video - Potentiometer-controlled LED blink speed

Potentiometer-controlled LED blink speed.

Reflection

This series of tests helped me better understand the difference between digital and analog input devices.

Digital sensors tested

Analog sensors tested

What I learned