모터 > 변속기 - Davide Gironi - sound

인기검색어 > 아두이노 센서 ATMEGA128

최신글 질문게시판 동영상강좌 가입하기

▼ BASIC4MCU 후원업체 신제품 정보 ▼

▲ BASIC4MCU 후원업체 신제품 정보 ▲

BASIC4MCU > 모터

BLDC모터 | 변속기 - Davide Gironi - sound

페이지 정보

작성자 키트 작성일17-09-05 15:16 조회1,447회 댓글0건

본문

//
#include
#include
#include
#include
#include
//
#define U_C unsigned char
#define U_I unsigned int
#define U_L unsigned long
//
#define DIR_SW     PINC.5
//
#define FET_PORT   PORTD
#define FET_DDR    DDRD
//#define FET_WH   PORTD.7
//#define FET_WL   PORTD.6
//#define FET_VH   PORTD.5
//#define FET_VL   PORTD.4
//#define FET_UH   PORTD.3
//#define FET_UL   PORTD.2
//
#define STOP  FET_PORT=0x00; //AH=AL=BH=BL=CH=CL=0; //000000xx (CC-BB-AA) //running free(stop)
#define BREAK FET_PORT=0xA8; //A+    B+    C+       //101010xx (CC-BB-AA) //break
//
//                                        CCBBAA
//                                        +-+-+-
//#define RUN0  FET_PORT=0x18; // A+ B- //000110xx
//#define RUN1  FET_PORT=0x48; // A+ C- //010010xx
//#define RUN2  FET_PORT=0x60; // B+ C- //011000xx
//#define RUN3  FET_PORT=0x24; // B+ A- //001001xx
//#define RUN4  FET_PORT=0x84; // C+ A- //100001xx
//#define RUN5  FET_PORT=0x90; // C+ B- //100100xx
char commut_table[]={0x18,0x48,0x60,0x24,0x84,0x90};
U_C commut_step=0;        // current commut step
//
bit dir,dir_old;          // CW dir=1,CCW dir=0
bit enabled=0;            // current running status
//
//---------------------------------------------------------------------------------------------------------
char sound_table[]={0,3,2,5,4,1};
//
void sound_stop(){ BREAK; STOP; _delay_us(1200); }
//
void power_on_sound(){ /* power on sound */
    U_C d,i;
    for(d=0;d<20;d++){ // 20*(( 20+1200)*6)=146.4ms
        for(i=0;i<6;i++){ FET_PORT=commut_table[sound_table[i]]; _delay_us( 20); sound_stop(); } //820Hz
    } delay_ms(30);
    for(d=0;d<20;d++){ // 20*((120+1200)*6)=158.4ms
        for(i=0;i<6;i++){ FET_PORT=commut_table[sound_table[i]]; _delay_us(120); sound_stop(); } //758Hz
    } delay_ms(30);
    for(d=0;d<20;d++){ // 20*((240+1200)*6)=172.8ms
        for(i=0;i<6;i++){ FET_PORT=commut_table[sound_table[i]]; _delay_us(240); sound_stop(); } //694Hz
    } delay_ms(30);
}
//---------------------------------------------------------------------------------------------------------
#define STARTUP_commutS 29
//
U_I startup_delays[30]={                  //[30] //setup startup delays array 10ms-->1.5ms(1000rpm-->6666rpm)
    400,380,360,320,280,240,200,160,120,110,100,96,92,88,84,80,76,72,71,70,69,68,67,66,65,64,63,62,61,60
};
//
void dly_25us(U_I dly){ U_I i; for(i=0;i;i++)delay_us(25);>
//
void startup_motor(){ /* * startup motor cicle */
    U_C i=0,j=0;
    commut_step=0;                      // reset to first commut
    for(;;){                            // run commuts
        FET_PORT=commut_table[commut_step];
        if(commut_step==0){
            if(++i>1){ i=0; if(++j==STARTUP_commutS)break; }
        }
        dly_25us(startup_delays[j]);
        if(dir){ if(++commut_step>5)commut_step=0; } // do next commut
        else   { if(--commut_step<0)commut_step=5; } // do next commut
    }
}
//---------------------------------------------------------------------------------------------------------
U_I adc_read(){ U_I adc; ADCSRA|=0x40; while(!(ADCSRA&0x10)); adc=ADCW; ADCSRA|=0x10; return(adc); }
//---------------------------------------------------------------------------------------------------------
#define ZC_THRESHOLD  150 // zc bemf threshold value
#define ZC_ERRORS     100 // number of zc threshold reading error befor emissions a motor startup
//
//
bit emissions=1;    // emissions or skip emission
bit startup=0;      // startup selector
U_C zc_errors=0;    // count zc errors
U_I current_bemf=0; // bemf value used in zc detection
//
interrupt [TIM1_COMPA] void timer1_compa_isr(void){ /* * main bldc timer */
    if(enabled){
        if(emissions){ emissions=0;
            STOP; delay_us(10); FET_PORT=commut_table[commut_step];
            if(dir){
                switch(commut_step){
                  case 0: ADMUX=1; commut_step=1; break;
                  case 1: ADMUX=0; commut_step=2; break;
                  case 2: ADMUX=2; commut_step=3; break;
                  case 3: ADMUX=1; commut_step=4; break;
                  case 4: ADMUX=0; commut_step=5; break;
                  case 5: ADMUX=2; commut_step=0; break;
                }
            }
            else{
                switch(commut_step){
                  case 0: ADMUX=0; commut_step=5; break;
                  case 1: ADMUX=1; commut_step=4; break;
                  case 2: ADMUX=2; commut_step=3; break;
                  case 3: ADMUX=0; commut_step=2; break;
                  case 4: ADMUX=1; commut_step=1; break;
                  case 5: ADMUX=2; commut_step=0; break;
                }
            }
            zc_errors=0;
        }
        //
        if(!emissions){
            current_bemf=adc_read();
            if(dir){
                switch(commut_step){
                  case 0: if(current_bemf>ZC_THRESHOLD){ emissions=1; STOP; } break; // ZC↓ 
                  case 1: if(current_bemf){>
                  case 2: if(current_bemf>ZC_THRESHOLD){ emissions=1; STOP; } break; // ZA↓ 
                  case 3: if(current_bemf){>
                  case 4: if(current_bemf>ZC_THRESHOLD){ emissions=1; STOP; } break; // ZB↓ 
                  case 5: if(current_bemf){>
                }
            }
            else{
                switch(commut_step){
                  case 0: if(current_bemf){>
                  case 1: if(current_bemf>ZC_THRESHOLD){ emissions=1; STOP; } break; //  ZB↓
                  case 2: if(current_bemf){>
                  case 3: if(current_bemf>ZC_THRESHOLD){ emissions=1; STOP; } break; //  ZC↓
                  case 4: if(current_bemf){>
                  case 5: if(current_bemf>ZC_THRESHOLD){ emissions=1; STOP; } break; //  ZA↓ 
                }
            }
            //
            if(++zc_errors>ZC_ERRORS){ zc_errors=0; startup_motor(); commut_step=0; emissions=1; }
        }
    }
}
//---------------------------------------------------------------------------------------------------------
void set_stop() { if( enabled){ SREG&=0x7F; enabled=0; STOP; SREG|=0x80; } } /* * set stop */
void set_start(){ if(!enabled){ SREG&=0x7F; enabled=1;       SREG|=0x80; } } /* * set start */
//---------------------------------------------------------------------------------------------------------
//
void main(void){
    U_I pot_speed=0;
    //
    FET_DDR=0xFC; // #define FET_DDR  DDRD
    DDRE.2=1;     // COMP_INPUT output //COMP_INPUT=0; // COMP_INPUT off
    //
    ADCSRA=0x83;  // Prescaler 8
    //
    set_stop();   //set dir
    //
    BREAK; delay_ms(5); STOP; // precharge bootstrap_caps
    //
    TCCR1B=0x0A; TIMSK=0x10;  // 0.5us*200=10us
    //
    power_on_sound();         // sound start
    //
    dir_old=!DIR_SW;
    //
    OCR1A=100; set_start();
    //
    SREG|=0x80;
    while(1){
        if(DIR_SW!=dir_old){ dir=dir_old=DIR_SW; //dir changed
            set_stop();
            ADMUX=3; pot_speed=adc_read();          // 속도조절 가변저항 모터 정지 시에만 읽음
            OCR1A=(U_I)((float)pot_speed*100.0/1023.0); // 0~100으로 변환
            delay_ms(2000);                             // wait for the motor to stop
            startup_motor(); set_start();
        }
    }
}

이해하기 쉽게 소스를 재구성 했습니다.

//---------------------------------------------------------
char sound_table[]={0,3,2,5,4,1};
//
void sound_stop(){ BREAK; STOP; _delay_us(1200); }
//
void power_on_sound(){ /* power on sound */
    U_C d,i;
    for(d=0;d<20;d++){ // 20*(( 20+1200)*6)=146.4ms
        for(i=0;i<6;i++){ FET_PORT=commut_table[sound_table[i]]; _delay_us( 20); sound_stop(); } //820Hz
    } delay_ms(30);
    for(d=0;d<20;d++){ // 20*((120+1200)*6)=158.4ms
        for(i=0;i<6;i++){ FET_PORT=commut_table[sound_table[i]]; _delay_us(120); sound_stop(); } //758Hz
    } delay_ms(30);
    for(d=0;d<20;d++){ // 20*((240+1200)*6)=172.8ms
        for(i=0;i<6;i++){ FET_PORT=commut_table[sound_table[i]]; _delay_us(240); sound_stop(); } //694Hz
    } delay_ms(30);
}

//---------------------------------------------------------
모터로 소리를 발생 시키는 부분만 뽑았습니다.

void dly_us(U_I d){ int i; for(i=0;i;i++)delay_us(1);>
1us 딜레이를 변수를 사용해서 호출하고 있는데
c 루프 실행 시간이 좀 되서 실제 시간은 계산 값보다 길어집니다.
//
char sound_table[]={0,3,2,5,4,1};
commutation step 순서는 이 배열에서 하고 있습니다.
어떤 순서로 출력하든 회전하지 못하도록 순서를 엉망으로 출력하면 됩니다.

3660040649_o89Be4Ow_25C125A625B825F1_25BE25F825C025BD.PNG3Ftype3Dw740
전에 만들어둔 글도 참고하세요


void power_on_sound(){
    U_C d,i;
    for(d=0;d<123;d++){ FET_PORT=commut_table[0]; _delay_us( 20); BREAK; STOP; _delay_us(1200); } //820Hz
    delay_ms(30);
    for(d=0;d<114;d++){ FET_PORT=commut_table[0]; _delay_us(120); BREAK; STOP; _delay_us(1200); } //758Hz
    delay_ms(30);
    for(d=0;d<104;d++){ FET_PORT=commut_table[0]; _delay_us(240); BREAK; STOP; _delay_us(1200); } //694Hz
    delay_ms(30);
}
한 개의 commutation step만 사용한다면 더 간단해지겠죠

댓글 : 0

조회수 : 1,447

등록된 댓글이 없습니다.

게시물 검색

모터 목록

게시물 검색


Privacy Policy
MCU BASIC ⓒ 2017
PC버전