วันศุกร์ที่ 24 มีนาคม พ.ศ. 2560

STM32 5kW 3 Phase Motor Controller Original Video Thank You Very Much Fo...

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

 }
  
}

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

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