ارتباط I2C بین بردهای آردوینو

سه شنبه, 12 دی 1396 16:17
این مورد را ارزیابی کنید
(7 رای‌ها)

شاید گاهی اوقات ما بخواهیم حجم کاری برد آردوینو را با بردهای دیگر به اشتراک بگذاریم. یا شاید ما می‌خواهیم پین‌های دیجیتال یا آنالوگ بیشتری داشته باشیم. در این حالت بهترین راه‌حل استفاده از ارتباط I2C است. در این پروژه از برد آردوینو استفاده شده است. در صورتی که به آردوینو علاقه‌مند هستید، می‌توانید آموزش کامل آردوینو (مبتدی و پیشرفته) را مطالعه کنید.

ارتباط I2C یک پروتکل جالب است که معمولاً برای ارتباط بین قطعات در مادربردها، دوربین‌ها و یا هر سیستم الکترونیکی استفاده می‌شود. در این آموزش ما قصد داریم تا از این پروتکل ارتباطی برای ارتباط میان دو برد آردوینو استفاده کنیم.

در این آموزش یک برد آردوینو که برد راهبر یا مستر (Master) است را برنامه‌نویسی می‌نماییم تا به برد آردوینو دیگر که برد رهرو یا اسلیو (Slave) خوانده می‌شود فرمان بدهد که LED داخلی استفاده‌شده در برد را بسته به فرمان و مقدار دریافتی از برد آردوینو مستر با چه سرعتی روشن و خاموش کند.

برای این منظور به قطعات زیر نیاز است.

قطعات موردنیاز

برد آردوینو UNO R3 + کابل USB 

2 عدد
سیم اتصال به برد بورد 65 تایی 1 عدد

 

شماتیک مداری

 I2C

طبق شکل نشان داده‌شده و شماتیک مداری، پین‌های A4 و A5 هر برد آردوینو را به همان پین از برد آردوینو دیگر متصل کنید و پین GND هر دو برد باید مشترک باشد. پس آن پین را هم برای هر دو برد به یکدیگر متصل کنید.

فقط توجه داشته باشید که پین‌های 3.3 و 5 ولت بردها را هیچ‌وقت به یکدیگر متصل نکنید چراکه باعث آسیب رساندن به پورت 3.3 ولتی بردها می‌شود.

i2c

برنامه‌نویسی

برای این آموزش، همان‌طور که پیش‌تر گفتیم دو برد آردوینو مستر و اسلیو به کار گرفته‌شده است؛ بنابراین، برای هر یک برنامه متناسب با خود آن باید نوشته شود. برنامه نوشته‌شده برای برد آردوینو مستر به‌صورت زیر است:

// Include the required Wire library for I2C<br>#include <Wire.h>

int x = 0;

void setup() {

  // Start the I2C Bus as Master

  Wire.begin();

}

void loop() {

  Wire.beginTransmission(9); // transmit to device #9

  Wire.write(x);              // sends x

  Wire.endTransmission();    // stop transmitting

  x++; // Increment x

  if (x > 5) x = 0; // `reset x once it gets 6

  delay(500);

{

در این برنامه به این صورت عمل شده است که ابتدا کتابخانه <Wire.h> را با دستور زیر فراخوانی می‌کنیم:

#include <Wire.h>

سپس، در قسمت Setup function ارتباط I2C را با دستور Wire.begin() شروع می‌کنیم. این دستور به این صورت است که اگر در داخل پرانتز این تابع آرگومانی قرار نگیرد، برد به‌عنوان برد مستر تلقی می‌شود.

درنهایت یک کاراکتر x که بین 0 و 5 است را ارسال می‌کنیم. ما از توابع زیر برای شروع انتقال به برد آردوینو دیگر با آدرس 9، نوشتن کاراکتر و سپس توقف انتقال استفاده کردیم:

Wire.beginTransmission(9); // transmit to device #9

Wire.write(x);             // sends x

Wire.endTransmission();    // stop transmitting

حال برنامه برد آردوینو اسلیو را در ادامه می‌نویسیم که فرامین ارسالی از برد مستر را تفسیر می‌کند:

// Include the required Wire library for I2C<br>#include <Wire.h>

int LED = 13;

int x = 0;

void setup() {

  // Define the LED pin as Output

  pinMode (LED, OUTPUT);

  // Start the I2C Bus as Slave on address 9

  Wire.begin(9);

  // Attach a function to trigger when something is received.

  Wire.onReceive(receiveEvent);

}

void receiveEvent(int bytes) {

  x = Wire.read();    // read one character from the I2C

}

void loop() {

  //If value received is 0 blink LED for 200 ms

  if (x == '0') {

    digitalWrite(LED, HIGH);

    delay(200);

    digitalWrite(LED, LOW);

    delay(200);

  }

  //If value received is 3 blink LED for 400 ms

  if (x == '3') {

    digitalWrite(LED, HIGH);

    delay(400);

    digitalWrite(LED, LOW);

    delay(400);

  }

}

در این برنامه هم ابتدا کتابخانه I2C را فراخوانی می‌کنیم ولی برای شروع ارتباط این بار دستور Wire.begin(9) را وارد می‌کنیم. شماره 9 به‌کاررفته در این دستور آدرسی است که ما به این برد آردوینو اسلیو داده‌ایم تا با آن شناخته شود. تمامی دستگاه‌های با آدرس 9 می‌توانند فرامین ارسالی از برد مستر را بگیرند.

حال نیاز داریم تا هر زمان که فرمانی از طریق ارتباط I2C ارسال شد در پاسخ به آن برد اسلیو عکس‌العملی از خود نشان دهد. با استفاده از تابع زیر هر زمان که آردوینو یک کاراکتر را بر روی I2C دریافت می‌کند، عملکردی را اجرا می‌کند که ما مدنظر ما است:

Wire.onReceive(receiveEvent);

و تابع مدنظر به‌صورت زیر است که در اینجا ما می‌خواهیم فقط مقدار کاراکتر دریافتی را ذخیره کند:

void receiveEvent(int bytes) {

   x = Wire.read();

}

در قسمت loop() برنامه هم ما فقط گفته‌ایم که بسته با مقدار کاراکتر دریافتی LED قرارگرفته روی برد آردوینو اسلیو به چه سرعتی خاموش و روشن شود.

اطلاعات بیشتر درباره ارتباط I2C

برای دریافت اطلاعات بیشتر در رابطه با ارتباط I2C می‌توانید به آموزش "آشنایی با پروتکل های ارتباطی: درس سوم(I2C)" مراجعه کنید. ولی به‌طور خلاصه باید گفت که ارتباط I2C به دو خط دیجیتال نیاز دارد که یک خط آن Serial Data line (SDA) برای انتقال اطلاعات و خط دیگر Serial Clock Line (SCL) برای کلاک یا زمان است. در هر ارتباط I2C می‌توان یک برد مستر و چندین برد اسلیو داشته باشیم. برد مستر می‌تواند فرامین را به بردهای اسلیو بفرستد و یا از آن‌ها درخواست اطلاعات کند. ولی هیچ برد اسلیوی نمی‌تواند به‌طور مستقیم به برد مستر یا بردهای اسلیو دیگر فرمانی را صادر کند. هر برد اسلیو هم آدرس مخصوص به خود را دارد که برد آردوینو مستر برای ارتباط با آن‌ها نیاز به داشتن آن آدرس دارد.

هر ارتباط I2C تا 112 دستگاه را می‌تواند به یکدیگر ارتباط دهد که همگی با زمین یا پورت GND مشترکی داشته باشند و با سرعت 100 kb/s می‌توانند با یکدیگر در ارتباط باشند که سرعت زیادی نیست ولی قابل‌قبول و بسیار قابل‌استفاده است. امکان وجود و استفاده از چند مستر هم وجود دارد که خیلی پیچیده است.

بیشتر سنسورهای موجود از ارتباط I2C می‌توانند استفاده کنند ولی توجه شود که این ارتباط برای استفاده از سیم‌های بلند و ارتباطات طویل ساخته نشده است که با توجه به نوع کابل ارتباط کمتر از 2 متر مناسب است.

تمامی بردهای آردوینو دارای پروتکل ارتباط I2C هستند که فقط شماره پین‌های آن‌ها با یکدیگر متفاوت است که به شرح زیر می‌باشد:

Uno, Pro Mini A4 (SDA), A5 (SCL)

Mega, Due 20 (SDA), 21 (SCL)

Leonardo, Yun 2 (SDA), 3 (SCL)

اگر نیاز به ارتباط تعداد بردهای بیشتری داشتید هم فقط کافی است تا خط‌های SDA و SCL آن‌ها را به یکدیگر وصل کنید و آدرس هر یک را به برد مستر بدهید.

 

نظرات، پيشنهادات و انتقادات خود را براي بهتر شدن محتواي مطالب با ما در ميان بگذاريد...

 


ترجمه شده توسط تيم الکترونيک صنعت بازار | منبع: سايت instructable.com

خواندن 9164 دفعه
پشتیبانی

عباس بطالبلو دانش‌آموخته کارشناس ارشد رشته مهندسی مکاترونیک از دانشگاه صنعتی خواجه نصیرالدین طوسی و عضو گروه رباتیک جراح آزمایشگاه ارس (ARAS) هستند. موضوع پایان نامه کارشناسی ارشد ایشان در زمینه ی «طراحی و پیاده سازی ربات ۲RT برای جراحی از دور چشم» بوده است. ایشان سابقه پیاده سازی و ساخت ربات هایی چون ربات موازی جراحی چشم، ربات سری SCARA، ربات Palletizer و … را دارند.

کاربرانی که در این گفتگو شرکت کرده اند

نظرات (19)

  1. حسن

سلام وظیفه sda و scl در پاور های سویچینگ چیست

 
  1. پشتیبانی    حسن

سلام حسین عزیز
sda و scl راه های ارتباطی بوده و به پاور سویچ ارتباطی ندارند.
موفق باشید

 
  1. bahman

سلام استاد وقت بخیر یک سوال داشتم ببخشید ? آیا از دو پروتکل ارتباطی در آردوینو میشه همزمان استفاده کرد . ما یک سنسور فشار دیجیتال داریم و یک استپر موتور که با درایور tmc کنترل میشه . پروتکل ارتباطی سنسور i2c و درایور فقط spi هست . حالا کد های...

سلام استاد وقت بخیر یک سوال داشتم ببخشید ? آیا از دو پروتکل ارتباطی در آردوینو میشه همزمان استفاده کرد . ما یک سنسور فشار دیجیتال داریم و یک استپر موتور که با درایور tmc کنترل میشه . پروتکل ارتباطی سنسور i2c و درایور فقط spi هست . حالا کد های کنترل سنسور و کنترل موتور جدا جدا درست کار میکنن ولی وقتی تو یک برنامه combine میکنم هر دوتا کد رو ، موتور قفل میکنه و به نظر میاد درایور درست عمل نمیکنه . حدس زدم شاید مشکل از این باشه که وقتی سنسور داره اطلاعات رد و بدل میکنه ، برد نمیتونه همزمان ارتباط SPI با درایور برقرار کنه

ادامه مطلب
 
  1. پشتیبانی    bahman

سلام بهمن عزیز
استفاده همزمان از این دو پروتکل ارتباطی مشکلی ایجاد نمی کند. کد نوشته شده خودتون رو به دقت بررسی کنید و به فروم لینک های زیر هم مراجعه کنید:
https://b2n.ir/282046
https://b2n.ir/371455
https://b2n.ir/313128
https://b2n.ir/527285
موف...

سلام بهمن عزیز
استفاده همزمان از این دو پروتکل ارتباطی مشکلی ایجاد نمی کند. کد نوشته شده خودتون رو به دقت بررسی کنید و به فروم لینک های زیر هم مراجعه کنید:
https://b2n.ir/282046
https://b2n.ir/371455
https://b2n.ir/313128
https://b2n.ir/527285
موفق باشید

ادامه مطلب
 
  1. محمد

سلام من میخواستم از دوتا حلقه استفاده کنم(هر دو هم زمان کار کنند)اما در اردینیو uno بخواطر تک هسته بودن سی پی یو مثل اینکه نمیشه.
الان ۲ تا uno دارم. با این روش می توان ۲ تا حلقه باهم و همزمان کار کنند؟

 
  1. پشتیبانی    محمد

سلام محمد عزیز
برای راه اندازی دوحلقه به صورت همزمان باید در واقع شما از یک حلقه استفاده کنید و مشابه مثال Blink without delay عمل کنید. برای این منظور پیشنهاد میشه به لینک زیر مراجعه کنید که دموی مربوطه رو قرار داده است.
https://bit.ly/3nL6i60
بل...

سلام محمد عزیز
برای راه اندازی دوحلقه به صورت همزمان باید در واقع شما از یک حلقه استفاده کنید و مشابه مثال Blink without delay عمل کنید. برای این منظور پیشنهاد میشه به لینک زیر مراجعه کنید که دموی مربوطه رو قرار داده است.
https://bit.ly/3nL6i60
بله از دو برد می تونید استفاده کنید.
موفق باشید

ادامه مطلب
 
  1. صالح

سلام یک اردیو UNO اصل ویکی چینی میتونیم به هم وصل کنیم

 
  1. پشتیبانی    صالح

سلام صالح عزیز
بله مشکلی نداره می تونید تست کنید.
موفق باشید

 
  1. محسن

با سلام
ایا میشه سه تا اردوینو که مستقل کاری رو انجام میدن رو از این طریق به یک lcd وصل کرد؟

 
  1. پشتیبانی    محسن

سلام محسن عزیز

درواقع در این روش استفاده از I2C و LCD برد آردوینو شما مستر هست و LCD اسلیو. شما می خواید multiple master داشته باشید که معمول نیست ولی شدنی هست و کتابخانه فک کنم نوشته نباشه واسش. می تونید امتحان کنید مثلا یک برد رو مستر برای LCD...

سلام محسن عزیز

درواقع در این روش استفاده از I2C و LCD برد آردوینو شما مستر هست و LCD اسلیو. شما می خواید multiple master داشته باشید که معمول نیست ولی شدنی هست و کتابخانه فک کنم نوشته نباشه واسش. می تونید امتحان کنید مثلا یک برد رو مستر برای LCD در نظر بگیرید.
موفق باشید

ادامه مطلب
 
  1. ideveloper

ممنون از آموزش خوبتون!
ینی با این کار میشه تعداد پین های بیشتری داشت ؟
و اینکه گفتین 0 تا 5، ینی فقط میتونیم 6 تا از پین های Slave رو داشته باشیم ؟

 
  1. پشتیبانی    ideveloper

سلام دوست عزیز
این اتباط 2 سیم هست و از این لحاظ شما تعداد پین های بیشتری دارید. برای اطلاعات بیشتر حتما آموزش "آشنایی با پروتکل های ارتباطی: درس سوم(I2C)" در لینک زیر رو دنبال کنید و با سایر ارتباط ها مثل Uart و SPI مقایسه کنید:

آشنایی با...

سلام دوست عزیز
این اتباط 2 سیم هست و از این لحاظ شما تعداد پین های بیشتری دارید. برای اطلاعات بیشتر حتما آموزش "آشنایی با پروتکل های ارتباطی: درس سوم(I2C)" در لینک زیر رو دنبال کنید و با سایر ارتباط ها مثل Uart و SPI مقایسه کنید:

آشنایی با پروتکل های ارتباطی: درس سوم(I2C): https://bit.ly/3mZZnGz
آشنایی با پروتکل های ارتباطی: درس دوم(UART): https://bit.ly/3jbJl9Z
آشنایی با پروتکل های ارتباطی: درس اول(پروتکل SPI): https://bit.ly/30bA6PW

صفر تا 5 مقداری بود که در کد تعریف کرده بودیم و ربطی به پین های برد ندارد. مقدار x هست.
موفق باشید

ادامه مطلب
 
  1. bahman niknam

میشه توضیح بدید چرا تو کد اسلیو ، اونجا که عدد ارسالی از آردوینو مستر رو در شرط if چک میکنید از علامت ' ' استفاده کردید ؟ یعنی اعداد بعد از ارسال کارکتر میشن ؟

 
  1. پشتیبانی    bahman niknam

سلام دوست عزیز
'x' در واقع مقدار عددی کاراکتر x رو نمایش میده که ما در این برنامه نیاز داریم.
موفق باشید

 
  1. امید رضوی

سلام و خسته نباشد خدمت شما
اگر ممکنه کمکم کنید من می خوام همزمان هم شیف اینکدر خوانده شود و هم همزمان برنامه به صورت جدا گانه بر روی یک برد آردیونو اجرا شود البته لازم به ذکر است که از وقفه ها استفاده کردم برای خواندن شفت انکودر ولی به محض اجرای...

سلام و خسته نباشد خدمت شما
اگر ممکنه کمکم کنید من می خوام همزمان هم شیف اینکدر خوانده شود و هم همزمان برنامه به صورت جدا گانه بر روی یک برد آردیونو اجرا شود البته لازم به ذکر است که از وقفه ها استفاده کردم برای خواندن شفت انکودر ولی به محض اجرای برنامه برنامه قطع و به زیر برنامه خواندن شیفت اینکدر پرش می کرد

ادامه مطلب
 
  1. پشتیبان    امید رضوی

سلام امید عزیز
در این مورد چند نکته به نظرم میرسه. اول اینکه تابع ISR باید تا حد امکان کوتاه باشه، چون اگه تابع زمان بری باشه ممکنه در حین اجرا، وقفه دیگه ای فعال بشه.
دوم اینکه توابع مربوط به I2C رو توی ISR قرار ندید و به حلقه اصلی منتقل شون...

سلام امید عزیز
در این مورد چند نکته به نظرم میرسه. اول اینکه تابع ISR باید تا حد امکان کوتاه باشه، چون اگه تابع زمان بری باشه ممکنه در حین اجرا، وقفه دیگه ای فعال بشه.
دوم اینکه توابع مربوط به I2C رو توی ISR قرار ندید و به حلقه اصلی منتقل شون کنید.
اگه مشکل تون حل نشد، کدتون رو بذارید تا دقیق تر بررسی بشه.

ادامه مطلب
 
  1. ابراهیم

سلام
برای ارسال مقدار x به arduino دیگر بیش از ۲۵۵ نمیتوانم بفرستم.میتونید به من کمک کنید .ممنون

 
  1. پشتیبان    ابراهیم

سلام ابراهیم عزیز
ارتباط I2C دیتا رو به صورت بایت به بایت میفرسته به همین خاطر نمیتونید بیش از 255 (1 بایت) ارسال کنید. در صورتی که عددی بیشتر از 1 بایت میخواید بفرستید از دستور (Wire.Write(data,length استفاده کنید. که در آن data مقداری که...

سلام ابراهیم عزیز
ارتباط I2C دیتا رو به صورت بایت به بایت میفرسته به همین خاطر نمیتونید بیش از 255 (1 بایت) ارسال کنید. در صورتی که عددی بیشتر از 1 بایت میخواید بفرستید از دستور (Wire.Write(data,length استفاده کنید. که در آن data مقداری که میخواهید بفرستید به صورت آرایه ای از بایت ها و length تعداد بایت آن است.

ادامه مطلب
 
  1. no amooz

سلام ممنون میشم جواب منو بدید خیلی مهمه میشه به جای یکی از برد های اردوینو یه یک برد نود ام سی یو جایگزین کرد؟کد ها همین هستن؟

 
هیچ نظری در اینجا وجود ندارد

نظر خود را اضافه کنید.

ارسال نظر بعنوان یک مهمان
پیوست ها (0 / 3)
مکان خود را به اشتراک بگذارید
عبارت تصویر زیر را بازنویسی کنید. واضح نیست؟

محتوای آموزشی استفاده شده در این سایت محافظت شده می باشد و هرگونه کپی برداری از محتواهای تولید شده توسط تیم صنعت بازار موجب پیگرد خواهد بود. استفاده از مطالب صنعت بازار تنها با ذکر منبع به صورت لینک فعال بلامانع است

ما را دنبال کنید:

Copyright © 2017-2018 | Sanatbazar.com