BLDC sürücü sonunda bitti !

Başlatan bulut_01, 24 Eylül 2012, 01:42:47

bulut_01

sayın arkadaslar temel benden geliştrip güzel devre olacagına inanıyorum önerilerizi bekliyorum pcb hakkında yorum yok begendininiz sanırım  :)
YENİLMEZ..

bulut_01

iyi aksamlar bu devredeyi arkadasların önerısıne uyarak daha fazla hız kazanmak ıcın kodda degısıklık yapdım yanlız bldc motor hall sensörlerınden aldıgım (101-100-110--010-011-001) bilgileri devamlı oldugu ıcın kodda devamlı kesmeye gidiyor ve kod switch satırına dallanmıyor. devamlı kesmede kaldıgı ıcın  sorum şu şekilde kesme sürekli oldugu ıcın  switch nasıl dallandırırım ?

#include <18f1330.h> 
#fuses INTRC_IO,NOWDT,NOMCLR
#use delay(clock=40M,oscillator=10M)
#use fast_io(a)
#use fast_io(b) 


int8 x ;
 int16 duty1=0;
 int16 duty2=0;
 int16 duty3=0;
int16 p=50 ;

#int_RB
void RB_kesme ()

{

x=0;
if(input(pin_a1 ))
x=x+1;

if(input(pin_B2 ))
x=x+2;

if(input(pin_B3 ))
x=x+4;

disable_interrupts (int_RB);



switch (x)
{
case 1:
     
      output_low(pin_b4);
      
      duty3=p*64;
    set_power_pwm4_duty(duty3);
     output_high(pin_b0); 
    break ;
   
case 2:
     
     output_low(pin_b0);
     
     duty2=p*64;
    set_power_pwm2_duty(duty2);
    output_high(pin_b6); 
       break ;
case 3:
     set_power_pwm4_duty(duty3=0x00);
     
     
     duty2=p*64;
   set_power_pwm2_duty(duty2);
   output_high(pin_b0);
      break ;
case 4:
     set_power_pwm0_duty(duty1=0x00);
     output_low(pin_b6);
     
     duty1=p*64;
    set_power_pwm0_duty(duty1);
    output_high(pin_b4);
       break ;
case 5:
     set_power_pwm0_duty(duty1=0x00);
     
     
     duty3=p*64;
    set_power_pwm4_duty(duty3);
    output_high(pin_b4);
      break ;
case 6:
    set_power_pwm2_duty(duty2=0x00);
    output_low(pin_b6);
    
    duty1=p*64;
   set_power_pwm0_duty(duty1);
   output_high(pin_b6);
     break ;
}
 }


           void main()
{
   setup_power_pwm_pins(PWM_odd_on,PWM_odd_on,PWM_odd_on,PWM_odd_on);
   setup_power_pwm(PWM_CLOCK_DIV_64|PWM_FREE_RUN,1,0,4095,0,1,0); 
   setup_adc_ports(NO_ANALOGS); 
   setup_adc( ADC_OFF );
   setup_comparator(NC_NC_NC); 
   set_tris_a(0b000000011);
   set_tris_b(0b000001100);
   OUTPUT_B(0x00);
  
  clear_interrupt(INT_EXT); 
  ext_int_edge(L_TO_H);
    enable_interrupts(GLOBAL);
   enable_interrupts(int_RB);

while(TRUE)
{

}
}
YENİLMEZ..

fryrmnd

disable_interrupts (int_RB);  kısmını kesmeye girdiğiniz gibi yazsanız. Çalışmasını pek bilimyorum ama ilk bakışta bu geldi aklıma.

bulut_01

Alıntı yapılan: fryrmnd - 07 Ekim 2012, 22:21:43
disable_interrupts (int_RB);  kısmını kesmeye girdiğiniz gibi yazsanız. Çalışmasını pek bilimyorum ama ilk bakışta bu geldi aklıma.
kesmeye girdiği gibi derken ne demek istedin anlamadım acık yazarsan ?
YENİLMEZ..

fryrmnd

şimdi yanlış anlamadıysam

void RB_kesme ()

{

x=0;
if(input(pin_a1 ))
x=x+1;

if(input(pin_B2 ))
x=x+2;

if(input(pin_B3 ))
x=x+4;

disable_interrupts (int_RB);


kısmında

void RB_kesme ()

{
 

den sonra switch case e kadar olan kısımda kesme geliyor olabilir. O yüzden kesmeleri

void RB_kesme ()
dan sonra pasif (
disable_interrupts (int_RB);
) yapabilirsin.

yani kesme rutinine hemen girdiğinde.

yanlışım da olabilir tabii.


skara1214

hocam bu rb kesmesi düşündüğünüz kadar hızlı cevap vermiyor.Bence bundan vazgeçin.
yok illa bunu kullanacam diyorsanız disable_interrupts(int_rb) satırını direk interrupta girdiğinizde yazın.Ama göreceksinizki kaçıracak ve performans alamayacaksınız.İnterruptın sonundada  enable yazıp interruptı bitirin
Herkes ölür ama herkes gerçekten yaşamaz

bulut_01

#36
evt arkadaslar bu kesme algoritması kosunda fikirlerinizi bekliyorum.

mesaj birleştirme:: 07 Ekim 2012, 23:38:26

şuanda kod calısıyor sadece pıc ılk enerjı anında kesme olusdugu ıcın ılk anda calısmıyor ben hall gelen ucları swich ıle verdıgımde proteus ile similasyonda sınyalleri pıc calısıyor motor. ılk an pıc enerjılendıgı an kesmeden cıkıp swıch dallanmaması tek sorunum kodun son hali:

#include <18f1330.h> 
#fuses INTRC_IO,NOWDT,NOMCLR
#use delay(clock=40M,oscillator=10M)
#use fast_io(a)
#use fast_io(b) 


int8 x ;
 int16 duty1=0;
 int16 duty2=0;
 int16 duty3=0;
int16 p=250 ;



#int_RB
void RB_kesme ()

{


disable_interrupts (int_RB);

x=0;
if(input(pin_a1 ))
x=x+1;

if(input(pin_B2 ))
x=x+2;

if(input(pin_B3 ))
x=x+4;

enable_interrupts (int_RB);



switch (x)
{
case 1:
     
      output_low(pin_b4);
      
      duty3=p*64;
    set_power_pwm4_duty(duty3);
     output_high(pin_b0); 
    break ;
   
case 2:
     
     output_low(pin_b0);
     
     duty2=p*64;
    set_power_pwm2_duty(duty2);
    output_high(pin_b6); 
       break ;
case 3:
     set_power_pwm4_duty(duty3=0x00);
     
     
     duty2=p*64;
   set_power_pwm2_duty(duty2);
   output_high(pin_b0);
      break ;
case 4:
     set_power_pwm0_duty(duty1=0x00);
     output_low(pin_b6);
     
     duty1=p*64;
    set_power_pwm0_duty(duty1);
    output_high(pin_b4);
       break ;
case 5:
     set_power_pwm0_duty(duty1=0x00);
     
     
     duty3=p*64;
    set_power_pwm4_duty(duty3);
    output_high(pin_b4);
      break ;
case 6:
    set_power_pwm2_duty(duty2=0x00);
    output_low(pin_b6);
    
    duty1=p*64;
   set_power_pwm0_duty(duty1);
   output_high(pin_b6);
     break ;
}
 }


           void main()
{
   
   setup_power_pwm_pins(PWM_odd_on,PWM_odd_on,PWM_odd_on,PWM_odd_on);
   setup_power_pwm(PWM_CLOCK_DIV_64|PWM_FREE_RUN,1,0,4095,0,1,0); 
   setup_adc_ports(NO_ANALOGS); 
   setup_adc( ADC_OFF );
   setup_comparator(NC_NC_NC); 
   set_tris_a(0b000000011);
   set_tris_b(0b000001100);
   OUTPUT_B(0x00);

  
  clear_interrupt(INT_EXT); 
  ext_int_edge(L_TO_H);
    enable_interrupts(GLOBAL);
   enable_interrupts(int_RB);

while(TRUE)
{

}
}
YENİLMEZ..

iyildirim

Case bloğunda ki kod çok verimsiz.. 

Case kısmındaki kod tamamen kaldırılıp, yerine elektriksel döngünün 6 farklı durumu için hangi PWM kanallarının aktif olması gerektiği OVDCOND registerine göre yazılıp, bir diziye atılır. Devrenize göre de OVDCONS = 0x00 olmalı..
Sensörden okunan 3 bit den oluşturulacak bir sayı bu dizinin indisi olarak kullanılıp bütün case bloğunun yerine 1-2 clock harcayarak  PWM kanalı anahtarlaması IC kesmesinde yapılır.

Bunun dışında akım , hız, hızlanma gibi olmazsa olmaz kontroller eksik.. 


bulut_01

Alıntı yapılan: iyildirim - 08 Ekim 2012, 00:24:24
Case bloğunda ki kod çok verimsiz.. 

Case kısmındaki kod tamamen kaldırılıp, yerine elektriksel döngünün 6 farklı durumu için hangi PWM kanallarının aktif olması gerektiği OVDCOND registerine göre yazılıp, bir diziye atılır. Devrenize göre de OVDCONS = 0x00 olmalı..
Sensörden okunan 3 bit den oluşturulacak bir sayı bu dizinin indisi olarak kullanılıp bütün case bloğunun yerine 1-2 clock harcayarak  PWM kanalı anahtarlaması IC kesmesinde yapılır.

Bunun dışında akım , hız, hızlanma gibi olmazsa olmaz kontroller eksik..

dediklerine göre bir algoritma olusturursanız ve dedıgınız register kullanarak bi kod örnediği yazarsanız bu devreye baya katkınız olur.
YENİLMEZ..

iyildirim

Sensörün hangi konumunda hangi PWM kanallarının aktif olacağını hazırlarsan olur..


bulut_01

#40
tabi
sensör bilgisi
    101 (set_power_pwm4_duty) output_high(pin_b4)
    100 (set_power_pwm4_duty) output_high(pin_b0)
    110 (set_power_pwm2_duty) output_high(pin_b0)
    010 (set_power_pwm2_duty) output_high(pin_b6)
    011 (set_power_pwm0_duty) output_high(pin_b6)
    001 (set_power_pwm0_duty) output_high(pin_b4)

tablo yukardekı gıbıdır her 3 bitlik veriden sonra önceki pwm kanalı sıfırlanmalıdır.
YENİLMEZ..

iyildirim

#41
Global değişken olarak tanımlanacaklar..
char OvrArr[8], IOBArr[8];



Main içinde ana döngüden önce ;
//101 (set_power_pwm4_duty) output_high(pin_b4)
OvrArr[0b00000101] = 0b00010000;
IOBArr[0b00000101] = 0b00010000;

//100 (set_power_pwm4_duty) output_high(pin_b0)
OvrArr[0b00000100] = 0b00010000;
IOBArr[0b00000100] = 0b00000001;

//110 (set_power_pwm2_duty) output_high(pin_b0)
OvrArr[0b00000110] = 0b00000100;
IOBArr[0b00000110] = 0b00000001;

//010 (set_power_pwm2_duty) output_high(pin_b6)
OvrArr[0b00000010] = 0b00000100;
IOBArr[0b00000010] = 0b01000000;

//011 (set_power_pwm0_duty) output_high(pin_b6)
OvrArr[0b00000011] = 0b00000001;
IOBArr[0b00000011] = 0b01000000;


//001 (set_power_pwm0_duty) output_high(pin_b4)             
OvrArr[0b00000001] = 0b00000001;
IOBArr[0b00000001] = 0b00010000;


OVDCONS = 0x00;


Kesme içinde; 
Switch(x) bloku komple silinip yerine;
OVDCOND = OvrArr[x];
PORTB = IOBArr[x];


değişikliklerini yapınca söylemiş olduğum mantık ile çalışıyor olacak..
http://ww1.microchip.com/downloads/en/DeviceDoc/39758D.pdf 
datasheetin sf:140 sayfasında detaylıca anlatılıyor..

Duty' yi herhangi bir yerde ayarlayabilirsiniz. Örneğin bir pota veya okunan bir bilgiye bağlı olarak hız ayarlanabilir. 
Eğer motorun sabit bir devirde dönmesi isteniyorsa kesmeden çıkarken bir timer kurup, kesmeye tekrar girdiğinde geçen süreye göre deviri hesaplayabilir ve duty ile oynayarak ayarlayabilirsiniz.

bulut_01

suanda pc kapattım tel giiriyorım yarın bakarım koda ilginc komut ilk defa böle komut setı gordum pekı yazılımla frekans degıstırerek tork ayarıda yapsak guzel olmazmıydı?
YENİLMEZ..

iyildirim

Frekans, PWM frekansı ise verimlilikle ilgili.. Modeller için satilan BLDC motorların çoğu için 8khz lik bir frekans öneriliyor.
Tork ile devir ilişkili. Motor yüklenince ister istemez devri düşecek. Tork fazla olunca devir artacak. Bu da iki kesme arasındaki süreden anlaşılır. Devir düşüyorsa PWM duty uygun bir kontrol kullanılarak arttırılır.  Değişken yük altında istenen devir sabit tutulabiliyorsa motor zaten uygun tork ile çalışıyordur.

bulut_01

yıldırım kardesım 8 khz yuksek frekans bu frekans motor yukdeyken hıc dönecegı sanmıyorum dusuk frekans yuksek tork alınıyor örnek 20 hz max tork gıbı frekans ıle tork ters orantılı olarak calısıyor.
YENİLMEZ..