Arduino UNO R3 ile temel projeler | Elektronik ve Mekanik Forumu
Atmel'in Atmega 328P işlemcisini kullanan Arduino UNO R3 ve bu karta uygun bir de LCD tuş takımı ve ekran modülünü (LCD Keypad Shield) sipariş etmiştim. Ayrıca daha sonra başlamayı düşündüğüm, alarm sistemleri için darbe sensörü projesi için de bir Adafruit Pro Trinket kartlarını sipariş etmiştim, İkisi de elime ulaştı.
Trinket'i bir kenara koyuyoruz ve UNO R3'e daha yakından bakalım. Bu kartın Çin malı ucuz klonları da var, ama ben orijinalini almayı tercih ettim. Sayısız Çin malı klonlar arasında olabilecek ufak tefek farklardan dolayı yaptığımız deneylerde farklı sonuçlar alınabilir, o yüzden kendi açımdan ne olduğu tam olarak bilinen ve iyi dokümantasyona sahip olan orijinal UNO R3 ile çalışmanın daha mantıklı olduğunu düşünüyorum. Ama bu sizin de mutlaka orijinal UNO R3 kullanmanız gerektiği anlamına gelmez. İstediğiniz çeşidini kullanabilirsiniz, ama orijinal UNO R3'e göre farklılıklarını bilerek yaparsanız herhangi bir sürpriz ile karşılaşmamış olursunuz.
UNO R3'e yakından bakalım:
Ynt: Arduino UNO R3 ile temel projeler
UNO R3 kartının şeması ekte. Arduino'nun en yaygın kullanılış biçimi, Arduino IDE denen ve PC'de çalışan bir yazılımla, küçük program parçaları geliştirmek. Sonra da bu program parçalarını Arduino üzerindeki mikrokontroller'a (Atmega 328P-PU) transfer edip çalıştırmak. Atmega328'in üzerinde, fabrikada programlanmış olan bir firmware var. Bizim yazdığımız program parçaları, bu firmware'in kontrolü altında işlemcinin dahili belleğine transfer edilmektedir ve sonra da bu firmware'in kontrolü altında çalıştırılmaktadır. Yani bizim yazacağımız programlar, %100 olarak Atmega328'e hakim değildir, mevcut firmware'in bir alt programı gibidir.
Eğer Atmega328 işlemcisine %100 hakim bir firmware geliştirmek istersek, Arduino IDE'yi kullanamayız. Onun yerine, "Atmel Studio" yazılımı ile direkt olarak C/C++ veya assembly dilinde firmware geliştirip sonra da bir çip programlayıcı ile Atmega'nın firmware'ini silip bizim yeni firmware'i yerine yazmamız lazım. Bu da ilerisi için planladığım projelerden birisidir.
81.4 KB Görüntüleme: 51
İnternette Arduino programlama ile ilgili araştırma yaptığımızda, en yaygın kullanılan başlangıç projeleri, bir LED'nin blink edilmesi, bir butona basılınca LED'nin yakılması veya durum değiştirmesi gibi şeylerdir. Bu kadar hazır materyal varken, benim de burada tekrar bir blink kodu yazdırmam anlamsız olur diye düşünüyorum. Onun yerine, birçok temel konuyu kapsayan ve pratikte de kullanılabilecek kapsamlı bir proje yapacağız.
Proje, 8 haneli bir kronometre. Çözünürlüğü şimdilik 0.1 saniye olarak belirliyoruz. Sonradan bunu artırmak için de çaba göstereceğiz ve ne tür zorluklar çıkacağını göreceğiz. Bir tane başlat butonu olacak, bir tane durdur butonu, bir tane de sıfırlama butonu. Bu projenin yapımı, hem temel dijital elektronik bilgisi gerektiriyor, hem de programlama ile ilgili bazı temel tekniklerin kullanımını gerektiriyor:
- Arduino'da, 8 tane 7 segment display sürecek kadar port yoktur. Her bir haneye BCD dekoder koymuş olsak bile, bunun için de gene yeterince port yok. O halde, hanelere tek tek, çok hızlı bir şekilde tarayarak rakamları yazdırmamız gerekecek. Eğer yeterince fazla sayıda tarama yapabilirsek, kullanıcı herhangi bir titreme görmeden sayaçtaki rakamı rahatlıkla okuyabilecek.
- Kronometreyi başlatmak/durdurmak için Arduino üzerinde mekanik butonlar kullanacağız. Ama bu butonlara basıldığında oluşan parazitik etkiler nedeniyle, buton birden fazla basılmış gibi bir etki ortaya çıkacak. Bunu uygun bir yazılımla engellememiz gerekecek.
- Kronometrenin doğru sayması için, bizim yazılımın hassas olarak 0.1 saniyede bir kontrolü ele alması lazım ve sayaç değerini güncellemesi lazım. Eğer burada bir değişkenlik varsa, bizim kronometre, gerçek bir kronometreye göre ya yavaş kalacaktır, yada fazla hızlı olacak.
Muhtemelen internette araştırırsanız, Arduino için hazır kronometre programları da bulunabilir. Ama burada bizim için önemli olan, başkasının yazdığı hazır kodu alıp körü körüne kullanmak değil. O yazan kişi, yukarıda bahsettiğimiz sorunların hepsine bir çözüm getirmiş ve kodu yazmış, işi öğrenmiş. Bizim de aynı sorunlarla boğuşup, çözümü kendimiz bulmamız lazım. Ancak bu şekilde birşeyler öğrenmiş oluruz.
Diyeceksiniz ki "tekerleği yeniden icat etmeye ne gerek var? Adam yapmış, al kullan!". İşte, bizi millet olarak onlarca yıl böyle uyuttular. Bizler millet olarak ne zaman özgün birşeyler yapmaya kalksak, hemen devreye girdiler: "ya ne gerek var bununla uğraşıyorsunuz. Biz size çok ucuza verelim!". Ve böylelikle de çok az şeyi derinlemesine öğrenebildik, hep onlara muhtaç kaldık. Tekerleği yeniden icat edeceğiz kardeşim! O tekerleğin en ince detayına kadar nasıl çalıştığını öğrenmenin tek yolu bu. Çünkü gün gelecek, o tekerlek bize en çok lazım olduğu anda, adamlar bize satmayacaklar. Biz de o zaman tekerleği çaresiz yeniden icat etmek zorunda kalacağız, ama iş işten geçmiş olacak.
Projenin en önemli tarafı, belirlenmiş zaman aralıklarında, aşağıdaki iki işi yapmak:
1) kronometrenin zaman sayaçlarını güncellemek. kronometre çözünürlüğünü daha önce 0.1 saniye olarak belirlemiştik. Yani saniyede 10 defa, kronometrenin zaman sayacını artırmamız lazım.
2) 7 segment displayleri, titreme olmayacak kadar hızlı bir şekilde güncellemek. Bunun için displayleri en az saniyede 50 defa güncellemeyi deneyeceğiz. Eğer titreme oluyorsa, güncelleme frekansını artırmayı deneyeceğiz.
Her iki işi yapmak için arduino'da ayrı ayrı zamanlayıcılar tanımlayabiliriz, ve her bir zamanlayıcı da tanımlanan aralıklarla bizim yazdığımız bir fonksiyonu çağırır. Bu tip fonksiyonlara "kesme" deniyor, çünkü bunlar programın normal akışını "kesip" belli bir işi yapıyor, sonra da program, kesildiği yerden devam ediyor.
Bir kesme, kronometre sayacını artırır, diğer kesme de 7 segment display'leri günceller. Veya, saniyede 50 defa çalışan bir tek kesme tanımlarız ve bu kesme her çağırıldığında 7 segmentleri günceller, 5 çağırmada bir de kronometre sayacını günceller. Sistemin basit olması açısından, tek kesme kullanmak daha iyidir, çünkü bağımsız çalışan birden fazla kesme olması durumunda, bu kesmelerin birbirine göre öncelikleri farklı olacaktır ve yüksek öncelikli bir kesme, düşük öncelikli bir kesmeyi de "kesecektir". Ayrıca program karmaşıklaşacak, problem ayıklamak daha zor olacak, ve her kesmenin de bir işlem zamanı maliyeti olduğundan ekstrem durumlarda zamanlama sorunları yaşayabileceğiz.
Öncelikle konsepti kanıtlamak açısından aşağıdaki basit programı yazalım. Bu program, saniyede 100 kere çağırılan bir kesme fonksiyonu tanımlıyor. Tanımlanan kesme fonksiyonu da, arduino'nun 12'nci pininde bir pulse üretiyor:
/* tanimladigimiz kesme fonksiyonunun saniyede kac defa
cagirilacagini belirleyen degisken */
int isr_rate = 100;
/* 12 numarali pini cikis olarak tanimliyoruz */
/* Atmel 328 in birinci timer'ini kesme kaynagi
olarak yapilandiriyoruz */
OCR1A = 16000000 / (isr_rate * 64) - 1;
TCCR1B = (1 << WGM12) | (1 << CS11) | (1 << CS10);
/* daha once cikis olarak tanimladigimiz 12 numarali pin'de,
osiloskop'ta kesmenin olusumunu gozlemlemek icin bir pulse uretiyoruz */
/* ana programda hicbir sey yapmiyoruz, sadece tanimladigimiz
kesme fonksiyonu belirli araliklarla cagiriliyor */
Burada Atmel 328'in timer'ini nasıl yapılandırdım? Bunun için bu işlemcinin datasheet'ini inceledim. Burada kullanılan timer, 16 bitlik bir sayaca sahip. Bu sayacın hangi frekanstaki bir clock ile çalıştıracağımızı belirliyoruz. Sonra sayaç hangi değere ulaştığında kesme üretecek onu belirliyoruz. Bunları yaptıktan sonra sayacı aktif hale getiriyoruz.
Konu ile ilgili epey detay var, o yüzden datasheet'i incelemenizi tavsiye ederim:
Ama netice itibarı ile, timer'i yapılandırdıktan sonra, bizim tanımladığımız kesme fonksiyonu, belirlediğimiz sıklıkta (saniyede 100 defa) çağırılmaya başlıyor. Sonraki aşama, saniyede 100 defa çağırılan bu kesme fonksiyonunda, hem 7 segment displayleri güncellemek, hem de 10 kesmede bir, kronometre sayacını artırmak.
Kesme tarafından üretilen pulse'ları osiloskop ile doğruluyoruz