/*
Este código controla um painel solar que segue a trajetória do sol ao longo do dia,
movendo-se de leste para oeste. O sistema simula o movimento do sol ao mover o
painel em pequenos passos a cada intervalo de tempo definido, ao longo de um ciclo
de "dia" completo.
Para a demonstração, o ciclo é ajustado para um tempo reduzido em vez de um dia real.
Essa velocidade mais rápida facilita a visualização do funcionamento do sistema
em tempo real. Em uma aplicação real, o tempo entre os passos seria ajustado para
cobrir um período de várias horas (por exemplo, das 8h às 18h).
Ao final de cada ciclo, o painel retorna automaticamente à posição inicial para
prepará-lo para o próximo dia. A função millis() é usada para calcular o tempo
entre cada passo, o que permite que o painel funcione de forma autônoma sem
necessidade de um módulo de relógio em tempo real (RTC).
*/
#include <Wire.h>
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <LiquidCrystal_I2C.h>
#include <AccelStepper.h>
// Configuração do MPU6050
Adafruit_MPU6050 mpu;
// Configuração do LCD 16x2 I2C (Endereço padrão 0x27)
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Configuração do Motor de Passo com A4988
#define DIR_PIN 2
#define STEP_PIN 3
AccelStepper stepper(AccelStepper::DRIVER, STEP_PIN, DIR_PIN);
// Parâmetros do ciclo diário de movimento (reduzido para demonstração)
const unsigned long cycleDuration = 600000UL; // 10 minutos em milissegundos para demonstração
const int totalSteps = 2000; // Total de passos para o ciclo completo
const unsigned long stepInterval = cycleDuration / totalSteps; // Intervalo entre cada passo
unsigned long lastStepTime = 0; // Armazena o último momento em que o motor deu um passo
void setup() {
Serial.begin(115200);
// Inicializando o LCD
lcd.begin(16, 2);
lcd.print("Painel Solar");
delay(1000);
lcd.clear();
lcd.print("Iniciando...");
// Inicializando o MPU6050
if (!mpu.begin()) {
lcd.clear();
lcd.print("Erro no MPU6050");
Serial.println("Erro: MPU6050 nao encontrado!");
while (1); // Trava o código se o MPU6050 não for encontrado
}
lcd.clear();
lcd.print("MPU6050 OK!");
// Configurando o motor de passo
stepper.setMaxSpeed(100); // Velocidade máxima do motor
stepper.setAcceleration(50); // Aceleração para movimento suave
// Configurando o MPU6050
mpu.setAccelerometerRange(MPU6050_RANGE_2_G);
mpu.setGyroRange(MPU6050_RANGE_250_DEG);
mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);
delay(1000); // Pausa inicial para o LCD
lcd.clear();
}
void loop() {
unsigned long currentTime = millis(); // Tempo decorrido desde que o Arduino foi ligado
// Verifica se é hora de dar o próximo passo
if (currentTime - lastStepTime >= stepInterval) {
lastStepTime = currentTime;
// Define o próximo passo do motor em direção ao oeste
stepper.move(stepper.currentPosition() + 1); // Move para o próximo passo absoluto
}
// Executa o movimento do passo e mantém o motor avançando
stepper.run();
// Lendo os dados do sensor MPU6050
sensors_event_t a, g, temp;
mpu.getEvent(&a, &g, &temp);
// Novo cálculo do ângulo de inclinação no eixo X para monitoramento
float angleX = atan2(a.acceleration.x, sqrt(a.acceleration.y * a.acceleration.y + a.acceleration.z * a.acceleration.z)) * 180 / PI;
// Mostrar o ângulo e progresso no LCD
lcd.setCursor(0, 0);
lcd.print("Angulo X: ");
lcd.print(angleX, 1); // Exibe o ângulo com uma casa decimal
lcd.print((char)223); // Símbolo de grau
lcd.print(" "); // Limpa o final da linha para evitar sobreposição
// Calcula e exibe o progresso
int progress = map(stepper.currentPosition(), 0, totalSteps, 0, 100); // Calcula o progresso em %
lcd.setCursor(0, 1);
lcd.print("Progresso: ");
lcd.print(progress);
lcd.print("% ");
delay(500); // Pequeno delay para atualização
}