วันศุกร์ที่ 7 เมษายน พ.ศ. 2560

ดูคลิป เกี่ยวกับเรื่อง วงจรอิเล็กทรอนิกส์

//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 
}

//Arduino Atmega 1280 2560 good version 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
#include "arduino.h" //Store data in flash (program) memory instead of SRAM
#include "avr/pgmspace.h"
#include "avr/io.h"
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) 
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#define UN        (400.0)    
#define FN        (50.0)     
#define P         (UN/FN)    
#define T_PWM     (0.000255) 
#define T_MAX     (4.0)     
#define T_MIN     (0.02)     
#define K_MAX     floor(T_MAX/T_PWM)  
#define K_MIN     ceil(T_MIN/T_PWM)   
volatile static unsigned int dlugosc_tab_sin;                                                   //okresie napiecia wyjsciowego
static unsigned int i = 0;                      
volatile static unsigned int licznik_glowny = 0;
                                                
static unsigned int next_value_sin = 0; 
static double t_param=100;              
static float t = T_PWM;                 
static float omega_t;                   
static float t_out;                     
static float U_o_param;                 
                                        
static unsigned int ocr0a, ocr0b, ocr1a;
static unsigned int ocr1b, ocr2a, ocr2b;
static unsigned int ocr3a, ocr3b, ocr3c;
static unsigned int ocr4a, ocr4b, ocr4c;//^
static unsigned int ocr5a, ocr5b, ocr5c;//
static double sin_in;       
static double blad = 1;       
static unsigned int analog=0;
static double U_in = 0;      
static double U_rms_max;     
static bool a=0;              
int main() 
{
  io_init();     
  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 D 13
    ocr0b = ocr0a - 1;//pin D 4
    ocr1a = round(blad*(U_o_param*(sin(sin_in-2.09)+1)*254/2)+1);//pin D 11
    ocr1b = ocr1a - 1;//pin D 12
    ocr2a = round(blad*(U_o_param*(sin(sin_in+2.09)+1)*254/2)+1);//pin D 10
    ocr2b = ocr2a - 1;//pin D 9
        
    ocr3a = round(blad*(U_o_param*(sin(sin_in)+1)*254/2)+1);//pin D 5
    ocr3b = ocr3a-1;//r3a-1;//ocr3a - 1;//pin D 2
    ocr4a = round(blad*(U_o_param*(sin(sin_in-2.09)+1)*254/2)+1);//pin D 6
    ocr4b = ocr4a-1;//ocr3c-1;//ocr3c - 1;//pin D 7
    ocr5a = round(blad*(U_o_param*(sin(sin_in+2.09)+1)*254/2)+1);//pin D 46
    ocr5b = ocr5a-1;//ocr4a -1; //pin D 45
    
    ocr3c = ocr0b;//round(blad*(U_o_param*(sin(sin_in)+1)*254/2)+1);//pin D 3
    ocr4c = ocr1b;//round(blad*(U_o_param*(sin(sin_in+2.09)+1)*254/2)+1);//pin D 8
    ocr5c = ocr2b;//round(blad*(U_o_param*(sin(sin_in-2.09)+1)*254/2)+1);//pin D 44
    
//uaktualnienie wartosci w rejestrach/
    cli();                              //zabronienie na obsloge przerwan na wypadek gdyby 
                                        //podczas uaktualniania wystapilo przerwanie
    OCR0A = ocr0a;    //pin D13
    OCR0B = ocr0b;    //pin D4
    OCR1A = ocr1a;   //pin D11
    OCR1B = ocr1b;   //pin D12
    OCR2A = ocr2a;    //pin D10
    OCR2B = ocr2b;    //pin D9
    
    OCR3A = ocr3a;    //pin D5
    OCR3B = ocr3b;    //pin D2
    OCR3C = ocr3c;    //pin D3
    OCR4A = ocr4a;    //pin D6
    OCR4B = ocr4b;    //pin D7
    OCR4C = ocr4c;    //pin D8
    
    OCR5A = ocr5a;    //pin D46
    OCR5B = ocr5b;    //pin D45
    OCR5C = ocr5c;    //pin D44
    
    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
 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(CS41);        //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);  


//zerowanie wartosci licznik๓w
TCNT0 = 0;
TCNT1L = 0;
TCNT2 = 0;


TCNT3 = 0;
TCNT4L = 0;
TCNT5 = 0;


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); //OC3C
  pinMode(52, INPUT);
  pinMode(53, INPUT);
  pinMode(50, OUTPUT); 
  
  pinMode(2, OUTPUT); //OC3B
  pinMode(4, OUTPUT); //OC0B
  pinMode(7, OUTPUT); //OC1A
  pinMode(8, OUTPUT);//OC4C
  pinMode(12, OUTPUT);//OC2A
  pinMode(13, OUTPUT); //OC2B
  
  pinMode(44, OUTPUT);//OC4C
  pinMode(45, OUTPUT);//OC2A
  pinMode(46, OUTPUT); //OC2B
   
  pinMode(A3, INPUT); //OC1A
  pinMode(A4, OUTPUT);//OC1B
  pinMode(A5, OUTPUT);//OC2A
  pinMode(A6, OUTPUT); //OC3C
  pinMode(A1, OUTPUT);
  pinMode(A0, OUTPUT);
  pinMode(A9, OUTPUT); 
  
  pinMode(A10, OUTPUT); //OC0A
  pinMode(A11, OUTPUT); //OC0B
  pinMode(A12, OUTPUT); //OC1A
  pinMode(A13, OUTPUT);//OC4C
  pinMode(A14, OUTPUT);//OC2A
  pinMode(A15, OUTPUT); //OC2B
}
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(50, 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;  
  bool up;          
  bool down;        
  up =  digitalRead(52);     
  down = digitalRead(53);   
  if(up==1) t_param--;      
  if(down==1) t_param++;    
  if(t_param<0) t_param=0;    
  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(50, LOW); //zapalenie diody 
}

// 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);  
//zerowanie wartosci liczników
 
        //TCNT0 = 0;
        //TCNT1L = 0;
        //TCNT2 = 0;    
 //Programming PWM_R and PWM_S
 //OCR1A=0x00;
 //OCR1B=0x00;
 //TCCR1A=0xA1; //D10 OC1A and OC1B used, phase correct PWM, 8bit D10
 //TCCR1B=0x03; //D9 1:1 prescaller - 15kHz PWM D9

 //Programming PWM_T
 //OCR2=0x00;
 //TCCR2=0x64; //phase correct PWM, no prescaller - 15kHz PWM


 //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();

 }
  
}

// Code นี้ ใช้บอร์ด Arduino Uno ได้เลย ไม่ต้องใช้ Atmega 8 ครับ
 //เครื่องปรับรอบมอเตอร์สามเฟสแบบ มีแม่เหล็ก ปรับแรงบิดได้ ให้ดูจากCode นะครับ simple demo //software for small 3-phase inverter
//Danijel Gorupec, 2015
//Edit  prescaller  And Sine wave For   IGBT   GT15J331   L6569  4 Khz  PWM By   //Sompong Tungmepol   //2/16/2017
#include <avr/io.h>
#include <avr/interrupt.h>

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;PORTC|=0x10;SREG|=0x80;}
#define LED_OFF {SREG&=0x7F;PORTC&=0xEF;SREG|=0x80;}
#define INVERTOR_ENABLE {PORTC|=0x20;PORTD|=0x03;}
#define INVERTOR_DISABLE {PORTC&=0xDF;PORTD&=0xFC;}
#define INPUT_JOG ((PINC&0x02)==0)
#define INPUT_RUN ((PINC&0x04)==0)
#define INPUT_DIR ((PINC&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;

 //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 (PORTC==0xFF) DDRB|=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);


 //program IO pins of the ATMega8 microcontroller
  //D0 - reset hold (can be kept high to ensure high level on reset pin C6)
  //D1 - not used
  //D2 - not used
  //D3 - not used
  //D4 - not used
  //D5 - not used
  //D6 - not used
  //D7 - not used
 DDRD=(unsigned char)0xF8;
  //B0 - not used (ICR1 is modified if this bit is changed)
  //B1 - PWM_R
  //B2 - PWM_S
  //B3 - PWM_T (MOSI SPI)
  //B4 - not used (MISO SPI)
  //B5 - not used (SCK SPI)
  //B6 - not used (always +5V)
  //B7 - not used
 DDRB=(unsigned char)0x0E;
  //C0 - programable input 1 (speed reference - inverted analog input, +5V=min speed, 0V=max speed)
  //C1 - programable input 2 (jog - digital input, active low)
  //C2 - programable input 3 (run signal - digital input, active low)
  //C3 - programable input 4 (rotation direction - digital input, active low)
  //C4 - LED output
  //C5 - enable output
  //C6 - RESET
 DDRC=(unsigned char)0x30;


 //enable pull-up resistors on inputs 1, 2, 3 & 4
 //note: this is nasty, it would be better if we have external pull-down resistors for analog inputs
 //     because now we have to use analog input in inverted way (+5V=min speed, 0V=max speed) so that
 //      the motor slows down if the wire disconnects
 PORTC|=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);
            
        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;    
 //Programming PWM_R and PWM_S
 //OCR1A=0x00;
 //OCR1B=0x00;
 //TCCR1A=0xA1; //D10 OC1A and OC1B used, phase correct PWM, 8bit D10
 //TCCR1B=0x03; //D9 1:1 prescaller - 15kHz PWM D9

 //Programming PWM_T
 //OCR2=0x00;
 //TCCR2=0x64; //phase correct PWM, no prescaller - 15kHz PWM


 //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=(int)speed+180; //ปรับแรงบิด ปกติ +18 ไม่เกิน +180 This setting is for asynchronous motor in delta connection (230VAC delta / 400VAC star)
   int VFfactor=speed/2+14; //ปรับแรงบิด ปกติ 4/+15 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;
   for (i=0;i<255;i++) 
   {
    SREG&=0x7F;
    pwm_table[i]=128;
    SREG|=0x80;
   }
   led_cntr=0;
   LED_OFF;
   speed=10;
  }

  ReadAnalogs();

 }
  
}

//ใช้ขับมอเตอร์สามเฟส ได้พร้อมกัน 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 : 1
  
  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 : 1
 
  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 : 1
  
  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 : 1
  
  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 : 1
  
  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
}

ไม่มีความคิดเห็น:

แสดงความคิดเห็น