#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 "ss_oled.h"
#include "hardware/timer.h"
// definições oled
#define SDA_PIN 16
#define SCL_PIN 17
#define RESET_PIN -1
int rc;
SSOLED oled;
static uint8_t ucBuffer[1024];
#define OLED_WIDTH 128
#define OLED_HEIGHT 64
// 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 = 15;
char sequence[MAX_SEQUENCE] = ""; // Array pra armazenar string
bool last_sw_state = false; // Variável para armazenar o estado anterior do botão
/* intro oled**/
void init_oled() {
uint8_t uc[8];
int i, j;
char szTemp[32];
int rc = oledInit(&oled, OLED_128x64, 0x3c, 0, 0, 1, SDA_PIN, SCL_PIN, RESET_PIN, 1000000L);
if (rc != OLED_NOT_FOUND) {} // em caso de erro não travar
int x, y;
oledFill(&oled, 0, 1);
oledWriteString(&oled, 0,0,1,(char *)"JoySustainable", FONT_NORMAL,0,1);
sleep_ms(2000);
/*transição oled*/
for (x=0; x<OLED_WIDTH-1; x+=2)
{
oledDrawLine(&oled, x, 0, OLED_WIDTH-x, OLED_HEIGHT-1, 1);
}
for (y=0; y<OLED_HEIGHT-1; y+=2)
{
oledDrawLine(&oled, OLED_WIDTH-1,y, 0,OLED_HEIGHT-1-y, 1);
}
sleep_ms(800);
oledFill(&oled, 0, 1);
oledWriteString(&oled, 0,0,1,(char *)"JoySmart", FONT_NORMAL,0,1);
sleep_ms(2000);
/*transição oled*/
for (x=0; x<OLED_WIDTH-1; x+=2)
{
oledDrawLine(&oled, x, 0, OLED_WIDTH-x, OLED_HEIGHT-1, 1);
}
for (y=0; y<OLED_HEIGHT-1; y+=2)
{
oledDrawLine(&oled, OLED_WIDTH-1,y, 0,OLED_HEIGHT-1-y, 1);
}
sleep_ms(800);
oledFill(&oled, 0, 1);
oledWriteString(&oled, 0,0,1,(char *)"JoySecure", FONT_NORMAL,0,1);
sleep_ms(2000);
/*transição oled*/
for (x=0; x<OLED_WIDTH-1; x+=2)
{
oledDrawLine(&oled, x, 0, OLED_WIDTH-x, OLED_HEIGHT-1, 1);
}
for (y=0; y<OLED_HEIGHT-1; y+=2)
{
oledDrawLine(&oled, OLED_WIDTH-1,y, 0,OLED_HEIGHT-1-y, 1);
}
sleep_ms(800);
oledFill(&oled, 0, 1);
oledWriteString(&oled, 0,0,1,(char *)"JoySimple", FONT_NORMAL,0,1);
sleep_ms(2000);
/*transição oled*/
for (x=0; x<OLED_WIDTH-1; x+=2)
{
oledDrawLine(&oled, x, 0, OLED_WIDTH-x, OLED_HEIGHT-1, 1);
}
for (y=0; y<OLED_HEIGHT-1; y+=2)
{
oledDrawLine(&oled, OLED_WIDTH-1,y, 0,OLED_HEIGHT-1-y, 1);
}
sleep_ms(800);
oledFill(&oled, 0, 1);
oledWriteString(&oled, 0,0,1,(char *)"JoySavvy", FONT_NORMAL,0,1);
sleep_ms(2000);
/*transição oled*/
for (x=0; x<OLED_WIDTH-1; x+=2)
{
oledDrawLine(&oled, x, 0, OLED_WIDTH-x, OLED_HEIGHT-1, 1);
}
for (y=0; y<OLED_HEIGHT-1; y+=2)
{
oledDrawLine(&oled, OLED_WIDTH-1,y, 0,OLED_HEIGHT-1-y, 1);
}
sleep_ms(800);
oledFill(&oled, 0,1);
for (x=0; x<OLED_WIDTH-1; x+=2)
{
oledDrawLine(&oled, x, 0, OLED_WIDTH-1-x, OLED_HEIGHT-1, 0);
}
for (y=0; y<OLED_HEIGHT-1; y+=2)
{
oledDrawLine(&oled, OLED_WIDTH-1,y, 0,OLED_HEIGHT-1-y, 0);
}
oledWriteString(&oled, 0,0,1,(char *)"JoySwitch", FONT_NORMAL,0,1);
sleep_ms(2000);
oledFill(&oled, 0, 1);
oledDumpBuffer(&oled, ucBuffer);
oledWriteString(&oled, 0,0,1,(char *)"Embarcatech 2025", FONT_SMALL,0,1);
sleep_ms(2000);
oledFill(&oled, 0, 1);
}
// 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
}
}
// 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);
// Ajusta a cor do LED com base na luz ambiente
if (ldr_value > 1000) {
// Posição máxima (geralmente 180 graus)
set_servo_pulse(1000);
} else {
gpio_put(rgb_R, 0);
gpio_put(rgb_G, 0);
gpio_put(rgb_B, 0);
}
}
// Função para verificar se a sequência corresponde a um comando específico
void check_command() {
if (strcmp(sequence, "LUC") == 0) { // se as strings são iguais
printf("Luz vermelha\n"); // LEFT-UP-CENTER ativa o LED vermelho
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) { // RIGHT-RIGHT-UP ativa o LED verde
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, "DDC") == 0) { // DOWN-DOWN-DOWN-CENTER ativa o LED azul
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);
/*inicia pinos do rgb*/
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);
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);
init_oled();
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');
else if (vrx_value < 1000) add_to_sequence('R');
if (vry_value > 3000) add_to_sequence('U');
else if (vry_value < 1000) add_to_sequence('D');
if (!last_sw_state && sw_value) { // debounce
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);
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);
check_command();
check_ldr();
sleep_ms(250);
}
return 0;
}//main