این مطلب قسمت شانزدهم از آموزش جامع آردوینو (مبتدی و پیشرفته) است. در این قسمت قصد داریم به معرفی ماژول اترنت و نحوه راهاندازی آن به کمک آردوینو بپردازیم. این ماژول در واقع همان درگاه کابل شبکه است که اکثر کامپیوترها آن را دارند. هرچند که شاید اتصال تجهیزات به روش بیسیم جذابتر باشد و نیاز به سیمکشی را از بین میبرد اما در صورتی که شبکه اینترنت یا یک روتر ASDL و کابل شبکه در اختیار دارید و دستگاهتان یک وسیله متحرک نیست، استفاده از ماژول اترنت به دلیل ثبات در اتصال و سرعت انتقال اطلاعات بالا، میتواند گزینه مناسبی برای شما باشد.
قطعات مورد نیاز
معرفی پروتکل Ethernet
در اینترنت هر دستگاه متصل، یک آدرس منحصر به فرد دارد که با آن در شبکه شناسایی میشود. به این آدرس، Internet Protocol Address یا IP گفته میشود. آدرس دستگاه به محلی که از آنجا به شبکه متصل است مربوط شده و در صورت اتصال دستگاه از محلهای مختلف، متفاوت خواهد بود. برای تعریف IP در حال حاضر دو روش استفاده میشود. در روش اول که به آن Ipv4 گفته میشود از یک عدد ٣٢ بیتی استفاده میشود که شامل چهار بخش و هر بخش شامل یک عدد ٨ بیتی است و بخشهای مختلف با نقطه از هم جدا شدهاند مانند: 172.16.254.1
روش دوم که جدیدتر بوده و Ipv6 نام دارد، به صورت یک عدد ۱۲۸ بیتی است. طول بیشتر این نوع آدرس امکان تعریف تعداد بسیار بیشتری دستگاه را میدهد. برای مثال آدرس ورژن ۶ به این صورت است: fe80::b880:ab44:edb:16e2
بیشتر دستگاههای کنونی هر دو آدرس Ipv4 و Ipv6 را میپذیرند. میتوانید آدرس ورژن ۴ و ورژن ۶ دستگاهتان را در تنظیمات سیستم ببینید. مثلا در ویندوز آدرس IP در Control Panel به صورت زیر وجود دارد:
بعضی از دستگاهها ممکن است از آدرس ورژن ۶ پشتیبانی نکنند اما حتما از آدرس ورژن ۴ پشتیبانی خواهند کرد. اگر آدرس ورژن ۶ نداشته باشید نمیتوانید سایتهایی که از این استاندارد استفاده میکنند را ببینید. به هر حال آدرس Ipv4 متداولتر بوده و معمولا از آن استفاده میشود.
Default Gateway
اتصال به اینترنت از طریق Access Point ها یا Gateway ها امکانپذیر است. در یک شبکه کوچک خانگی Router ها نقش Access Point را ایفا میکنند. در واقع روتر به شبکه متصل شده و یک شبکه داخلی را تشکیل میدهد و اتصال دستگاههای دیگر را کنترل میکند. در یک شبکه داخلی، آدرس دهی هم به صورت داخلی انجام میشود. روتر همیشه اولین آدرس ممکن را به خودش و آدرسهای مجاز دیگر را به سایر دستگاهها اختصاص میدهد. برای مثال در خانه شما ممکن است آدرس روتر به صورت زیر باشد:
192.168.1.1
و آدرس دستگاههای دیگر متصل به شبکه به این صورت باشد:
192.168.1.2
192.168.1.3
192.168.1.10
192.168.1.16
در این سیستم به آدرس Access Point یا روتر، Default Gateway میگویند. در حالت عادی تخصیص آدرس به دستگاهها توسط روتر صورت میگیرد. این نوع آدرسدهی تحت پروتکل DHCP یا Dynamic Host Configuration Protocol انجام میشود. در شبکههای کوچک سرویس DHCP بر روی روتر انجام میشود در حالی که در یک شبکه بزرگ یک سرور در شبکه قرار میگیرد که تنها وظیفه اختصاص IP از طریق پروتکل DHCP را دارد. این آدرسدهی به صورت پویا یا Dynamic انجام میشود. با این وجود دستگاههای متصل به شبکه میتوانند درخواست آدرس مشخصی را به روتر یا سرور بدهند. در صورت تایید روتر، یک آدرس ثابت یا Static به آن دستگاه داده میشود. آدرس Static در هر بار اتصال به شبکه تغییر نمیکند در حالی که آدرس Dynamic میتواند در دفعات مختلف اتصال یک دستگاه یکسان به شبکه مقادیر متفاوتی را اختیار کند.
Subent Mask
تعریف دیگری که در مورد شبکه باید بدانید Subnet Mask است. Subnet Mask یک عدد است که IP های مجاز برای اختصاص درون یک شبکه را تعیین میکند. وجود تنها یک Subnet Mask ، تعداد دستگاههایی که میتوانند همزمان به شبکه متصل شوند را تعیین میکند در حالی که وجود چندین Subnet Mask ، شبکه را به تعدادی زیر شبکه تقسیم میکنند. دستگاههای درون یک زیر شبکه میتوانند مستقیما با هم ارتباط داشته باشند در حالی که دستگاههای موجود در زیرشبکههای مختلف باید از طریق یک روتر با هم ارتباط برقرار کنند. Subnet Mask ، یک آدرس مشابه Ipv4 است. در هر کدام از ۴ بخش IP، اعداد بزرگتر از مقادیر متناظر در Subnet Mask تعداد حالات ممکن آدرس IP را مشخص میکند. بگذارید این موضوع را با مثال واضحتر کنیم: مثلا اگر آدرس Subnet Mask به صورت 255.255.255.0 باشد، IP دستگاههای موجود در این زیر شبکه فقط در بخش چهارم میتوانند تفاوت داشته باشند (چون ٢۵۵ بزرگترین عدد ٨ بیتی ممکن است پس در این مثال، IP ها نمیتوانند در سه بخش اول آدرس، مقادیر مختلفی داشته باشند). در صورت که Subnet Mask به صورت بالا باشد، دستگاههای با آدرس 192.168.1.15 و 192.168.1.20 در یک زیر شبکه هستند در حالی که دستگاه 192.168.2.14 در زیر شبکه متفاوتی است. در یک شبکه خانگی معمولا از Subnet Mask با مقدار 255.255.255.0 استفاده میشود در حالی که در بعضی شبکههای اداری از مقدار 255.255.255.192 مورد استفاده قرار میگیرد (در این شبکه تعداد ۶۴=۱۹۲-٢۵۵ آدرس مختلف میتواند وجود داشته باشد). بر اساس تعریف Subnet Mask کلاسهای مختلفی برای شبکهها تعریف شده است. سه کلاس معروف شبکه به صورت زیر است:
آدرسهایی که در اینجا معرفی شد را میتوانید برای کامپیوترتان به روش زیر به راحتی مشاهده کنید: کلید Win+R را فشار دهید، عبارت cmd را وارد کرده و OK را بزنید.
پنجره Command Prompt باز میشود. عبارتipconfigرا وارد کرده و کلید Enter را بزنید. مشخصات اتصال شما به شبکه نشان داده خواهد شد.
آدرس MAC
علاوه بر آدرسهایی که توضیح دادیم، هر دستگاه یک آدرس منحصر به فرد دارد که به آن آدرس MAC دستگاه میگویند. این آدرس مثل شماره شناسنامه هر دستگاه است و برخلاف IP در شرایط مختلف تغییر نمیکند و به محل اتصال یا پارامترهای دیگر وابسته نیست. MAC یک آدرس ۴۸ بیتی یا ١٢ رقم Hex است. البته در بعضی موارد آدرس MAC را میتوان به صورت دستی عوض کرد. آدرس MAC در آموزش راهاندازی ماژول بلوتوث نیز استفاده شد.
راهاندازی اولیه ماژول Ethernet
در این قسمت میخواهیم ماژول اترنت را به کمک آردوینو به شبکه وصل کرده و آدرسهای آن را در پروتکل DHCP به دست آوردیم. اگر نگاهی به ماژول اترنت بیاندازید، مشاهده میکنید که ١٢ پین بر روی آن وجود دارد در حالی که در اینجا تنها از ۶ پین آن استفاده میکنیم. این ماژول از پروتکل SPI برای ارتباط با میکروکنترلر استفاده میکند.
توجه کنید که بر روی بسیاری از ماژولهای اترنت موجود در بازار عناوین پینها به درستی نوشته نشده است. برای مثال ماژولی که من استفاده کردم 3.3V است در حالی که بر روی آن 5V نوشته شده است. اگر بر روی ماژول شما عبارت 3.3V نوشته شده، احتمالا عنوان پینها درست است در غیر این صورت احتمالا عنوان درست هر پین مانند عکس زیر است:
پینهای SPI ماژول را مطابق آنچه قبلا یاد گرفتید به پایههای ١١ تا ١٣ آردوینو وصل کنید. پین SS را هم به پایه ١٠ و مثبت و منفی ماژول را هم به 3.3V و GND آردوینو وصل کنید.
برای استفاده از ماژول اترنت باید از کتابخانه مناسب استفاده کنید. اگر از ماژولی استفاده میکنید که دارای تراشه W5100 است، کتابخانهEthernet.hآردوینو کارتان را راه میاندازد. کار با این کتابخانه خیلی راحت است. اما بر روی بیشتر ماژولهای اترنت موجود در بازار از تراشه ENC28J60 استفاده شده است. کتابخانه Ethernet که به صورت پیشفرض در IDE آردوینو وجود دارد امکان ارتباط با این تراشه را ندارد. به همین دلیل از یک کتابخانه دیگر به نامEtherCard.hاستفاده میکنیم. این کتابخانه قابلیتهای خوبی در ارتباط شبکهای دارد ولی کار با آن کمی پیچیدگی دارد. چند نمونه از کاربردهای این کتابخانه به صورت زیر است:
راهاندازی ماژول
برای راهاندازی ماژول از دستور()ether.beginبه صورت زیر استفاده میشود. در این کتابخانه برای راحتی، به صورت پیشفرض یک کلاس اترنت به نام ether ایجاد شده است که میتوانید مستقیما از آن استفاده کنید:
uint8_t Ethernet::buffer[700]; // configure buffer size to 700 octets
static uint8_t mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 }; // define (unique on LAN) hardware (MAC) address
uint8_type vers = ether.begin(sizeof Ethernet::buffer, mymac);
if(vers == 0)
{
انجام تنظیمات با DHCP
برای اختصاص آدرس پویا برای ماژول در شبکه از دستور()ether.dhcpSetupاستفاده میشود:
if(!ether.dhcpSetup())
{
// handle failure to obtain IP address via DHCP
}
ether.printIp("IP: ", ether.myip); // output IP address to Serial
ether.printIp("GW: ", ether.gwip); // output gateway address to Serial
ether.printIp("Mask: ", ether.netmask); // output netmask to Serial
ether.printIp("DHCP server: ", ether.dhcpip); // output IP address of the DHCP server
اختصاص آدرس Static
همچنین میتوانید با دستور()ether.staticSetupآدرس ثابتی به ماژول بدهید:
const static uint8_t ip[] = {192,168,0,100};
const static uint8_t gw[] = {192,168,0,254};
const static uint8_t dns[] = {192,168,0,1};
if(!ether.staticSetup(ip, gw, dns);
{
// handle failure to configure static IP address (current implementation always returns true!)
}
برنامه زیر را در آردوینو آپلود کنید. این برنامه ماژول را شناسایی کرده و در شبکه یک آدرس پویا به آن میدهد:
/*
automee
Arduino Tutorial Series
Author: Davood Dorostkar
Website: www.automee.ir
*/
#include <EtherCard.h>
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
byte Ethernet::buffer[700];
#define SS 10
void setup () {
Serial.begin(9600);
Serial.println(F("\n[testDHCP]"));
Serial.print("MAC: ");
for (byte i = 0; i < 6; ++i) {
Serial.print(mymac[i], HEX);
if (i < 5)
Serial.print(':');
}
Serial.println();
if (ether.begin(sizeof Ethernet::buffer, mymac, SS) == 0)
Serial.println(F("Ethernet chip not responding"));
Serial.println(F("DHCP initializing ..."));
if (!ether.dhcpSetup())
Serial.println(F("DHCP failed"));
ether.printIp("My IP: ", ether.myip);
ether.printIp("Netmask: ", ether.netmask);
ether.printIp("GateWay IP: ", ether.gwip);
ether.printIp("DNS IP: ", ether.dnsip);
}
void loop () {
ether.packetLoop(ether.packetReceive());
}
ارسال اطلاعات سنسور دما با Ethernet
در این بخش میخواهیم مقادیر سنسور دمای DHT22 را خوانده و از طریق اترنت به یک سیستم دیگر بفرستیم. برای این کار از پروتکل UDP استفاده خواهیم کرد که در آموزش راهاندازی ماژول وایرلس معرفی شد. البته ماژول اترنت با پروتکل TCP هم کار میکند. سنسور DHT22 را به صورتی که در آموزش سنسورهای دما یاد گرفتید به پین 2 دیجیتال آردوینو وصل کنید. ماژول اترنت را هم مانند قبل به پورتهای SPI وصل کنید. ماژول را با یک کابل شبکه به روتری که به کامپیوترتان وصل است متصل کنید. به روشی که قبلا توضیح دادیم، IP کامپیوترتان را پیدا کنید.
حالا برنامه زیر را در آردوینو آپلود کنید. این برنامه مقادیر دما و رطوبت را از سنسور خوانده و منتظر میماند تا از کامپیوتر درخواستی دریافت کند. سپس مقادیر دما و رطوبت را به IP کامپیوتر میفرستد.
/*
automee
Arduino Tutorial Series
Author: Davood Dorostkar
Website: www.automee.ir
*/
#include <IPAddress.h>
#include <EtherCard.h>
#include <dht.h>
#define SS 10
#define dhtPin 2
static byte mymac[] = {0x74, 0x69, 0x69, 0x2D, 0x30, 0x31};
byte Ethernet::buffer[700];
const int dstPort PROGMEM = 1234;
const int srcport PROGMEM = 42;
uint8_t dstip[] = "192.168.1.138";
dht DHT22;
String temperature;
String humidity;
void udpSerialPrint(uint16_t dest_port, uint8_t src_ip[4], uint16_t src_port, const char *data, uint16_t len)
{
IPAddress src(src_ip[0], src_ip[1], src_ip[2], src_ip[3]);
ether.printIp("SRV: ", ether.hisip);
Serial.print("dest_port: ");
Serial.println(dest_port);
Serial.print("src_port: ");
Serial.println(src_port);
Serial.print("src_ip: ");
ether.printIp(src_ip);
Serial.println("");
Serial.println("data: ");
Serial.println(data);
Serial.print("Lenght: ");
Serial.println(strlen(data));
const char *t = temperature.c_str();
const char *h = humidity.c_str();
ether.sendUdp(t, sizeof(t), dest_port, src_ip, src_port);
ether.sendUdp(h, sizeof(h), dest_port, src_ip, src_port);
}
void setup()
{
Serial.begin(9600);
Serial.println("\n[testDHCP]");
Serial.print("MAC: ");
for (byte i = 0; i < 6; ++i)
{
Serial.print(mymac[i], HEX);
if (i < 5)
Serial.print(':');
}
Serial.println();
if (ether.begin(sizeof Ethernet::buffer, mymac, SS) == 0)
Serial.println("Ethernet chip not responding");
else if (!ether.dhcpSetup())
Serial.println("failed to setup DHCP");
else
{
Serial.println("Setting up DHCP ... ");
ether.printIp("Module IP: ", ether.myip);
ether.printIp("Netmask: ", ether.netmask);
ether.printIp("GateWay IP: ", ether.gwip);
ether.printIp("DNS IP: ", ether.dnsip);
}
ether.udpServerListenOnPort(&udpSerialPrint, srcport);
}
void loop()
{
ether.udpServerPauseListenOnPort(srcport);
DHT22.read(dhtPin);
temperature = (String)DHT22.temperature;
humidity = (String)DHT22.humidity;
ether.udpServerListenOnPort(&udpSerialPrint, srcport);
ether.packetLoop(ether.packetReceive());
}
در قسمت اول این برنامه کتابخانهها و متغیرهای مورد نیاز تعریف شده است. قبل از هر چیز توجه کنید که مقادیر IP کامپیوترتان و نیز پایهها، پورت اترنت و آدرس MAC را در صورت نیاز متناسب با سیستمتان تغییر دهید.
#include <IPAddress.h>
#include <EtherCard.h>
#include <dht.h>
#define SS 10
#define dhtPin 2
static byte mymac[] = {0x74, 0x69, 0x69, 0x2D, 0x30, 0x31};
byte Ethernet::buffer[700];
const int dstPort PROGMEM = 1234;
const int srcport PROGMEM = 42;
uint8_t dstip[] = "192.168.1.138";
dht DHT22;
String temperature;
String humidity;
در این برنامه تابعی به نام()udpSerialPrintتعریف شده است که با استفاده از تعاریف کتابخانه EtherCard دادهای را از ماژول دریافت کرده و در جواب آن مقادیر دما و رطوبت خوانده شده را میفرستد.
void udpSerialPrint(uint16_t dest_port, uint8_t src_ip[4], uint16_t src_port, const char *data, uint16_t len)
{
IPAddress src(src_ip[0], src_ip[1], src_ip[2], src_ip[3]);
ether.printIp("SRV: ", ether.hisip);
Serial.print("dest_port: ");
Serial.println(dest_port);
Serial.print("src_port: ");
Serial.println(src_port);
Serial.print("src_ip: ");
ether.printIp(src_ip);
Serial.println("");
Serial.println("data: ");
Serial.println(data);
Serial.print("Lenght: ");
Serial.println(strlen(data));
const char *t = temperature.c_str();
const char *h = humidity.c_str();
ether.sendUdp(t, sizeof(t), dest_port, src_ip, src_port);
ether.sendUdp(h, sizeof(h), dest_port, src_ip, src_port);
}
در هر حلقه برنامه نیز مقادیر دما و رطوبت به روز شده و تابع()udpSerialPrintفراخوانی میشود.
ether.udpServerPauseListenOnPort(srcport);
DHT22.read(dhtPin);
temperature = (String)DHT22.temperature;
humidity = (String)DHT22.humidity;
ether.udpServerListenOnPort(&udpSerialPrint, srcport);
ether.packetLoop(ether.packetReceive());
برای ارسال و دریافت اطلاعات راههای مختلفی وجود دارد. میتوانید یک صفحه HTML تعریف کنید و در مرورگرتان اطلاعات سنسور را ببینید یا اینکه یک برنامه اندروید برای تلفن همراهتان بنویسید تا این مقادیر را نشان دهد. اگر چنین قصدی دارید باید اطلاعات تخصصیتری در زمینههای فوق داشته باشید. در اینجا ما از یک روش سادهتر استفاده کردهایم: نرمافزارهای آمادهای وجود دارند که مدیریت ارسال و دریافت اطلاعات شبکه را انجام میدهند، مانند نرمافزار Hercules. این نرمافزار را میتوانید از لینک زیر دانلود کنید:
وارد نرمافزار شوید، تب UDP را باز کرده و مقادیر خواسته شده را وارد کنید. یک کاراکتر به ماژول ارسال کنید و منتظر جواب بمانید.
نتیجه گیری
در این آموزش با ماژول اترنت آشنا شدید. اگر به مباحث شبکه و نحوه کار با پروتکلهای آن علاقه دارید، استفاده از این ماژول را به شما توصیه میکنم. مباحث مربوط به انتقال اطلاعات در شبکه در تمام ماژولهای مرتبط، یکسان است و تسلط به هر کدام، استفاده از سایر ماژولها را هم ساده میکند. ماژولهای شبکه سنگ بنای اجرای پروژههای IoT هستند.
در آموزش بعدی، مبانی اولیه در مورد نحوه نوشتن کتابخانه در آردوینو مطرح خواهد شد.
نظرات شما باعث بهبود محتوای آموزشی ما میشود. اگر این آموزش را دوست داشتید، همینطور اگر سوالی در مورد آن دارید، از شنیدن نظراتتان خوشحال خواهیم شد.