My favorite activity is sleeping. I often turn off my alarm to keep sleeping, but because of that, I sometimes arrive late to places. That is why I wanted to make an alarm for my project that would be harder for me to turn off, so I thought of an alarm that tries to escape.
My boyfriend always says I am like a hamster (small and easily scared), so I thought I would love for my project to be shaped like a hamster to make it funny.
I think I could do the electronics with a Xiao, use molds to make the hamster shape, and laser cutting for the internal structure, as well as 3D printing. I also want to make an interface to set the alarms.
This is a bit of what I think I could do, but as I advance in the Fab path, I will clarify my ideas.
Systems integrating my project:
Plan for the next weeks:
SOLIDWORKS
The first thing I did for my project was the shell in Blender to be able to visualize the available space I had, I made the base in SolidWorks to be able to add dimensions to my hamster, the base turned out like this:
To be able to see a little more about how to use SolidWorks you can check my WEEK02.
Where each of the parts has a function which is the following:
Then in SolidWorks I made a small sketch for the shell shape taking into account the size of the base, this is how my small sketch turned out.
As you can see it looks too square this is because I did it in SolidWorks and here it is hard to make more organic shapes, so I saved it as an STL following these steps:
I exported my finished Blender model as STL: File> Export> STL and opened it in Prusa Slicer, to know more about the settings to 3D print you can see my WEEK05
The result of my print was this
Since I had the 3D printed shell what I did was cover it with plush type fabric to give it a cuter touch the first version was this.
Although because of the color they told me it looked more like a rat so I decided to change the fabric and this is how it ended up, this is the version before I trimmed the excess fabric.
For the base I decided to cut it with black acrylic to know more about how the laser cutter works you can see my WEEK03, the parameters to cut acrylic were the following:
For inputs I used three things a capacitive sensor so that this serves as a button so that when it detects an increase in capacitance when the user grabs the hamster it turns off besides an RTC with which we can detect the time so that the speaker begins to sound and the motors move when it is equal to the time that the user set in the interface and finally the sensors that help prevent the hamster from getting trapped.
First I did some tests which I did during my WEEK09, this is the schematic of how the sensor works.
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);
}
Then I placed it on the internal part of my shell and did some tests of how much the values change when you place your hand over the hamster.
The first thing I did was test the Real-Time Clock (RTC) sensor for my hamster alarm clock, since with this reading the hamster will start ringing. This uses I2C communication. During WEEK09 you can find more information.
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.
The image below shows the registers through which the RTC operates; you can find this map in the datasheet.
#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);
}
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.
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);
}
Although since I used the xiaoesp32 c6 and it only has three analog pins and one of the analog pins was already occupied by the capacitive button I didn't have any more left so I decided to make a board with an attiny that would be in charge of reading the value of the three sensors and then communicating it via I2C to my xiao.
ESQUEMATICO
PLACA TERMINADA
To program it it is important that we have these three pins to connect it to an Arduino uno: VCC, GND AND UPDI.
The steps to program the attiny are the following:
The code I uploaded to my attiny to detect the distance of our sensors was the following:
#include <Wire.h>
const int SLAVE_ADDRESS = 8;
void setup() {
Serial.begin(115200);
delay(2000);
Serial.println("Iniciando maestro I2C en ESP32-C6...");
Wire.begin();
}
void loop() {
Wire.requestFrom(SLAVE_ADDRESS, 3);
if (Wire.available() == 3) {
uint8_t distIzq = Wire.read();
uint8_t distDer = Wire.read();
uint8_t distAtras = Wire.read();
Serial.print("Izquierda: ");
Serial.print(distIzq);
Serial.print(" cm | Derecha: ");
Serial.print(distDer);
Serial.print(" cm | Atrás: ");
Serial.print(distAtras);
Serial.println(" cm");
} else {
Serial.println("Error: No se recibieron los datos del ATtiny412.");
}
delay(100);
}
For output I have my motors and the speaker, in WEEK 10 I tested making the board for one motor.
I'm going to use small DC motors for when I escape, so do the following; for more information you can see my WEEK 10.
For my DC motor, I made the H-bridge using the TB67H451AFNG; this is the schematic of my H-bridge.
const int IN1 = 27; // PINS WHERE WE ARE GOING TO CONNECT THE MOTOR INPUTS
const int IN2 = 28;
void setup() { // We configure both pins as OUTPUT
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
detenerMotor();
}
void loop() {
moverMotor(200); // We move the motor at a power of
// in one direction for 2 seconds
delay(2000);
detenerMotor();// We stop the motor
delay(1000);
moverMotor(-200);// We start turning in the other direction
delay(2000);
detenerMotor();
delay(1000);
}
void moverMotor(int velocidad) {
if (velocidad > 0) {
analogWrite(IN1, velocidad); // Function to make it turn to the right
analogWrite(IN2, 0);// Sends IN2 to 0, so that one has no signal
} else if (velocidad < 0) {
analogWrite(IN1, 0); // Sets IN1 to 0, so that one has no signal
analogWrite(IN2, abs(velocidad));// Function to make it turn to the left
} else {
detenerMotor();
}
}
void detenerMotor() {
analogWrite(IN1, 0);// Sets both IN to 0 so the motor does not turn
analogWrite(IN2, 0);
}
But for my project I took charge of making my board for two motors where my schematic is the following:
The code I tested for the operation of the H-bridge was the following:
For the speaker to sound what I used was the DFplayer Mini MP3 Player module which I connected in the following way with my XIAO.
The steps you have to follow to play sounds are the following:
CODE
To avoid having so many jumpers for what I did was align the connection pins of the H-bridge with the output pins of my main board where my xiao and my speaker module are located.
This is how the assembly of my boards turned out
Since I couldn't avoid the cables for my distance sensors what I did was make a third board where the attiny is that is in charge of reading the sensors processes the values and communicates it with I2C to the main board where I tried to have the fewest cables possible which were VCC, GND,SCL AND SDA.
I did some tests of how the structure moves
Here you can download the source files created during this week: