/**
* Universidade Federal da Paraíba
* Departamento de Engenharia Elétrica
* Laboratório 03 - Geração de Sinal Trifásico Senoidal via PWM
*
* Código SIMPLIFICADO - Defasagem MATEMATICAMENTE GARANTIDA
*/
#include <Arduino.h>
// ==================== CONFIGURAÇÕES ====================
#define PIN_PHASE_A D3
#define PIN_PHASE_B D5
#define PIN_PHASE_C D6
#define POT_PHASE_A A0
#define POT_PHASE_B A1
#define POT_PHASE_C A2
#define FREQUENCY_HZ 60
#define PWM_RESOLUTION 200
#define PWM_PERIOD_US 10
#define SINE_UPDATE_US 833 // 60Hz × 200 amostras = 12kHz
// ==================== VARIÁVEIS GLOBAIS ====================
unsigned long lastPwmUpdate = 0;
unsigned long lastSineUpdate = 0;
uint16_t pwmCounter = 0;
uint16_t dutyA = 100, dutyB = 100, dutyC = 100;
// Contador de amostras (0-199 para 200 amostras por ciclo)
uint16_t sampleCount = 0;
// ==================== SETUP ====================
void setup() {
pinMode(PIN_PHASE_A, OUTPUT);
pinMode(PIN_PHASE_B, OUTPUT);
pinMode(PIN_PHASE_C, OUTPUT);
digitalWrite(PIN_PHASE_A, LOW);
digitalWrite(PIN_PHASE_B, LOW);
digitalWrite(PIN_PHASE_C, LOW);
Serial.begin(115200);
Serial.println("SISTEMA TRIFASICO - DEFASAGEM 120° GARANTIDA");
}
// ==================== LOOP PRINCIPAL ====================
void loop() {
unsigned long currentTime = micros();
// 1. ATUALIZAÇÃO DA SENÓIDE (833μs = 200 amostras/ciclo a 60Hz)
if (currentTime - lastSineUpdate >= SINE_UPDATE_US) {
lastSineUpdate = currentTime;
updateSineWave();
}
// 2. ATUALIZAÇÃO PWM (10μs)
if (currentTime - lastPwmUpdate >= PWM_PERIOD_US) {
lastPwmUpdate = currentTime;
updatePWMOutput();
}
}
// ==================== FUNÇÕES ====================
/**
* Gera as 3 senóides com defasagem matemática
*/
void updateSineWave() {
// Lê potenciômetros
uint16_t potA = analogRead(POT_PHASE_A);
uint16_t potB = analogRead(POT_PHASE_B);
uint16_t potC = analogRead(POT_PHASE_C);
// Ângulo base (0-359 graus em escala 0-199)
uint16_t angle = (sampleCount * 360) / 200;
// Ângulos com defasagem fixa de 120°
uint16_t angleA = angle; // 0°
uint16_t angleB = (angle + 120) % 360; // 120°
uint16_t angleC = (angle + 240) % 360; // 240°
// Calcula senos (0-255 scale)
uint8_t sinA = calculateSine(angleA);
uint8_t sinB = calculateSine(angleB);
uint8_t sinC = calculateSine(angleC);
// Aplica amplitudes e offset para duty cycle (0-200)
dutyA = 100 + (sinA * potA) / 4095;
dutyB = 100 + (sinB * potB) / 4095;
dutyC = 100 + (sinC * potC) / 4095;
// Saturação
dutyA = constrain(dutyA, 0, PWM_RESOLUTION);
dutyB = constrain(dutyB, 0, PWM_RESOLUTION);
dutyC = constrain(dutyC, 0, PWM_RESOLUTION);
// Avança amostra
sampleCount++;
if (sampleCount >= 200) {
sampleCount = 0;
// Debug a cada ciclo completo (16.67ms)
static unsigned long lastDebug = 0;
if (millis() - lastDebug >= 1000) {
lastDebug = millis();
printDebugInfo(angleA, angleB, angleC);
}
}
}
/**
* Seno simplificado usando mapeamento linear
*/
uint8_t calculateSine(uint16_t angle) {
angle = angle % 360;
if (angle <= 90) {
return map(angle, 0, 90, 0, 255);
} else if (angle <= 180) {
return map(angle, 90, 180, 255, 0);
} else if (angle <= 270) {
return map(angle, 180, 270, 0, -255);
} else {
return map(angle, 270, 360, -255, 0);
}
}
/**
* Atualiza saídas PWM
*/
void updatePWMOutput() {
pwmCounter++;
if (pwmCounter >= PWM_RESOLUTION) {
pwmCounter = 0;
}
digitalWrite(PIN_PHASE_A, (pwmCounter < dutyA) ? HIGH : LOW);
digitalWrite(PIN_PHASE_B, (pwmCounter < dutyB) ? HIGH : LOW);
digitalWrite(PIN_PHASE_C, (pwmCounter < dutyC) ? HIGH : LOW);
}
/**
* Debug com verificação matemática da defasagem
*/
void printDebugInfo(uint16_t angleA, uint16_t angleB, uint16_t angleC) {
Serial.println("=== VERIFICAÇÃO MATEMÁTICA ===");
Serial.print("Ângulos: A=");
Serial.print(angleA);
Serial.print("° B=");
Serial.print(angleB);
Serial.print("° C=");
Serial.print(angleC);
Serial.println("°");
// Calcula defasagens
int diffAB = (angleB - angleA + 360) % 360;
int diffBC = (angleC - angleB + 360) % 360;
int diffCA = (angleA - angleC + 360) % 360;
Serial.print("Defasagens: AB=");
Serial.print(diffAB);
Serial.print("° BC=");
Serial.print(diffBC);
Serial.print("° CA=");
Serial.println(diffCA);
// Verificação CRÍTICA
bool correct = (diffAB == 120) && (diffBC == 120) && (diffCA == 120);
if (correct) {
Serial.println("✅ DEFASAGEM 120° PERFEITA!");
Serial.print("Tempo entre fases: ");
Serial.print(1000.0 / (3 * 60), 1);
Serial.println("ms");
} else {
Serial.println("❌ ERRO NA DEFASAGEM!");
}
Serial.println("---------------------------");
}