Elektroda.pl
Elektroda.pl
X
PCBway
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Komunikacja pomiędzy 3 arduino (ic2)

01 Paź 2017 20:34 2052 38
  • Poziom 10  
    Witam,
    robię projekt z wykorzytaniem 3 arduino.
    Główny(master) zbiera sygnały + wykonuje większość zadań.
    Dwa pozostałe(oddalone o ok 10 m) będą odpowiadały za wyświetlanie przetworzonych informacji.

    Znalazłem taki wątek:
    Transmisja I2C pomiędzy dwoma modułami Arduino

    Problem polega na tym że nie wiem jak w najprostszy sposób przesyłać dowolną liczbę zmiennych.
    Mam np zmienne rs, k, l, m1, czas1, czas2(unsigned long).
    Załóżmy że tylko jedna z wartości ulega zmianie, np rs.
    Czy da się wysłać w jakiś sposób informację że rs = 3? Bez przesyłania pozostałych zmiennych?
    Biorąc pod uwagę odległość, im mnie wysłanych danych, tym lepiej.

    Nie chciałbym wymyślać koła na nowo. Proszę, podpowiedzcie mi z jakich poleceń skorzystać, jak się za to zabrać?

    Dzięki
  • PCBway
  • Pomocny post
    Moderator Mikrokontrolery Projektowanie
    Zacznij od zmiany założeń - I2C nie nadaje sie do transmisji na 10m. I2C został stworzony do transmisji pomiędzy układami na tej samej PCB. Użyj np. RS232, RS485, itp.
  • Pomocny post
    Poziom 13  
    alienHater napisał:
    Czy da się wysłać w jakiś sposób informację że rs = 3? Bez przesyłania pozostałych zmiennych?

    To już wszystko zależy od Ciebie, jak zbudujesz ramkę danych. Możesz wysłać co tylko chcesz. Jeśli chcesz wysyłać np. wartość jednej zmiennej, musisz jeszcze wysłać informację która to jest zmienna.
    Jeśli

    Dodatkowo, jak wspomniane wyżej. Do komunikacji na taką odległość I2C czy też SPI się nie nadaje.
  • Poziom 10  
    Ok. Z tego co widzę, rs232 wykorzystuje 2 piny Tx i Rx. Będą potrzebne 3 konwertery na 12V. Pytanie, czy moduł główny może łączyć się tymi samymi pinami z dwoma odbiornikami, tak jak ic2(adresowanie). I pozostaje kwestia przesyłania wielu zmiennych(int i unsigned long). Dzięki za wszystkie sugestie.

    Edit: mogę prosić o przykład jak zbudować taką ramkę, na jakiej zasadzie się to robi? większość przykładów na jakie do tej pory trafiłem dotyczyły jednej zmiennej. Są jakieś polecenia do określenia zawartości ramki, czy wszystko trzeba robić ręcznie? Jakiekolwiek szkice, standardowe rozwiązania? Na ich podstawie już sobie poradzę.
  • Pomocny post
    Moderator Mikrokontrolery Projektowanie
    RS232 standardowo łączy dwa urządzenia. Można jeden nadajnik (w masterze) podłączyć do dowolnej liczby odbiorników. Problem będzie z transmisją od odbiornika do nadajnika, gdyż bez specjalnych zabiegów nadajników łączyć nie można. W twoim przypadku wydaje się, że transmisja zwrotna jest niepotrzebna, więc nie będzie problemów. Jeśli byłaby niezbędna to wybrałbym np. RS485. Tu możesz podłączyć więcej urządzeń i transmitować pomiędzy nimi dane. Elektrycznie ten interfejs jest inny, jednak można na nim transmitować dane tak jak po RS232, z wykorzystaniem portu UART mikrokontrolera.
    Przesyłanie zmienych - tak jak kolega powyżej napisał, wszystko zależy od tego jak zbudujesz ramkę danych. Mozna to zrobić np. tak, że najpierw transmitujesz info o tym jaką zmienną prześlesz, a potem jej wartość. Warto też na koniec dodać np. CRC dla kontroli danych.
  • Poziom 10  
    Raczej nie będę potrzebował dwustronnej komunikacji. Jednak urządzenia odbiorcze mają wyświetlać inne dane. W związku z tym rs232 chyba wystarczy?
    W jaki sposób określić tą ramkę?
    Bo jedyne co przychodzi mi do głowy wydaje mi się drogą naokoło.
    Widzę to tak.
    Wykorzystuje
    if (Serial.available() > 0) i Serial.read
    z użyciem if{} sprawdzam czy dane są dla tego odbiornika
    0b00000011 odbiornik1
    0b00000100 odbiornik2
    jeśli to ten odbiornik to pobieram kolejny bajt
    i serią następujących po sobie if{} i == sprawdzam która to jest zmienna.
    Zawsze jeden if będzie == true i w jego pętli będę nadpisywał wartość danej zmiennej, wartością z kolejnego, trzeciego(lub trzeciego i czwartego w przypadku unsigned long) bajtu.
    Oczywiście musiałbym do każdej nazwy zmiennej przypisać jakąś wartość żeby mieć co sprawdzać w w/w pętlach.
    W ten sposób powstaje swoiste drzewko pętli if.
    Na tym to polega czy robię to w zły sposób?

    Edit:
    Wydaje mi się że mógłbym wykorzystać tablicę zawierającą moje zmienne.
  • PCBway
  • Pomocny post
    Moderator Mikrokontrolery Projektowanie
    RS232 będzie ok. Do transmisji wykorzystaj tryb MPCM interfejsu UART, który umożliwa automatyczną adresację urządzeń. To tez załatwi problem z synchronizacją początku transmisji. Co do ifów i przypisania zmiennej to mniej więcej tak to wygląda. Zamiast ifów można dać switch/case, lub użyć numeru zmiennej do indeksacji wskaźników na funkcje przypisujące (kompilator mniej więcej tak zaminieni switch/case, tyle, że zrobi to automatycznie).
  • Poziom 10  
    Dziękuję wszystkim za pomoc. Jutro napiszę odpowiedni kod interpretujący zmienne(co prawda dla ic2 - muszę zaczekać na przesyłkę z konwerterami). Poczytam o trybie MPCM. Mam nadzieję że sobie z tym poradzę. Jak skończę, wrzucę tutaj kod ze szkicem, jak realizować taką transmisję. Może komuś nowemu się przyda :D
  • Pomocny post

    Poziom 28  
    Przy odległościach o jakich piszesz możesz spokojnie testować połączenie bez konwerterów RS232. Po prostu połącz masy płytek, pin TX mastera z pinami RX slave'ów, nie szalej z prędkością transmisji ( 9600 baud na początek ) i na pewno ruszy. Uruchom komunikację między dwoma płytkami a jeśli ruszy i bedziesz zadowolony z rezultatów, dodaj trzecią płytkę. Jeśli masz skrętkę, wykorzystaj ją do wykonania połączenia.

    PS - także I2C można "spokojnie" uruchomić na magistralach o długości nawet 100m :https://www.nxp.com/docs/en/application-note/AN10658.pdf" target="_blank" rel="nofollow" class="postlink ">Link
  • Moderator Mikrokontrolery Projektowanie
    @zster Owszem można, stosując jak w pokazanej nocie nadajniki/odbiorniki różnicowe, tak naprawdę transceivery z I2C na dwie pary różnicowe, lub różne bufory. Równie dobrze można napisać, że RS232 można przesłać na 100 km, stosując transceivery światłowodowe.
    Do testów można wykorzystać RS232-TTL, natomiast w gotowym urządzeniu nie oszczędzałbym paru złotych na transceivery. Podłączanie do MCU 10m przewodów nie jest dobrym pomysłem, nawet jeśli chwilowo to działa.
  • Pomocny post

    Poziom 28  
    W pełni się zgadzam. I2C na duże odległości stosuje się rzadko i w specyficznych sytuacjach. Tutaj najlepiej spisało by się wspomniane RS485 ale jeśli faktycznie komunikacja będzie jednostronna, prosta aplikacja RS232 także się nada. Jednak jeśli autor wątku chce przetestować swoją koncepcję i program już, nie musi czekać na konwertery - może to zrobić i bez nich o czym mógł nie wiedzieć :) Często mylone i utożsamiane są protokoły z warstwami fizycznymi. Konwertery TTL na RS232 można dołożyć później.
  • Poziom 10  
    Dziękuję za żywą dyskusję.
    Faktycznie, nie wiedziałem że mogę przetestować rs232 bez dodatkowej warstwy fizycznej. Natomiast moduł główny łączy się również z expanderem pcf8574(8 bitowy, ic2) odległym o ok 5m. Mam do niego podpięte 7 przycisków. Planuję dorzucić również w panelu mały wyświetlacz znakowy lcd(ic2) Expander zastosowałem aby ograniczyć liczbę wykorzystanych pinów oraz żył w przewodzie. Z zastosowaniem rad dołączonych w linku powinno to śmigać? Nie widzę innych możliwych rozwiązań, mam też już działający kod, do obsługi panelu.
  • Pomocny post

    Poziom 28  
    RS232 to własnie tylko warstwa fizyczna. To, co i w jaki sposób będziesz przesyłać, zależy tylko od Ciebie i można to zrobić rożnymi warstwami fizycznymi. Spokojnie możesz testować bez żadnych konwerterów które dołożysz później.
    I2C na tych odległościach, bez buforów nie pójdzie. Z dobrymi przewodami i niską częstotliwością zegara do 2m jako tako ruszy ale to loteria i raczej eksperyment niż poważna aplikacja. Jeśli jednak chcesz koniecznie I2C - musisz wykorzystać odpowiednie układy buforów/konwerterów ( przykłady opisane w nocie aplikacyjnej od NXP ).
  • Poziom 10  
    Nie upieram się przy ic2 między modułem głównym a panelem(5m) jeżeli nie będzie to stabilne(nawet z wykorzystaniem konwerterów z noty). Jeżeli mogę podpiąć te przyciski + wyświetlacz w inny sposób, chętnie to zrobię. Nie jestem na tyle obeznany w elektronice i zastosuję się do waszych sugestii.

    Edit:
    Użycie w panelu czwartego arduino i transmisja przez rs232 wydaje mi sie nazbyt wygodnym rozwiązaniem. Musi być tańszy i równie skuteczny sposób.

  • Poziom 28  
    Korzystając z układów wspomnianych w nocie, będzie wszystko stabilne na I2C. Możesz też te przyciski podłączyć do jakiegoś arduino mini za kilka złotych i przesyłać dane po RS232 do modułu głównego. Możesz sam złożyć sobie "arduino" z garścią elementów. Jeśli masz tam tylko przyciski, możesz zrobić tzw. drabinkę rezystorową / klawiaturę rezystorową i odczytywać modułem głównym wartości napięcia z tej klawiatury - wtedy potrzebujesz tylko jeden pin z Arduino w module głównym - pin wejścia ADC. Są też inne rozwiązania ale te chyba są najprostsze.

    EDIT : opisz proszę dokładniej, co i gdzie masz i co chcesz osiągnąć.
    Jeden moduł główny, i do niego połączone zdalnie przyciski oraz kolejny moduł, oddalony od pozostałych, z wyświetlaczem ?
  • Użytkownik usunął konto  
  • Poziom 10  
    Moduł główny zbiera sygnały z czujników i ma główny kod. Dwa moduły(10m od głównego) wyświetlają dane na wyświetlaczach ośmiosegmentowych które zrobiłem.
    Panel(5m od głównego arduino) z przyciskami i wyświetlaczem lcd. Nie mogę głównego modułu umieścić w panelu.

    Biorąc pod uwagę że te wyświetlacze wykorzystują ic2, wykorzystałem expander do przycisków zamiast drabinki.
    Edit:
    Ponieważ wyświetlacze 8segmentowe mają wyświetlać czasy(mam różne tryby czasu stopery, minutniki itd) arduina pomocnicze mają przerobiony kod źródłowy(arduina głównego).

    Polega to na tym że wybieram progam z listy(np2 z listy 1-9 widocznej na wyświetlaczu alfanumerycznym, opis programu na lcd). Po naciśnięciu start na panelu, arduino główne rozpoczyna pomiar a Arduino pomocnicze również zaczyna odliczanie aby móc wyświetlać wartości. Po wykryciu stopu(czujnik podpięty do głównego modułu) następuje obliczenie czasu końcowego i przesłanie go do Arduino pomocniczego(aby uniknąć błędów pomiarowych, zastąpi on wartość wyliczoną w arduino pomocniczym). A więc nie jest wymagana jakas super szybka transmisja. Jedynie przyciski mają reagować błyskawicznie(np awaryjny przycisk stop gdy czujnik zawiedzie).

    Początkowo zamiast Arduin pomocniczych korzystałem z expanderów 16 bitowych, nie są one jednak w stanie wysterować w pełni driverów na 24V(diody nie świeciły pełną mocą). Pojawiały się smużenia, poświaty(nieaktywne diody jarzyły się lekko) mimo odległości 0,5m.
    Nawet arduina mają z tym lekki problem. Napisalem kod w ten sposób że poświaty nie ma ale m.in ze wzgledu na odświeżanie nie świecą one 100%mocy - jednak efekt jest zadowalający.
  • Użytkownik usunął konto  
  • Poziom 10  
    Schemat wyglądał, jak w załączniku.
    Trochę na wyrost każdy cyfra ma swoją parę układów(TD i ULN; 6 cyfr na ekran). Problem polegał na tym że układ TD otwierał się w może 85%, diody świeciły wyraźnie słabiej. Trzeba przy tym wziąć pod uwagę na zasadę działania.
    Arduino wysyłało po kolei wartości dla każdej z 6 cyfr 1 ekranu,
    następnie nawiązywało łączność z drugim expanderem(w tym czasie expander1 zapamiętuje ostatnią wartość - dlatego, aby ostatnia cyfra nie świeciła mocniej - bo dłużej, wysyłałem "1" na piny układu TD i "0" na ULN, tym samym zapewniając lepsze otwarcie układu TD) i wysyłało wartości cyfr 7-12.

    Najlepsze rezultaty były przy takim kodzie:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Jednak nawet przy komunikacji z 1 ekranem, kompletny max to był 85%. Ostatecznie, przy mniej więcej takim kodzie wygaszone segmenty się nie jarzyły. Mówiąc jarzyły mam na myśli słabo widoczny zarys poprzedniej cyfry.

    Expandery ostatecznie odrzucam. Wersja z arduino jest znacznie stabilniejsza, choćby ze względu na fakt wysyłania tylko sygnałów sterujących i wartości końcowych, po zakończonym pomiarze.
    Komunikacja pomiędzy 3 arduino (ic2)
  • Użytkownik usunął konto  
  • Poziom 10  
    Wcześniej testowałem to na rejestrach 4094. Tyle że SPI jest do 40 cm.
    Zgadza się, każda kolejna cyfra to problem. Nie wiem po co i jak używać tu przerwania?
    Biorąc pod uwagę odległość wymagającą rs232 (ewentualnie ic2 + układy z noty, wybieram rs232)
    wykorzystam arduina pomocnicze, bezpośrednio podpięte pod drivery(sterujące segmentami).
  • Pomocny post
    Użytkownik usunął konto  
  • Poziom 10  
    Wersja z rejestrami raczej odpada.
    Rejestr potrzebuje w praktyce 3 pinów. Czyli w module głównym tracę 6 pinów. To problem.

    Myślałem o UART z wykorzystaniem np takiego konwertera:
    MODUŁ KONWERTERA RS232-TTL OPARTY O MAX3232

    Jeżeli faktycznie RS422/485 będzie lepszy to mogę go wykorzystać.

    Jak ustaliliśmy expandery na IC2 odpadają. Nawet przy prościutkim programie którego jedynym zadaniem jest wyświetlanie stałej wartości na 1 cyfrze(a nie 6/12) - jasność nie jest zadowalająca.

    Wykorzystanie takich modułów pcf8574 + układ z BCD wcale nie jest prostsze. Dlatego wygodniej zastąpić je modułem arduino.

    Jestem zwolennikiem jak najprostszych rozwiązań. Nie robię tego dla papierku.

    Dalej zastanawia mnie kwestia przerwań programowych. Czy będę je musiał je stosować w arduino pomocniczym. Robiłem już testy i ładnie to śmiga bez nich.

    Ponieważ wyświetlam obraz na zasadzie:
    micros(2000) zapalona 1 cyfra,
    micros(300) wszystko zgaszone
    micros(2000) 2 cyfra zapalona
    micros(300) przerwy
    i tak dla 6 cyfr.

    Procesor spokojnie zdąży przejść przez cały program kilkanaście razy i w odpowiednim momencie zająć się wyświetlaczem(w/w sekcją).
    Zawsze testy zaczynam od jak najprostszego wariantu(np wyświetlanie 1 segmentu albo stałej wartości na 1 cyfrze) a dopiero później 6 cyfr wyświetlających stoper, następnie dowalony cały program - w każdym przypadku obraz wyświetlany jest w tej samej jakości/ jasności.

    Jaśniej(100%) jest tylko gdy na stałe ustawię stany pinów. Ale jak wiadomo multipleksowanie wiąże się ze spadkiem jasności(patrz załącznik).

    Przerwy(300) stosuję, ponieważ - jak sądzę - piny nie są w stanie tak szybko się ustalić swojego stanu(lub drivery) i bez tego opóźnienia widać poprzednią wartość(widmo) lekko jarzącą się na kolejnej cyfrze.
    Zastosowanie takiej przerwy niweluje problem do 0 (nawet w nocy nieaktywnych LEDów nie widać bo są zgaszone).
  • Użytkownik usunął konto  
  • Poziom 10  
    300 us to czas przerwy który gwarantuje prawidłową prace. Wyliczona częstotliwość jest błędna.
    A wyświetlacz działa więc chyba mam dobre założenia.

    Gdybym robił to na zasadzie(kod na szybko):
    a...g - segmenty
    e1...e6 - nr cyfry(ULN masujący)

    Kod: c
    Zaloguj się, aby zobaczyć kod


    to byłoby to złe.
    Stąd dorzucam 300 us.
    Więc druga cyfra zapala się po 2300 us.

    Częstotliwość(na pinach e1..e6) to ok 75 Hz. Więcej nie trzeba. Telewizory miały po 50 Hz :p
    Piny od segmentów mogą mieć inną ze względu na zmieniające się wartości.
    Dla oka bez różnicy.
    Wiadomo że im dłuższy czas przerwy tym byłoby ciemniej(wypełnienie).

    Jest jakiś inny, lepszy sposób?


    Jeżeli nie korzystam z delay() i innych cudów które mogłyby zatrzymać lub zapętlić program, co może pójść źle?
    Pytam całkiem poważnie, dopiero się uczę i chciałbym dobrze to zrozumieć.

    Przecież po to stosuje się funkcje if w zestawieniu z micros() aby program był płynny. przerwania zawieszają działanie programu. I na dobrą sprawę, nie mam pojęcia jak je zastosować w moim przypadku.
  • Użytkownik usunął konto  
  • Poziom 17  
    Trochę to przekombinowane jak dla mnie i próba naginania technologi. Po co, skoro są dostępne stosowne rozwiązania?

    Wstaw po stronie wyświetlaczy ATTINY lub jakaś mniejsza ATMEGA i połącz wszystko RS485.
    uC jest niewiele droższy niż expander I2C, a dodatkowo może zająć się multiplexowaniem.
  • Poziom 10  
    @sawitar
    właśnie taki jest mój zamiar.
    Zamiast jakiegoś attiny wolę jednak wrzucić arduino.
    Powód?
    Arduino IDE jest przyjazne, dodatkowo planuję dorzucić akumulatory i dodać opcję transmisji przez wifi. SparkFuny nadają się do tego idealnie.
  • Moderator Mikrokontrolery Projektowanie
    @alienHater Zrobienie multipleksowania to parę linii kodu, to jest przyjazne nawet w asemblerze :) Przy okazji pomyśl o użyciu dedykowanych układów do sterowania LEDami - np. coś z serii SCT - masz rejestr z buforami z kontrolą prądu. W jednym scalaku masz nawet 16 bitów, więc można też zrobić sterowanie statyczne wyświetlaczami.
  • Poziom 10  
    Mam 6cyfr x 8 segmentów = 300 led. Zasielanie 24V.
    Taki układ załatwiłby sprawę? Jak rozumiem dotychczasowe drivery nie byłyby potrzebne?