/* Embarcatech: 28-01-2025
Autor: Marcio Barbosa
7 - Microcontroladores - Projeto Prático - Equipe Firmware
Projeto: Sistema de segurança para máquina de Serra de Fita de Bancada
Para realizar este experimento, foi necessário os seguintes componentes:
1 x Raspberry Pi Pico W ,
1 x HCSR04
1 x Buzzer
2 x Leds
2 x Resistores
3 x botões (verde - liga, azul - desliga e vermelho - emergência)
*/
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/pwm.h"
#include "hardware/irq.h"
// Definição dos pinos
#define TRIG_PIN 3 // Pino TRIG do HC-SR04
#define ECHO_PIN 4 // Pino ECHO do HC-SR04
#define LED_G 5 // LED Verde (segurança)
#define LED_R 6 // LED Vermelho (alerta)
#define BUZZER_PIN 7 // Buzzer para alarme
#define EMERGENCY_BTN 8 // Botão de emergência (Vermelho)
#define START_BTN 10 // Botão para ligar a máquina (Verde)
#define STOP_BTN 11 // Botão para desligar a máquina (Azul)
#define MOTOR_PIN 9 // Motor simulado com PWM
volatile bool flag_emergency = false; // Flag de emergência, testar o botão vermelho
volatile bool status_machine = false; // Estado da máquina - deligada (false) | ligada (true)
// Tratar todos os botões ## estava montando separado da erro por causa do tempo de acionamento do botão
void gpio_button(uint gpio, uint32_t events) {
if (gpio == EMERGENCY_BTN && (events & GPIO_IRQ_EDGE_FALL)) {
flag_emergency = true;
status_machine = false;
printf("## EMERGÊNCIA: Máquina desligada! ##\n");
}
else if (gpio == START_BTN && (events & GPIO_IRQ_EDGE_FALL)) {
if (!flag_emergency) {
status_machine = true;
printf("## Máquina LIGADA pelo operador ##!\n");
}
}
else if (gpio == STOP_BTN && (events & GPIO_IRQ_EDGE_FALL)) {
if (!flag_emergency) {
status_machine = false;
printf("## Máquina DESLIGADA pelo operador ##.\n");
}
}
}
// Simulação da leitura do HC-SR04
float measure_distance() {
static int distance = 10;
distance += 10;
if (distance < 0 || distance > 100) { //coloquei para acionar a 100 cm, se ajustar aqui deve ajustar no fluxo abaixo
printf("ERRO: Leitura de distância inválida: %.2f cm!\n", distance);
printf("ERRO: Verifique as conexões e a alimentação do sensor HC-SR04. .\n");
return distance;
}
else{
distance = 100; // detectado problema com o sensor HC-SR04, desliga a máquina
printf("## Distância detectada: %d cm ##\n", distance);
return distance;
}
}
// Função para controlar o motor com PWM
void set_motor_speed(uint16_t duty_cycle) {
pwm_set_gpio_level(MOTOR_PIN, duty_cycle);
}
// Funções para controlar o buzzer via PWM
void buzzer_on() {
// Configure o BUZZER_PIN como PWM
gpio_set_function(BUZZER_PIN, GPIO_FUNC_PWM);
uint slice_num = pwm_gpio_to_slice_num(BUZZER_PIN);
// Configure para gerar 2 kHz com 50% de duty cycle.
// Exemplo: se o clock é 125MHz, com divisor 25, o clock do slice será 5MHz.
// Para 2 kHz, o wrap deve ser aproximadamente 2500 (5,000,000 / 2,000 = 2500).
pwm_set_clkdiv(slice_num, 25.0f);
pwm_set_wrap(slice_num, 2500);
pwm_set_chan_level(slice_num, pwm_gpio_to_channel(BUZZER_PIN), 1250);
pwm_set_enabled(slice_num, true);
}
void buzzer_off() {
// Desabilita o PWM no buzzer e o coloca em nível baixo.
uint slice_num = pwm_gpio_to_slice_num(BUZZER_PIN);
pwm_set_enabled(slice_num, false);
gpio_set_function(BUZZER_PIN, GPIO_FUNC_SIO);
gpio_put(BUZZER_PIN, 0);
}
int main() {
stdio_init_all();
// Inicializa os pinos de saída
gpio_init(TRIG_PIN);
gpio_set_dir(TRIG_PIN, GPIO_OUT);
gpio_put(TRIG_PIN, 0);
gpio_init(ECHO_PIN);
gpio_set_dir(ECHO_PIN, GPIO_IN);
gpio_init(LED_G);
gpio_set_dir(LED_G, GPIO_OUT);
gpio_init(LED_R);
gpio_set_dir(LED_R, GPIO_OUT);
gpio_init(BUZZER_PIN);
gpio_set_dir(BUZZER_PIN, GPIO_OUT);
// Inicializa os pinos dos botões e ativa os pull-ups
gpio_init(EMERGENCY_BTN);
gpio_set_dir(EMERGENCY_BTN, GPIO_IN);
gpio_pull_up(EMERGENCY_BTN);
gpio_init(START_BTN);
gpio_set_dir(START_BTN, GPIO_IN);
gpio_pull_up(START_BTN);
gpio_init(STOP_BTN);
gpio_set_dir(STOP_BTN, GPIO_IN);
gpio_pull_up(STOP_BTN);
// Registra um único callback para todos os pinos com interrupção
gpio_set_irq_enabled_with_callback(EMERGENCY_BTN, GPIO_IRQ_EDGE_FALL, true, &gpio_button);
gpio_set_irq_enabled(START_BTN, GPIO_IRQ_EDGE_FALL, true);
gpio_set_irq_enabled(STOP_BTN, GPIO_IRQ_EDGE_FALL, true);
// Configuração do PWM para o motor
gpio_set_function(MOTOR_PIN, GPIO_FUNC_PWM);
uint slice_num = pwm_gpio_to_slice_num(MOTOR_PIN);
pwm_set_wrap(slice_num, 100);
pwm_set_enabled(slice_num, true);
while (1) {
if (flag_emergency) {
// Se a emergência for acionada, desliga tudo
gpio_put(LED_G, 0);
gpio_put(LED_R, 1);
//gpio_put(BUZZER_PIN, 1);
// Liga o PWM (buzzer soa)
//pwm_set_enabled(slice_buzzer, true);
buzzer_on();
sleep_ms(3000);
buzzer_off();
set_motor_speed(0);
printf("Máquina desligada por emergência! Pressione o botão verde para reiniciar.\n");
flag_emergency = false;
status_machine = false;
}
if (!status_machine) {
// Se a máquina estiver desligada, aguarda o start
set_motor_speed(0);
gpio_put(LED_G, 0);
gpio_put(LED_R, 1);
//gpio_put(BUZZER_PIN, 0);
//pwm_set_enabled(slice_buzzer, false);
buzzer_off();
printf("Máquina DESLIGADA. Pressione o Botão Verde para ligar.\n");
sleep_ms(1000);
continue;
}
// Se a máquina estiver ligada, realiza a medição da distância
float distance = measure_distance();
if (distance > 90) {
// Alerta: operador ausente, desligando a máquina
gpio_put(LED_G, 0);
gpio_put(LED_R, 1);
//gpio_put(BUZZER_PIN, 1);
// pwm_set_enabled(slice_buzzer, true);
buzzer_off();
printf("ALERTA: Operador ausente! Máquina será desligada.\n");
// Reduz gradualmente a velocidade do motor antes de desligar
for (int speed = 100; speed >= 0; speed -= 10) {
set_motor_speed(speed);
printf("Reduzindo motor: %d%%\n", speed);
sleep_ms(500);
}
buzzer_on();
sleep_ms(2000);
status_machine = false;
printf("Máquina desligada automaticamente por ausência do operador.\n");
buzzer_off();
} else {
// Operação normal
gpio_put(LED_G, 1);
gpio_put(LED_R, 0);
//gpio_put(BUZZER_PIN, 0);
// pwm_set_enabled(slice_buzzer, false);
buzzer_off();
set_motor_speed(100);
printf("SEGURO: Máquina operando normalmente. Distância = %.2f cm.\n", distance);
}
sleep_ms(2000);
}
return 0;
}