#include <stdio.h> // Biblioteca para entrada e saída (printf).
#include "pico/stdlib.h" // Biblioteca do Pico para GPIO e temporização.
#include "hardware/adc.h" // Biblioteca para controle do ADC (Conversor Analógico-Digital).
#include "hardware/pwm.h" // Biblioteca para controle do PWM (servo motor).
#include <string.h> // Biblioteca para manipulação de strings.
#include "dht.h" // biblioteca própria criada pro dht
#include "ssd1306.h"
#include "hardware/i2c.h"
// Definições dos pinos para o joystick, botão, LEDs, servo motor e LDR
#define VRX_PIN 26 // Pino GP26 para o eixo X do joystick (Canal ADC0).
#define VRY_PIN 27 // Pino GP27 para o eixo Y do joystick (Canal ADC1).
#define SW_PIN 22 // Pino GP22 para o botão do joystick (entrada digital).
#define rgb_R 12 // Pino GP12 para o LED vermelho.
#define rgb_G 13 // Pino GP13 para o LED verde.
#define rgb_B 11 // Pino GP11 para o LED azul.
#define SERVO_PIN 18 // Pino GP18 para controle do servo motor.
#define LDR_PIN 28 // Pino GP28 para leitura do sensor de luz (Canal ADC2).
#define MAX_SEQUENCE 4 // Tamanho máximo para a sequência de comandos
const uint DHT_PIN = 16; // porta dht
#define SDA_PIN 14 //
#define SCL_PIN 15
#define Ap 3 // A+ line
#define Am 2 // A- line
#define Bp 4 // B+
#define Bm 7 // B-
#define BUZZER_1 10
#define BUZZER_2 21
#define BUTTON_A 6
#define BUTTON_B 5
#define DEBOUNCE_DELAY_MS 200
//ultrassonico
#define TRIG_PIN 27
#define ECHO_PIN 22
volatile uint32_t last_debounce_time[2] = {0, 0};
volatile bool button_a_pressed = false;
volatile bool button_b_pressed = false;
#define I2C_PORT i2c1 // porta i2c selecionada
#define UART_ID uart0
#define BAUD_RATE 115200
#define TX_PIN 0
#define RX_PIN 1
ssd1306_t oled;
char sequence[MAX_SEQUENCE] = ""; // Array pra armazenar string
bool last_sw_state = false; // Variável para armazenar o estado anterior do botão
// Função para adicionar um movimento à sequência
void add_to_sequence(char move) {
if (strlen(sequence) < MAX_SEQUENCE - 1) { // Garante que a sequência não exceda o tamanho máximo
int len = strlen(sequence);
sequence[len] = move; // Adiciona o novo movimento à sequência
sequence[len + 1] = '\0'; // Finaliza a string corretamente
}
}
void button_callback(uint gpio, uint32_t events)
{
uint32_t now = to_ms_since_boot(get_absolute_time());
if (gpio == BUTTON_A && ((now - last_debounce_time[0]) > DEBOUNCE_DELAY_MS)) //debounce
{
last_debounce_time[0] = now;
button_a_pressed = true;
}
if (gpio == BUTTON_B && ((now - last_debounce_time[1]) > DEBOUNCE_DELAY_MS)) // debounce
{
last_debounce_time[1] = now;
button_b_pressed = true;
}
}
// Função para configurar e movimentar o servo motor
void set_servo_pulse(uint16_t pulse_width) {
pwm_set_gpio_level(SERVO_PIN, pulse_width);
}
// Função para ler o LDR e ajustar a iluminação
void check_ldr() {
adc_select_input(2); // Seleciona o canal ADC2 (LDR)
uint16_t ldr_value = adc_read(); // Faz a leitura do LDR
float voltage = ldr_value * (3.3f / (1 << 12)); // Converte para tensão
//printf("LDR: %d, Tensão: %.2f V\n", ldr_value, voltage);// se quiser ver
// Ajusta a cor do LED com base na luz ambiente
if (ldr_value > 1000) {
// Posição máxima, ou seja, para barrar luz
set_servo_pulse(2850);
gpio_put(rgb_R, 0);
gpio_put(rgb_G, 0);
gpio_put(rgb_B, 0);
}else{ // persiana posição mínima, para entrar luz
set_servo_pulse(1000);
}
}
void check_dht(){
dht_reading reading;
read_from_dht(&reading, DHT_PIN); // função de dht.h
float fahrenheit = (reading.temp_celsius * 9 / 5) + 32;
printf("Humidity = %.1f%%, Temperature = %.1fC (%.1fF)\n",
reading.humidity, reading.temp_celsius, fahrenheit);
if (reading.temp_celsius>=25){
int I = 0;
while (I++ < 5) { // aqui ele faz 36 graus, coloquei esse valor pequeno pra não travar os outros comandos do código
sleep_ms(10);
gpio_put(Bm, false); gpio_put(Ap, true);
sleep_ms(10);
gpio_put(Ap, false); gpio_put(Bp, true);
sleep_ms(10);
gpio_put(Bp, false); gpio_put(Am, true);
sleep_ms(10);
gpio_put(Am, false); gpio_put(Bm, true);
}
}
}
// Função para verificar se a sequência corresponde a um comando específico
void check_command() {
if (button_a_pressed){
button_a_pressed = false;
printf("Botão A pressionado\n");
gpio_put(rgb_R, 1);
gpio_put(rgb_G, 1);
gpio_put(rgb_B, 1);
} else if (button_b_pressed){
button_b_pressed = false;
printf("Botão B pressionado\n");
gpio_put(rgb_R, 0);
gpio_put(rgb_G, 0);
gpio_put(rgb_B, 0);
} else if (strcmp(sequence, "LUC") == 0) { // se as strings são iguais
printf("Luz VERMELHA\n");
gpio_put(rgb_R, 1);
gpio_put(rgb_G, 0);
gpio_put(rgb_B, 0);
memset(sequence, 0, sizeof(sequence)); // Limpa a sequência após verificar
} else if (strcmp(sequence, "RRU") == 0) {
printf("Luz VERDE\n");
gpio_put(rgb_R, 0);
gpio_put(rgb_G, 1);
gpio_put(rgb_B, 0);
memset(sequence, 0, sizeof(sequence)); // Limpa a sequência após verificar
} else if (strcmp(sequence, "LRC") == 0) {
printf("Luz AMARELA\n");
gpio_put(rgb_R, 1);
gpio_put(rgb_G, 1);
gpio_put(rgb_B, 0);
memset(sequence, 0, sizeof(sequence)); // Limpa a sequência após verificar
} else if (strcmp(sequence, "CUR") == 0) {
printf("Luz MAGENTA\n");
gpio_put(rgb_R, 1);
gpio_put(rgb_G, 0);
gpio_put(rgb_B, 1);
memset(sequence, 0, sizeof(sequence)); // Limpa a sequência após verificar
} else if (strcmp(sequence, "CCU") == 0) {
printf("Luz CIANO\n");
gpio_put(rgb_R, 0);
gpio_put(rgb_G, 1);
gpio_put(rgb_B, 1);
memset(sequence, 0, sizeof(sequence)); // Limpa a sequência após verificar
} else if (strcmp(sequence, "DDC") == 0) {
printf("Luz AZUL\n");
gpio_put(rgb_R, 0);
gpio_put(rgb_G, 0);
gpio_put(rgb_B, 1);
memset(sequence, 0, sizeof(sequence)); // Limpa a sequência após verificar
} else if(strlen(sequence) == MAX_SEQUENCE - 1){
printf("Comando não reconhecido\n");
memset(sequence, 0, sizeof(sequence)); // Limpa a sequência após verificar
} else {
printf("Comando não reconhecido\n");
}
}
int main() {
stdio_init_all(); // Inicializa a comunicação serial
adc_init(); // Inicializa o ADC
adc_gpio_init(VRX_PIN); // Inicia ADC0 (pino 26)
adc_gpio_init(VRY_PIN); // Inicia ADC1 (pino 27)
adc_gpio_init(LDR_PIN); // Mesma coisa pro LDR, inicia o GP28 como o ADC2
gpio_init(SW_PIN);
gpio_set_dir(SW_PIN, GPIO_IN);
gpio_pull_up(SW_PIN);
gpio_init(rgb_R);
gpio_set_dir(rgb_R, GPIO_OUT);
gpio_put(rgb_R, 0);
gpio_init(rgb_G);
gpio_set_dir(rgb_G, GPIO_OUT);
gpio_put(rgb_G, 0);
gpio_init(rgb_B);
gpio_set_dir(rgb_B, GPIO_OUT);
gpio_put(rgb_B, 0);
gpio_init(DHT_PIN); // INICIA pino do DHT
gpio_set_function(SERVO_PIN, GPIO_FUNC_PWM); // servo como pwm
uint slice_num = pwm_gpio_to_slice_num(SERVO_PIN);
pwm_set_wrap(slice_num, 20000);
pwm_set_clkdiv(slice_num, 64);
pwm_set_enabled(slice_num, true);
// Configurar botões
gpio_init(BUTTON_A);
gpio_set_dir(BUTTON_A, GPIO_IN);
gpio_pull_up(BUTTON_A);
gpio_set_irq_enabled_with_callback(BUTTON_A, GPIO_IRQ_EDGE_FALL, true, &button_callback); // interrupção com callback
gpio_init(BUTTON_B);
gpio_set_dir(BUTTON_B, GPIO_IN);
gpio_pull_up(BUTTON_B);
gpio_set_irq_enabled_with_callback(BUTTON_B, GPIO_IRQ_EDGE_FALL, true, &button_callback);// interrupção com callback
/*pinos dc motor*/
gpio_init(Ap);
gpio_init(Am);
gpio_init(Bp);
gpio_init(Bm);
gpio_set_dir(Ap, GPIO_OUT);
gpio_set_dir(Am, GPIO_OUT);
gpio_set_dir(Bp, GPIO_OUT);
gpio_set_dir(Bm, GPIO_OUT);
/* INTRO OLED*/
i2c_init(I2C_PORT, 400 * 1000);
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);
ssd1306_init(&oled, 128, 64, 0x3C, I2C_PORT);
ssd1306_clear(&oled);
char* display_text = NULL;
display_text = "JoySustainability";
ssd1306_draw_string(&oled, 15, 20, 1.5, display_text);
ssd1306_show(&oled);
sleep_ms(1000);
ssd1306_clear(&oled);
display_text = "JoySmart";
ssd1306_draw_string(&oled, 30, 20, 1, display_text);
ssd1306_show(&oled);
sleep_ms(1000);
ssd1306_clear(&oled);
display_text = "JoySecurity";
ssd1306_draw_string(&oled, 30, 20, 1, display_text);
ssd1306_show(&oled);
sleep_ms(1000);
ssd1306_clear(&oled);
display_text = "JoySimple";
ssd1306_draw_string(&oled, 30, 20, 1, display_text);
ssd1306_show(&oled);
sleep_ms(1000);
ssd1306_clear(&oled);
display_text = "JoySwitch";
ssd1306_draw_string(&oled, 30, 20, 1, display_text);
ssd1306_show(&oled);
sleep_ms(2000);
while (true) {
adc_select_input(0);
uint16_t vrx_value = adc_read();
adc_select_input(1);
uint16_t vry_value = adc_read();
bool sw_value = gpio_get(SW_PIN) == 0;
if (vrx_value > 3000) add_to_sequence('L'); // LEFT
else if (vrx_value < 1000) add_to_sequence('R'); // RIGHT
if (vry_value > 3000) add_to_sequence('U'); // UP
else if (vry_value < 1000) add_to_sequence('D'); //DOWN
if (!last_sw_state && sw_value) { // debounce simplificado
add_to_sequence('C');
}
last_sw_state = sw_value;
printf("VRX: %u, VRY: %u, SW: %d, Sequence: %s\n", vrx_value, vry_value, sw_value, sequence);
check_command();
check_ldr();
check_dht();
sleep_ms(400);
}
return 0;
}//main