วันอาทิตย์ที่ 31 ธันวาคม พ.ศ. 2560

3-phase motor controller on Arduino board.



Time = ธรรม

ดู 3,201 ครั้ง
เผยแพร่เมื่อ 2 ต.ค. 2016
http://www.avrfreaks.net/forum/3-phas...
Arduino uno 3phase frequency driver controller for 3 phase induction motor CODE BY Tomasz Drazek Poland THANK YOU VERY MUCH SIR https://onedrive.live.com/?authkey=%2...
Sompong Tungmepol
//Arduino Atmega 168 Atmega 328P 3 phase induction motor Variable Speed Controller //Code
// Complier By Arduino Version 101 Version 106 Software
//รุ่นนี้เป็นแบบ AUTO RE RUN โค๊ดนี้ใช้วอลลุ่ม 5KB ตัวเดียวทำหน้าที่ ปิด -ปิด ปรับรอบ ให้ใช้ R //4K7 ต่อ ไฟ+5Vdc แล้วต่อเข้า ขาข้างด้าน + MAX ของ VR ต่อ R 1K-10 K ต่อ เข้า A3 ของ //ATmega 168 ATmega 328 P
#define UN (400.0) //napiecie znamionowe silnika
#define FN (50.0) //czestotliwosc znamionowa silnika
#define P (UN/FN) //wsp. okreslajacy proporcje napiecia do czestotliwoci znamionowej
#define T_PWM (0.000255) //okres sygnalu PWM - ustawiony przez preskaler w licznikach
#define T_MAX (4.0) //okreslenie maksymalnego okresu napiecia wyjsciowego
#define T_MIN (0.02) //minimalny okres napiecia wyjsciowego
#define K_MAX floor(T_MAX/T_PWM) //liczba wartosci okresu dla T_MAX
#define K_MIN ceil(T_MIN/T_PWM) //liczba wartosci okresu dla T_MIN

volatile static unsigned int dlugosc_tab_sin; //zmienna zawierajaca liczbe wartosci w pelnym
//okresie napiecia wyjsciowego
static unsigned int i = 0; //zmienna pomocniacza
volatile static unsigned int licznik_glowny = 0;//zmienna wystepujaca w przerwaniu czyklicznie
//^ co okres T_PWM zwiekszajaca swoja wartosc o 1
static unsigned int next_value_sin = 0; //zmienna ktora wartosc sin nalezy obliczyc
static double t_param=100; //parametr okreslajacy okres napiecia wyjsciowego
static float t = T_PWM; //T_PWM
static float omega_t; //pulsacja napiecia wyjsciowego pomnozona przez T_PWM
static float t_out; //okres wyjsciowy napiecia
static float U_o_param; //parametr okreslajacy wielkosc napiecie wyjsciowego
//^ obliczony na podstawie t_out i U_in
static unsigned int ocr0a, ocr0b, ocr1a;//zmienne pomocnicze do przechowywania obl. wypelnien
static unsigned int ocr1b, ocr2a, ocr2b;//^
static double sin_in; //zmienna zawierajaca parametr funkcji sin
static double blad = 1; //zmienna uzyta do zatrzymania generowania napiecia przy przeciazeniu
static unsigned int analog=0; //zmienna zawierajaca zmierzona wartosc
static double U_in = 0; //zmienna przechowujนca pomiar napiecia ukladu posredniczacego
static double U_rms_max; //maksymalna aktualnie mozliwa do generacji wartosc skuteczna napiecia
static bool a=0; //zmienna logiczna do realizacji dwoch naprzemiennych pomiarow
int main()
{
io_init(); //inicjalizacja wejsc i wyjsc
timers_init(); //inicjalizacja licznikow PWM
adc_init(); //inicjalizacja przetwornika ADC
while(1) //nieskonczona petla z programem glownym
{
if(i==185) //warunek okreslajacy wejscie do funkcji zmiany
{ //parametrow napiecia wysjciowego, wywolanie co okolo 100ms
zmien_predkosc(); //funkcja zmiany parametrow napiecia wyjsciowego
i=0;
}
next_value_sin = licznik_glowny%dlugosc_tab_sin; //kolejna wartoœๆ sinusa do obliczenia
sin_in=omega_t*next_value_sin;

//obliczenie wartosci do rejestrow okreslajacych wypelnienie sygnalu wyjscioweg/
ocr0a = round(blad*(U_o_param*(sin(sin_in)+1)*254/2)+1);//pin 6
ocr0b = ocr0a - 1;
ocr1a = round(blad*(U_o_param*(sin(sin_in-2.09)+1)*254/2)+1);//pin 9
ocr1b = ocr1a - 1;
ocr2a = round(blad*(U_o_param*(sin(sin_in+2.09)+1)*254/2)+1);//pin 11
ocr2b = ocr2a - 1;

//uaktualnienie wartosci w rejestrach/
cli(); //zabronienie na obsloge przerwan na wypadek gdyby
//podczas uaktualniania wystapilo przerwanie
OCR0A = ocr0a; //pin 6
OCR0B = ocr0b; //pin 5
OCR1AL = ocr1a; //pin 9
OCR1BL = ocr1b; //pin 10
OCR2A = ocr2a; //pin 11
OCR2B = ocr2b; //pin 3
sei(); //zezwolenie na obsloge przerwan
i++;
}
}
void adc_init()
{
ADCSRA |= _BV(ADEN);//uruchomienie przetwornika
ADCSRA |= _BV(ADPS2);//ustawienie preskalera
ADCSRA |= _BV(ADPS1);//^
ADCSRA |= _BV(ADPS0);//^
ADMUX |= _BV(REFS0);// napiecie odniesienia ustawione jako napiecie zasilania
ADMUX |= ADMUX &= 0b11110000; //wybranie wejscia ADC0 do pomiaru
}
void timers_init()
{
cli(); // obsloga przerwan zabroniona
//timer0 init
TCCR0A |= _BV(COM0A1) | _BV(COM0B0) | _BV(COM0B1) | _BV(WGM00);
TCCR0B |= _BV(CS01); //preskaler 8
TIMSK0 |= _BV(TOIE0); //flaga od wartosci 0 wlaczona
//timer1 init
TCCR1A |= _BV(COM1A1) | _BV(COM1B0) | _BV(COM1B1) | _BV(WGM10);
TCCR1B |= _BV(CS11); //preskaler 8
//timer2 init
TCCR2A |= _BV(COM2A1) | _BV(COM2B0) | _BV(COM2B1) | _BV(WGM20);
TCCR2B |= _BV(CS21); //preskaler 8
//zerowanie wartosci licznik๓w
TCNT0 = 0;
TCNT1L = 0;
TCNT2 = 0;
/* licznik zlicza w g๓re do 255, nastepnie w d๓ณ: /\/\/\
przy wartosci 255 jest przerwanie przy ktorym dokonuje sie
pomiarow napiec i pradow
*/
sei(); //zezwolenie na obsloge przerwan
}
void io_init()
{
pinMode(6, OUTPUT); //OC0A
pinMode(5, OUTPUT); //OC0B
pinMode(9, OUTPUT); //OC1A
pinMode(10, OUTPUT);//OC1B
pinMode(11, OUTPUT);//OC2A
pinMode(3, OUTPUT); //OC2B
pinMode(2, INPUT);
pinMode(4, INPUT);
pinMode(12, OUTPUT);
}
ISR(TIMER0_OVF_vect) //przerwanie przy wartosci 0 licznika0
{
analog = ADC;
if(a)
{
U_in = 0.0709*analog;
ADMUX |= _BV(MUX0); //wybranie wejscia ADC1 do pomiaru pradu
}
else
{
ADMUX |= ADMUX &= 0b11110000; //wybranie wejscia ADC0 do pomiaru napiecia
if(analog>579)
{
blad = 0; //jezeli przeciazenie wylaczenie generacji napiecia
digitalWrite(12, HIGH); //zapalenie diody
}
}
ADCSRA |= _BV(ADSC);//start odczytywania pomiaru
a=a^1; //bramka XOR neguje wartosc logiczna a
licznik_glowny++;
if(licznik_glowny>=dlugosc_tab_sin) licznik_glowny = 0;
}
void zmien_predkosc()
{

t_param = map(analogRead(3),0,1023,0,100);
U_rms_max = U_in*0.62; //wartosc 0.62 wyzanczona eksperymentalnie
bool up; //zmienna logiczna, informuje o nacisnietym przycisku zwieksz czestotliwosc
bool down; //zmienna logiczna, informuje o nacisnietym przycisku zmiejsz czestotliwosc
up = digitalRead(4); //odczyt: czy nacisniety przycisk zwieksz czestotliwosc
down = digitalRead(2); //odczyt: czy nacisniety przycisk zmiejsz czestotliwosc
if(up==1) t_param--; //jezeli nacisniety przycisk zwieksz czestotliwosc to zmiejsz okres
if(down==1) t_param++; //jezeli nacisniety przycisk zmniejsz czestotliwosc to zwieksz okres
if(t_param<0) t_param=0; //zabezpieczenie przekroczenia wartosci skrajnych
if(t_param>100) t_param=100;//^
dlugosc_tab_sin = ceil((K_MAX-K_MIN)*t_param/500+K_MIN);//ilosc wartosci wypelnien w jednym okresie
t_out = T_PWM*dlugosc_tab_sin; //obliczenie okresu napiecia wyjsciowego
omega_t = t*2*PI/t_out; //obliczenie pulsacji napiecia wyjsciowego
U_o_param = (P/t_out)/U_rms_max; //obliczenie parametru okreslajacego wielkosc napiecia wyjsciowego
if(t_out>1) U_o_param = 0.5*(18.5/U_rms_max); //napi๊cie na wyjsciu przy niskiej czestotliwosci 10V
if(U_o_param>1) U_o_param=1;
//zabezpieczenie przekroczenia wartosci skrajnych
blad = 1; //jezeli przeciazenie wylaczenie generacji napiecia
digitalWrite(12, LOW); //zapalenie diody
}
Sompong Tungmepol
การสร้างเครื่อง Solft start motor สามเฟส อินเวอร์เตอร์แบบเพียวซายน์ และ แบบ สามเฟส รุ่นใหม่ ชนิด โปรแกรมได้ วงจรและโค๊ด หาได้จากที่นี่ครับ https://onedrive.live.com/?authkey=%21AGul_y3NOhiUL68&id=5D7E6463F144D1A1%2174036&cid=5D7E6463F144D1A1
https://www.youtube.com/watch?v=fHoEmjUX8_8
http://www.emergingtechs.org/p/blog-page_14.html
รุ่นใหม่ ราคาประหยัด ครับ นำไปบัดกรีและต่อเติมตามถนัดครับ..มี บอร์ด Arduino 1 บอร์ด ราคา 700 บาท ซื้อ เฉพาะไอซี Atmega 328 P ที่UPLOAD โปรแกรมแล้ว ก็ได้ครับ แล้วนำไป บัดกรีเอง ราคา 300 บาท และ PS21244 1 ตัว หรือ PS21963 PS219A2 ราคา 200 บาท ครับ ลงวันที่ 31 ธันวาคม 2560 โปรแกรม เป็นแบบ PURE SINE เฟสเดียว แบบ สามเฟส หรือ แบบ DC FULL BRIDGE ก็ ได้ครับ ติดต่อที่ Line 020453653 Email sompongindustrial@gmail.com mrsompongt@hotmail.com
Sompong Tungmepol
// software for direct drive motor Arduino mega2560
//Danijel Gorupec, 2015
//Edit prescaller 4khz And Sine wave For IGBT GT15J331 L6569 4 Khz PWM By Sompong Tungmepol //2/16/2017
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>



#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))





char sin_table[64]=
{
0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45,
48, 51, 54, 57, 59, 62, 65, 67, 70, 73, 75, 78, 80, 82, 85, 87,
89, 91, 94, 96, 98, 100,102,103,105,107,108,110,112,113,114,116,
117,118,119,120,121,122,123,123,124,125,125,126,126,126,126,126,
};

unsigned char pwm_table[256]; //holds V-F curve adjusted PWM outputs

unsigned char speed; //output frequency (uint: 0.25Hz)
unsigned char direction; //rotation direction (0 forwared, 1 reverse)
unsigned int phase; //the phase of output sine signal


//some handy macros
#define LED_ON {SREG&=0x7F;PORTF|=0x10;SREG|=0x80;}
#define LED_OFF {SREG&=0x7F;PORTF&=0xEF;SREG|=0x80;}
#define INVERTOR_ENABLE {PORTF|=0x20;PORTB|=0x03;PORTE|=0x03;PORTG|=0x03;PORTH|=0x03;PORTL|=0x03;}
#define INVERTOR_DISABLE {PORTF&=0xDF;PORTB&=0xFF;}
#define INPUT_JOG ((PINF&0x02)==0)
#define INPUT_RUN ((PINF&0x04)==0)
#define INPUT_DIR ((PINF&0x08)==0)
#define JOG_SPEED 20


//timer interrupt routing
//It is called in fixed intervals. It advances sine wave phase.
ISR (TIMER0_OVF_vect)
{
if (direction==0)
phase+=speed; //phase: 0...16384 equals 0...2*pi
else
phase-=speed;

unsigned int p=phase/64;
unsigned char p1=p%256;
unsigned char p2=p1+85;
unsigned char p3=p1+171;

OCR1A=pwm_table[p2];//pwm_table[p1];
OCR1B=OCR1A-1;//pwm_table[p2];
OCR2A=pwm_table[p3];//pwm_table[p3];
OCR0A=pwm_table[p1];//OCR1A-1;
OCR0B=OCR0A-1;//OCR1B-1;
OCR2B=OCR2A-1;//OCR2A-1;

OCR3A=pwm_table[p2];//pwm_table[p1];
OCR3B=OCR3A-1;//pwm_table[p2];
OCR4A=pwm_table[p3];//pwm_table[p3];
OCR3C=pwm_table[p1];//OCR1A-1;
OCR4B=OCR4A-1;//OCR1B-1;
OCR4C=OCR3C-1;//OCR2A-1;

OCR5A=pwm_table[p2];//pwm_table[p1];
OCR5B=pwm_table[p3];//pwm_table[p3];
OCR5C=pwm_table[p1];//OCR1A-1;
//adjust the next timer interrupt time
TCNT0=256-240;
}


//this function makes a short pause
//time uint: about 10 microseconds (100 = 1 millisecond)
void WaitLoop(unsigned int time)
{
unsigned int i,j;
for (j=0;j<time;j++)
{
for (i=0;i<8;i++) //the ATmega is runs at 8MHz

if (PORTF==0xFF) DDRB|=0x02;DDRE|=0x02;DDRG|=0x02;DDRH|=0x02;DDRL|=0x02;//just a dummy instruction

}
}



char analog_channel=0;
void ReadAnalogs(void)
{
if (ADCSRA&(1<<ADSC)) {return;} //the conversion still not finished

if (analog_channel==0)
{
//ADCH is the speed reference (but inverted!!! - 255=min speed, 0=max speed)
unsigned char spd_ref=255-ADCH;

if (INPUT_JOG) spd_ref=JOG_SPEED;

if (INPUT_DIR)
{
if (direction==0) spd_ref=10;
if (speed==10) direction=1; //only allow direction change at minimum speed
}
else
{
if (direction==1) spd_ref=10;
if (speed==10) direction=0; //only alow direction change at minimum speed
}

if (spd_ref>speed) speed++;
if (spd_ref<speed) speed--;
if (speed<10) speed=10; //the minimum speed

//in next reading we again read this channel because there are no other analog channels used
analog_channel=0;
ADMUX=0x60;
}

ADCSRA|=(1<<ADSC);
}



int main()
{
//Set ATmega8 fuses to 8MHz, internal RC
//Hardware cosist of ATMega8 microcontroller, 6xIRF840 MOSFET (3 halfbridges)

//wait a bit, cca 300ms, for easier programming
//(otherwise programmer has problems downloading)
WaitLoop(30000);


//F0 - programable input 1 A0(speed reference - inverted analog input, +5V=min speed, 0V=max speed)
//F1 - programable input 2 A1(jog - digital input, active low)
//F2 - programable input 3 A2(run signal - digital input, active low)
//F3 - programable input 4 A3(rotation direction - digital input, active low)
//F4 - LED output A4
//F5 - enable output A5
DDRF=(unsigned char)0xF8;
DDRB=(unsigned char)0xF0;
DDRE=(unsigned char)0x38;
DDRG=(unsigned char)0x20;
DDRH=(unsigned char)0x78;
DDRL=(unsigned char)0x38;

PORTF|=0x0F;

INVERTOR_DISABLE;

//LED test (0.3 sec)
LED_ON;
WaitLoop(30000);
LED_OFF;


//configuring ADC (trigger mode)
ADMUX=0x60; //AVcc for reference, right aligned, mux=ADC0
ADCSRA=0xC7; //ADC frequency (62.5kHz), results in 4.8kHz sampling rate

//wait one more milisecond
WaitLoop(100);
//timer0 init
TCCR0A |= _BV(COM0A1) | _BV(COM0B0) | _BV(COM0B1) | _BV(WGM00);
TCCR0B |= _BV(CS01); //preskaler 8
TIMSK0 |= _BV(TOIE0); //flaga od wartosci 0 wlaczona
//timer1 init
TCCR1A |= _BV(COM1A1) | _BV(COM1B0) | _BV(COM1B1) | _BV(WGM10);
TCCR1B |= _BV(CS11); //preskaler 8
//timer2 init
TCCR2A |= _BV(COM2A1) | _BV(COM2B0) | _BV(COM2B1) | _BV(WGM20);
TCCR2B |= _BV(CS21); //preskaler 8
//timer3 init
TCCR3A |= _BV(COM3A1) | _BV(COM3B0) | _BV(COM3B1) | _BV(WGM30);
TCCR3B |= _BV(CS31);
TCCR3C |= _BV(COM3A1) | _BV(COM3B0) | _BV(COM3B1) | _BV(WGM33);
TCCR3C |= _BV(CS31);//;|(1 << CS00); //preskaler 8

cbi (TCCR3A, COM3C0);
sbi (TCCR3A, COM3C1);



//timer4 init
TCCR4A |= _BV(COM4A1) | _BV(COM4B0) | _BV(COM4B1) | _BV(WGM40);
TCCR4B |= _BV(CS41);
TCCR4C |= _BV(CS40); //preskaler 8

cbi (TCCR4A, COM4C0);
sbi (TCCR4A, COM4C1);

//timer5 init
TCCR5A |= _BV(COM5A1) | _BV(COM5B0) | _BV(COM5B1) | _BV(WGM50);
TCCR5B |= _BV(CS51); //preskaler 8
TCCR5C |= _BV(CS51);

cbi (TCCR5A, COM5C0);
sbi (TCCR5A, COM5C1);
//configuring timer 0
TCNT0=0x00; //timer set to start value
TCCR0A|=0x04; //timer/counter 0 input frequency divider set to /8 (that is, 1MHz)
TIMSK0|=0x01; //timer/counter 0 interrupt enabled
SREG|=0x80; //global interrupt enabled


speed=10; //2.5 Hz

//OCR1A=128;
//OCR1B=128;
//OCR2=128;

unsigned char led_cntr=0;

while (1)
{
int i;

if ((INPUT_RUN) || (INPUT_JOG))
{
if (led_cntr>16) LED_OFF else LED_ON //we just make short blinks to save power
led_cntr++;

//The VFfactor defines VF curve (how V depends on speed)
int VFfactor=240; //ปกติ +18 ไม่เกิน +180 This setting is for asynchronous motor in delta connection (230VAC delta / 400VAC star)
//int VFfactor=speed/2+14; //this settign is for 200VAC servo motor with permanent magnet
if (VFfactor>255) VFfactor=255;

//computing PWM ratios (as we have nothing else to do, this is not optimized)
for (i=0;i<64;i++)
{
int A=sin_table[i];
if (A>127) A=-256+A; //wow! how come I cannot cast char to int?

A=A*VFfactor;
A=A/256;

A+=128+6;
if (A>250) A=250; //because signal delay, we cannot actually create very short impulses

SREG&=0x7F;
pwm_table[i]=A;
pwm_table[127-i]=A;
SREG|=0x80;
A=255-A;
SREG&=0x7F;
pwm_table[i+128]=A;
pwm_table[255-i]=A;
SREG|=0x80;
}

INVERTOR_ENABLE;
}
else
{
INVERTOR_DISABLE;
OCR1A=128;
OCR1B=128;
OCR2A=128;
OCR0A=128;
OCR0B=128;
OCR2B=128;
OCR3A=128;
OCR3B=128;
OCR3C=128;
OCR4A=128;
OCR4B=128;
OCR4C=128;
OCR5A=128;
OCR5B=128;
OCR5C=128;
for (i=0;i<255;i++)
{
SREG&=0x7F;
pwm_table[i]=128;
SREG|=0x80;
}
led_cntr=0;
LED_OFF;
speed=10;
}

ReadAnalogs();

}

}
สมพงศ์ อินดัสเตรียล อิเล็กทรอนิคส์
การต่อกับ Arduino UNO Atmega328 ต่อตามนี้ครับ D6= UP D9= VP D11=WP D5=UN D10=VN D3=WN ในคลิปเป็นการต่อกับ MC3PHAC ครับ ดูรายละเอียด จาก คลิป ก่อนหน้านี้ ประกอบการตัดสินใจ ซื้อ นะครับ..ขอบคุณมากครับ...ที่ติดตาม..อะไหล่และอุปกรณ์ ตามคลิป มีจำหน่าย ที่ sompong industrial electronics ท่านที่จะนำไปใช้ ส่วนรวม วัด โรงเรียน โรงพยาบาล ศาสนสถาน ผมยินดี บริจาคให้ ไม่คิดมูลค่า ครับ ..ขอ อนุโมทนา..ครับ. หรือท่านที่ สนใจงานด้านนี้ เพื่อ ทำไปใช้งานส่วนตัว งานอาชีพ ที่ไม่ผิดศีล ผิดธรรม วินัย ไม่เบียดเบียน สรรพสัตว์ สรรพชีวิต งานด้านสร้างสรรค์ แต่ไม่มี เงิน พอที่จะซื้อ ได้ ผมก็ ยินดี บริจาคให้โดย ไม่คิดมูลค่า ครับ ( เท่าที่ของ พอมีอยู่นะครับ...หมดแล้วหมดเลยครับ หมดเป็น รุ่น รุ่นไป ของจากคลิปเก่า ไม่มีแล้วครับ ขอบพระคุณ และอนุโมทนา สาธุ ครับ) ลงวันที่ 24 ตุลาคม 2559 ติด ต่อทาง Email ที่ sompongindustrial@gmail.com mrsompongt@hotmai.com

TM52A หมดแล้วครับ เบอร์ใหม่ ดูจากคลิป นะครับ เป็นเบอร์ GT15J331 และ PS21244 ครับผม..https://www.youtube.com/watch?v=A9fDf...
ทดสอบPower Module GT15J331 โดยใช้มอเตอร์สามเฟสครับ....ใช้งานจริง ต้องติดตั้งบนแผ่นระบายความร้อน..และติดพัดลม..ด้วยนะครับ
https://www.youtube.com/watch?v=YfVvJ...
ระบบอินเวอร์เตอร์ inverter ใช้ร่วมกับโซล่าเซลล์ประหยัดไฟได้จริงหรือไม่ดูจากคลิปนี้ครับPOWER MODULE ควบคุมมอเตอร์สามเฟส Tm52A หมดแล้วนะครับ...วันนี้ต้องเป็นเบอร์ GT15J331 PS21244 ครับ..
TM 51 รับแรงดันไฟฟ้ากระแสตรงตั้งแต่ 24 Voltsถึง 300 Volts ครับ รับกระแสได้ 10 ถึง 15 Amps แล้วจะทำหน้าที่ เปลี่ยนเป็นไฟฟ้ากระแสตรง -ทีแรงดัน 370-375 Volts เพื่อนำไปจ่ายให้กับ PS21244 PS21963 PS219A2 GT15J331 ทำหน้าที่ขับมอเตอร์ สามเฟส 220/380 Volts สูงสุดที่ประมาณ 1/2 แรงม้า ถึง3 แรงม้าแนะนำให้ใช้ที่..1 แรงม้าครับ..บอร์ด Arduino ทำหน้าที่ สร้างและกำหนดค่าของสัญญาณ สามเฟส SINE WAVE แบบ PWM ครับ..มีจำหน่ายหลายที่ครับ ติดต่อกันเองก็แล้วกัน ถ้าหาไม่ได้ ลองโทรไปที่ 02 951 1356 และ 081-803-6553 นะครับ...LINE pornpimon 1411 หรือ ติดต่อที่ s o m p o n g i n d u s t r i a l @ g mail .com m r s o m p o n g t @h o t mail.comm ก็ได้ครับ จำหน่าย PS 21244 MITSUBISHI SEMICONDUCTOR TRANSFER-MOLD TYPE INSULATED TYPE
6 DI 15 S -050 C 6 DI 15 S-050 D TM 51 สำหรับสร้างเครื่องควบคุมมอเตอร์สามเฟส...
วิธีทำให้ TM51จ่ายแรงดันไฟฟ้า 280โวลต์ไม่เกิน320โวลต์เพื่อใช้กับ PS21244 PS21963 PS219A2 MP6501A 6DI15S-050
karolina maria
hello good night, I'm experimenting with a 3-phase inverter design with arduino nano, put the program that is here on the internet, but the fault that I present is that it rotates like a stepper motor, please please me you can indicate that it may be happening thank you, karolinamarialopezjhonson@hotmail.com

hola buenas noches, estoy experimentando con un diseño de inversor trifásico con arduino nano, pongo el programa que está aquí en internet, pero la falla que les presento es que gira como un motor paso a paso, por favor, me pueden indicar que puede estar sucediendo gracias, karolinamarialopezjhonson@hotmail.com
Mani sambandam
can i use this in inverter to excite the induction generator? do you have Spwm or SVM code for 3 phase inverter?
Mani sambandam
i can use directly these code in 328? is that closed loop control?
Sompong Tungmepol
//ใช้ขับมอเตอร์สามเฟส ได้พร้อมกัน 5 ตัว
// DDS Sine Generator 3 phase motor x5 mit ATMEGA 2560 PWM 4KHZ


#include "arduino.h" //Store data in flash (program) memory instead of SRAM
#include "avr/pgmspace.h"
#include "avr/io.h"

const byte sine256[] PROGMEM = {
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,238,239,240,
242,243,244,245,247,248,249,249,250,251,252,252,253,253,253,254,254,254,254,254,254,254,253,253,253,252,252,251,250,249,249,248,247,245,244,243,242,240,239,238,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 a bit to have the properties of a clear bit operator
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))//define a bit to have the properties of a set bit operator

int PWM1= 2;// PWM1 output, phase 1
int PWM2 = 3; //[WM2 ouput, phase 2
int PWM3 = 4; //PWM3 output, phase 3

int PWM4= 5;// PWM1 output, phase 1
int PWM5 = 6; //[WM2 ouput, phase 2
int PWM6 = 7; //PWM3 output, phase 3

int PWM7 = 8;// PWM1 output, phase 1
int PWM8 = 9; //[WM2 ouput, phase 2
int PWM9 = 10; //PWM3 output, phase 3

int PWM10 = 11;// PWM1 output, phase 1
int PWM11 = 12; //[WM2 ouput, phase 2
int PWM12 = 13; //PWM3 output, phase 3

int PWM13 = 44;// PWM1 output, phase 1
int PWM14 = 45; //[WM2 ouput, phase 2
int PWM15 = 46; //PWM3 output, phase 3

int offset_1 = 85; //offset 1 is 120 degrees out of phase with previous phase, Refer to PWM to sine.xls
int offset_2 = 170; //offset 2 is 120 degrees out of phase with offset 1. Refer to PWM to sine.xls
int program_exec_time = 52; //monitor how quickly the interrupt trigger
int ISR_exec_time = 53; //monitor how long the interrupt takes

double dfreq;
const double refclk=31376.6; // measured output frequency

// variables used inside interrupt service declared as voilatile
volatile byte current_count; // Keep track of where the current count is in sine 256 array
volatile byte ms4_delay; //variable used to generate a 4ms delay
volatile byte c4ms; // after every 4ms this variable is incremented, its used to create a delay of 1 second
volatile unsigned long phase_accumulator; // pahse accumulator
volatile unsigned long tword_m; // dds tuning word m, refer to DDS_calculator (from Martin Nawrath) for explination.

void setup()
{
pinMode(PWM1, OUTPUT); //sets the digital pin as output
pinMode(PWM2, OUTPUT); //sets the digital pin as output
pinMode(PWM3, OUTPUT);

pinMode(PWM4, OUTPUT); //sets the digital pin as output
pinMode(PWM5, OUTPUT); //sets the digital pin as output
pinMode(PWM6, OUTPUT); //sets the digital pin as output

pinMode(PWM7, OUTPUT); //sets the digital pin as output
pinMode(PWM8, OUTPUT); //sets the digital pin as output
pinMode(PWM9, OUTPUT);

pinMode(PWM10, OUTPUT); //sets the digital pin as output
pinMode(PWM11, OUTPUT); //sets the digital pin as output
pinMode(PWM12, OUTPUT);

pinMode(PWM13, OUTPUT); //sets the digital pin as output
pinMode(PWM14, OUTPUT); //sets the digital pin as output
pinMode(PWM15, OUTPUT);

pinMode(50, OUTPUT); //sets the digital pin as output
pinMode(52, OUTPUT); //sets the digital pin as output
pinMode(53, OUTPUT);


sbi(PORTB,program_exec_time); //Sets the pin

Setup_timer0();
Setup_timer1();
Setup_timer2();
Setup_timer3();
Setup_timer4();
Setup_timer5();
//Disable Timer 1 interrupt to avoid any timing delays
cbi (TIMSK0,TOIE0); //disable Timer0 !!! delay() is now not available
sbi (TIMSK2,TOIE2); //enable Timer2 Interrupt


tword_m=pow(2,32)*dfreq/refclk; //calulate DDS new tuning word

}






void loop()
{
while(1)
{
sbi(PORTB,program_exec_time); //Sets the pin
if (c4ms > 0) // c4ms = 4ms, thus 4ms *250 = 1 second delay
{
c4ms=0; //Reset c4ms
//dfreq=map(analogRead(0),0,1230,0,1000);
dfreq=map(analogRead(0),0,1023,0,1000); //Read voltage on analog 1 to see desired output frequency, 0V = 0Hz, 5V = 1.023kHz
cbi (TIMSK2,TOIE2); //Disable Timer2 Interrupt
tword_m=pow(2,32)*dfreq/refclk; //Calulate DDS new tuning word
sbi (TIMSK2,TOIE2); //Enable Timer2 Interrupt
}
}
}

void Setup_timer0(void)
{


TCCR0B = (TCCR0B & 0b11111000) | 0x02;
// Timer1 PWM Mode set to Phase Correct PWM
cbi (TCCR0A, COM0A0);
sbi (TCCR0A, COM0A1);
cbi (TCCR0A, COM0B0);
sbi (TCCR0A, COM0B1);

// Mode 1 / Phase Correct PWM
sbi (TCCR0A, WGM00);
cbi (TCCR0A, WGM01);

}

void Setup_timer1(void)
{

TCCR1B = (TCCR1B & 0b11111000) |0x02;
// Timer1 Clock Prescaler to : 8

cbi (TCCR1A, COM1A0);
sbi (TCCR1A, COM1A1);
cbi (TCCR1A, COM1B0);
sbi (TCCR1A, COM1B1);


sbi (TCCR1A, WGM10);
cbi (TCCR1A, WGM11);
cbi (TCCR1B, WGM12);
cbi (TCCR1B, WGM13);
}


void Setup_timer2()
{

TCCR2B = (TCCR2B & 0b11111000) | 0x02;// Timer2 Clock Prescaler to : 8

cbi (TCCR2A, COM2A0); // clear Compare Match
sbi (TCCR2A, COM2A1);
cbi (TCCR2A, COM2B0);
sbi (TCCR2A, COM2B1);

// Mode 1 / Phase Correct PWM
sbi (TCCR2A, WGM20);
cbi (TCCR2A, WGM21);
cbi (TCCR2B, WGM22);
}
void Setup_timer3(void)
{


TCCR3B = (TCCR3B & 0b11111000) |0x02;// Timer1 Clock Prescaler to : 8

cbi (TCCR3A, COM3A0);
sbi (TCCR3A, COM3A1);
cbi (TCCR3A, COM3B0);
sbi (TCCR3A, COM3B1);
cbi (TCCR3A, COM3C0);
sbi (TCCR3A, COM3C1);

// Mode 1 / Phase Correct PWM
sbi (TCCR3A, WGM30);
cbi (TCCR3A, WGM31);
cbi (TCCR3B, WGM32);
cbi (TCCR3B, WGM33);
cbi (TCCR3C, WGM33);
cbi (TCCR3C, WGM33);
}


void Setup_timer4()
{

TCCR4B = (TCCR4B & 0b11111000) | 0x02;// Timer2 Clock Prescaler to : 8

cbi (TCCR4A, COM4A0); // clear Compare Match
sbi (TCCR4A, COM4A1);
cbi (TCCR4A, COM4B0);
sbi (TCCR4A, COM4B1);
cbi (TCCR4A, COM4C0);
sbi (TCCR4A, COM4C1);

sbi (TCCR4A, WGM40);
cbi (TCCR4A, WGM41);
cbi (TCCR4B, WGM42);
cbi (TCCR4C, WGM43);
cbi (TCCR4C, WGM43);

}

void Setup_timer5(void)
{

TCCR5B = (TCCR5B & 0b11111000) |0x02;// Timer1 Clock Prescaler to : 8

cbi (TCCR5A, COM5A0);
sbi (TCCR5A, COM5A1);
cbi (TCCR5A, COM5B0);
sbi (TCCR5A, COM5B1);
cbi (TCCR5A, COM5C0);
sbi (TCCR5A, COM5C1);


sbi (TCCR5A, WGM50);
cbi (TCCR5A, WGM51);
cbi (TCCR5B, WGM52);
cbi (TCCR5B, WGM53);
cbi (TCCR5C, WGM50);
}


ISR(TIMER2_OVF_vect)
{
cbi(PORTD,program_exec_time); //Clear the pin
sbi(PORTD,ISR_exec_time); // Sets the pin

phase_accumulator=phase_accumulator+tword_m; //Adds tuning M word to previoud phase accumulator. refer to DDS_calculator (from Martin Nawrath) for explination.
current_count=phase_accumulator >> 24; // use upper 8 bits of phase_accumulator as frequency information
//motor 1
OCR3B = pgm_read_byte_near(sine256 + current_count); // read value fron ROM sine table and send to PWM
OCR3C = pgm_read_byte_near(sine256 + (uint8_t)(current_count + offset_1)); // read value fron ROM sine table and send to PWM, 120 Degree out of phase of PWM1
OCR0B = pgm_read_byte_near(sine256 + (uint8_t)(current_count + offset_2));// read value fron ROM sine table and send to PWM, 120 Degree out of phase of PWM2
//motor 2
OCR3A = OCR3B;
OCR4A = OCR3C;
OCR4B = OCR0B;
//motor 3
OCR4C = OCR3B;
OCR2B = OCR3C;
OCR2A = OCR0B;
//motor 4
OCR1A = OCR3B;
OCR1B = OCR3C;
OCR0A = OCR0B;
//motor 5
OCR5A = OCR3B;
OCR5B = OCR3C;
OCR5C = OCR0B;


//increment variable ms4_delay every 4mS/125 = milliseconds 32uS
if(ms4_delay++ == 125)

{
c4ms++;
ms4_delay=0; //reset count
}

cbi(PORTD,ISR_exec_time); //Clear the pin
}

8 ความคิดเห็น:

  1. #ทางบรรลุมรรคผล#ถ้าจิตเราเป็นกลางเราไม่ได้มุ่งพุทธภูมิ#เราไม่ได้ทำกรรมชั่วหยาบมา#จิตเราจะก้าวกระโดดเกิดอริยมรรคขึ้นมา ขั้นแรกมันจะรวมลงก่อน รวมเข้า อัปปนาสมาธิ รวมเองโดยที่ไม่ได้เจตนาจะรวม ไม่ได้คิดได้ฝันที่จะรวม รวมโดยอัตโนมัติ เมื่อรวมลงมาแล้วจะเห็นสภาวธรรมเกิดดับ เกิดดับ สองขณะบ้าง สามขณะบ้าง ถัดจากนั้นจิตจะวางการรับรู้อารมณ์ ทวนกระแสเข้ามาหาธาตุรู้ เมื่อทวนกระแสเข้าถึงธาตุรู้แล้วสิ่งที่ห่­­อหุ้มปิดบังจิตอยู่คือ อาสวกิเลส ทั้งหลาย สังโยชน์ทั้งหลายถูกขาดสะบั้นออกไป

    ตอบลบ

  2. #ดูก่อนสุทัตตะ !#เมื่อรากยังมั่นคงแม้ต้นไม้จะถูกตัดแล้ว #มันยังสามารถขึ้นได้อีก #ฉันเดียวกันเมื่อบุคคลยังไม่ถอนตัณหานุสัยขึ้นเสียจากดวงจิต #ความทุกข์ย่อมเกิดขึ้นได้บ่อยๆ “ #สุทัตตะเอยน้ำตาของสัตว์ผู้ต้องร้องไห้เพราะความทุกข์โทมนัสทับถม #ในขณะที่ท่องเที่ยวอยู่ในสังสารวัฏนี้มีจำนวนมากเหลือคณา #สุดที่จะกล่าวได้ว่ามีประมาณเท่านี้เท่านั้น #กระดูกที่เขาทอดทิ้งลงทับถมปฐพีดลเล่า
    #ถ้านำมากองรวมกันมิให้กระจัดกระจายคงจะสูงเท่าภูเขา #บนพื้นแผ่นดินนี้ไม่มีช่องว่างเลยแม้แต่สักนิดเดียวที่สัตว์ไม่เคยตาย #ปฐพีนี้เกลื่อนกล่นไปด้วยกระดูกแห่งสัตว์ผู้ตายแล้วตายเล่า #เป็นที่น่าสังเวชสลดใจอย่างยิ่งทุกย่างก้าวของมนุษย์และสัตว์เหยียบย่ำไปบนกองกระดูก #เขานอนบนกองกระดูกนั่งบนกองกระดูก #สนุกสนานเพลิดเพลินอยู่บนกองกระดูกทั้งสิ้น ”#บางครั้งพระพุทธเจ้าตอนท่านอายุเยอะขึ้นแล้ว #ท่านแสดงธรรมเช้าตั้งแต่เช้ามามีธุระตลอดเลย #ตอนค่ำๆต้องแสดงธรรมให้พระฟังอีก#ตอนเย็นๆแสดงให้โยมฟัง #เขาทำงานเสร็จแล้วเขาก็เข้ามาวัดมาฟังธรรม#ตอนค่ำๆท่านก็ต้องเทศน์ให้พระฟังอีก#แล้วตอนดึกๆคนอื่นนอนแล้ว #พวกเทพก็จะมาไม่ใช่เรื่องประหลาด #พวกเทพที่จะมาฟังธรรมจะมาตอนดึกๆบางทีท่านนอนอยู่หรือท่านภาวนาอยู่ #บางทีท่านหลับอยู่เขาจะมาท่านก็จะตื่น

    #จิตท่านจะตื่นกายท่านจะตื่นหรือเปล่าไม่รู้แต่จิตนั้นแสดงธรรมได้#ท่านเหนื่อยมากตั้งแต่เช้าเช้ามืดทำงานตลอด #เพราะเป็นพระพุทธเจ้าเช้ามืดขึ้นมาท่านจะพิจารณาแล้ว#วันนี้ท่านจะไปสอนใครจะสอนที่ไหนจะสอนอย่างไรสอนแล้วจะได้ผลอย่างไร#ท่านจะพิจารณาก่อนตอนออกไปบิณฑบาต
    #ท่านก็จะแวะไปสำนักโน้นสำนักนี้ไปคุยกับปริพาชกคนนี้ไปคุยกับฤๅษีคนนี้#หรือแวะไปโปรดฆราวาสญาติโยมอย่างบางคนไปอาบน้ำในแม่น้ำอยู่
    พระพุทธเจ้าก็ไปโปรด#คือท่านพิจารณาตั้งแต่เช้ามืดเลย#ในขณะที่พวกเรายังนอนไม่ตื่นพระพุทธเจ้าทำงานแล้ว#ไปสงเคราะห์ว่าวันนี้ควรจะไปสงเคราะห์ใคร#บางคนยังไม่ควรจะได้ธรรมะตอนนี้หมายถึงอินทรีย์ยังไม่แก่กล้า #ท่านไปให้โอกาสเขาได้ทำทานเป็นการทำประโยชน์ #กลับมาท่านฉันอะไรอย่างนี้หลังจากนั้นก็รับแขกแล้ว #เดี๋ยวคนโน้นมาคนนี้มาตกเย็นๆญาติโยมก็เข้าวัดเยอะแยะ #ถัดจากนั้นก็สอนพระตรงที่สอนพระบางทีท่านเหนื่อยมากแล้ว #ร่างกายถึงท่านจะเป็นพระพุทธเจ้าจิตท่านจะวิเศษวิโสแค่ไหน#แต่ร่างกายท่านมันก็คือธาตุขันธ์แบบเดียวกับพวกเรานี้ไม่ได้ต่างกันหรอก#มันก็แก่ได้เจ็บได้ตายได้เหมือนกันฉะนั้นท่านเหนื่อยท่านก็จะใช้สาวก#เอ้าองค์นี้แสดงธรรมให้ทีท่านจะพักผ่อนแล้ว#ท่านจะต้องเอนหลังอะไรอย่างนี้ก็ลงไปนอนพักข้างๆ#พระสารีบุตรบ้างองค์โน้นองค์นี้ก็แสดงธรรมไป#พอแสดงธรรมจบแล้วพระพุทธเจ้าท่านก็ลุกขึ้นมาบอกว่าแสดงได้ดี #ถ้าให้ท่านเทศน์ท่านก็เทศน์อย่างนี้ล่ะหรือบางวันท่านเห็นว่าท่านมีสาวกที่เก่งๆมาอยู่ด้วย #อย่างมีพระมหากัจจายนะมาอยู่ด้วยอย่างนี้ท่านก็แสดงธรรมย่อๆพูดไม่กี่คำ #บอกว่าวันนี้เราเหนื่อยแล้วจะพักแล้วท่านก็พักเข้ากุฏิท่านเลยพระอื่นๆก็ฟังแล้วยังไม่เข้าใจ#ยังไม่จุใจอะไรอย่างนี้ไปถามพระมหากัจจายนะ#ท่านก็ขยายความให้ฟังแจกแจงธรรมะให้ฟังเห็นไหมสาวกสอนไม่ใช่เรื่องธรรมดา#อย่าดูถูกโง่มากๆเลยที่ดูถูกพระสาวก
    พระสาวกสอนพระสาวกบรรลุพระอรหันต์อะไรต่ออะไร#มีเยอะแยะหรือบรรลุโสดาบันพระสารีบุตรเก่งในการสอนพระสอนโยม
    ให้บรรลุพระโสดาบัน#พระโมคคัลลานะเก่งในการสอนภิกษุด้วยกันหรือญาติโยมอะไรนี่ให้บรรลุพระอรหันต์#พระโมคคัลลานะสอนแล้วบรรลุพระอรหันต์ได้เยอะ#พระสารีบุตรสอนแล้วบรรลุโสดาบันได้เยอะฟังแล้วงงไหมเอ๊ะทำไมเป็นเอตทัคคะ#เป็นอัครสาวกฝ่ายขวามีปัญญามากสอนได้โสดาบันสอนปุถุชนให้เป็นพระโสดาบันยากที่สุดเลย#ยิ่งกว่าต้อนควายขึ้นภูเขาอีกพร้อมจะแว้งเอาส่วนคนที่เป็นพระโสดาบันแล้วอย่างไรๆวันหนึ่งก็ต้องเป็นพระอรหันต์มันง่ายกว่ากัน #เพราะฉะนั้นความยากที่สุดอยู่ในขั้นแรกนี้ล่ะ

    ตอบลบ
  3. Arduino Atmega 168 Atmega 328 Atmega 1280 Atmega 2560 For 3 phase induction motor speed controller

    ตอบลบ
  4. // DDS Sine Generator 3 phase motor x5 mit ATMEGA 2560 PWM 4KHZ





    #include "arduino.h" //Store data in flash (program) memory instead of SRAM

    #include "avr/pgmspace.h"

    #include "avr/io.h"



    const byte sine256[] PROGMEM = {

    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,238,239,240,

    242,243,244,245,247,248,249,249,250,251,252,252,253,253,253,254,254,254,254,254,254,254,253,253,253,252,252,251,250,249,249,248,247,245,244,243,242,240,239,238,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 a bit to have the properties of a clear bit operator

    #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))//define a bit to have the properties of a set bit operator



    int PWM1= 2;// PWM1 output, phase 1

    int PWM2 = 3; //[WM2 ouput, phase 2

    int PWM3 = 4; //PWM3 output, phase 3



    int PWM4= 5;// PWM1 output, phase 1

    int PWM5 = 6; //[WM2 ouput, phase 2

    int PWM6 = 7; //PWM3 output, phase 3



    int PWM7 = 8;// PWM1 output, phase 1

    int PWM8 = 9; //[WM2 ouput, phase 2

    int PWM9 = 10; //PWM3 output, phase 3



    int PWM10 = 11;// PWM1 output, phase 1

    int PWM11 = 12; //[WM2 ouput, phase 2

    int PWM12 = 13; //PWM3 output, phase 3



    int PWM13 = 44;// PWM1 output, phase 1

    int PWM14 = 45; //[WM2 ouput, phase 2

    int PWM15 = 46; //PWM3 output, phase 3



    int offset_1 = 85; //offset 1 is 120 degrees out of phase with previous phase, Refer to PWM to sine.xls

    int offset_2 = 170; //offset 2 is 120 degrees out of phase with offset 1. Refer to PWM to sine.xls

    int program_exec_time = 52; //monitor how quickly the interrupt trigger

    int ISR_exec_time = 53; //monitor how long the interrupt takes



    double dfreq;

    const double refclk=31376.6; // measured output frequency



    // variables used inside interrupt service declared as voilatile

    volatile byte current_count; // Keep track of where the current count is in sine 256 array

    volatile byte ms4_delay; //variable used to generate a 4ms delay

    volatile byte c4ms; // after every 4ms this variable is incremented, its used to create a delay of 1 second

    volatile unsigned long phase_accumulator; // pahse accumulator

    volatile unsigned long tword_m; // dds tuning word m, refer to DDS_calculator (from Martin Nawrath) for explination.



    void setup()


    ตอบลบ
  5. // reliable in start/stop-mode without acceleration/decceleration
    const byte stepperPulsePin = 9;
    unsigned long stepFrequency = 200;
    // on fullstep-mode on a 1.8° per Step motor 800 steps means 800 / 200 = 4 full turns
    // on halfstep-mode on a 1.8° per Step motor 800 steps means 800 / 200 = 2 full turns
    unsigned long numberOfSteps = 600;

    //nbt nonblockingtimer
    boolean TimePeriodIsOver (unsigned long &expireTime, unsigned long TimePeriod) {
    unsigned long currentMillis = millis();
    if ( currentMillis - expireTime >= TimePeriod )
    {
    expireTime = currentMillis; // set new expireTime
    return true; // more time than TimePeriod) has elapsed since last time if-condition was true
    }
    else return false; // not expired
    }
    unsigned long BlinkTimer = 0;
    const int onBoardLED = 13;

    unsigned long DebugTimer = 0;

    volatile long HighCounter = 0;
    volatile long StepCounter = 0;
    volatile boolean CreateStepSignal = false;

    void setupTimerInterrupt(unsigned long ISR_call_frequency) {
    const byte Prescaler___8 = (1 << CS20);
    const byte Prescaler__32 = (1 << CS21) + (1 << CS20);
    const byte Prescaler__64 = (1 << CS22);
    const byte Prescaler_128 = (1 << CS22) + (1 << CS20);
    const byte Prescaler_256 = (1 << CS22) + (1 << CS21);
    const byte Prescaler1024 = (1 << CS22) + (1 << CS21) + (1 << CS20);

    const unsigned long CPU_Clock = 16000000;
    const byte toggleFactor = 2;

    unsigned long OCR2A_value;

    cli();//stop interrupts

    TCCR2A = 0;// set entire TCCR2A register to 0
    TCCR2B = 0;// same for TCCR2B
    TCNT2 = 0;//initialize counter value to 0

    TCCR2A |= (1 << WGM21); // turn on CTC mode
    TIMSK2 |= (1 << OCIE2A); // enable timer compare interrupt

    // the prescaler must be setup to a value that the calculation
    // of the value for OCR2A is below 256
    TCCR2B = Prescaler___8;
    OCR2A_value = (CPU_Clock / ( 8 * ISR_call_frequency * toggleFactor) ) - 1;

    if (OCR2A_value > 256) { // if value too big
    TCCR2B = Prescaler__32; // set higher prescaler
    OCR2A_value = (CPU_Clock / ( 32 * ISR_call_frequency * toggleFactor) ) - 1;
    }

    if (OCR2A_value > 256) { // if value too big
    TCCR2B = Prescaler__64;// set higher prescaler
    OCR2A_value = (CPU_Clock / ( 64 * ISR_call_frequency * toggleFactor) ) - 1;
    }

    if (OCR2A_value > 256) { // if value too big
    TCCR2B = Prescaler_128;// set higher prescaler
    OCR2A_value = (CPU_Clock / ( 128 * ISR_call_frequency * toggleFactor) ) - 1;
    }

    ตอบลบ