#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/i2c.h"
#include "hardware/pwm.h"
/* -------------PINS------------ */
#define I2C_PORT i2c0
#define SDA_PIN 4 /*Pins to connect the DS3231 we must make sure that if they are SDA and SCL */
#define SCL_PIN 5
#define DS3231_ADDR 0x68
#define SERVO_PIN 13 /*Pin to connect the servo */
#define BUZZER_PIN 7 /*Pin to connect the buzzer */
#define BOTON_PIN 19 /*Pin to connect the button*/
// With this part of the code we convert from binary to decimal.
/* The watch stores the data in two parts that are a binary number and a binary number.
For example, 25 looks like this: 0010 (2) 0101 (5) Then it becomes val >> 4: Move everything to the right to keep only the 2.
Then multiply it by 10 (20).
And val & 0x0F: Delete the left side to keep only the 5. then add it and there are 25. */
uint8_t bcd_to_dec(uint8_t val) {
return ((val >> 4) * 10) + (val & 0x0F);
}
/* ------------SERVO----------------*/
void setup_servo(uint pin) {
gpio_set_function(pin, GPIO_FUNC_PWM); //configure the pin for the servo with PWM
uint slice = pwm_gpio_to_slice_num(pin);
pwm_set_clkdiv(slice, 64.0f);
pwm_set_wrap(slice, 39062);
pwm_set_enabled(slice, true);
}
void set_servo_position(uint pin, int degrees) {
uint32_t duty = (degrees * 2000 / 180) + 1000; // Function that helps us map the servo position from degrees to PWM units
pwm_set_gpio_level(pin, duty);
}
/* ------------BUZZER------------- */
void setup_buzzer(uint pin) {
gpio_set_function(pin, GPIO_FUNC_PWM);
uint slice = pwm_gpio_to_slice_num(pin);
pwm_set_clkdiv(slice, 4.0f); // Reduce base frequency
pwm_set_wrap(slice, 31250); // Audible base
pwm_set_enabled(slice, true);
}
void set_buzzer_freq(uint pin, uint freq) { //give it specific sound commands.
uint slice = pwm_gpio_to_slice_num(pin);
if (freq == 0) {
pwm_set_gpio_level(pin, 0); //Line to prevent our buzzer from sounding
return;
}
uint32_t wrap = 125000000 / 4 / freq;
pwm_set_wrap(slice, wrap);
pwm_set_gpio_level(pin, wrap / 2); // This line calculates how long a clock cycle needs to be to fit exactly the amount of "vibrations" (freq) you want to hear in one second.
}
/* --------------- MAIN ------------------- */
int main() {
stdio_init_all();
i2c_init(I2C_PORT, 100000);
gpio_set_function(SDA_PIN, GPIO_FUNC_I2C);
gpio_set_function(SCL_PIN, GPIO_FUNC_I2C);
gpio_pull_up(SDA_PIN);
gpio_pull_up(SCL_PIN);
setup_servo(SERVO_PIN);
setup_buzzer(BUZZER_PIN);
gpio_init(BOTON_PIN);
gpio_set_dir(BOTON_PIN, GPIO_IN);
gpio_pull_up(BOTON_PIN);
//We initialize our pins as output or input
int h_alarma, m_alarma;
bool alarma_disparada = false;
// For the user to enter the time
printf("Configuración de Alarma Hamster\n");
printf("Hora (0-23): ");
scanf("%d", &h_alarma);
printf("Minuto (0-59): ");
scanf("%d", &m_alarma);
printf("Alarma fijada a las %02d:%02d\n", h_alarma, m_alarma);
uint8_t reg = 0x00;
uint8_t data[3];
//Timer registration
while (true) {
// Read the RTC (DS1307)
i2c_write_blocking(I2C_PORT, DS3231_ADDR, ®, 1, true);
i2c_read_blocking(I2C_PORT, DS3231_ADDR, data, 3, false);
uint8_t minutos = bcd_to_dec(data[1]);
uint8_t horas = bcd_to_dec(data[2] & 0x3F);
//activate the alarm at the time the user logged in
if (horas == h_alarma && minutos == m_alarma && !alarma_disparada) {
alarma_disparada = true;
printf("¡Alarma activada!\n");
}
if (alarma_disparada) {
// if the alarm is activate the buzzer and the servo are activated
set_servo_position(SERVO_PIN, 20);
set_buzzer_freq(BUZZER_PIN, 1000);
sleep_ms(200);
set_servo_position(SERVO_PIN, 270);
set_buzzer_freq(BUZZER_PIN, 1500);
sleep_ms(200);
// if the button is activated the buzzer and the servo are desactivated
if (gpio_get(BOTON_PIN) == 0) {
alarma_disparada = false;
set_buzzer_freq(BUZZER_PIN, 0);
set_servo_position(SERVO_PIN, 90);
printf("Alarma apagada.\n");
sleep_ms(60000);
}
} else {
printf("Hora actual: %02d:%02d\n", horas, minutos);
sleep_ms(1000);
}
}
}