#include <Arduino.h>
#include <math.h>
// Pinos de saída PWM
const uint8_t PWM_PINS[3] = { D3, D5, D6 };
const uint8_t ADC_PINS[3] = { A0, A1, A2 };
// Parâmetros
#define F_SINE_HZ 60.0f // Frequência fundamental
#define DOIS_PI 6.28318530718f
#define DT_SINE_MS 1.0f // Atualiza seno a cada 1 ms (~1 kHz)
#define PWM_TOP 200 // Resolução do PWM por software
#define TICK_US 10 // Passo do PWM em microssegundos -> f_pwm ≈ 500 Hz
// Defasagens (rad)
const float DEFASAGEM_A = 0.0f;
const float DEFASAGEM_B = -2.0f * PI / 3.0f; // -120°
const float DEFASAGEM_C = 2.0f * PI / 3.0f; // +120°
volatile uint16_t pwmCount = 0;
int dutyCount[3] = {0, 0, 0};
unsigned long lastPwmTickUs = 0;
unsigned long lastSineTickUs = 0;
unsigned long lastPrintMs = 0;
float theta = 0.0f;
void setup() {
for (int i = 0; i < 3; i++) {
pinMode(PWM_PINS[i], OUTPUT);
digitalWrite(PWM_PINS[i], LOW);
}
Serial.begin(115200);
}
void loop() {
const unsigned long nowUs = micros();
const unsigned long nowMs = millis();
// 1) Atualização da senóide e leitura dos potenciômetros (~1 ms)
if (nowUs - lastSineTickUs >= (unsigned long)(DT_SINE_MS * 1000.0f)) {
lastSineTickUs += (unsigned long)(DT_SINE_MS * 1000.0f);
// Leitura dos potenciômetros e normalização [0..1]
float A[3];
for (int i = 0; i < 3; i++) {
int raw = analogRead(ADC_PINS[i]); // 0..4095 (12 bits)
A[i] = constrain(raw / 4095.0f, 0.0f, 1.0f);
}
// Cálculo dos senos trifásicos com defasagem
float seno_A = sinf(theta + DEFASAGEM_A);
float seno_B = sinf(theta + DEFASAGEM_B);
float seno_C = sinf(theta + DEFASAGEM_C);
// Mapeamento para duty (0..1)
float duty[3] = {
0.5f + 0.5f * A[0] * seno_A,
0.5f + 0.5f * A[1] * seno_B,
0.5f + 0.5f * A[2] * seno_C
};
// Saturação e conversão para contagem (0..PWM_TOP)
for (int i = 0; i < 3; i++) {
duty[i] = constrain(duty[i], 0.0f, 1.0f);
dutyCount[i] = (int)(duty[i] * PWM_TOP);
}
// Avança ângulo (Δθ = 2π f Δt)
theta += DOIS_PI * F_SINE_HZ * (DT_SINE_MS / 1000.0f);
if (theta > DOIS_PI) theta -= DOIS_PI;
// 2) Impressão das senoides no Serial Plotter (a cada 10ms para suavizar gráfico)
if (nowMs - lastPrintMs >= 10) {
lastPrintMs = nowMs;
Serial.print(seno_A, 3); Serial.print(",");
Serial.print(seno_B, 3); Serial.print(",");
Serial.println(seno_C, 3);
}
}
// 3) PWM por software (a cada TICK_US)
if (nowUs - lastPwmTickUs >= TICK_US) {
lastPwmTickUs += TICK_US;
pwmCount++;
if (pwmCount >= PWM_TOP) pwmCount = 0;
for (int i = 0; i < 3; i++) {
digitalWrite(PWM_PINS[i], (pwmCount < dutyCount[i]) ? HIGH : LOW);
}
}
}