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 순서는 이 배열에서 하고 있습니다.
어떤 순서로 출력하든 회전하지 못하도록 순서를 엉망으로 출력하면 됩니다.
전에 만들어둔 글도 참고하세요
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
등록된 댓글이 없습니다.