The objective this week was to integrate two distinct data input methods using the Seeed Studio XIAO RP2350; the board I used was the one I made in week 8. This week's assignment consisted of
capturing distance through an analog sensor and obtaining the current time via a Real-Time Clock (RTC) module using digital communication.
For more information on how input devices function, you can visit our GROUP PAGE.
Analog sensors
Analog sensors (such as potentiometers, LDR light sensors, or temperature sensors) output a continuous voltage signal. The XIAO RP2350 features a high-resolution Analog-to-Digital Converter (ADC).
If the sensor outputs 1.65V (which is exactly half of the 3.3V reference), the ADC references its internal "ruler" to assign a digital value. In this case, with a 12-bit resolution, it would correspond to level 2048.
The specific sensor I am using is the Sharp GP2Y0E02A (you can find its datasheet here). It has an effective measuring range of 4 to 50 cm.
RTC Module (Real Time Clock) via I2C
Unlike the main processor, which loses track of time if it loses power, the RTC module maintains the exact time thanks to an external battery. To communicate it with the XIAO RP2350, I used the I2C protocol.
I used the dedicated pins on the XIAO (SDA and SCL). The microcontroller requests information from a specific address (e.g., 0x68), and the RTC responds by sending packets of bytes representing seconds, minutes, and hours.
RTCs typically deliver data in Binary Coded Decimal (BCD) format, which requires a small mathematical conversion in the code to display the numbers in standard decimal format.
The image below shows the registers through which the RTC operates; you can find this map in the datasheet.
1. Programming the XIAO RP2350
To program the XIAO RP2350 in the Arduino IDE, I followed these steps:
Go to File > Preferences.
In the Additional Boards Manager URLs section, paste the following link:
https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
Go to Tools > Board > Boards Manager...
Search for Raspberry Pi Pico/RP2040/RP2350 and install it.
#include <stdio.h>
#include "hardware/i2c.h"
#include "pico/binary_info.h"
// Hardware Configuration
#define I2C_PORT i2c1
#define PIN_SDA 6
#define PIN_SCL 7
#define DS3231_ADDR 0x68
// BCD conversion functions
uint8_t bcdToDec(uint8_t val) { return ((val / 16 * 10) + (val % 16)); }
void setup() {
Serial.begin(115200);
// Wait for serial monitor
while (!Serial && millis() < 3000);
// Initialize I2C
i2c_init(I2C_PORT, 100 * 1000);
gpio_set_function(PIN_SDA, GPIO_FUNC_I2C);
gpio_set_function(PIN_SCL, GPIO_FUNC_I2C);
// Active pull-ups
gpio_pull_up(PIN_SDA);
gpio_pull_up(PIN_SCL);
Serial.println("--- MODO LECTURA: Reloj DS3231 Activo ---");
}
void loop() {
uint8_t reg = 0x00; // Start recording (seconds)
uint8_t data[3]; // Buffer for [0]=sec, [1]=min, [2]=hours
i2c_write_blocking(I2C_PORT, DS3231_ADDR, ®, 1, true);
int bytes_read = i2c_read_blocking(I2C_PORT, DS3231_ADDR, data, 3, false);
if (bytes_read < 0) {
Serial.println("Error: No se detecta el reloj. Revisa cables.");
} else {
// Convert data from BCD to Decimal
uint8_t segundos = bcdToDec(data[0]);
uint8_t minutos = bcdToDec(data[1]);
uint8_t horas = bcdToDec(data[2] & 0x3F); // Mask for 24h format
Serial.print("\nHora actual: ");
if (horas < 10) Serial.print('0');
Serial.print(horas);
Serial.print(':');
if (minutos < 10) Serial.print('0');
Serial.print(minutos);
Serial.print(':');
if (segundos < 10) Serial.print('0');
Serial.print(segundos);
Serial.print("\t");
}
delay(1000);
}
RESULT
ANALOGIC SENSOR
The Sharp sensor is connected as follows: the blue arrow can also be connected to a programming pin so that we can activate and deactivate it in operation; having it connected to VCC, the sensor will always be active.
CODE
const int sensorPin = A2;
void setup() {
Serial.begin(115200);
// Use the native resolution of the RP2350 (12-bit)
analogReadResolution(12);
pinMode(sensorPin, INPUT);
Serial.println("GP2Y0E02A Sensor ready...");
}
void loop() {
// 1. Read raw value (0 - 4095)
int rawValue = analogRead(sensorPin);
// 2. Convert to Voltage (3.3V Reference)
float voltage = rawValue * (3.3 / 4095.0);
// 3. Calculate distance in cm using the datasheet slope
// Using the linear equation: y = mx + b
// Based on datasheet points: (0.55V, 50cm) and (2.2V, 4cm)
float distanceCm = (voltage - 2.2) * (50.0 - 4.0) / (0.55 - 2.2) + 4.0;
Serial.print("Voltage: ");
Serial.print(voltage, 2);
Serial.print("V | Distance: ");
// 4. Range validation and output
if (distanceCm > 55) {
Serial.println("Fuera de rango (Lejos)");
} else if (distanceCm < 3) {
Serial.println("Fuera de rango (Cerca)");
} else {
Serial.print(distanceCm, 1);
Serial.println(" cm");
}
delay(100);
}
RESULT
STEP RESPONSE
I made this sensor with the help of Adrian Torres' documentation and Neil Gershenfeld's examples. What this sensor does is that its value increases when our hand approaches because the space between the two pieces of copper is reduced, which causes the capacitance to change.
The first thing I did was design a PCB to connect my sensor; we need two pins to connect our XIAO, which are an analog pin and a digital pin.
One of the copper plates is connected to two 1M ohm resistors that must go one to VCC and the other to GND; this connection goes to the analog pin, and the other copper plate goes to the digital pin.
This is the schematic of my board; the files to manufacture this board can be found in the files section.
CODE
long result; // Stores the total sum of samples
int analog_pin = A2; // Receiver pin where capacitance is measured
int tx_pin = D10; // Transmitter pin
void setup() {
// Configures the transmitter pin as data output
pinMode(tx_pin, OUTPUT);
Serial.begin(115200);
delay(1000);
}
long tx_rx() {
int read_high; // Variable for reading with active pulse
int read_low; // Variable for reading with deactivated pulse
int diff; // Difference between charge and discharge
long sum = 0; // Accumulator for all samples
int N_samples = 100; // Number of measurements to average and reduce noise
for (int i = 0; i < N_samples; i++) {
digitalWrite(tx_pin, HIGH);
read_high = analogRead(analog_pin);
delayMicroseconds(100);
digitalWrite(tx_pin, LOW);
read_low = analogRead(analog_pin);
diff = read_high - read_low;
sum += diff;
}
return sum; // Returns the total of the 100 samples
}
void loop() {
result = tx_rx();
// Converts the summed value (approx range 15000-25000) to a scale of 0 to 1024
long mapped_result = map(result, 15000, 25000, 0, 1024);
Serial.print("Raw (Crudo): ");
Serial.print(result);
Serial.print(" | Mapped (Escalado): ");
Serial.println(mapped_result);
delay(50);
}
RESULT
FILES
Here you can download the source files created during this week: