#include <Arduino.h>
#include <driver/ledc.h>
#include <math.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

const int adc = 36; // Pino ADC para leitura de sinal analógico
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

#define PWM_RESOLUTION LEDC_TIMER_10_BIT // Resolução de 10 bits (0-1023)
#define PWM_PIN_1 25
#define PWM_PIN_2 26
#define PWM_PIN_3 27
#define POT_PIN 32 // Pino do potenciômetro

// Definição dos canais PWM como ledc_channel_t
ledc_channel_t PWM_CHANNEL_1 = LEDC_CHANNEL_0;
ledc_channel_t PWM_CHANNEL_2 = LEDC_CHANNEL_1;
ledc_channel_t PWM_CHANNEL_3 = LEDC_CHANNEL_2;

// Variáveis para controle da barra de progresso
int barWidth = 0;             // Largura atual da barra
int lastBarWidth = -1;        // Última largura da barra desenhada

// Inicialização do LCD I2C (endereço 0x27, 20 colunas, 4 linhas)
LiquidCrystal_I2C lcd(0x27, 20, 4);

// Protótipo da função para exibir o texto "IFSP"
void displayIFSP();

void setup() {
  Serial.begin(115200);

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Endereço 0x3C para 128x64
    Serial.println(F("Falha na alocação SSD1306"));
    for (;;);
  }
  delay(2000);
  display.clearDisplay();

  // Exibe "IFSP" por 5 segundos ao iniciar
  displayIFSP();
  
  // Inicializa o LCD
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Freq1: 0 Hz");
  lcd.setCursor(0, 1);
  lcd.print("Freq2: 0 Hz");
  lcd.setCursor(0, 2);
  lcd.print("Freq3: 0 Hz");
  lcd.setCursor(0, 3);
  lcd.print("Pot: 0");

  // Configura o timer PWM para os três canais
  ledc_timer_config_t ledc_timer;
  ledc_timer.speed_mode = LEDC_HIGH_SPEED_MODE;
  ledc_timer.timer_num = LEDC_TIMER_0;
  ledc_timer.duty_resolution = PWM_RESOLUTION;
  ledc_timer.freq_hz = 5000; // Frequência inicial
  ledc_timer.clk_cfg = LEDC_AUTO_CLK;
  ledc_timer_config(&ledc_timer);

  // Configura os canais PWM
  ledc_channel_config_t ledc_channel;
  ledc_channel.speed_mode = LEDC_HIGH_SPEED_MODE;
  ledc_channel.timer_sel = LEDC_TIMER_0;
  ledc_channel.duty = 512; // 50% de duty cycle (resolução de 10 bits)
  ledc_channel.hpoint = 0;

  // Canal 1
  ledc_channel.channel = PWM_CHANNEL_1;
  ledc_channel.gpio_num = PWM_PIN_1;
  ledc_channel_config(&ledc_channel);

  // Canal 2
  ledc_channel.channel = PWM_CHANNEL_2;
  ledc_channel.gpio_num = PWM_PIN_2;
  ledc_channel_config(&ledc_channel);

  // Canal 3
  ledc_channel.channel = PWM_CHANNEL_3;
  ledc_channel.gpio_num = PWM_PIN_3;
  ledc_channel_config(&ledc_channel);

  // Ajuste inicial dos sinais PWM defasados em 120 graus
  setPWMPhase(PWM_CHANNEL_1, 0); //  fpr yhe first motor 
  setPWMPhase(PWM_CHANNEL_2, 120); // for tye second Motor 
  setPWMPhase(PWM_CHANNEL_3, 240); // For yhe last motor 
}

void loop() {
  // Leitura do valor do ADC
  int adcValue = analogRead(adc);
  // Converte o valor do ADC para um valor percentual de 0 a 100
  int percent = map(adcValue, 0, 4095, 0, 100);

  // Atualiza a largura da barra de progresso de forma suave
  updateBarWidth(percent);

  // Atualiza o texto no display SSD1306
  updateDisplay(percent);

  // Leitura do valor do potenciômetro
  int potValue = analogRead(POT_PIN);

  // Converte o valor do potenciômetro para a frequência desejada
  float frequency = map(potValue, 0, 4095, 0, 5000);
  setPWMSpeed(frequency);

  // Atualiza o LCD com as novas frequências e valor do potenciômetro
  lcd.setCursor(0, 0);
  lcd.print("Freq1: ");
  lcd.print(frequency);
  lcd.print(" Hz   ");

  lcd.setCursor(0, 1);
  lcd.print("Freq2: ");
  lcd.print(frequency);
  lcd.print(" Hz   ");

  lcd.setCursor(0, 2);
  lcd.print("Freq3: ");
  lcd.print(frequency);
  lcd.print(" Hz   ");

  lcd.setCursor(0, 3);
  lcd.print("Pot: ");
  lcd.print(potValue);
  lcd.print("    ");

  delay(100); // Aguarda um pouco antes de alterar a velocidade novamente
}

void setPWMSpeed(float frequency) {
  if (frequency > 0) {
    // Define a frequência para cada canal PWM
    ledc_set_freq(LEDC_HIGH_SPEED_MODE, LEDC_TIMER_0, frequency);
  } else {
    // Para o PWM se a frequência for 0
    ledc_set_freq(LEDC_HIGH_SPEED_MODE, LEDC_TIMER_0, 1);
  }
}

void setPWMPhase(ledc_channel_t channel, float phase) {
  // Calcula o duty cycle com base na fase desejada
  uint32_t duty = 512 + 512 * sin(phase * PI / 180);
  ledc_set_duty(LEDC_HIGH_SPEED_MODE, channel, duty);
  ledc_update_duty(LEDC_HIGH_SPEED_MODE, channel);
}

void updateBarWidth(int percent) {
  // Calcula a nova largura da barra proporcionalmente ao percentual
  int newBarWidth = map(percent, 0, 100, 0, SCREEN_WIDTH);

  // Atualiza a barra apenas se houver uma mudança significativa na largura
  if (newBarWidth != lastBarWidth) {
    lastBarWidth = newBarWidth;

    // Limpa a área onde a barra será desenhada
    display.fillRect(0, 0, SCREEN_WIDTH, 10, BLACK);

    // Desenha a barra de progresso horizontal no display SSD1306
    display.fillRect(0, 0, newBarWidth, 10, WHITE);
    display.display(); // Mostra a barra de progresso
  }
}

void updateDisplay(int percent) {
  // Atualiza o texto no display SSD1306
  display.clearDisplay();
  display.setTextSize(2); // Tamanho grande para o texto
  display.setTextColor(WHITE); // Cor do texto

  // Centraliza o texto verticalmente
  int textHeight = 16; // Altura do texto
  int centerY = (SCREEN_HEIGHT - textHeight) / 2; // Posição central vertical

  // Imprime o valor percentual
  display.setCursor(0, centerY);
  display.print(percent);
  display.print("%"); // Símbolo de percentagem

  // Texto "Fator de aceleracao" abaixo do valor percentual
  display.setTextSize(1); // Tamanho normal para o texto
  display.setCursor(0, centerY + textHeight + 4); // Posição do texto abaixo do percentual
  display.println("Fator de");
  display.println("aceleracao");

  display.display(); // Mostra tudo na tela
}

void displayIFSP() {
  // Exibe o texto "IFSP" de forma grande no display
  display.clearDisplay();
  display.setTextSize(3); // Tamanho grande para o texto
  display.setTextColor(WHITE); // Cor do texto

  // Centraliza o texto horizontal e verticalmente
  int textWidth = 3 * 6 * 4; // Largura aproximada do texto "IFSP" em pixels
  int textHeight = 3 * 8;   // Altura aproximada do texto "IFSP" em pixels
  int centerX = (SCREEN_WIDTH - textWidth) / 2; // Centraliza horizontalmente
  int centerY = (SCREEN_HEIGHT - textHeight) / 2; // Centraliza verticalmente

  // Exibe o texto "IFSP"
  display.setCursor(centerX, centerY);
  display.println("IFSP");

  display.display(); // Mostra o texto no display

  delay(5000); // Mantém o texto visível por 5 segundos
  display.clearDisplay(); // Limpa o display após 5 segundos
}










Loading chip...chip-max485
D0D1D2D3D4D5D6D7GNDLOGIC
Loading chip...chip-max485