วันจันทร์ที่ 8 มกราคม พ.ศ. 2561

ระบบ ขับเคลื่อน ด้วย ไฟฟ้า

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

 }
  
}

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

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