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

3 PHASE INDUCTION MOTOR SPEED CONTROLLER

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

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


  1. atme ga 2560 pwm pin
    200
    ย้อนกลับการแชทภาพวิดีโอแผนที่ข่าวเพิ่มเติม
    เครื่องมือ
    เกี่ยวกับผลลัพธ์ 221,000
    รวมผลลัพธ์สำหรับ at mega 2560 pwm pin
    คุณต้องการผลลัพธ์สำหรับ atme ga 2560 pwm pin เท่านั้นใช่หรือไม่

    PWM: 2 to 13 and 44 to 46. Provide 8-bit PWM output with the analogWrite () function. SPI: 50 (MISO), 51 (MOSI), 52 (SCK), 53 (SS). These pins support SPI communication using the SPI library. The SPI pins are also broken out on the ICSP header, which is physically compatible with the Uno, Duemilanove and Diecimila.
    Arduino Mega 2560 Pinout - ElectroSchematics.com
    www.electroschematics.com/arduino-mega-2560-pinout/
    www.electroschematics.com/arduino-mega-2560-pinout/
    ข้อมูลนี้เป็นประโยชน์หรือไม่
    และผู้คนยังถามถึง

    How many EEPROM pins does a Mega 2560 have?
    The ATmega2560 features 4kb (4096 bytes) of EEPROM, a memory which is not erased when powered off. The Mega 2560 has 54 digital pins, whereas 15 supports PWM, and 16 analog input pins. Connect to several devices through the 4x hardware serial ports (UARTs) to your Arduino Mega. All you need to know to get started with your new Arduino board.
    Mega 2560 Rev3 - Arduino Docs

    docs.arduino.cc/hardware/mega-2560/

    What is the pin number of the ATmega2560?
    ATmega2560 -Arduino Pin Mapping Pin Number Pin Name Mapped Pin Name 1 PG5 ( OC0B ) Digital pin 4 (PWM) 2 PE0 ( RXD0/PCINT8 ) Digital pin 0 ( RX0) 3 PE1 ( TXD0 ) Digital pin 1 ( TX0) 4 PE2 ( XCK0/AIN0 ) 64 more rows ...
    ATmega2560-Arduino Pin Mapping | Arduino Documentation

    ตอบลบ