Arduino Control Pure sine wave inverter [LEP]

ในตอนสุดท้าย เป็นการควบคุมแรงดันเอาต์พุตคงที่ด้วยการใช้หม้อแปลงขนาดแรงดัน 220Vac : 6Vac (หม้อแปลงขนาดเล็ก) เป็นตัวป้อนกลับสัญญาณเข้าที่ขา A1 ของตัวบอร์ด Arduino UNO เพื่อประมวล ผลและได้ค่าแรงดันกระแสสลับที่เอาต์พุตของอินเวอร์เตอร์ตามที่ตั้งค่าไว้ และสำหรับการเขียนโปรแกรมไมโครคอนโทรลเลอร์ควบคุมในตัว Arduino UNO จะเพิ่มคำสั่งเล็กน้อยและเข้าใจง่าย โดยการทดลองครั้งนี้จะมีด้วยกัน 2 แบบคือ ทดลองการควบคุมแบบเปิด (Open loop control) และการควบคุมแบบปิด (Close loop control) ทั้งนี้เพื่อให้เห็นความแตกต่างของผลที่เกิดขึ้นจากการทดลองครั้งนี้

ในรูปที่ 1 เป็นลักษระของการต่ออุปกรณ์ต่างๆ ที่ใช้ในการทดลองทั่วไป ซึ่งเป็นวงจรต้นแบบโดยในส่วนต่างๆ จะเชื่อมต่อด้วยกันผ่านสายแพรและสายไฟปกติ ทั้งนี้เพื่อให้ง่ายสำหรับการปรับแต่งหรือแก้ไขในระหว่างการทดลอง

รูปที่ 2 เป็นหม้อแปลงความถี่ต่ำ 220Vac : 6Vac สำหรับส่งสัญญาณป้อนกลับให้กับบอร์ดประมวลผล Arduino UNO โดยในด้านเอาต์พุต (6V) จะใช้วงจรเร็กติไฟร์และฟิลเตอร์ (Rectifier and filter circuit) เพื่อเปลี่ยนไฟฟ้ากระแสสลับให้เป็นกระแสตรง โดยแรงดันส่วนนี้จะเป็นสัดส่วนกับแรงดันทางด้านอินพุต (220V) และเราสามารถปรับค่าแรงดันที่ต้องการตั้งค่าได้อีกส่วนหนึ่งด้วยตัวต้านทานปรับค่า

รูปที่ 3 แสดงตัวต้านทานปรับค่าทั้ง 2 ตัว ซึ่งในแต่ละตัวจะทำหน้าที่ปรับค่าความถี่ทางด้านเอาต์พุตได้ (Adjsible frequency) และอีกตัวหนึ่งจะให้เราปรับค่าแรงดันที่เอาต์พุตได้เช่นกัน (Adjsible VAC output) ทั้งนี้เราจะต้องเขียนโปรแกรมให้กับตัวควบคุมสามารถรับค่าเหล่านี้ได้เช่นกัน
*** CodeProgram Arduino UNO [*Reference [1]]
// 3 phase PWM sine INVERTER
// (c) 2016 C. Masenas
// Modified from original DDS from:
// KHM 2009 / Martin Nawrath
// https://3phaseinverter.blogspot.com/
// https://github.com/cmasenas/3-Phase-Sine-Arduino/blob/Release/DDS_Generator.ino
// table of 256 sine values / one sine period / stored in flash memory
PROGMEM const unsigned char sine256[] = {
127,130,133,136,139,143,146,149,152,155,158,161,164,167,170,173,176,178,181,184,187,190,192,195,198,200,
203,205,208,210,212,215,217,219,221,223,225,227,229,231,233,234,236,236,
236,238,238,238,239,239,240,241,242,243,245,247,247,248,249,249,250,
251,251,252,252,252,252,252,
250,250,249,249,248,248,247,247,246,246,245,245,243,240,240,238,238,
236,236,234,233,231,229,227,225,223,221,219,217,215,212,210,208,205,203,
200,198,195,192,190,187,184,181,178,176,173,170,167,164,161,158,155,152,149,146,143,139,136,133,130,127,124,121,118,115,111,108,105,102,99,96,93,90,87,84,81,78,
76,73,70,67,64,62,59,56,54,51,49,46,44,42,39,37,35,33,31,29,27,25,23,21,20,18,16,15,14,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,16,18,20,21,23,25,27,29,31,
33,35,37,39,42,44,46,49,51,54,56,59,62,64,67,70,73,76,78,81,84,87,90,93,96,99,102,105,108,111,115,118,121,124
};
define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
int testPin = 7;
int enablePin = 8 ;
int sensorPin = A0;
int sensorValue = 0;
int ValueFB = 0;
float k = 0;
int Adj_Frq=25;
volatile float freq=1;
const float refclk=122.549 ; // 16 MHz/510/256
// variables used inside interrupt service declared as voilatile
volatile unsigned long sigma; // phase accumulator
volatile unsigned long delta; // phase increment
byte phase0, phase1, phase2 ;
void setup()
{
Serial.begin(9600); // Connect to the serial port
Serial.println("DDS Test");
pinMode(enablePin,OUTPUT); // sets the digital pin as output
pinMode(testPin,OUTPUT); // sets the digital pin as output
pinMode(5,OUTPUT);
pinMode(6,OUTPUT);
pinMode(9,OUTPUT);
pinMode(10,OUTPUT);
pinMode(11,OUTPUT);
pinMode(3,OUTPUT);
Setup_timer2();
Setup_timer1();
Setup_timer0();
digitalWrite(enablePin, HIGH);
// the waveform index is the highest 8 bits of sigma
// choose refclk as freq to increment the lsb of the 8 highest bits
// for every call to the ISR of timer2 overflow
// the lsb of the 8 highest bits is 1<<24 (1LL<<24 for long integer literal)
delta = (1LL<<24)*freq/refclk ;
}
void loop(){
ValueFB = analogRead(A1); // Voltage FB
if(ValueFB>500 && k>0.1) k-=0.01;
if(ValueFB<500 && k<0.99) k+=0.01;
delayMicroseconds(50);
sensorValue = analogRead(A0); // Adj_Frq
Adj_Frq = (sensorValue/9);
if (Adj_Frq <25) {
Adj_Frq = 25;
}
changeFreq(Adj_Frq);
}
void changeFreq(float _freq){
cbi (TIMSK2,TOIE2); // disable timer2 overflow detect
freq = _freq;
delta=(1LL<<24)*freq/refclk; // update phase increment
sbi (TIMSK2,TOIE2); // enable timer2 overflow detect
}
//**
// timer2 setup
// set prscaler to 1, fast PWM
void Setup_timer2() {
// Timer2 Clock Prescaler to : 1
sbi (TCCR2B, CS20); // set
cbi (TCCR2B, CS21); // clear
cbi (TCCR2B, CS22);
// Timer2 PWM Mode
cbi (TCCR2A, COM2A0); // clear OC2A on Compare Match, PWM pin 11
sbi (TCCR2A, COM2A1);
// set 2-8-60 ----------------------
sbi (TCCR2A, COM2B0); // clear OC2A on Compare Match, PWM pin 3
sbi (TCCR2A, COM2B1);
// set 2-8-60 ----------------------
// set to fast PWM
sbi (TCCR2A, WGM20); // Mode 1, phase correct PWM
cbi (TCCR2A, WGM21);
cbi (TCCR2B, WGM22);
sbi (TIMSK2,TOIE2); // enable overflow detect
}
// timer1 setup (sets pins 9 and 10)
// set prscaler to 1, PWM mode to phase correct PWM, 16000000/510 = 31372.55 Hz clock
void Setup_timer1() {
// Timer1 Clock Prescaler to : 1
sbi (TCCR1B, CS10);
cbi (TCCR1B, CS11);
cbi (TCCR1B, CS12);
// Timer1 PWM Mode set to Phase Correct PWM
cbi (TCCR1A, COM1A0); // clear OC1A on Compare Match, PWM pin 9
sbi (TCCR1A, COM1A1);
sbi (TCCR1A, COM1B0); // clear OC1B on Compare Match, PWM pin 10
sbi (TCCR1A, COM1B1);
sbi (TCCR1A, WGM10); // Mode 1 / phase correct PWM
cbi (TCCR1A, WGM11);
cbi (TCCR1B, WGM12);
cbi (TCCR1B, WGM13);
}
void Setup_timer0() {
sbi (TCCR0B, CS00);
cbi (TCCR0B, CS01);
cbi (TCCR0B, CS02);
// Timer0 PWM Mode set to Phase Correct PWM
cbi (TCCR0A, COM0A0); // clear OC0A on Compare Match, PWM pin
sbi (TCCR0A, COM0A1);
sbi (TCCR0A, COM0B0); // clear OC0B on Compare Match, PWM pin
sbi (TCCR0A, COM0B1);
sbi (TCCR0A, WGM00); // Mode 1 / phase correct PWM
cbi (TCCR0A, WGM01);
cbi (TCCR0B, WGM02);
}
//**
// Timer2 Interrupt Service at 31372,550 KHz = 32uSec
// this is the timebase REFCLOCK for the DDS generator
// runtime : 8 microseconds ( inclusive push and pop)
// OC2A - pin 11
// OC1B - pin 10
// OC1A - pin 9
// https://www.arduino.cc/en/Tutorial/SecretsOfArduinoPWM
ISR(TIMER2_OVF_vect) {
sigma=sigma+delta; // soft DDS, phase accu with 32 bits
phase0=sigma >> 24; // use upper 8 bits for phase accu as frequency information
// read value fron ROM sine table and send to PWM DAC
phase1 = phase0 +55 ; // 65
phase2 = phase0 +180 ; // 200
OCR1A = pgm_read_byte_near(sine256 + phase1)*k; // pwm pin 9 (+B)
OCR1B = OCR1A+3; // pwm pin 10
OCR0A = pgm_read_byte_near(sine256 + phase2)*k; // pwm pin 6 (+B)
OCR0B = OCR0A+3; // pwm pin 5
}

รูปที่ 4 เป็นลักษณะของการทดลอง ซึ่งในการทดลองนี้จะใช้มอเตอร์เป็นโหลดในการทดสอบวงจรอินเวอร์เตอร์ โดยตัวมอเตอร์จะมีขนาด 220V/0.53A เพื่อให้เห็นการตอบสนองการทำงานต่อโหลดที่นำมาต่อในเบื้องต้น

รูปที่ 5 เป็นลักษณะของการทดลองปรับค่าต่างๆ เพื่อสังเกตการทำงานของวงจรที่ออกแบบ และลักษณะของการประมวลผลของโปรแกรมที่สามารถทำงานได้ตามแนวความคิดที่กำหนด รวมทั้งผลที่เกิดขึ้นในด้านอื่นเพื่อเป็นประสบการณ์และหาทางแก้ไขอีกต่อไป

รูปที่ 6 เป็นวงจรที่ใช้ในการทดลองโครงงานนี้ โดยในส่วนด้านล่างของรูปกรอบสีน้ำเงิน จะเป็นวงจรป้อนกลับสัญญาณทางด้านเอาต์พุต (Feedback Signal) มายังตัวควบคุม โดยวิธีการนี้เป็นการใช้งวจรที่เข้าใจง่ายและไม่ยากมากนัก
Datasheet for IPM Power IGBT BM64364S-VA
สำหรับโครงงานการควบคุมอินเวอร์เตอร์ 1 เฟส ด้วยบอร์ด Arduino UNO นี้ ยังคงเป็นต้นแบบเล็กๆ ที่จะช่วยให้ท่านได้เห็นลักษณะการทำงานและการทดลองอีกแบบหนึ่ง ซึ่งท่านสามารถนำไปเป็นแนวทางสำหรับพัฒนาวงจรที่ต้องการและเหมาะสมต่อไปนะครับ.
Reference
- https://github.com/cmasenas/3-Phase-Sine-Arduino/blob/Release/DDS_Generator.ino
- 3-Phase-Sine-Arduino/DDS_Generator.ino at Release · cmasenas/3-Phase-Sine-Arduino · GitHub
- http://www.eprojectszone.com/how-to-generate-a-sine-wave-from-arduino-or-atmega-328/
- https://www.youtube.com/watch?v=mmwsh00No2c
- https://drive.google.com/file/d/1C91GSlEiPzmXDcwhuriaN-Rf8SkgqWoG/view?usp=sharing
- https://theorycircuit.com/arduino-inverter-circuit/
- https://www.electroschematics.com/sine-wave-generator-circuit/