Arduinolar arasında iletişim için seçenekler

Aralarında komutlar ve veri göndermek için ~ 5-10 Arduino arasında iletişim kurmaya çalışıyorum. "Arduino" ile Arduino programlama çerçevesi kullanılarak programlanan ATmega328 kastediyorum.

Cihazların her biri aynı PCB'de olacaktır.

I2C'nin ve SPI'nın bir dereceye kadar iletişim kurabildiğini biliyorum, ancak gerçekten çok sayıda mikro denetleyiciyi birbirine bağlamak yerine bir mikro denetleyiciye bağlı olan çevre birimi aygıtları için olduklarını ve genellikle bir seferde yalnızca birkaç bayt veri gönderdiklerini biliyorum . Öte yandan, LCD ekranların onları kullanarak sürülebileceğini biliyorum ve bu durumlarda çok fazla verinin aktarıldığını düşünüyorum.

Mikro kontrolörler arasında iletişim kurmak için I2C (çoklu-master, çoklu-slave, tek-uçlu, seri bilgisayar bus) gibi bir şey var mı? Her bir cihazın, istenmediği cihazlara veri göndermesine izin vermek. Örneğin, A cihazında bir düğmeye basıldığında, B düğmesine, bir anahtara basıldığında her zaman B cihazı sorulmadan söylenir. ve tersi.

Edit: I found some libraries that may do what I want with RS-485. Is this the only viable option for ~1k bps transmission between 5-10 devices? I would imagine TCP/IP over Ethernet would work as well, but that seems like too much. Are there any I2C libraries that allow sending that amount of data between only master devices?

5
RS-485 mi demek istiyorsun?
katma yazar user7461, kaynak
@Paul Kaygıların ayrılmasını istiyorum. Daha fazla kesinti ve I/O ile daha büyük bir kontrol cihazı alabileceğimi biliyorum, ancak cihaz seviyesinde işleri basit tutmayı tercih ederim. Ayrıca, her bir alt sistem bağımsız olarak tasarlanıp hatta inşa edilebileceği ve daha sonra birlikte bağlanabileceği için başkalarıyla işbirliği yaparken de yardımcı olur. Ayrıca ünite testi ve değiştirilmesi/yükseltilmesi daha kolay olabilir.
katma yazar user7461, kaynak
@ frarugi87 Bir otobüs topolojisinin en iyi şekilde çalışacağını düşünüyorum, başka bir cihazla iletişim kurarak ve bağlantıyı başlatan herhangi bir cihazla. Yani köle yok.
katma yazar user7461, kaynak
RS-485 gibi elektronik bir "standart" olan ancak 5V TTL gibi bir fiziksel katmana (kablolama veya kart) ihtiyacınız vardır. O zaman ne tür bir otobüs tahkim (yuvarlak-robin, master-slave ya da yayın mesajları) seçmeniz ve muhtemelen bazı adresleme ya da hata kontrollerini uygulamak zorundasınız.
katma yazar dotnetengineer, kaynak
Bir breadboard üzerinde, RS485 kullanmaz, çünkü alıcı-vericilere ihtiyaç duyar. Bir mantık 1 için bir mantık 1 ve 0v için sadece 5v. Ama bu noktadan sonra, olanaklar sonsuzdur. Ayrıca hız gereksinimlerine vb.
katma yazar dotnetengineer, kaynak
Neden böyle bir şey yaratmak istediğini söylemedin. IO pinlerine kısa iseniz, IO-genişleticiler kullanabilirsiniz. Daha iyi çözümler olabilir. Eğer bir hobi/konsept kanıtı ise, bunun gibi diğer projeleri kontrol edebilir ve "geliştirmeyi/ayarlamayı" deneyebilirsiniz.
katma yazar dotnetengineer, kaynak
Seri bağlantıya baktın mı?
katma yazar user67244, kaynak
Burada çok benzer bir soru var: Ana ışıkları/anahtarları kontrol etmek için bir Rpi ile birden fazla Arduino'yu birbirine nasıl bağlayacağınız - Rpi bölümünü göz ardı ederek (bu soruyla gerçekten alakalı değildi) bunu istediğiniz şeyle hemen hemen aynı şekilde sayıyorum. yap. Orada bir "haddeleme ustası" sistemi yapmak konusunda uzun bir cevap verdim. Lütfen diğer soru/cevabı okuyun ve ne düşündüğünüzü görün.
katma yazar Nick Gammon, kaynak
Başka bir mikro n olmalısın, ama işe yarıyor. Son çözüm dediğin şey, yani aynı otobüste konuşan herkes, ama çarpışma tespitine ihtiyacınız olacak. Bu durumda size CAN veriyolunu öneririm, çünkü zaten çarpışmaları yönetiyor (ancak bunu kodunuzda uygulamanız gerekecek).
katma yazar Tom Collins, kaynak
Peki, otobüs topolojisi için tamam, ama bir otobüs ustası ve diğer kölelerin hepsini yapmanızı öneririm. Aksi takdirde çarpışmalarınız olur ve çarpışmaların tespit edilmesi/önlenmesi “zor” bir görevdir. Sadece bir ustan varsa, bundan kaçınılabilirsin, çünkü sadece konuşmak için izin verebilir. Bu ustaları RX her bir yardımcı aygıta RX master TX bağlayan bir tel, ve (3-durumlu tamponun ile belki) köle TX bağlayan bir tel ile, bir seri (UART) otobüs yapabilir. Aksi takdirde papatya zinciri yapabilirsiniz: TX1 RX2'ye, TX2'den RX3'e ... RX1'e TXn. Bu konuştuğu için biraz daha az verimli
katma yazar Tom Collins, kaynak
Belki de sadece onu bulamadım, ama temel soruyu okumadım, "ihtiyacınız olan topoloji nedir"? Herkese konuşan herkese ihtiyacın var mı? Merkezi erişim (yani biriyle konuşan herkes)? Karma bir çözüm mü?
katma yazar Tom Collins, kaynak

4 cevap

Hayalinizi gerçekleştirmenize yardımcı olabilecek çeşitli kavramlar var. Bu cevabın içinde, tam olarak ne istediğinizi nasıl uygulayacağınızı söyleyemem, ama size bunu gerçekleştirmenize yardımcı olacak kavramları gösterebilirim.

İlk önce bus master kavramı var. Bu, iletişimi örnekleyen cihaz değil - bunun yerine, veriyolunun sahibi ve denetimleri olan cihazdır.

Veri yolu yöneticisi olmayan bir cihaz veri yolu üzerinde iletişim kurmak istediğinde, ilk önce veriyolu yöneticisinden izin ister. Eski Z80 (iyi, "eski" diyorum, ama bugün hala birçok formda kullanılıyorlar) bu kavramı diğer çiplerin veriyi kullanmasına ve otobüsleri adreslemesine izin vermek için kullandı. BUSRQ ve BUSACK olmak üzere iki sinyalden oluşur. Bir aygıt, BUSRQ veya BUSACK öğelerinin herhangi birinin etkin olup olmadığına bakar ve ikisi de BUSRQ'yi etkinleştirmez. Eğer veri yolu yöneticisi, veriyolunu diğer cihaza bırakmaya istekliyse (o anda kullanmıyorsa) BUSACK'i etkinleştirir ve diğer cihaz daha sonra veriyolunu kullanabileceğini bilir. BUSRQ ve BUSACK her ikisi de serbest bırakılıncaya kadar başka hiçbir şey kullanamaz. Güzel ve sade ve zarif.

Ama mükemmel değil. İki cihaz da aynı anda otobüse sormaya karar verirse, bir çarpışma elde edersiniz. Bu, bu gibi paylaşılan veri yolu sistemleri arasında ortak bir sorundur ve düzgün bir şekilde nasıl işleneceğini bilmediğiniz sürece anlatılmamış sorunlara neden olur.

Dinle-sen-konuş kavramını girin. Bu, otobüse gönderen cihazın, ayrı bir alıcı aracılığıyla otobüse gönderilenleri dinlemesini de içerir. Daha sonra otobüse ne yolladığının otobüste gerçekten bittiği şeyi bilir. Örneğin, iki cihaz aynı anda konuşursa ve biri 10011001 'i gönderirse ve diğeri 11001100 ' i gönderirse, otobüste görünen sonuç aslında başka bir şey gibi olabilir. Veriyolu sinyallerinin nasıl oluşturulduğuna bağlı olarak 11011101 veya belki 10001000 . Yani, ne gönderdiğini biliyorsan bozuldu, şimdi bunun hakkında bir şeyler yapabilirsin.

Sonraki konsept: yedekleme . Her iki gönderenin de kısa bir süre beklemesi ve tekrar göndermesi. Her ikisi de farklı bir süreliğine geciktikleri sürece, ilk denemeyi yapacak ve iletişim kurabilecektir. Fakat ikisinin de farklı zamanlarda ertelenmesini nasıl garanti edersiniz? Cevabın basit olduğunu düşünebilirsiniz: rand() veya random() gibi rastgele bir sayı kullanın. Ama bu aynı zamanda sorunlu:

Another concept: The pseudo random number generator

Arduino rastgele sayılar üretmiyor. Sadece bize, rastgele görün olan bir dizi dizi oluşturmak için karmaşık bir matematiksel formül kullanır. Öyle değiller. Seriye rastgele 10 seri basmak ve birden çok kez basmak için küçük bir program yazin (reset dümesine basin). Aynı "rastgele" sayıları her seferinde aynı sırayla bulacaksınız. Başka bir Arduino üzerinde deneyin ve aynı sayıları tekrar elde edersiniz. Her zaman aynı.

Peki ne yapmalı? Cevap tohumlama rasgele sayı üreteci olarak adlandırılır. rand() tarafından üretilen bir sonraki sayı, son olarak oluşturulan sayıya bağlıdır. Yani ilk numarasını değiştirin ve sayının kalan kısmı değişecektir. Bununla birlikte, 22 yakalama durumunuz var. Rastgele sayı üretecini, rastgele sayı üretecini tohumlamak için rastgele bir sayı üretebilmek için rasgele sayı üretecini tohumlamak için rastgele bir sayıya ihtiyacınız var ... ad infinitum. Nereye gittiğini görüyor musun? Rastgele bir kaynaktan tohumlanana kadar rand() rastgele olmadığından rand() 'dan tohumlayamazsınız. Bu yüzden rastgele bir kaynak bulmanız gerekiyor.

Ve bu kolay bir iş değil. Bilindiği gibi entropi için en iyi kaynak beyaz gürültü . Bu, bir dizi farklı devrelerle, bir diyot bağlantısının parçalanmasından, dirençteki termal dalgalanmaların çok yüksek kazançlı yükseltilmesine kadar bir çok yolla üretilebilir.

Tüm bunlar gerçekten istediğiniz şey için oldukça karmaşıktır, ancak daha az rastlantısal, daha basit bir yöntem vardır - bir şeye bağlı olmayan bir analog giriş okuyun. Uygun bir entropy jeneratörü kadar geniş bir aralığa sahip olmayacaktır, ancak her bir cihazın farklı bir tohum elde etme şansı vermek için yeterli rastgelelik sağlamalıdır.

Bir başka yararlı konsept, kesintidir.

Bu, tüm çarpışmalar ile çok-üslu bir otobüsün karmaşıklığını istemediğiniz bir durumda iyidir. Bir otobüste tüm işi yapan tek bir usta var ve bir köle cihazı söylemek için önemli bir şey olduğunda efendi bir kesinti ile dürtüyor. Efendi sonra "Evet? Ne istiyorsun?" Kölenin cevapladığı "Birisi düğüme bastı".

Bu şekilde, master, düğmeye basılmış olup olmadığını görmek için köleyi sürekli olarak yoklamamaktadır. Genellikle SPI gibi veri yolu düzenlemelerinde kullanılır ve IO genişletici yongaları gibi çok sayıda yonga vardır, bunlar giriş pinlerinden birinin durumu değiştiğinde bir kesinti yapabilir.

Ama eğer 20 cihazınız varsa, 20 interrupt pininiz var demektir? Şart değil. Yeni konsept: kablolu VEYA .

Aynı kesme pinini kullanarak birden fazla farklı köle elde etmek mümkün. Pim normalde bir dirençle YÜKSEK tutulur (dahili bir pullup direnç olabilir) ve her bir köle, bu pime bağlı bir açık drenaj çıkışına sahiptir. Açık bir tahliye çıkışı, "kapalı" olduğunda, herhangi bir şeye bağlı değildir - pim giriş modunda olduğu gibi (aslında giriş ve çıkış modu arasında geçiş yaparak açık tahliye olmayan talaşlar üzerinde taklit edilebilir). Çıkış "açık" olduğunda, bir düğme gibi, IO pinini aşağı çekerek, pimi toprağa bağlar.

O zaman, kimin dikkat etmesi gerektiğini görmek için bu kesintiye eklendiğini bildiği kölelere doğru ilerlemek için ustaya kalıyor. Tabii ki, her biri üzerinde farklı köle gruplarına sahip bir dizi farklı kesme pimi uygulayabilirsiniz - belki de tek bir cihazla yüksek öncelikli ve örneğin her birinde birden fazla cihazla daha düşük öncelikli olanlar.

Aynı fiziksel kabloları paylaşan birden fazla cihazın kullanımına izin vermek için aynı kablolu VEYA ve açık süzme kavramı kullanılabilir. Bu tam olarak I2C'nin nasıl çalıştığını gösterir - iki veri yolu hattı dirençler tarafından çekilir ve üzerindeki aygıtlar farklı mantık seviyelerini oluşturmak için arkaya doğru serbest bırakmak için hattı serbest bırakmak için açık tahliye çıkışları kullanır. İki cihaz birlikte alçalırsa, sadece düşük olur. Açık tahliye metodu olmadan, 1 çıkışı veren bir cihazınız varsa ve başka bir 0 çıktığında, temelde ikisinin arasında kısa bir devre alırsınız ve zarar veren talaşlara son verirsiniz.

Ve daha sonra, eşzamanlı ve eşzamansız iletişim kavramına sahipsiniz, fakat bu tamamen farklı bir su ısıtıcısıdır. Bununla birlikte, saatin üretildiği bir master'a sahip olan SPI ve I2C gibi bir saatli protokollerin senkronize olduğunu söyleyin. UART ve RS-232, RS-485, vb. Gibi protokoller eşzamansızdır - her iki uçta da verinin ne kadar hızlı gönderileceğini (baud oranı) kabul ederler, böylece sinyalleri geldikçe nasıl yorumlayacaklarını bilirler.

2
katma
@EdgarBonet tel kütüphanesi çoklu-ustayı destekliyor mu? Bu kadar kolay mı? michael.bouvy.net/blog/en/2013/05/25/…
katma yazar user7461, kaynak
Sadece I2C'nin teorik olarak çoklu-master yeteneğine sahip olduğunu ve rasgele sayılara ihtiyaç duymayan bir tahkim planına sahip olduğunu eklemek istiyorum. Ancak, Atmel'in uygulamasında bir sorun var gibi görünüyor. Bakınız: örneğin, TWI modülü çoklu ana iletişimde buggy görünüyor/a> ve Atmel AVR Mikrodenetleyicilerle Çoklu Master Problemi . Tek usta + kesmeler bana en kolay çözüm gibi geliyor.
katma yazar Sprogz, kaynak
@EdgarBonet Bir çok otobüs tahkim sistemi uygulandığında tüm protokoller çok-usta yapılabilir. Bazıları buna diğerlerine göre daha uygundur ve I2C gibi bazılarının bunu yapmak için resmi bir yolu vardır, bazıları da diğerlerinden daha iyi çalışır. En güvenilir yol, elbette, çok usta bir sisteme ihtiyaç duymamaktır :)
katma yazar Majenko, kaynak

PJON - https://github.com/gioblu/PJON adresine bakın. Tek telli bir alternatif.

1
katma
Lütfen alternatiflerin neden daha iyi olduğuna dair bir bilgi verin. Teşekkürler!
katma yazar hintbw, kaynak
PJON sadece Arduino değil, çoklu platformlar için hazır hale getirilmiştir. I2C/tek telden daha basittir. Gürültüyü daha iyi idare eder. Çoklu ana desteği var. Vikiyi bağlantıdan oku.
katma yazar Peter Green, kaynak
Lütfen cevabınızı, muhtemelen bir kullanım şekli ya da artıları ve eksileri olan bir örnek olarak açıklayabilirsiniz.
katma yazar RSM, kaynak

@ Majenko'nun mükemmel cevabına ek olarak, ne iletişim kurduğunuzu düşünmelisiniz.

Tek bir bit iletişim kurmak istediğiniz gibi geliyor - belki de bireysel iğnelerle uzaklaşabilirsiniz? Bir master'ınız varsa ve 13'e kadar köle varsa, her bir slave üzerinde bir dirençli (bir direnç aracılığıyla) master üzerinde bir pini olabilir. Eğer köle A, sinyalin sinyalini vermek istediyse, pimi yükseltirdi; Sonra master, her bir pimi sırayla sorgulayabildi, kim ne olduğunu söyledi.

0
katma
Özür dilerim ki, bu sonuncusu, aygıtların, sorgulama yerine verileri birbirine "itmesi" nasıl mümkün olabileceğinin bir örneğiydi. Aslında, daha fazla veri göndermek istiyorum. ~ 100 bayt saniyede 10 kez.
katma yazar user7461, kaynak

Başka bir seçenek SPI.

SPI, bir halkada herhangi bir sayıda cihazla kullanılabilir. Bana şu şekilde açıklandı: herhangi bir katılımcı, saat aralığını 8 kez kendi tamponunda, bir sonraki aygıtın arabelleğine, bir halka içindeki hareket ettirmek için; Cihaz önceki cihazdan bir bayt alır. Birisi saati 8 kez değiştirirse, yeni baytın hazır olduğunu bildirirsiniz (bu donanımda yapılır).

Bunun için bir protokol hakkında dikkatli düşünmeniz gerekir - bir "adres", "uzunluk", "komut" ve daha sonra herhangi bir sayıda parametre. Gönderen "adres" baytını gönderir, arabellekte "uzunluk" baytını ayarlar ve kalanını hazır tutar. Bir sonraki cihaz "adres" baytını aldı ve hedeflenen alıcı olup olmadığını görür. Değilse, bunu not eder ve zinciri yuvarlaklaştırır, uzunluğu not eder ve ELSE'nin bir çok baytını itmesine kadar bekler. Sizinki ise, verilerin geri kalanını okuyun, verileri etrafa itin ve gittiğinizde (geri gelmeyi durdurmak için) boşluk bırakın. Boş bir adres (ör. 0), "bununla bir şey yapma, başkasının onu itmesini bekleyin ve bir sonraki adres olarak bir sonraki baytı okuyun" anlamına gelir. Başlangıçta tüm cihazların 0'a başlaması gerekecek.

Adresleri dinamik olarak ayarlamanız gerekiyorsa, "tüm istasyonlar" özel bir bayt ayarlayarak, "cihaz numaranız X demektir ve bir sonraki aygıtın cihaz numarası X + 1 olduğunu" söyleyen bir komut kullanın. Elbette bunu birisinin başlatması gerekecek.

Aynı zamanda iki cihaz aynı anda göndermeye başlarsa veya bir şey yapması gereken şey aktarmazsa (örneğin bir çip kapatılırsa) çarpışma riskini de üstlenirsiniz. Bundan nasıl tespit edeceğinizi/nasıl kurtaracağınızı düşünmelisiniz.

0
katma