17 Mayıs 2012 Perşembe

KASVA MiNi SUMO ROBOTU                                                                          



         


ARM STM32FDISCOVERYKasva mini sumo

KASVA mini sumo ARM işlemci kullanarak, ARM platformunda yazılım geliştirme deney amaçlı yapılmış bir mini sumodur.  PİC mikro denetleyicisinin günümüzde hemen hemen bütün robot yapanların başvurduğu ilk kontrolördür. PİC  ortam şartlarından, manyetik alandan ve voltaj düşmesinden aşırı etkilenip Reset atmaya sebebiyet vere bilmektedir. PİC 'in sınırına geldiğini düşünenler için iyi bir tercih olacağını düşünüyorum.

Robotlar da fazla görmeye alışkın olmadığımız gömme tekerlek kullanmak istedik. Tabi gömme tekerlek motorun neredeyse tamamını içerisine alan bir tasarım.  

mini sumo kasa

           Tekerleklerin jant kısmı İzmir 1.Sanayiden CNC den çıkarttırdık.  Kasada pileksi den lazer kesim yaptırdık.  Robotumuzun önünü Boumax den aldığımız kazıma bıçağını kullandık.  El matkabı kullanarak önleri yaklaşık 20 derece açı yapacak şekilde aldım.  




Mini sumo tekerleği

    


       Kazıma bıçağını öne yapıştırmak için  pattex repair extreme markalı yapıştırıcı kullandık emin olabilirsiniz piyasadaki en iyi yapıştırıcılardan biri. (reklam için para almadım, memnuniyetten :] :D ) Fakat çok geç yapıştırma işlemi gerçekleştiriyor. Motorları ve sensörleri yapıştırmak içinde bu apıştırıcıyı kullandım.
Süper yapıştırıcı





          Kullandığımız motorlar ise Finger Tech markalı 20:1 oranlı      motorlar yukarıda verdiğim tabloda motora verilen voltajın tork ve hızı   etkileşimi gösterilmektedir. Kullandığımız bu motorun diğer özelliklerinden biride Türkiye deki standart mini sumo motorlarından biraz daha küçük olması.
mini sumo motoru


lipo pil
  


            Kullandığımız piller nano-tech 1000mah 2S 25~50C Lipo 7.4V bu pilden 2 adet kullandık seri şekilde bağlayarak 14.8 v bir gerilim ile motorları besledik. Pilleri full şarj ettiğimizde seviye 15.4 e kadar çıka bildi.
SHARP 340k kullanım










        Sensör olarak SHARP 340k kullandık mini sumo için en ideal sensörlerden biri





     

     Sensörleri delikli plakete kurup yukarıdaki şemada gösterilmiş olan 1mikrofarat ve 1 ohmluk malzemeleri en ideal şekilde yerleştirmeye çalıştım.








        
            Zemin sensörlerimiz ise QRD1114 markalı sensörleri tercih ettik boyutları ve algılama kararlılığı ile temiz bi sensör


QRD 1114 zemin sensörü kullanımı beyaz algılama


           
          Malum f4 den elektronik devre için çok kısıtlı alanımız olduğundan delikli plaket yardımı ile sensörler için gerekli elektronik malzemeleri üzerlerine lehimledik yukarı da ki resimde zemin sensörü için bulduğumuz çözüm.



      

          Yandaki şemada QRD1114 ün lojik 1, dijital olarak kullanıma uygun hale getirilmesi. Bu sensörler için sanırım en stabil kullanım açısından gerekli olan devre budur.
.
letsmakerobots.com  sitesini de tavsiye ederim.









 Sensörlere enerji ulaştırmak için bi kablo yardımıyla paralel olacak biçimde kabloların sensörlerin VDD ve GND bacaklarının üzerlerindeki kısımları maket bıçağı ile kestim ve lehimleme işlemi gerçekleştirdim. Bu şekilde her sensörden bir kablo çıkartarak değilde tek kabloyu tüm sensörlerin üzerinden gezdirerek enerji dağıtma işleminin üstesinden geldim.
           
           Regüle devremiz ise lm2575 entegresi kullandık internette bu entegre ile ilgili çeşitli hazırlanmış devreler bulunmakta benim çizdiğim devrede 2 adet çıkış soketi belirledim. F4 için ve sensörler için daha sonra sürücü kartı için gerekli olan +5v ise F4 ün üzerinden verdim. 



            
               Artık oldukça yaygınlaşan bi yöntem olan sürücüleri paralel bağlayıp yüksek verimlilikte motor sürücü elde etme yöntemini biz de kullandık. Yukarıdaki resimde bunu görmekteyiz.




TB6612fng kullanımı
Sürücüden genel olarak bahsetmek gerekirse 


VM = 15v max

VCC =2,7-5,5V

Çıkış akımı =1,2A ortalama \3,24A (peak)

  Kullanımı gayet kolay ve ekstra elaman istemiyor.  Temiz iş :] .







Yerleşimde aşağıda olduğu gibi



STM32FDISCOVERY
   

        Evet sırada saygı değer STM32FDISCOVERY son zamanlarda ARM nin adını tablet bilgisayarlarda duyar olduk.Teknoloji fazla uzaklaşmadan STMicroelectronics firmasının geliştirdiği bu kartı kullanmayı tercih ettik. ARM ye başlayan herkes gibi bizde kaynak bulmakta büyük sıkını yaşadık ama Yiğit YILDIRIM yazılımda kütüphaneleri ve genel algoritmayı oluşturdu. PWM 1...4094 en yüksek 1 en düşük 4096



#include "STM32F4xx.h"
#include "stm32f4xx_regs.h"
#include "delay.c" 
#include "stm32f4xx_TIMER.h"

#define buton5sn PA->IDR.pin.p0 // Portları aklımızda kolay tutabilmek için isimlendirdik.


#define on_sensor PB->IDR.pin.p0    

#define sol_sensor PE->IDR.pin.p8
#define sag_sensor PA->IDR.pin.p4
#define arka_sensor PB->IDR.pin.p7
#define onsol_sensor PC->IDR.pin.p4  
#define onsag_sensor PB->IDR.pin.p2

#define sag_zemin PA->IDR.pin.p2  

#define sol_zemin PE->IDR.pin.p10

#define sol_led PD->ODR.pin.p15

#define arka_led PD->ODR.pin.p14
#define sag_led PD->ODR.pin.p13
#define on_led PD->ODR.pin.p12

char i,x,j,g,y;   // Yazılımda kulladığımız değişkenleri tanımladık.


void SystemInit() // Bu kısım Stm32F4 ün boot edilmesi için gerekli olan kısım

{
unsigned int i;

    for (i=0;i<0x00100000;i++);          // OSC oturtma ve kurtarma rutini
    RCC->CFGR |= 0x00009400;         // AHB ve APB hizlarini max degerlere set edelim
    RCC->CR |= 0x00010000;            // HSE Xtal osc calismaya baslasin        
    while (!(RCC->CR & 0x00020000));// Xtal osc stabil hale gelsin
    RCC->PLLCFGR = 0x07405408;      // PLL katsayilarini M=8, N=336, P=2 ve Q=7 yapalim
//  RCC->PLLCFGR = 0x07402A04;     // PLL katsayilarini M=4, N=168, P=2 ve Q=7 yapalim
    RCC->CR |= 0x01000000;            // PLL calismaya baslasin  (Rehber Sayfa 95)
    while(!(RCC->CR & 0x02000000)); // Pll hazir oluncaya kadar bekle
//  FLASH->ACR = 0x00000705;        // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
    FLASH->ACR = 0x00000605;        // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
    RCC->CFGR |= 0x00000002;        // Sistem Clk u PLL uzerinden besleyelim
    while ((RCC->CFGR & 0x0000000F) != 0x0000000A); // Besleninceye kadar bekle
    RCC->AHB1ENR |= 0x00000FFF;    // GPIO A,B,C,D clock'u aktif edelim 
    GPIOD->MODER = 0x55000000;     // GPIOD nin 15, 14, 13, 12 pinleri cikis tanimlandi (LEDler icin)
    PA->MODER.pin.p3 = PORT_OUTPUT; //önceden kullanıma açılan pinleri giriş yada çıkış olduklarının tanımı
PA->MODER.pin.p5 = PORT_OUTPUT; //önceden kullanıma açılan pinleri giriş yada çıkış olduklarının tanımı
PE->MODER.pin.p11 = PORT_OUTPUT; //önceden kullanıma açılan pinleri giriş yada çıkış olduklarının tanımı
PE->MODER.pin.p13 = PORT_OUTPUT; //önceden kullanıma açılan pinleri giriş yada çıkış olduklarının tanımı
PA->MODER.pin.p0 = PORT_INPUT; //önceden kullanıma açılan pinleri giriş yada çıkış olduklarının tanımı
PB->MODER.pin.p0 = PORT_INPUT; //önceden kullanıma açılan pinleri giriş yada çıkış olduklarının tanımı
PE->MODER.pin.p8 = PORT_INPUT; //önceden kullanıma açılan pinleri giriş yada çıkış olduklarının tanımı
PA->MODER.pin.p4 = PORT_INPUT; //önceden kullanıma açılan pinleri giriş yada çıkış olduklarının tanımı
PB->MODER.pin.p7 = PORT_INPUT;  //önceden kullanıma açılan pinleri giriş yada çıkış olduklarının tanımı
PC->MODER.pin.p4 = PORT_INPUT;  //önceden kullanıma açılan pinleri giriş yada çıkış olduklarının tanımı
PB->MODER.pin.p2 = PORT_INPUT;  //önceden kullanıma açılan pinleri giriş yada çıkış olduklarının tanımı
PA->MODER.pin.p6 = PORT_INPUT;  //önceden kullanıma açılan pinleri giriş yada çıkış olduklarının tanımı
PA->MODER.pin.p2 = PORT_INPUT;  //önceden kullanıma açılan pinleri giriş yada çıkış olduklarının tanımı
PE->MODER.pin.p10 = PORT_INPUT;  //önceden kullanıma açılan pinleri giriş yada çıkış olduklarının tanımı
GPIOA->OSPEEDR= 0xFFFFFFFF;   // GPIOD nin tum cikislari en yuksek hizda kullanacagiz 
GPIOB->OSPEEDR= 0xFFFFFFFF;
GPIOC->OSPEEDR= 0xFFFFFFFF;
GPIOD->OSPEEDR= 0xFFFFFFFF;
GPIOE->OSPEEDR= 0xFFFFFFFF;

// Aşağıdaki kısım ise Timmer ile PWM Üretmek için Timmerın ayarlarının bulunduğu kısım

RCC->APB1ENR|=0x00000002;       // Timer3 CLK'u aktif edelim (84 Mhz)
     TIM3->PSC = 1;  //  Ön bölücü f/2 48MHz (Fck_PSC / (PSC_VAL+1)) 
     TIM3->ARR = 4096;   // CCR1 ile karşılaştırılacak sayı. (12 bit PWM)

// TIM3->DIER = 0x0001;

     TMR3->DIER.UIE = TMR_UIE_UPDATE_IRQ_DISABLE; // Interrupt kapalı. Açılırsa her periyotta interrupt üretir.
       
     //TIM3->CCMR1 |= 0x0068; //PWM mode 1, preload enable
     TMR3->CCMR1.OCR.OC1PE = TMR_OCPE_PRELOAD_ENABLE;
     TMR3->CCMR1.OCR.OC1M = TMR_OCM_PWM_MODE1;
     
     //TIM3->CCER |= 0x0002; // Polarite seçimi 
     TMR3->CCER.CC1P = TMR_CCP_OC_ACTIVE_LOW;
     
     //TIM3->CR1 = 0x0080;  // ARPE auto reload preload
     TMR3->CR1.ARPE = TMR_ARPE_NOTPRELOAD;

     //TIM3->EGR |=0x0001; // Update generation

     TMR3->EGR.UG = TMR_UG_UPDATE_REINIT;
     
     //TIM3->CCER |= 0x0001; // CC1 aktif.
     TMR3->CCER.CC1E = TMR_CCE_OC_ACTIVE;

     PB->AFR.pin.p4 = PORT_AF2_TIM3;   // PORT_B4 TIM3 ile ilişkilendirildi

     PB->MODER.pin.p4 = PORT_ALTERNATE_FUNC; // PORT_B4 alternatif fonksiyon
     PB->OSPEEDR.pin.p4 = PORT_HI_SPEED; // PORT_B4 çıkışı en yüksek hızda çalışacak
     PB->OTYPER.pin.p4 = PORT_PUSH_PULL; // Çıkış tipi Push-Pull

     //TIM3->CR1 |= 0x0001; // sayıcıyı başlat. 

  TMR3->CR1.CEN = TMR_COUNTER_ENABLE;
     
RCC->APB1ENR|=0x00000001;
TIM2->PSC = 1; // ön bölücü 2 42MHz (Fck_PSC / (PSC_VAL+1))
     TIM2->ARR = 4096;


// TIM3->DIER = 0x0001;

     TMR2->DIER.UIE = TMR_UIE_UPDATE_IRQ_DISABLE; // Interrupt kapalı. Açılırsa her periyotta interrupt üretir.
       
     //TIM3->CCMR1 |= 0x0068; //PWM mode 1, preload enable
     TMR2->CCMR1.OCR.OC1PE = TMR_OCPE_PRELOAD_ENABLE;
     TMR2->CCMR1.OCR.OC1M = TMR_OCM_PWM_MODE1;
     
     //TIM3->CCER |= 0x0002; // Polarite seçimi 
     TMR2->CCER.CC1P = TMR_CCP_OC_ACTIVE_LOW;
     
     //TIM3->CR1 = 0x0080;  // ARPE auto reload preload
     TMR2->CR1.ARPE = TMR_ARPE_NOTPRELOAD;

     //TIM3->EGR |=0x0001; // Update generation

     TMR2->EGR.UG = TMR_UG_UPDATE_REINIT;
     
     //TIM3->CCER |= 0x0001; // CC1 aktif.
     TMR2->CCER.CC1E = TMR_CCE_OC_ACTIVE;

     PA->AFR.pin.p15 = PORT_AF1_TIM2;   // PORT_B4 TIM3 ile ilişkilendirildi

     PA->MODER.pin.p15 = PORT_ALTERNATE_FUNC; // PORT_B4 alternatif fonksiyon
     PA->OSPEEDR.pin.p15 = PORT_HI_SPEED; // PORT_B4 çıkışı en yüksek hızda çalışacak
     PA->OTYPER.pin.p15 = PORT_PUSH_PULL; // Çıkış tipi Push-Pull

     //TIM3->CR1 |= 0x0001; // sayıcıyı başlat. 

  TMR2->CR1.CEN = TMR_COUNTER_ENABLE;


}

void set_motor (int in1, int in2, int bekle) //Bu alt program ise motorların yönünü ve ne kadar hızla gitmesi gerektiğini //tanımlayan alt program

{
if (in1 < 0) //girilen in1 değeri 0 dan küçük ise  1.motorumuz için (negatif birdeğerise)
{
PA->ODR.pin.p3 = 1; //A portunda 3. pini 1 yap
PA->ODR.pin.p5 = 0; //A portunda 5. pini 0 yap
// Motorlar bu döngüde sol tarafa dönecektir
}
else //değilse 1.motorumuz için (pozitif bir değerise)
{     
PA->ODR.pin.p3 = 0; //A portunda 3. pini 0 yap
PA->ODR.pin.p5 = 1; //A portunda 5. pini 1 yap
} // Motor bu döngüde sağ tarafa dönecektir
if (in2 < 0){ //girilen in2 değeri 0 dan küçük ise 2.motorumuz için  (negatif birdeğerise)
PE->ODR.pin.p11 = 0; //E portunda 11. pini 0 yap
PE->ODR.pin.p13 = 1; //E portunda 13. pini 1 yap
} // Motorlar bu döngüde sol tarafa dönecektir
else //değilse 2.motormuz için (pozitif bir değerise)
{  
PE->ODR.pin.p11 = 1; //E portunda 11. pini 1 yap
PE->ODR.pin.p13 = 0; //E portunda 13. pini 0 yap
} // Motorlar bu döngüde sağ tarafa dönecektir
{ //pwm için gerekli olan timer yerin bulunduğu alt programa gönderilmesi için
TIM3->CCR1 = (abs(in1));
TIM2->CCR1 = (abs(in2));
delay_ms(bekle); // pwm varken o durumda işlemi nekadar sürede yapmasını 
} // istiyorsak onun için bi bekleme alt programı
}

  void fren( int bekle)   // motorları durdurması için gerekli alt program

{
GPIOA->ODR= 0x00000028;
GPIOE->ODR= 0x00002800;
TIM3->CCR1 = 10;
TIM2->CCR1 = 10;
delay_ms(bekle);
}

void Led (char x) // Ledleri sırayla yakmak için böylebir programa ihtiyaç duyduk

{
if (x==0) {on_led = 0; sag_led = 0; arka_led = 0; sol_led = 0;}
  if (x==1) {on_led = 1; sag_led = 0; arka_led = 0; sol_led = 0;}
if (x==2) {on_led = 0; sag_led = 1; arka_led = 0; sol_led = 0;}
if (x==3) {on_led = 0; sag_led = 0; arka_led = 1; sol_led = 0;}
if (x==4) {on_led = 0; sag_led = 0; arka_led = 0; sol_led = 1;}
if (x==5) {on_led = 0; sag_led = 0; arka_led = 1; sol_led = 0;}
if (x==6) {on_led = 0; sag_led = 1; arka_led = 0; sol_led = 0;}
if (x==7) {on_led = 1; sag_led = 0; arka_led = 0; sol_led = 0;}
if (x==8) {on_led = 1; sag_led = 1; arka_led = 1; sol_led = 1;}
}



void zemin_oku()  // zemin sensör
{
if (sag_zemin == 0 ) // (sağ için) qrd zemin sensörleri beyazda 0 a çektiği için zemin 0 sa 
{ // geri  doğru bi salto hareketi yapmasını sağlayak alt program
 fren (2);
 set_motor ( 1700, 1700, 350);
 set_motor ( -2500, 3048, 120);
 }
else if (sol_zemin == 0 ) // (sol için) 
{ // geri  doğru bi salto hareketi yapmasını sağlayak alt program
 fren (2);
 set_motor ( 1700, 1700, 350);
 set_motor ( 3048, -2500, 120);
} // sag zemin
}



void sensor_oku() // rakip  Sensörleri

{
if ((on_sensor == 0) & (onsag_sensor == 0) & (onsol_sensor == 0)) { on_led =1; sol_led =1; sag_led =1; set_motor ( -1, -1, 5); zemin_oku (); } //ön sensölerin 3 üde görüyorsa full
else if (on_sensor == 0) {on_led = 1; set_motor ( -1000, -1000, 5);} // öne doğru git // pwm le ileri gitmesini sağlayan yazılım
else if (onsag_sensor == 0) {fren(1); on_led = 1; sag_led = 1; set_motor ( 1100, -2000, 6);} // ön sag cprz dön
else if (onsol_sensor == 0) {fren(1); on_led = 1; sol_led = 1; set_motor ( -1100, 2000, 6);} // ön sol cprz dön
else if (sag_sensor == 0) {fren(1); sag_led = 1; set_motor ( 300, -1400, 50);} // sag dön
else if (sol_sensor == 0) {fren(1); sol_led = 1; set_motor ( -300, 1400, 50);} // sol dön
else  { set_motor (-2400, -2400, 5); on_led =0; sol_led = 0; sag_led =0; arka_led =0; zemin_oku (); } // görüldüğü gibi her //parametrinin// altında zemin oku var bunun nedeni 
} // ARM işlemcilerin hızlı çalışması ve her //işlemden sonra 
// zemini okumasını sağlamak

int main ()

{

 

  for (i=1;i<=8;i++) {delay_ms(20); Led(i);} // ARM nin reset atıp atmadığını kontrol etmek amacıyla ledleri açılışta çok kısa bir süre //yakıp söndürür
  delay_ms(20);
Led(0);
 if ( sag_zemin == 1 ) { g = 1; sol_led = 1; } // Açılışta zemin sensörüne parmağımızı koyarak rakibin yönünü robotumuza //bildiriyoruz
 else if ( sol_zemin == 1 ) { y = 1; sag_led = 1; }
 while(buton5sn == 0);  i = 1; // 5 sn ye butonuna basılınca robotun başlamasını sağlayan program
if ( i == 1) 
{
i = 1;
for (j=0;j<5;j++)
{
for(i=1;i<=8;i++)
{delay_ms(100); Led(i);}
}
if ( g == 1 ) { set_motor ( -300, 1400, 100);}
if ( y == 1 ) { set_motor ( 300, -1400, 100);}
Led(0);
zemin_oku ();
}




    while(1)  //5sn butonuna bastıktan sonra bu döngü içine girerek robotun çalışmasını sağlar

{
zemin_oku ();   //zemini okur
sensor_oku ();   // rakibi kontrol eder
}

     

Kütüphane dosyaları ve yazılımın orjinali: 
   https://hotfile.com/dl/156201348/7e189d1/KasvaV1_11.rar.html 

Yaptığımız Hatalar
  1. Tekerleklerin çok büyük olmasından dolayı setskur deliği 3mm açtık bu da haliyle yetmedi ve tekerlek yalpalama yaptı. çözüm ise daha büyük bi steskul değili ile motorun şaftına iyi tutunma sağlamak.
  2. F4 kiti çok büyük olduğu için sürücü ve regüle ayrı ayrı modüllerde yapmak zorunda kaldı bu yüzden robot çok yüksek oldu.
  3. Yazıcı tekerleği yerine silikon tekerlek kullanmak verimi dahada artıra bilir.(imkanımız yoktu :] )


Teşekkürler


  1. Manevi katkıları ve bize Çınarlı argesini kullanıma açtığı için Ali Deniz YETKİN 'e
  2. Öğretmenimiz Serkan AYYILDIZ 'a
  3. Yarışma yerinde tekerlekri sabitlemek için japon yapıştırıcısını kullandığımız Fırat DEDE 'ye :]





                                                                  Bu çalışma Ahmet Yasin CİVAN & Yiğit YILDIRIM 'ın ürünüdür    
                                                                                                                                                Mayıs 2012 
stm32f discovery

                                                               Kaynak gösterilerek alıntı yapılabilir.