高速回転ダクトファン(3相2極ブラシレスモーターの位置センサレス駆動)

【概要】

AIR CRAFT製のDIY AC ブラシレスモーターにラジコン飛行機用ダクトファンを使用しコントローラを外付けで作成したものです。

モーター駆動はセンサレスによりV−F制御チョッピングによる強制通電パターンにて25000rpm/minまで脱調せずスムーズに回転します。

【使用部品】

部品名

型式

メーカー

備考

MCU

PIC16F877

マイクロチップ

フラッシュ8Kbyte

軸流ファンモーター

DIYモータ

AIR CRAFT

センサレス

モーター駆動トランジスタ

2SK1567、2SJ438

 

 

LCD

SC2004

 秋月通商にて購入

チョッピングPWM、転流タイマ割込み、通電パターンを表示

電源3端子レギュレータ

78M05

 

MCU電源

モータ駆動回路は全波(バイポーラ)駆動、始動はPWM50%で600rpm/min。

 

【作成日記】

初期にMCUをルネサスH8−300で作成をしていたが100回程度しかフラッシュROMに書換えができない作りで、デバック中に

MCUに書込みの際に電圧を書込み仕様の15Vにせず5Vで書込み処理をして、1回目で書けなくなったりした。

これは、1個¥3800もするH8−300は貧乏人には使えないと思い、泣く泣くPICの書換え10万回以上可能である16F877に

変更した。基板もユニバーサルでせっせと配線はんだ付けで2日かかった。

 

 

                fig1.ダクトファンモーター回転時                                                      fig2.ダクト停止時

 

                    fig3.基板パターン図                                                    fig4.基板回路図            

 

 

5). PICマイコン16F877のメインソースプログラム

★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆

#include <16F877.h>

#use delay(clock=20000000)

#fuses HS,NOWDT, NOPROTECT, BROWNOUT,PUT

#use fast_io(a)

#use fast_io(b)

#use fast_io(c)

#use fast_io(d)

#use fast_io(e)

 

#define pwm_up      PIN_B1

#define pwm_down    PIN_B0

#define pwm_off     PIN_C0

#define mot_c_up    PIN_E0

#define mot_c_down  PIN_E1

 

 

#define tyata       20

#define mot_str_count   100

#define mot_str_cyc 65000

#define jyuden_out_cnt  33

 

#include    <lcd_lib5.c>

unsigned char pwm_up_cnt,pwm_down_cnt,pwm_off_cnt;

unsigned int    pwm_out;

unsigned char   sw_status,mot_status;

 

unsigned char   mot_cyc_che_cnt ;

 

 

static  unsigned int    mot_count,uvw_out;

unsigned long jyuden_out,mot_str_tim;

static unsigned long mot_cyc;

unsigned int mot_cyc_up_cnt,mot_cyc_down_cnt;

 

#bit pwmoff_flag = sw_status.0

#bit pwmup_flag = sw_status.1

#bit pwmdown_flag = sw_status.2

#bit mot_cyc_up_flag = sw_status.3

#bit mot_cyc_down_flag = sw_status.4

 

#bit mot_start_end = mot_status.0

#bit cyc_end_flag = mot_status.1

 

unsigned int const mot_out1[30]={

               0x09,0x09,0x09,0x09,0x09,

                  0x21,0x21,0x21,0x21,0x21,

                  0x24,0x24,0x24,0x24,0x24,

                  0x06,0x06,0x06,0x06,0x06,

                  0x12,0x12,0x12,0x12,0x12,

                  0x18,0x18,0x18,0x18,0x18,

                };                       //TPC出力テ゛ータ

 

unsigned int const mot_out2[30]={

                  0x19,0x09,0x09,0x09,0x09,

                  0x29,0x21,0x21,0x21,0x21,

                  0x25,0x24,0x24,0x24,0x24,

                  0x26,0x06,0x06,0x06,0x06,

                  0x16,0x12,0x12,0x12,0x12,

                  0x1A,0x18,0x18,0x18,0x18,

                };

 

 

 

 

#int_timer0

void intval0()

{

    set_timer0(177);

if( input(pwm_off) == 0 )

    {   if( pwm_off_cnt < 1 )

            {   pwmoff_flag = 1;

                pwm_off_cnt = tyata;

            }else{

                pwm_off_cnt--;

                }

    }else{

        }

 

 

if( input(pwm_up) == 0 )

    {   if( pwm_up_cnt < 1 )

            {   pwmup_flag = 1;

                pwm_up_cnt = tyata;

            }else{

                pwm_up_cnt--;

                }

   }

if( input(pwm_down) == 0 )

    {   if( pwm_down_cnt < 1 )

            {   pwmdown_flag = 1;

                pwm_down_cnt = tyata;

            }else{

                pwm_down_cnt--;

                }

   }

if( input(mot_c_up) == 0 )

    {   if( mot_cyc_up_cnt < 1 )

            {   mot_cyc_up_flag = 1;

                mot_cyc_up_cnt = tyata;

            }else{

                mot_cyc_up_cnt--;

                }

   }

 

if( input(mot_c_down) == 0 )

    {   if( mot_cyc_down_cnt < 1 )

            {   mot_cyc_down_flag = 1;

                mot_cyc_down_cnt = tyata;

            }else{

                mot_cyc_down_cnt--;

                }

 

   }

 

if(pwmoff_flag == 1){

            pwm_out=0;

            sw_status = 0;

//          pwmoff_flag = 0;

            }

 

if(pwmup_flag == 1){

 

    if(pwm_out >= 255){

            pwm_out=255;

                }else{

            pwm_out++;

                    }

        sw_status = 0;

//      pwmup_flag= 0;

                    }

 

if(pwmdown_flag == 1){

 

    if(pwm_out <= 0){

            pwm_out=0;

                }else{

            pwm_out--;

                    }

        sw_status = 0;

 

                    }

 

if(mot_cyc_up_flag == 1){

 

     if(mot_cyc >= 65490){

            mot_cyc = 65490;

                        }else{

            mot_cyc++;

                                }

        sw_status = 0;

 

                        }

 

if(mot_cyc_down_flag == 1){

 

     if(mot_cyc <= 0){

            mot_cyc = 0;

                        }else{

            mot_cyc--;

                                }

        sw_status = 0;

                        }

 

    set_pwm1_duty(pwm_out);

 

    if(jyuden_out <= 0 && pwm_out > 0){

 

        if( mot_str_tim > 0 ){

        mot_str_tim --;

                }else{

            mot_str_tim = 0;

                    }

            }else{

            mot_str_tim = mot_str_count;

            mot_start_end = 0;

                }

 

    if(mot_str_tim <= 0 && cyc_end_flag == 1){

        mot_start_end = 1;

                }else{

        mot_start_end = 0;

                    }

 

}

 

 

#int_timer1

void intval1()

{

 

        set_timer1(mot_cyc);

 

if(pwm_out > 0){

    if( jyuden_out > 23 && mot_start_end == 0 ){

            uvw_out = 0x2A;

            jyuden_out--;

            pwm_out = 250;

    }else if( jyuden_out > 13 && mot_start_end == 0 ){

            uvw_out = 0x12;

            jyuden_out--;

            pwm_out = 200;

        }else if( jyuden_out > 3 && mot_start_end == 0 ){

            uvw_out = 0x18;

            jyuden_out--;

            pwm_out = 200;

        }else if( jyuden_out > 0 && mot_start_end == 0 ){

            uvw_out = 0x10;

            jyuden_out--;

            pwm_out = 200;

        }else if(jyuden_out <= 0 && mot_start_end == 0){

 

        pwm_out = 110;

        uvw_out=mot_out1[mot_count];

        mot_count++;

            }else if(jyuden_out <= 0 && mot_start_end == 1){

 

        if( mot_cyc_che_cnt == 0 ){

        mot_cyc = 65000;

                    }else{

 

                        }

        uvw_out=mot_out2[mot_count];

        mot_count++;

        mot_cyc_che_cnt = 1;

                                    }

            }else{

                mot_cyc = mot_str_cyc;

                uvw_out=0x00;

                mot_count = 0;

                jyuden_out=jyuden_out_cnt;

                cyc_end_flag = 0;

                mot_cyc_che_cnt = 0;

                mot_status = 0;

                }

 

      if(mot_count >= 30){

            mot_count = 1;

            cyc_end_flag = 1;

                              }

        output_D( uvw_out );

}

 

void main()

{

    set_tris_a(0x00);

    set_tris_b(0x03);

    set_tris_c(0x01);

    set_tris_d(0x00);

    set_tris_e(0x03);

    output_a(0x00);

    output_b(0x00);

    output_c(0x00);

    output_d(0x00);

    output_e(0x00);

    port_b_pullups(TRUE);

 

    pwm_off_cnt = tyata;

    pwm_up_cnt = tyata;

    pwm_down_cnt = tyata;

    mot_count = 0;

    sw_status = 0;

    jyuden_out=jyuden_out_cnt;

    mot_cyc_che_cnt = 0;

 

    mot_status = 0;

 

//  pwmoff_flag = 0;

//  pwmup_flag= 0;

//  pwmdown_flag = 0;

 

 

    setup_timer_0(RTCC_INTERNAL | RTCC_DIV_64);

    set_timer0(177);

    enable_interrupts(INT_TIMER0);

 

    setup_timer_1(T1_INTERNAL | T1_DIV_BY_4);

                //11900rpm

    mot_cyc = mot_str_cyc;

    set_timer1(mot_cyc);

    enable_interrupts(INT_TIMER1);

 

    enable_interrupts(GLOBAL);

 

 

 

    setup_ccp1(ccp_pwm);

    setup_timer_2(T2_DIV_BY_1,255,1);   //19.6khz分解能255

    pwm_out = 0x00;

    set_pwm1_duty(pwm_out);

 

   lcd_init();

   lcd_clear();

 

    while(1){

   lcd_cmd(0x80);

   printf(lcd_data,"pwm= %3u / 255 ",pwm_out);

   lcd_cmd(0xc0);

   printf(lcd_data,"uvw_out= %2LX hex",uvw_out);

   lcd_cmd(0x94);

   printf(lcd_data,"mot_count= %3u",mot_count);

   lcd_cmd(0xd4);

   printf(lcd_data,"mot_cyc= %5lu",mot_cyc);

 

   delay_ms(100);

 

 

        }

}

6).  ヘッダーFILE

★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆

#include <16F877.h>

#device adc=8

#use delay(clock=20000000)

#fuses HS, PUT, NOPROTECT, BROWNOUT, LVP

 

7). LCDのパラレルデータFILE

 ★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆

 ///////////////////////////////////////////////

//  LCD control Library

//  functions are below

//    lcd_init()-------- initialize

//    lcd_ready()------- busy check

//    lcd_cmd(cmd)------ send command

//    lcd_data(string)-- display string

//    lcd_clear() ------ clear display

//////////////////////////////////////////////

 

////// port define to port B

#byte   port = 6    //port B

#define set_tris_x  set_tris_b

#define mode    0x03

#define rs  PIN_B2

#define rw  PIN_C7

#define stb PIN_C6

 

/////////// lcd ready check function    

 

int lcd_ready(){

    int high,low;

    set_tris_x(mode | 0xF0);    //upper is input

    output_low(rs);

    output_high(rw);            //read mode

    output_high(stb);

    delay_us(1);

    high=port & 0xF0;           //input upper

    output_low(stb);

    output_high(stb);

    delay_us(1);

    low=port & 0xF0;            //input lower

    output_low(stb);

    set_tris_x(mode);

    return(high | (low>>4));    //end check

}

 

////////// lcd display data function

void lcd_data(int asci){

    port = (asci & 0xF0) | (port & 0x0F);   //set upper data

    output_low(rw);             //set write

    output_high(rs);            //set rs high

    output_high(stb);           //strobe

    delay_us(1);

    output_low(stb);

    asci=asci<<4;

    port = (asci & 0xF0) | (port & 0x0F);   //set lower data

    output_high(stb);           //strobe

    delay_us(1);

    output_low(stb);

    while(bit_test(lcd_ready(),7));

}

 

////////// lcd command out function

void cmdout(int cmd){

    port = (cmd & 0xF0) | (port & 0x0F);    //set upper data

    output_low(rw);             //set write

    output_low(rs);             //set rs low

    output_high(stb);           //strobe

    delay_us(1);

    output_low(stb);

    cmd=cmd<<4;

    port = (cmd & 0xF0) | (port & 0x0F);    //set lower data

    output_high(stb);           //strobe

    delay_us(1);

    output_low(stb);

}

void lcd_cmd(int cmd){

    cmdout(cmd);

    while(bit_test(lcd_ready(),7)); //end check

}

 

//////////  lcd display clear function

void lcd_clear(){

    lcd_cmd(1);                 //initialize command

}

 

///////// lcd initialize function

void lcd_incmd(int cmd){

    port = (cmd & 0xF0) | (port & 0x0F);    //mode command

    output_low(rw);             //set write

    output_low(rs);             //set rs low

    output_high(stb);           //strobe

    delay_us(1);

    output_low(stb);

    delay_ms(5);

}

void lcd_init(){

    set_tris_x(mode);               //initialise

    delay_ms(15);

    lcd_incmd(0x30);            //8bit mode set

    lcd_incmd(0x30);            //8bit mode set

    lcd_incmd(0x30);            //8bit mode set

    lcd_incmd(0x20);            //4bit mode set

    lcd_cmd(0x2E);              //DL=0 4bit mode

    lcd_cmd(0x08);              //disolay off C=D=B=0

    lcd_cmd(0x0D);              //display on C=D=1 B=0

    lcd_cmd(0x06);              //entry I/D=1 S=0

}