Hello, I need some help with my problem. I am working on a 4-switch inverter to drive a 3-phase induction motor. Based on the B4 inverter topology, using SVPWM or Space Vector PWM can produce 4 conditions, there are:
- q1: 0, q2: 0
- q1: 0, q2: 1
- q1: 1, q2: 0
- q1: 1, q2: 1
However, why does the code I wrote below only produce 3 conditions (the one not produced is q1: 1 and q2: 0)? I still can't find the issue why it can't output according to the given topology. If you have any suggestions, I would be very grateful. Thank you.
#include <PWM.h> // Pustaka PWM untuk mengontrol frekuensi sinyal PWM
const int SINE_PIN1 = 9; // Pin output PWM untuk fasa 1
const int SINE_PIN2 = 10; // Pin output PWM untuk fasa 2
const int SINE_PIN3 = 11; // Pin output PWM untuk fasa 3
const int SINE_RESOLUTION = 256; // Resolusi tabel sinus
const float Phi = 3.14159265358979323846;
const int pwmPin = 12; // PWM pin triangle
const int amplitude = 127; // Amplitude of the triangle wave
int q1; // Pin output PWM Q1
int q2; // Pin output PWM Q2
const int PWM_Q1 = 5; //channel 4
const int PWM_Q2 = 6;
const int frequency = 5000; // Frekuensi dalam Hz
const float minValue = -2.0; // Nilai minimum sinyal (dalam volt)
const float maxValue = 2.0; // Nilai maksimum sinyal (dalam volt)
const int numSteps = 200; // Jumlah langkah dalam satu periode sinyal
const float stepDelay = 100 / numSteps; // Waktu per langkah dalam mikrodetik
int period = 0.0002; // Calculate period in microseconds
int delayTime = period / (2 * amplitude); // Calculate delay time for each step
// Matriks A
#define A11 1.0
#define A12 -0.5
#define A13 -0.5
#define A21 0.0
#define A22 (sqrt(3.0) / 2.0)
#define A23 (-sqrt(3.0) / 2.0)
// Vektor V (asumsi x1, x2, x3 didefinisikan sebagai global variabel)
float V1, V2, V3;
// Definisi Bilangan Real dan Imajiner
float z_real, z_imajiner;
// Variabel untuk menyimpan hasil perhitungan
float y1, y2, z_mag, z_ang, alpha;
int Sec;
float tb;
float tc;
float triangleWaveValue;
float tb_combined;
float tc_combined;
float segitigaf;
int Sector;
float angle, Ts, M;
float t00, t01, t10, t11;
byte sineTable[SINE_RESOLUTION];
void setup() {
pinMode(PWM_Q1, OUTPUT);
pinMode(PWM_Q2, OUTPUT);
// Setting input dan output
Serial.begin(9600);
pinMode(SINE_PIN1, OUTPUT);
pinMode(SINE_PIN2, OUTPUT);
pinMode(SINE_PIN3, OUTPUT);
pinMode(pwmPin, OUTPUT);
// Generate the sine table
generateSineTable();
// Inisialisasi timer tanpa mengganggu timer 0
InitTimersSafe();
bool success = SetPinFrequencySafe(SINE_PIN1, frequency); // Set frequency to 16000 Hz
SetPinFrequencySafe(SINE_PIN2, frequency);
SetPinFrequencySafe(SINE_PIN3, frequency);
SetPinFrequencySafe(pwmPin, frequency);
if (!success) {
Serial.println("Unable to set PWM frequency, check the pin configuration.");
while (true);
}
}
void loop() {
static unsigned long lastUpdate = 0;
unsigned long currentTime = millis();
// Output gelombang sinus 3 fasa menggunakan PWM
for (int i = 0; i < SINE_RESOLUTION; i++) {
// Tulis nilai sinus ke pin PWM fasa 1
V1 = sineTable[i];
pwmWrite(SINE_PIN1, V1);
// Tulis nilai sinus ke pin PWM fasa 2 dengan fase 120 derajat
V2 = sineTable[(i + SINE_RESOLUTION / 3) % SINE_RESOLUTION];
pwmWrite(SINE_PIN2, V2);
// Tulis nilai sinus ke pin PWM fasa 3 dengan fase 240 derajat
V3 = sineTable[(i + 2 * SINE_RESOLUTION / 3) % SINE_RESOLUTION];
pwmWrite(SINE_PIN3, V3);
// Calculate alpha-beta values inside the loop
alpha_beta();
// Set nilai z_real dan z_imajiner
z_real = y1; // contoh
z_imajiner = y2; // contoh
sector();
fswitch();
// Update sinyal segitiga setiap periode tertentu sesuai dengan frekuensi
if (currentTime - lastUpdate >= (1000 / (frequency * numSteps * 2))) {
segitigaf = generateTriangleWave();
tb_combined = segitigaf - tb;
tc_combined = segitigaf - tc;
lastUpdate = currentTime;
}
}
// Fungsi untuk mengatur nilai q1 dan q2 berdasarkan tb_combined dan tc_combined
if (tb_combined >= 0) {
q1 = 1;
} else {
q1 = 0;
}
if (tc_combined >= 0) {
q2 = 1;
} else {
q2 = 0;
}
if (q1 == 1) {
digitalWrite(PWM_Q1, HIGH);
} else {
digitalWrite(PWM_Q1, LOW);
}
if (q2 == 1) {
digitalWrite(PWM_Q2, HIGH);
} else {
digitalWrite(PWM_Q2, LOW);
}
Serial.print("tb_combined: ");
Serial.print(tb_combined);
Serial.print(" tc_combined: ");
Serial.println(tc_combined);
Serial.print("q1: ");
Serial.print(q1);
Serial.print(" q2: ");
Serial.println(q2);
Serial.print(" segitigaf: ");
Serial.print(segitigaf);
}
// Fungsi untuk menghasilkan tabel sinus
void generateSineTable() {
for (int i = 0; i < SINE_RESOLUTION; i++) {
sineTable[i] = 127 + 127 * sin(2 * Phi * i / SINE_RESOLUTION);
}
}
void alpha_beta() {
// Perhitungan y1 dan y2
y1 = sqrt(2.0 / 3.0) * (A11 * V1 + A12 * V2 + A13 * V3);
y2 = sqrt(2.0 / 3.0) * (A21 * V1 + A22 * V2 + A23 * V3);
}
void sector() {
// Konversi Rectangular ke Polar
z_mag = sqrt(z_real * z_real + z_imajiner * z_imajiner);
z_ang = atan2(z_imajiner, z_real);
alpha = z_ang * 180.0 / 3.14;
// Penentuan sektor
if (alpha > 0 && alpha <= 90) {
Sec = 1;
} else if (alpha > 90 && alpha <= 180) {
Sec = 2;
} else if (alpha >= -180 && alpha <= -90) {
Sec = 3;
} else if (alpha > -90 && alpha <= 0) {
Sec = 4;
}
}
void fswitch() {
// Menentukan case berdasarkan Sector
M = 0.8;
Ts = 0.00025;
angle = z_ang;
Sec;
if (Sec == 1) {
t10 = M * Ts * sin(angle);
t00 = 0.5 * Ts - M * Ts * sin(angle - 3.14 / 3.0);
t11 = 0.5 * Ts - M * Ts * sin(angle + 3.14 / 3.0);
t01 = 0;
} else if (Sec == 2) {
t11 = -sqrt(3.0) * M * Ts * cos(angle);
t10 = 0.5 * Ts + M * Ts * sin(angle + 3.14 / 3.0);
t01 = 0.5 * Ts - M * Ts * sin(angle - 3.14 / 3.0);
t00 = 0;
} else if (Sec == 3) {
t01 = -M * Ts * sin(angle);
t00 = 0.5 * Ts + M * Ts * sin(angle + 3.14 / 3.0);
t11 = 0.5 * Ts + M * Ts * sin(angle - 3.14 / 3.0);
t10 = 0;
} else {
t00 = sqrt(3.0) * M * Ts * cos(angle);
t10 = 0.5 * Ts + M * Ts * sin(angle - 3.14 / 3.0);
t01 = 0.5 * Ts - M * Ts * sin(angle + 3.14 / 3.0);
t11 = 0;
}
// Menghitung Tb dan Tc
tb = (1.0 / Ts) * (-t00 + t10 + t11 - t01);
tc = (1.0 / Ts) * (-t00 - t10 + t11 + t01);
}
// Fungsi untuk menghasilkan sinyal segitiga
float generateTriangleWave() {
static float value = minValue;
static bool ascending = true;
float stepSize = (maxValue - minValue) / numSteps;
if (ascending) {
value += stepSize;
if (value >= maxValue) {
value = maxValue;
ascending = false;
}
} else {
value -= stepSize;
if (value <= minValue) {
value = minValue;
ascending = true;
}
}
return value;
}