Bir Arduino belirli bir (yani 56 kHz) taşıyıcı frekansını nasıl verebilir?


9

İki nokta arasında kablosuz olarak veri göndermek için bir boş alan optik projesi üzerinde çalışıyorum. Bunu yapmak için, verici için 56 kHz taşıyıcı frekansı ve alıcı için 56 kHz IR dedektör modülü ile ikinci bir Arduino'yu atan bir Arduino Uno'ya bağlı bir IR LED kullanıyorum.

Taşıyıcı frekansı oluşturmak için pin yüksek ve pin düşük komutları arasında delayMicroseconds () kullanmayı denedim. Bu tür çalışır, ancak frekans her zaman aynı değildir ve sinyali atmak için herhangi bir ek gecikme (yani işlevi çağırmak ve azaltma için gereken süre) değiştirebilir.

ATmega328 için veri sayfasını okumak, çipin zamanlayıcılarını kullanarak daha doğru bir darbe ayarlamanın bir yolu olduğu anlaşılıyor. Bu mümkün mü ve eğer öyleyse, zamanlayıcıları kullanarak 56 kHz'lik bir darbeyi nasıl oluşturabilirsiniz?


56KHz frekansınız için ihtiyacınız olan hassasiyet nedir? Yani projenizde hangi frekans aralığı kabul edilebilir? Soruyorum çünkü sadece Arduino zamanlayıcılarını kullanırken hassasiyetin sınırlamaları var.
jfpoilpret

55.5khz ila 56.5khz, dedektörde yüksek seviyede yanıt verebilirlik sağlamak için ideal olacaktır.
jlbnjmn

Yanıtlar:


10

Arduino zamanlayıcı ile 56 kHz'lik bir sinyal üretmek gerçekten mümkündür .

Bir zamanlayıcı, MCU'da, MCU saat frekansı (Arduino Uno'da 16 MHz) frekansında artırılan bir değeri (0'dan başlayarak) tutan özel bir kayıt olarak görülebilir; olasılık, çağrılan bir faktöre bölünür ölçeklendiren . Bu değer belirttiğiniz Eşleşmeyi Karşılaştırma adı verilen bir sınıra ulaştığında iki şey olur:

  • Zamanlayıcı kayıt değeri 0'a sıfırlanır.
  • Bir ISR (interrupt service rutine) geri çağırma işlevi çağrılır (bunu kendi kodunuzu gösterecek şekilde tanımlayabilirsiniz).

Fikir, ISR'yi her çağrıldığında mantıksal bir pimin çıkışını değiştirmek için kullanmaktır ( HIGH, sonra LOW, sonra HIGH...).

Şimdi, 56 kHz kare dalga oluşturmak için ISR'nizin 56000 * 2saniyede kez çağrılması * 2gerekir ( çünkü çıktı değerini dönem başına iki kez değiştirmeniz gerekir).

Aşağıdaki listeden zamanlayıcı için istediğiniz ön ölçekleyici değerini seçebilirsiniz:

  • 1 (saat frekansı bölünmez, dolayısıyla 16 MHz)
  • 8 (saat frekansı 8'e bölünür, dolayısıyla 2 MHz)
  • 64
  • 256
  • 1024

Arduino Uno'da iki boyutta zamanlayıcı / sayaç vardır (bunlar aslında zamanlayıcı / sayaç olarak adlandırılır ): 8 bit ve 16 bit.

Arduino Uno'da (ATmega328P), genel olarak üç zamanlayıcınız var, ancak bazıları Arduino çekirdek kütüphanesi veya eskizlerinizde kullanılan diğer kütüphaneler tarafından kullanılabilir (bunu kendiniz kontrol etmeniz gerekir):

  • timer0 (8 bit)
  • zamanlayıcı1 (16 bit)
  • timer2 (8-bit): daha fazla ön ölçekleme seçeneği var (1, 8, 32, 64, 128, 256 ve 1024)

Şimdi 16 MHz'den 56 kHz dalga üretmeniz gerekiyor, bu nedenle ön ölçekleme yapmadan şunları saymanız gerekir:

16000000 / (56000 * 2) - 1 = 141.857( - 1çünkü bir zamanlayıcı 0'dan bu değere kadar sayar ve yalnızca ulaşıldıktan sonra sıfırlanır )

Bu hesaplamadan iki gözlem çizebiliriz:

  1. 141.857 bir tamsayı değildir ve dolayısıyla tam olarak 56 kHz'lik bir dalga üretemezsiniz.
  2. Ön ölçekleme olmadan, 285 8 bit işaretsiz tam sayı olarak gösterilemediğinden 16 bit zamanlayıcıya ihtiyacınız vardır.

Artık iki seçeneğiniz var:

  1. 16 bitlik bir zamanlayıcı ( timer1 ) kullanın, prescaler = 1 kullanın 142ve Karşılaştırma Karşılaştırması olarak seçin ; size aşağıdaki frekansı verecektir:16000000 / (2 * (142 + 1)) = 55944 Hz
  2. 8 bitlik bir zamanlayıcı ( timer0 ) kullanın, prescaler = 8 kullanın 17ve Karşılaştırma Karşılaştırması olarak seçin ; bu, aşağıdaki frekansla daha az kesinlik sağlar: 16000000 / (8 * 2 * (17 + 1)) = 55555 Hzki bu hala gerekli aralıktadır.

Şimdi, bunun için taslağınızı nasıl yazacağınıza ilişkin olarak , çok eksiksiz ve okunması çok ilginç olan bu talimatı incelemenizi tavsiye ederim .

Tabii ki, ATmega328P tam veri sayfası , ne yaptığınızı en ufak ayrıntılarla anlamak istiyorsanız da önemlidir.

Bazı önemli notlar:

  • ISR, devre dışı bırakılmış kesintilerle yürütülür ve bu nedenle olabildiğince kısa olmalıdır. Özellikle, Arduino kütüphanesinden bir ISR'den çağrılmayacak birkaç işlev vardır.
  • Arduino Uno saati çok doğru değil (kuvars yerine seramik rezonatör kullanıyor, bu çok daha doğru olurdu), bu da çıkış frekansının daha fazla değişeceği anlamına geliyor.

2
Ayrıca belirtilen sınıra ulaşıldığında donanım bir raptiye değiştirebilir. Dolayısıyla ISR'leri kullanmaya gerek yoktur. Bir ISR ile her zaman titreme olacaktır çünkü bir talimat başladığında kesilemez. Ancak donanım her zaman pimi istenen hızda değiştirir.
Nick Gammon

Arduino Uno'nun seramik rezonatör kullanması şaşırtıcıdır, ancak bunun kaynağı Arduino UNO SSS'dir ( "Uno işlemci saati için bir rezonatör veya kristal kullanıyor mu?" ).
Peter Mortensen

3

tone()Herhangi bir pim üzerinde yüksek frekanslı darbeler üretmek için yararlı buldum . 56 KHz ile çalışabilmelidir. (Düzenle: jfpoilpret tarafından belirtildiği gibi, 16 MHz Arduino'da alabileceğiniz en yakın 555544 KHz'dir)

Zorluk açıkça veri sinyalinizle birleştirilecek. Bunu düşük seviyeli koda başvurmadan yazılımda yapabileceğinizi sanmıyorum. Dijital olduğu için donanımda oldukça kolay olmalı.

Yapmanız gereken tek şey veri sinyalinizi farklı bir pin üzerinde çıkarmak ve daha sonra bir AND geçidi kullanarak taşıyıcı ile birleştirmektir. Birleşik sinyal doğrudan IR vericinize gidebilir.

Kullanışlı bir AND geçidiniz yoksa, bir çift transistör kullanarak kendiniz yapmak oldukça basittir. Sadece "transistör ve kapı" için çevrimiçi arama yapın.


Alıcıların genellikle aktif düşük çıkışları vardır. LED'in üst kısmını 56khz'ye ve altını veri pininize bağlarsanız, veri pimi alçaldığında IR çıkışını alırsınız, bu da alıcının düşük olmasını sağlar. Hayır ve kapı gerekli, sadece bir led ve direnç. Tek sorun, mevcut io pinlerinin kullanabileceği her şeyle sınırlıdır.
EternityForest

2

Jfpoilpret'in kabul edilen cevabı çok iyi yazılmış, mükemmel derecede geçerli ve vakaların% 99'unda tam olarak açıkladığı şeyi yapacağım. Onun çözümleri sizin tanımladığınız parametrelerin içindedir, bu yüzden çok iyi çalışmalıdırlar. Ama " çok iyi " den daha iyi ne olabilir ? Mükemmellik! Sonuçta, soru kesin bir değer üretmekle ilgilidir. Dedi ki yeterince yakın çoğu durumda iyidir (tartışmalı olarak hepsi) ve 1 saniyenin 1 saniye olması gerektiğinde saatler gibi bir şeyle uğraşırken bile, hala kalıtsal parça kusurlarına maruz kalmanız gerekir.

Ne önereceğim her zaman mümkün değildir. Bazı durumlarda, bu mümkündür, ancak bu davadan çok daha fazla güçlük ve çaba ile. Bu duruma göre değişmeye değer mi? Amacım, gelecekteki referanslar için biraz daha iyi durumlarda daha iyi bir alternatif göstermek. Bu, elektronik konusunda geniş deneyime sahip olmayan acemi Arduino kullanıcıları ile yazılmıştır.

Daha ileri insanlar için bu muhtemelen çok ayrıntılı ve aptal görünecektir. Ama inanıyorum ki, aynı insanlar muhtemelen bunu zaten biliyorlar ve bu cevaba ihtiyaç duymuyorlar. Bu aynı zamanda her mikrodenetleyici ve her üretici ve mimari için de geçerlidir. Ancak diğer mikrodenetleyiciler için, doğru kayıtları ve reçete adlarını ve değerlerini bulmak için doğru veri sayfasına başvurmanız gerekir.

Sizin durumunuzda, belirli bir frekansa ve bununla ilgili güzel bir şeye ihtiyacınız var, tam olarak 56 kHz gerçekten çok kolay elde edilebilir (parçaların pratik kusurlarını saymamak). Yani bu da mükemmel bir örnek olay.

Bir sinyal üretmek, jfpoilpret tarafından iyi açıklandığı gibi mikrodenetleyicinin zamanlayıcılarına ve saat kaynağına bağlıdır. Cevabı sadece bir bakış açısıyla ilgilidir ve bu zamanlayıcılarla uğraşır. Ancak saat kaynağıyla da, hatta sinerji ve harika sonuçlar için daha da iyisi ile uğraşabilirsiniz. Ortam parametrelerini değiştirerek, bu durumda sistemi hackleyerek ve saat kaynağını değiştirerek, çok, çok daha kolay ve basit bir şekilde belirli bir sorunla başa çıkabiliriz.

İlk olarak, pin durumunu değiştirdiğinden, ISR'yi sinyal frekansından iki kat daha fazla yürütmeniz gerekir. Bu saniyede 112.000 kez. 56.000 ve 16.000.000, zaten belirtildiği gibi çok iyi bir şekilde toplanmıyor. Sinyal frekansını veya dokunma frekansını değiştirmemiz gerekir. Şimdilik değişmez bir sinyal frekansı ile başa çıkalım ve daha iyi bir saat hızı bulalım.

Sadece sıfır eklediğinizde ve bu tür bir matematik çoğu insan için en basit olduğu için, 56 kHz'den (veya 112 kHz'den daha büyük bir büyüklük sırasına sahip bir saat seçmek en basit yöntem olacaktır, ancak pratik olarak aynıdır). Ne yazık ki bu dünyadaki her şey bir şeyle bir çeşit uzlaşmadır. Her değer işe yaramaz.

İlk örnek çok düşük incelikli jeneratör hızıdır.

56.000 Hz'lik bir saat seçerseniz, her döngüde ISR'yi çağırmanız gerekeceği için başka bir şey yapamazsınız ve başka bir şey yapamazsınız. Tamamen işe yaramaz. 10 kat daha hızlı (560 kHz) hız seçerseniz, 9 (zamanlayıcının maksimum değerine ulaşması için 10 döngü - ISR işlevini çağırmak için bir döngü) işinizi yapmak için mikro denetleyici döngüleri olacaktır ve bu mümkün olmayabilir. Genellikle daha fazla hesaplama gücüne ihtiyacınız vardır.

Öte yandan çok büyük bir değer seçerseniz, 56 MHz olarak mikrodenetleyici bununla çalışamaz. Çok hızlı. Yani, sadece dükkandaki en büyük değeri seçmek de onu kesmeyecek.

Orijinal Arduino Uno R3'ün 16 MHz'de bir stok saati var, bu yüzden çalışması garanti edilen daha yavaş her şey. 56'dan büyük ve 16 MHz'den düşük bir büyüklük sırası olan bir sonraki değer 5,6 MHz'dir. Bu, ISR'yi her 50 döngüde bir araya getirebilecek ve mükemmel 112.000 Hz zamanlayıcı frekansını oluşturacaktır. Ve sinyaliniz tam olarak 56 kHz olacaktır. ISR çağrıları arasında programınızı yürütmek için 49 MCU döngünüz olacak, ancak yine de orijinal saatin hızının 1 / 3'ü kadardır. Baz olarak 112 kullanılabilir ve 11.2 MHz saat kullanılabilir ve bu da stok 16 MHz rezonatörün yaklaşık 2 / 3'ünü verecektir. ISR işlevi her 100 döngüde bir çağrılır ve yine de mükemmel bir 56 kHz sinyal üretir.

Ancak bu değerlerle ilgili iki büyük sorun vardır.

  • İlk sorun büyük ölçüde ihtiyaçlarınıza bağlıdır: Bulması kolay bir kayıt değeri (OCR iirc ) kullanan kesin sinyal frekansını elde etmek için maksimum hesaplama gücünüzün yaklaşık 1 / 3'ünü (11,2 MHz ile) feda edersiniz . Onunla iyi olabilirsin ya da olmayabilirsin.

  • İkinci sorun zor bir gösterici : Değerleri bulmak çok kolay, ancak çoğu zaman üretilen bir saat kaynağı olarak mevcut değiller. Bu, Farnell'in hem 5.6 MHz hem de 11.2 MHz'den yoksun rezonatör web sayfasıdır .

Bunu atlatmak için mevcut rezonatör değerlerine bakabilir ve tam olarak istenen değerleri üretmek için kullanılabilecek başka bir şey bulabiliriz. 56'yı 4'e bölersek 14 elde ederiz ve neyse ki 14 MHz rezonatör vardır. Bu bize çok daha yüksek hız ve daha fazla güç sağlar ve aynı derecede kolay kayıt değerini sağlar. ISR'yi saniyede 112.000 kez çağırmak için OCR kaydına ondalık 124 veya onaltılık 0x7C değerini koymamız gerekir, bu nedenle ISR'yi çağırmak için 124 döngü + 1 saymakla, istenen mükemmel değere ulaşırız.

NB

  1. ISR - interrupt service rutine (bu sadece oluşturulan interrupt'larda yürütülen koddur)
  2. Programınızın ne kadar büyük olabileceği bellek boyutuna bağlıdır! Saat hızı ile ilgisi yoktur ve ISR'yi ne sıklıkta çağırdığınızla hiçbir ilgisi yoktur.
  3. Mikrodenetleyici program komutuyla başladığında bir sayaç artırılır. Bir kesinti oluşursa, ISR çağrılır ve bu değer özel bir kayıt defterinde saklanır. ISR kodu tamamlandığında, program sayacının değeri bu özel kayıttan geri yüklenir ve program, hiç olmadığı gibi kesildiği yerden devam eder.

    Son derece aptalca bir örnek vereceğim. Eğer safkansanız, sizi uyarıyorum: Burun ve göz kanaması olabilir.

    Bir yerden bir yere yürümek zorunda olduğunuzu düşünün. Adım adım yol talimatları ana programınız ve komutlarıdır. Ne kadar hızlı yürüdüğünüz veya koştuğunuz, "saat hızınıza" bağlıdır, ancak rota talimatlarına bağlı değildir (30 adım ileri, 1 tur 90 derece sola, 10 adım ileri, 45 derece sağa vb.) Her zaman aynıdır . Şimdi küçük bir çocuk veya açgözlü, yozlaşmış bir yerel politikacının ayakkabılarınızı çözdüğünü düşünün. Bu bir kesinti oluşturan olaydır. Sonra son adımından sonra durursun, diz çöküp ayakkabını tekrar bağla. Bu ISR programınız.

    Sonra durduğunuz yerden devam edersiniz; en baştan başlamazsın. Dünyada ve her zaman dikkatsizce yürüdüğünüzde, ayakkabılarınızı her iki adımda bağlamanız gerekse bile umursamazsınız. Bununla birlikte, Olimpiyatlarda 100 metre koşmak (veya aç bir et yırtıcı hayvanından koşmak) gibi zaman kısıtlamaları ile yaparsanız, ayakkabılarınızı durdurmak ve bağlamak korkunç sonuçlar doğurabilir. Aynı şey mikrodenetleyiciler için de geçerlidir. Sadece bir satır kod çalıştırsanız bile, yavaş da olsa programınız devam edecektir. Hızı hiç umursamıyorsanız, sorun olmayacak. Zamanlayıcıya bağlı diğer eylemleri kullanmak gibi zamanla ilgili bir şeyler yapmanız gerekiyorsa, parazitlenme istenmeyen ve sorunlu olabilir.

  4. Az ama öz! Daha hızlı bir saat her zaman daha iyi değildir. Daha yavaş saat kullanan cihazlar önemli ölçüde daha az güç kullanır. Bu, pille çalışan bir cihazda çok önemli bir nokta olabilir.

  5. Gerekli döngüler bu formüllerden türetilir:
    (saat hızı / (ölçekleyici değeri * gerekli ISR ​​arama frekansı)) - 1


TLDR: Seramik 16 MHz osilatörü sökün ve tamsayı bölümü ile tam olarak 56 kHz'e izin veren bir başkasıyla değiştirin (örneğin 14 MHz ve 250'ye bölün).
Peter Mortensen

0

Taşıyıcı pin modunu çıkış ve giriş arasında değiştirerek taşıyıcıyı açıp kapatabilirsiniz. Bunu bir ısı pompasını 37KHz kızılötesi (uzaktan kumanda) portundan kontrol etmek için kullandım.


0

Taşıyıcıyı oluşturmak için bir ISR kullanmaya gerek yoktur. Gerekli taşıyıcı frekansında% 50 PWM çıkışı üretmek için bir zamanlayıcı ayarlayın. ISR, taşıyıcının - tipik olarak 0,5 veya 1 ms aralıklarla - çok daha rahat bir şekilde modüle edilmesinden sorumludur. Deneyimlerime göre, çoğu IR alıcısı tarafından taşıyıcı frekansındaki% 5'lik bir hata tolere edilmektedir. Freetronics EtherMega 2560 kullandım (ki bu da bol miktarda zamanlayıcıya sahip) ama eminim ki diğer CPU'lar da bunu yapacak.


O zaman taşıyıcının modülasyonu tam olarak nasıl uygulanır? Giriş (taşıyıcı kapalı) ile çıkış (taşıyıcı açık) arasındaki zamanlayıcı çıkışı yakalama pimi için mod değiştiriliyor mu?
Peter Mortensen
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.