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.
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.
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.
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ı.
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
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.
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
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
- 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.
- 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.
- Yazıcı tekerleği yerine silikon tekerlek kullanmak verimi dahada artıra bilir.(imkanımız yoktu :] )
Teşekkürler
- Manevi katkıları ve bize Çınarlı argesini kullanıma açtığı için Ali Deniz YETKİN 'e
- Öğretmenimiz Serkan AYYILDIZ 'a
- 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
Mayıs 2012
Makalemizi yayınlayan diğer siteler :
http://www.robots101.com/kasva-arm-islemcili-mini-sumo-robotu/
http://320volt.com/stm32f4-arm-sumo-robot-projesi/
stm32f discovery
Kaynak gösterilerek alıntı yapılabilir.