Week 9: Input Devices¶
Week 9 Assignment:
-
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
Notes from the Lecture
-
they are multiple ways to get input in:
- ports / pins
- comparator -> the one who will told you voltage is higher or lower. you can do it quickly
- A/D (Analog to Digital converter) -> give you a voltage and give you the number
- I2C -> digital protocol we use, digital signal
-
READ THE DATA SHEET to know what the hardware actually does
GROUP ASSIGNMENT¶
An Input Device’s Analog Levels and Digital Signals¶
INDIVIDUAL ASSIGNMENT¶

The input devices cardboard at Chaihuo Makers Space contains various modules, most of which are from Seeed’s Grove system.
This week, I experimented with different kinds of input devices, including a temperature sensor, touch sensor, mechanical keypad, thumb joystick, PIR motion sensor and RTC (Real-Time Clock).
For all the experiments, I used the XIAO ESP32C3 as the microcontroller.

Since all of the input devices are part of Seeed’s Grove ecosystem, I used the Grove Base for XIAO as an expansion board. This board acts as a bridge between the Seeed Studio XIAO and the Grove modules.

Grove Base for XIAO Information:
Feature:
- On-board Lithium Battery Charging and Management Function
- Grove connectors ( Grove IIC x 2, Grove UART x 1 ), all 14 GPIO led out
- Compact and Breakable Design
- Flash SPI Bonding Pad Reserved
- On-board Power Switch and Charging Status Indicator Light
Specifications:
| Item | Value |
|---|---|
| Operating Voltage | 3.3V / 3.7V Lithium Battery |
| Load Capacity | 800mA |
| Charging Current | 400mA (Max) |
| Operating Temperature | - 40°C to 85°C |
| Storage Temperature | -55°C to 150°C |
| Grove Interface | I2C 2 / UART 1 |
For programming, I used the Arduino IDE.
1. Temperature Sensor¶
-
Prepare the materials needed:
- XIAO ESP32C3
- Grove Base for XIAO
- Grove - Temperature Sensor V1.2
Grove - Temperature Sensor V1.2:
This temperature sensor measures ambient temperature (the temperature of the surrounding environment) using a thermistor. It operates within a range of −40 to 125 °C and has an accuracy of ±1.5 °C.
Specifications:
Item Value Voltage 3.3V ~ 5V Zero Power Resistance 100 KΩ Resistance Tolerance ±1% Operating Temperature Range -40 ~ +125 ℃ Nominal B-Constant 4250 ~ 4299K 
-
Connect Grove - Temperature Sensor to port A0 of Grove Base
-
Plug XIAO ESP32C3 to Grove Base
-
Connect XIAO ESP32C3 to PC via a USB-C cable

-
Copy the following code into Arduino IDE and upload the code:
#include <math.h> const int B = 4275000; // B value of the thermistor const int R0 = 100000; // R0 = 100k const int pinTempSensor = A0; // Grove Temperature Sensor on A0 float filteredTemp = 0; // Read averaged ADC value float readADC(int pin) { long sum = 0; const int samples = 20; for (int i = 0; i < samples; i++) { sum += analogRead(pin); delay(5); } return sum / (float)samples; } void setup() { Serial.begin(115200); delay(1000); analogSetPinAttenuation(pinTempSensor, ADC_11db); // improve range } void loop() { float a = readADC(pinTempSensor); // Convert ADC to resistance float R = R0 * (4095.0 / a - 1.0); // Convert resistance to temperature float temperature = 1.0 / (log(R / R0) / B + 1 / 298.15) - 273.15; // Smooth output (low-pass filter) if (filteredTemp == 0) { filteredTemp = temperature; // initialize } else { filteredTemp = 0.85 * filteredTemp + 0.15 * temperature; } // Output Serial.print("Raw Temp: "); Serial.print(temperature, 3); Serial.print(" | Filtered Temp: "); Serial.println(filteredTemp, 3); delay(200); }
-
Open the Serial Monitor in the Arduino IDE by clicking
Tools -> Serial Monitor. You should see results in the Serial Monitor, as shown below.
It is shown that the temperature at that time is 25°C.
2. Touch Sensor¶
-
Prepare the materials needed:
- XIAO ESP32C3
- Grove Base for XIAO
- Grove - LED Socket & LED
- Grove - Touch Sensor
Grove - Touch Sensor:
This sensor enables touch-based input by sensing capacitance changes caused by a nearby finger.
Specifications:
Item Value Operating Voltage 2.0V - 5.5V Operating Current(Vcc=3V) 1.5 - 3.0μA Operating Current(VDD=3V) 3.5 - 7.0μA Output Response Time 60 - 220ms Used Chipset TTP223-BA6 Interface Digital Port 
-
Connect Grove - Touch Sensor to port D0 and Grove LED Socket to port D1 of Grove Base
-
Plug XIAO ESP32C3 to Grove Base
-
Connect XIAO ESP32C3 to PC via a USB-C cable
-
Copy the following code into Arduino IDE and upload the code:
6. The LED turns on when we place our finger near the sensor, and it turns off when we move our finger away.const int TouchPin = D0; const int ledPin = D1; void setup() { pinMode(TouchPin, INPUT); pinMode(ledPin, OUTPUT); } void loop() { int sensorValue = digitalRead(TouchPin); if (sensorValue == HIGH) { digitalWrite(ledPin, HIGH); } else { digitalWrite(ledPin, LOW); } }

3. Mech Keypad¶
-
Prepare the materials needed:
- XIAO ESP32C3
- Grove Base for XIAO
- Grove - LED Socket & LED
- Grove - Mech Keycap
Grove - Mech Keypad:
A mechanical switch with a build-in LED
Features
- Programmable LED
- Reliable mechanical structure
- Extremely long operating Life
Specifications:
Item Value Operating Voltage 3.0V - 5.0V Insulation Resistance 100MΩ Min Contract Resistance 200 mΩ Max Operating Life without Load 20,000,000 times press 
-
Connect Grove - Mech Keypad to port D0 and Grove LED Socket to port D1 of Grove Base
-
Plug XIAO ESP32C3 to Grove Base
-
Connect XIAO ESP32C3 to PC via a USB-C cable
-
Copy the following code into Arduino IDE and upload the code:
This code is generated from ChatGPT
6. Toggle switch LED on and offconst int buttonPin = D0; const int ledPin = D1; bool ledState = false; // current LED state bool lastButtonState = HIGH; bool currentButtonState; void setup() { pinMode(buttonPin, INPUT); pinMode(ledPin, OUTPUT); } void loop() { currentButtonState = digitalRead(buttonPin); // Detect button press (HIGH → LOW transition) if (lastButtonState == HIGH && currentButtonState == LOW) { ledState = !ledState; // toggle LED digitalWrite(ledPin, ledState ? HIGH : LOW); } lastButtonState = currentButtonState; delay(50); // simple debounce }

4. Thumb Joystick¶
-
Prepare the materials needed:
- XIAO ESP32C3
- Grove Base for XIAO
- Grove - Thumb Joystick
Grove - Thumb Joystick
Grove Thumb Joystick uses two approximately 10k potentiometers for the X and Y axes, allowing it to detect movement in two dimensions by producing analog signals.
Specifications:
Item Min Typical Max Unit Working Voltage 4.75 5.0 5.25 V Output Analog Value (X-Coordinate) 206 516 798 \ Output Analog Value (Y-Coordinate) 203 507 797 \ 
-
Connect Grove - Thumb Joystick to the A0/A1 of Grove Base by using the 4-pin grove cable
-
Plug XIAO ESP32C3 to Grove Base
-
Connect XIAO ESP32C3 to PC via a USB-C cable
-
Copy the following code into Arduino IDE and upload the code:
This code is generated from ChatGPT
/* Thumb Joystick demo for XIAO ESP32C3 Grove Thumb Joystick connected to A0 & A1 */ const int pinX = 2; // A0 → GPIO2 const int pinY = 3; // A1 → GPIO3 void setup() { Serial.begin(115200); // Optional: set ADC resolution (default is 12-bit) analogReadResolution(12); } void loop() { int sensorValue1 = analogRead(pinX); int sensorValue2 = analogRead(pinY); Serial.print("X: "); Serial.print(sensorValue1); Serial.print(" Y: "); Serial.println(sensorValue2); delay(200); } -
When we move the joystick, we can see the X and Y values change in the Serial Monitor.

5. PIR Motion Sensor¶
-
Prepare the materials needed:
- XIAO ESP32C3
- Grove Base for XIAO
- Grove - PIR Motion Sensor
Grove - PIR Motion Sensor
This sensor is designed to detect movement, typically from human movement.
Features:
- Grove compatible interface
- Adjustable detecting distance
- Adjustable holding time
Specifications:
Item Value Operating Voltage 3V–5V Operating Current(VCC = 3V) 100uA Operating Current(VCC = 5V) 150uA Measuring Range 0.1 - 6m Default detecting distance 3m Holding Time 1 - 25s Working Wave Length 7 - 14um Detecting Angle 120 degrees 
-
Connect Grove - PIR Motion Sensor to port D2 of Grove Base
-
Plug XIAO ESP32C3 to Grove Base
-
Connect XIAO ESP32C3 to PC via a USB-C cable
-
Copy the following code into Arduino IDE and upload the code:
This code is generated from ChatGPT
6. If motion just started -> “🚶 Motion detected!”, if motion just stopped -> “👀 Motion ended”#define PIR_MOTION_SENSOR D2 // 👈 use a Grove digital port int lastState = LOW; void setup() { pinMode(PIR_MOTION_SENSOR, INPUT); Serial.begin(115200); } void loop() { int currentState = digitalRead(PIR_MOTION_SENSOR); if (currentState != lastState) { if (currentState == HIGH) { Serial.println("🚶 Motion detected!"); } else { Serial.println("👀 Motion ended"); } lastState = currentState; } delay(50); }
6. RTC (Real Time Clock)¶
-
Prepare the materials needed:
- XIAO ESP32C3
- Grove Base for XIAO
- Grove - RTC
Grove - RTC
This module supports I2C and uses R1225 battery to keep accurate time (including leap years) in 12- or 24-hour format up to the year 2100.
Specifications:
Item Value PCB Size 2.0cm*4.0cm Interface 2.0mm pitch pin header IO Structure SCL, SDA, VCC, GND ROHS YES VCC 3.3 ~ 5.5V Logic High Level Input 2.2 ~ VCC+0.3 V Logic Low Level Input -0.3 ~ +0.8 V Battery Voltage 2.0~3.5 V 
-
Connect Grove - RTC to port I2C of Grove Base
-
Plug XIAO ESP32C3 to Grove Base
-
Connect XIAO ESP32C3 to PC via a USB-C cable
-
Download the RTC Library
-
Open Arduino IDE. Click on
Sketch -> Include Library -> Add .ZIP Library
-
Check if the library install correctly. Click on
File -> Examples -> Grove - RTC DS1307 -> SetTimeAndDisplay
-
Copy the following code into Arduino IDE and upload the code:
This code is generated from ChatGPT
9. In the Serial Monitor, we can see the time, date, and day:#include <Wire.h> #include "DS1307.h" #define SDA_PIN 6 #define SCL_PIN 7 DS1307 rtc; // renamed from "clock" to "rtc" void setup() { Serial.begin(115200); Wire.begin(SDA_PIN, SCL_PIN); rtc.begin(); // Set time once, then comment out rtc.fillByYMD(2026, 3, 20); rtc.fillByHMS(12, 0, 0); rtc.fillDayOfWeek(FRI); rtc.setTime(); } void loop() { printTime(); delay(1000); } void printTime() { rtc.getTime(); Serial.print(rtc.hour, DEC); Serial.print(":"); Serial.print(rtc.minute, DEC); Serial.print(":"); Serial.print(rtc.second, DEC); Serial.print(" "); Serial.print(rtc.month, DEC); Serial.print("/"); Serial.print(rtc.dayOfMonth, DEC); Serial.print("/"); Serial.print(rtc.year + 2000, DEC); Serial.print(" "); switch (rtc.dayOfWeek) { case MON: Serial.print("MON"); break; case TUE: Serial.print("TUE"); break; case WED: Serial.print("WED"); break; case THU: Serial.print("THU"); break; case FRI: Serial.print("FRI"); break; case SAT: Serial.print("SAT"); break; case SUN: Serial.print("SUN"); break; } Serial.println(); }