Skip to content

Week09 | Input Devices

Overview

During this week, I explored different input devices and learned how to interface various sensors with my custom PCB. I tested multiple sensing techniques, such as motion tracking, distance measurement, and environmental sensing, to better understand how to capture and interpret real‑world data for embedded applications.

Group work

In the group work, we tested two sensors, a digital time of flight light sensor and a analog phototransistor sensor. We used, a multimeter and an oscilloscope to measure and analyze the signals.

Individual assignment

For the individual assignment I tried to test a few sensors: measuring distance using ToF, location with GPS, acceleration, rotation, orientation, temperature & humidity, microphone. I had time to test three of them, and I tried to test three more but I did not continue as I did not have time. If I had time, I will test them later and update this assignment.

9axis Accelerometer, gyroscope and magnetometer

I started with the ICM20948 sensor. For all tests this week, I used the PCB board I made in week08.

These are the hardwares and softwares that I used:

  • My PCB board which I made with RP2004
  • Sensor: ICM20948
  • USB C cable
  • Wires
  • Arduino IDE
  • Processing 4 software for visualization
  • Communication protocol: I2C

Step1: wiring

First I start with wiring. Using Seeed XIAO RP2040 datasheet I connected the sensors pins to microcontroller input pins:

  • VCC → 3V3
  • GND → GND
  • SDA → D4
  • SCL → D5

Step 2: Installed libraries

I install below libraries in Arduino:

  • Adafruit ICM20X
  • Adafruit BusIO
  • Adafruit Unified Sensor
  • Adafruit AHRS

Step 4: prepare the code

I used the origin Arduino code, I asked Grok to modify it.

#include <Adafruit_ICM20X.h>
#include <Adafruit_ICM20948.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_AHRS.h>
#include <Wire.h>

Adafruit_ICM20948 icm;

// Try Mahony first — change to Madgwick if you want to experiment
Adafruit_Mahony filter;  
// Adafruit_Madgwick filter;

float roll, pitch, yaw;

void setup() {
  Serial.begin(115200);
  while (!Serial) delay(10);

  Wire.begin();  // D4=SDA, D5=SCL on XIAO RP2040

  if (!icm.begin_I2C()) {
    Serial.println("Failed to find ICM20948 chip");
    while (1) delay(10);
  }

  Serial.println("ICM20948 Found!");

  icm.setAccelRange(ICM20948_ACCEL_RANGE_4_G);     // good compromise
  icm.setGyroRange(ICM20948_GYRO_RANGE_1000_DPS);
  // icm.setMagDataRate(AK09916_MAG_DATARATE_100_HZ);  // optional

  filter.begin(80);   // 80 Hz — realistic & stable on RP2040

  Serial.println("Roll,Pitch,Yaw_deg");
}

void loop() {
  sensors_event_t accel, gyro, mag, temp;
  icm.getEvent(&accel, &gyro, &temp, &mag);

  // ─────────────────────────────────────────────
  // Try these remapping options one by one if directions feel wrong
  // Option 1: Flip magnetometer signs (very common for ICM-20948 breakouts)
  // filter.update(gyro.gyro.x, gyro.gyro.y, gyro.gyro.z,
  //               accel.acceleration.x, accel.acceleration.y, accel.acceleration.z,
  //               -mag.magnetic.x, -mag.magnetic.y, -mag.magnetic.z);

  // Option 2: Swap mag X/Y + flip some signs
  filter.update(gyro.gyro.x, gyro.gyro.y, gyro.gyro.z,
                accel.acceleration.x, accel.acceleration.y, accel.acceleration.z,
                mag.magnetic.y, -mag.magnetic.x, mag.magnetic.z);

  // Default (no remap) — start here, then try options above
  // filter.update(gyro.gyro.x, gyro.gyro.y, gyro.gyro.z,
  //               accel.acceleration.x, accel.acceleration.y, accel.acceleration.z,
  //               mag.magnetic.x, mag.magnetic.y, mag.magnetic.z);
  // ─────────────────────────────────────────────

  roll = filter.getRoll();
  pitch = filter.getPitch();
  yaw = filter.getYaw();

  Serial.print(roll, 2);   Serial.print(",");
  Serial.print(pitch, 2);  Serial.print(",");
  Serial.print(yaw, 2);    Serial.println();

  delay(12);   // ≈ 80 Hz
}

After ran the code, the sensor worked and data showed in the serial monitor in Arduino. I recorded and it is in the next video. But I wanted to see the output, visually which is more sensitive. So, I used the Processing software for this purpose.

Step 5: Visualization:

I installed the Processing software. This is the code for visualization that Grok wrote it:

import processing.serial.*;

Serial port;
float roll = 0, pitch = 0, yaw = 0;

void setup() {
  size(1200, 1000, P3D);

  // ─────────────────────────────────────────────
  // CHANGE THIS TO YOUR PORT !
  // Look in Arduino IDE → Tools → Port
  port = new Serial(this, "COM7", 115200);   // ←←← change COM7 !!
  // Examples: "COM8", "COM10", "/dev/cu.usbmodem...", "/dev/ttyACM0"
  // ─────────────────────────────────────────────

  port.bufferUntil('\n');
  textSize(80);
  textAlign(LEFT, TOP);
}

void draw() {
  background(20);
  lights();
  translate(width/2, height/2, 0);

  // ─────────────────────────────────────────────
  // Rotation order & signs — try different combinations if cube moves wrong
  // Most common working for many ICM-20948 setups:
  rotateY(radians(-yaw));     // yaw (spin flat)
  rotateX(radians(-pitch));   // pitch (tilt forward/back)
  rotateZ(radians(roll));     // roll (tilt left/right)

  // Alternative order — try if above feels inverted
  // rotateX(radians(-pitch));
  // rotateY(radians(-yaw));
  // rotateZ(radians(-roll));
  // ─────────────────────────────────────────────

  fill(180, 80, 180);
  noStroke();
  box(200);

  // Info overlay
  fill(255);
  text("Roll:  " + nf(roll,  3,1) + "°", -width/2 + 40, -height/2 + 40);
  text("Pitch: " + nf(pitch, 3,1) + "°", -width/2 + 40, -height/2 + 80);
  text("Yaw:   " + nf(yaw,   3,1) + "°", -width/2 + 40, -height/2 + 120);
  text("Move sensor slowly in all directions", -width/2 + 40, -height/2 + 180);
}

void serialEvent(Serial p) {
  String in = p.readStringUntil('\n');
  if (in != null) {
    in = trim(in);
    String[] data = split(in, ',');
    if (data.length >= 3) {
      roll  = float(data[0]);
      pitch = float(data[1]);
      yaw   = float(data[2]);
    }
  }
}

Output of the test:

I started recording and slowly moved the sensor. At first, I observed the data appearing in the Serial Monitor. To establish a connection between the Arduino and the Processing software, I closed the Serial Monitor and then ran the Processing visualization code. The COM port used for communication in the Processing sketch is COM7.

Distance measurement

For measuring distance I tried both light and sound to measure distance using ToF technique.

Light ToF

I followed this webpage to have interaction with this sensor.

I downloaded and installed VL53L5CX firmware:

I got this above error, and since I did not have time, I did not to continue with this sensor.

Ultrasound ToF: HC-SR04

Ultrasonic ranging module HC - SR04 provides 2cm - 400cm non-contact measurement function, the ranging accuracy can reach to 3mm. The modules includes ultrasonic transmitters, receiver and control circuit. The basic principle of work: (1) Using IO trigger for at least 10us high level signal, (2) The Module automatically sends eight 40 kHz and detect whether there is a pulse signal back. (3) IF the signal back, through high level , time of high output IO duration is the time from sending ultrasonic to returning. Test distance = (high level time×velocity of sound (340M/S) / 2. Reference

To use this sensor, I followed the webpage here that is for ESP32, but for wiring and addresses the pins in code, considered the RP2040.

Step1: wiring:

Coding:

I got the original code from here, and did small modification based on RP2040 pins.

/*********
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp32-hc-sr04-ultrasonic-arduino/

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.

  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*********/

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

//define sound speed in cm/uS
#define SOUND_SPEED 0.034
#define CM_TO_INCH 0.393701

long duration;
float distanceCm;
float distanceInch;

void setup() {
  Serial.begin(115200); // Starts the serial communication
  pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
  pinMode(echoPin, INPUT); // Sets the echoPin as an Input
}

void loop() {
  // Clears the trigPin
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  // Sets the trigPin on HIGH state for 10 micro seconds
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  // Reads the echoPin, returns the sound wave travel time in microseconds
  duration = pulseIn(echoPin, HIGH);

  // Calculate the distance
  distanceCm = duration * SOUND_SPEED/2;

  // Convert to inches
  distanceInch = distanceCm * CM_TO_INCH;

  // Prints the distance in the Serial Monitor
  Serial.print("Distance (cm): ");
  Serial.println(distanceCm);
  Serial.print("Distance (inch): ");
  Serial.println(distanceInch);

  delay(1000);
}

The output:

I am recording a video with my phone while moving it close to the sensor. Meanwhile, the phone also plays the role of object for the sensor, which measures distance using the time-of-flight technique.

Temperature and humidity: AM2302 DHT22

I wanted to test this sensor because maybe I will use it in my final project, from here. wiring was easy, just three pins:

Step1: wiring:

The wiring was very simple.

  • GND to GND
  • Vcc to 3.3V
  • Data o D1

Step2: Install library:

Installed the DHT sensor library:

The copied original code, but at first try as always happened, there was no signal or start with an error. Why? I do not know:

After rechecked the code again, I understood that the pin number defined incorrect, as it can be seen in the above image: So, I changed the pins:

This is the recorded video, when I move the sensor close to laptop fans, the temperature started to increase. It seems that the sensor is acceptable sensitive.

As I mentioned earlier, I did not have time to continue with a few more below sensors. Hopefully, I will find some time to test them. I listed them here:

Reflection

This week helped me understand how different types of sensors behave and how important proper wiring, libraries, and communication protocols are for reliable data acquisition. I also realized how much time debugging takes for small issues like incorrect pin definitions or open serial ports can completely block progress. Working with multiple sensors gave me a clearer picture of how to choose the right input device for a specific application, and how visualization tools like Processing can make sensor data far more intuitive. Although I couldn’t test all the sensors I planned, the experience strengthened my confidence in integrating hardware and software, and I now feel more prepared to select and use sensors in my final project and I got to know how to start to work with input electronic. During the lecture I learned what type of different sensors are available and can be used in different applications.

Files I Created

  1. DHT22.ino

  2. HC-SR04.ino

  3. ICM20948.ino