ساخت ساعت های NTP با ESP8266
با اینکه ساخت ساعتهای دیجیتالی را نمیتوان از جذابترین پروژههای (DIY (Do It Yourself بهحساب آورد، اما هنوز هرساله علاقهمندان زیادی آنها را در اشکال و اندازه های مختلف میسازند. بسیاری از ساعتهای دیجیتالی خانگی (ساختهشده توسط علاقهمندان) با استفاده از اتصال بردهای آردوینو یا میکرو کنترلهای دیگر به یک تراشهی ساعت زمان واقعی یا (RTC (real time clock به دست میآید. اگر از مواد باکیفیت در ساخت ساعت استفاده شود، دقت آن میتواند بسیار خوب باشد.
محصولی که عموماً به اسم «ساعتهای اتمی» یا «ساعتهای دیجیتالی» شناخته میشود برای رفع مشکلات تنظیم دستی ساعت، تاریخ و خطاهای زمانی، به بازار عرضه شد. آنها تقریباً به هر شکل و اندازهای که میتوان متصور شد پدید آمدند.
این ساعتها از سیستم نقلوانتقال رادیویی WWV که توسط فورت کولینز (CO) معرفی شد پیروی میکنند و مکانیزمهای احتساب زمان خود را با سیستم بازخورد ساعت اتمی که برای این نوع نقلوانتقال مورد استفاده قرار میگیرد، هماهنگ میکنند. این موضوع دقت محاسبه و نمایش زمان آنها را تضمین میکند. ساعتهای اینچنینی معمولاً نیازمند تنظیم اولیه دستی یا انتخاب ساعت رسمی توسط مصرفکننده هستند، ولی بعضی از آنها گزینهای کنترلی برای تنظیم دستی زمان ندارند.
مکانیزم ساعت در کامپیوترهای شخصی متفاوت عمل میکند. کامپیوترهای شخصی معمولاً (RTC (real-time clock خود را با استفاده از یک نوع استاندارد اینترنتی که «زمان معین شبکه» یا «network time protocol» (بهاختصار NTP) نامیده میشود، تنظیم میکنند.
بنا به مرجع ویکیپدیا:
«پروتکل NTP، یک پروتکل شبکه برای هماهنگسازی ساعت بین کامپیوترها در شبکههای اطلاعاتی بهصورت بستهای-سوئیچینگ و متغیر-پنهانی، میباشد.
هدف NTP هماهنگسازی تمام کامپیوترهای مرتبط، با زمان بینالمللی تعیینشده (UTC) با خطایی در حد چند میلیثانیه هست.
معمولاً NTP توانایی حفظ دقت زمان را در حد چند ده میلیثانیه در محیط اینترنت عمومی داراست و همچنین میتواند در شرایط ایده آل به دقتی نظیر یک میلیثانیه در محدودهی اینترنت محلی دست پیدا کند.»
طراحی یک ساعت دیجیتالی بر پایهی NTP نیازمند دسترسی به اینترنت میباشد که ممکن است بهای تمامشده را بالا ببرد، اما امکان طراحی یک ساعت ساده را به دو دلیل فراهم میسازد. اول اینکه نیاز به باطری داخلی برای حفظ تنظیمات ساعت از میان برداشته میشود. زمانی که تغذیه ی ساعت قطع میشود، هنگام وصل مجدد آن ارتباط اینترنت دوباره برقرارشده و ساعت خود را با زمان صحیح بهصورت خودکار تنظیم میکند. دوم اینکه احتیاجی به امکان تنظیم دستی ضرورتی نخواهد داشت، چراکه تنظیمات زمان و تاریخ تماماً اتوماتیک انجام میگیرد.
دستگاههای خانواده ی ESP8266 امکان دسترسی ارزان و بیدردسر به اینترنت را فراهم میآورند، پس طبیعی است که از این دستگاهها در یک ساعت NTP استفاده شود.
قطعات خانوادهی ESP8266 مشخصاتی اساسی را به اشتراک میگذارند که شامل موارد زیر است:
- 802.11 b/g/n
- وایفای مستقیم p2p)، soft-AP)
- بسته ی داخلی پروتکل TCP/IP
- حالت 802.11b + 19.5 dBm قدرت خروجی
- حسگر داخلی دما
- سازگاری با انواع آنتنها
- نشتی جریان خاموشی کمتر از 10 میکرو آمپر
- پردازنده ی مرکزی داخلی و کممصرف 32 بیتی با توان مضاعف نسبت به یک پردازنده ی نرم افزاری
- مصرف حالت آمادهبهکار کمتر از 1 میلی وات (DTIM3)
- SDIO 2.0,SPI,UART,ADC,EEPROM
بهعبارتدیگر ماژولهای خانواده ی ESP8266 امتیازاتی نظیر مصرف کم، قدرت خروجی RF بالا و توانایی پشتیبانی از استانداردهای فعلی802.11 موردنیاز برای ارتباطات وایفای را، فراهم میسازند. ضمن اینکه با بسیاری از واسطهای سختافزاری استاندارد صنعتی سازگار بوده و میتوانند بهعنوان پردازنده ی نرمافزاری در مدلهای مختلف عمل کنند، چنانکه در این نمونه مشاهده میشود، ESP8266 یک قطعه ی 3.3 ولتی DC است.
دو چیز استفاده از این قطعات را جذابتر مینماید. نخست اینکه بسیاری از ماژولهای ESP8266 را میتوان به قیمت تکفروشی زیر 4 دلار خریداری کرد. ثانیاً این قطعات قابلبرنامهریزی در محیط IDE بوردهای آردوینو میباشند، لذا برنامهنویسان آردوینو مجبور به یادگیری زبان برنامه نویسی دیگری برای استفاده از آنها نخواهند بود.
در این مقاله، سعی کردم طراحی و ساخت یک ساعت دیجیتالی ساده ی NTP بر پایه ی ESP8266 که یک نمایشگر LCD را به کار میبندد، ارائه دهم. در حقیقت، من یک گونه ESP8266 را با نام NodeMCU LUA Amica استفاده کردم، به دلیل داشتن پایه های متعدد I\O دیجیتالی که اتصال راحت به نمایشگر را میسر میسازد. این ساعت دارای یک میکرو سوئیچ است که (در صورت تعریف و پیادهسازی حالت day light saving) کاربر را قادر میسازد با فشار آن ساعت را از حالت day light saving خارج نماید.
طراحی این ساعت باعث شد استفاده کردن از قابلیتها و وجوه دیگرِ ESP8266 را که تا قبل از این به کار نبرده بودم را، تجربه کنم؛ بهعلاوهی استفاده از واسط سختافزار SPI برای راهاندازی نمایشگر LCD و EEPROM داخلی برای ذخیرهسازی و بازیابی شاخص وضعیتیDST .
سختافزار
جدول قطعات سختافزاری موردنیاز برای ساخت این ساعتهای NTP را نشان میدهد. همانطور که خواهید دید تهیه آنها چنان سخت و گران نیست. شکل 1، یکشکل و دیاگرام اولیه و خاموش اتصالات برای ساعت NTP را نشان میدهد. شکل 2، طرح سیمکشی شده و در حال کار را بر روی برد بورد نمایش میدهد.
نکته: هیچ رابطه ای بین رنگ سیمها در شکل 1 و 2 وجود ندارد.
همانطور که نشان داده شد ساعت از طریق یک کابل USB و یک ماژول منبع ولتاژ USB تغذیه میشود. اتصالات سیم به سیم در جدول1 نشان دادهشده است. گزینههای انتخاب پایههای GPIO نیز در این جدول نشان دادهشدهاند. خطوط I/O به این شکل در کدنویسی آردوینو اشاره و تعریف شدهاند. نمایشگر LCD به کار برده شده دارای یک ورودی کارت حافظه ی میکرو SD و واسط برای استفاده از ESP8266، میباشد. موارد اشارهشده در این پروژه خاص موردنیاز نبودند.
نرمافزار
نرمافزار موردنیاز برای ساعت NTP تحت ESP8266، توسط محیط برنامهنویسی آردوینو کدنویسی شده بود. بدین منظور به مقالات قبلی من و یا فصلهایی از منابع رجوع کنید که در آنها از مهیاسازی محیط برنامهنویسی آردوینو بهمنظور استفاده از دستگاههای نوع ESP8266 بر روی کامپیوتر بحث شده است. مطمئن شوید که از سربرگ ابزار گزینه ی (NodeMCU 1.0 (ESP-12E Moduleرا بهعنوان نوع بورد خود انتخاب کنید.
نرمافزار ساعت NTP ESP8266 در لینک مقاله در دسترس بوده و Lindley_ESP8266NTPClock.zip نامگذاری شدهاست. برای استفاده از نرمافزار آن را unzip نموده و بعد از کپی از فایل مرجع ESP8266NTPClock آن را به کتابخانه یا همان فایلهای مرجع آردوینو انتقال دهید.
همانقدر که سختافزار این ساعت ساده و پیش پا افتاده به نظر میآید، برنامه ها و نرمافزارهای اساسی آن قدری درهم و پیچیدهتر میباشد. 7 فایلی که برای راهاندازی و شکلدهی کدنویسی نیاز است در جدول 2 توضیح دادهشدهاست. کد عملگر نمایشگر ESP8266_ST7735 برای امکان استفاده از واسط سختافزاری SPI در ESP8266، با کتابخانه یا مرجع Adafruit ST7735 سازگار شده است. اگر شما قصد دارید از یک نمایشگر متفاوت استفاده کنید، مجبور خواهید بود یک عملگر مناسب پیدا کرده و یا خودتان آن را بنویسید. بهاضافهی فایلهای بالا، یک فایل مرجع آردوینو نیز مورد نیاز هست. نسخهای از کتابخانههایی که برای ساخت این ساعت NTP استفادهشده، به فایل zip این مقاله اضافهشده است.
فراموش نکنید که کتابخانهها و فایلهای مرجع باید در آدرس Arduino/libraries از کامپیوتر مورداستفاده نصبشده و برای شناسایی آنها توسط محیط برنامهنویسی آردوینو، این برنامه باید راهاندازی مجدد شود.
بسیاری از کدهای موردنیاز برای شکلدهی ساعت NTP بسیار سرراست و بهآسانی قابلدرک هستند. فقط کد NTP در فایل NTP.h کمی پیچیده میباشد. برای بازیابی زمان، نیازمند دریافت آدرس IP از یک سرور زمانی در آدرس اشتراک عمومی time.nist.gov با استفاده از گزینهی hostbyname (میزبانی با نام) هستید، همانطور که در دستور زیر نشان دادهشده است. اگر هنگام عملکرد ساعت آدرس timeServerIP را زیر نظر گرفته باشید، احتمالاً دیدهاید که درخواست زمان در یک الگوریتم Round-Robin) RR) میان سرورها در time.nist.gov میچرخد.
اگر سروری برای درخواست دادن زمان پیدا کردید، باید یک بسته (UDP (packet که با مقادیر آمادهشده همخوانی داشته باشد ایجاد نموده و بهصورت یک پکیج بفرستید. لینک زیر را برای نمونههای بیشتر از زمینهها و محتویات پکیج درخواست ببینید:
https://tools.ietf.org/html/rfc5905#section-7.3
دستور sendNTPPacket نیز آن را انجام میدهد:
// Send an NTP request to the time server // at the given address unsigned long sendNTPpacket(IPAddress&addre ss) { // Set all bytes in the buffer to 0 memset(packetBuffer, 0, NTP_PACKET_SIZE); // Initialize values needed to form NTP // request packetBuffer[0] = 0b11100011; // LI, Version, Mode packetBuffer[1] = 0; // Stratum, or type of clock packetBuffer[2] = 6; // Polling Interval packetBuffer[3] = 0xEC; // Peer Clock Precision // 8 bytes of zero for Root Delay & Root // Dispersion packetBuffer[12] = 49; packetBuffer[13] = 0x4E; packetBuffer[14] = 49; packetBuffer[15] = 52; // All NTP fields have been given values, now // you can send a packet requesting a // timestamp: udp.beginPacket(address, 123); // NTP requests are to port 123 udp.write(packetBuffer, NTP_PACKET_SIZE); udp.endPacket(); }
وقتی پکیج درخواست فرستاده شد، شما منتظر جواب خواهید ماند. در آن جواب یک نشانگر زمان (4 بایتی که از 40 امین بایت پاسخ شروع میشود) زمانی را که پکیج فرستاده بود، واگذار میکند. واحد استفادهشده در این بسته، تعداد ثانیه از سال 1900 تا این لحظه بوده و عدد بسیار بزرگی است. این مقدار به زمان Unix (که تعداد ثانیههای اکنون تا تاریخ یکم ژانویهی 1970 بود) با کاستن تعداد ثانیههای مابین سالهای 1900 تا 1970، تغییر پیدا کرد.
این رقم بعدها بهوسیلهی اصلاح زمانی منطقهای تغییر و تائید شد. این اصلاح در کتابخانهی زمانی مورداستفاده قرارگرفته و به زمان و تاریخ دقیقی که این ساعت نمایش میدهد، تبدیل شده است.
دستور getNTPTime اطلاعات زیر را دریافت میکند:
// NTP Time Provider Code time_t getNTPTime() { int attempts = 10; // Try multiple attempts to return the NTP // time while (attempts—) { // Get a server from the pool WiFi.hostByName(ntpServerName,timeServerIP); Serial.print(“Time server IP address: “); Serial.println(timeServerIP); while (udp.parsePacket() > 0); // Discard any previously received packets Serial.println(“Transmitted NTP Request”); sendNTPpacket(timeServerIP); uint32_t beginWait = millis(); while (millis() - beginWait < 1500) { int size = udp.parsePacket(); if (size >= NTP_PACKET_SIZE) { Serial.println(“Received NTPResponse”); udp.read(packetBuffer, NTP_PACKET_SIZE); // Read packet into the buffer unsigned long secsSince1900; // Convert four bytes starting at // location 40 to a long integer secsSince1900 = (unsigned long) packetBuffer[40] << 24; secsSince1900 |= (unsigned long) packetBuffer[41] << 16; secsSince1900 |= (unsigned long) packetBuffer[42] << 8; secsSince1900 |= (unsigned long) packetBuffer[43]; Serial.println(“Got the time”); return secsSince1900 - 2208988800UL + realTimeZoneOffset * SECS_PER_HOUR; } delay(10); } Serial.println(“Retrying NTP request”); delay(4000); } Serial.println(“No NTP Response”); return 0; }
چیدمان کلی برای کاربران نرمافزار ساعت NTP
نرمافزار ساعت NTP باید قبل از شروع به کار دقیق، شکلدهی و سازگار شود. تمام موارد شکلدهی برای کاربران را در فایل ESP8266NTPClock.ino file میتوانید بیابید. لطفاً کدهای جدول زیر را در فایل جاگذاری کنید:
اولین و مهمترین کار این است که کد مربوطه را با اسم کاربری SS و رمز عبور وای فای اینترنت خود مطابقت دهید، وگرنه ساعت قادر به دسترسی به اینترنت و بهتبع آن به سرورهای NTP که زمان را در اختیار میگذارند، نخواهد بود. در مرحله بعد باید زمانی را که برای منطقه شما پیشبینیشده تنظیم کنید. زمانهای محلی معینشده را میتوان در لینک زیر یافت:
https://en.wikipedia.org/wiki/List_of_UTC_time_offsets
سپس باید تصمیم بگیرید که ساعت شما از گزینهی DST استفاده کند یا خیر و همچنین ساعت باید در حالت 12 ساعته کار کند یا حالت 24 ساعته. اگر از DST در ساعت استفاده میکنید USE_DST باید درست تنظیم شود، در صورت تنظیم شدن یا نشدن، بههرحال DST دائماً تحت تأثیر است. گزینه HOUR_FORMAT_12 را درست انتخاب کنید تا ساعت در حالت 12 ساعته کار کند، وگرنه در حالت 24 ساعته شروع به کار خواهد کرد.
برنامه زمانی میتواند تبدیلشده و بر روی دستگاه NodeMCU بارگذاری شود که اطلاعات کاملاً شکلدهی و سازگاری دادهشده باشند و تمام فایلهای مرجع موردنیاز بر روی محیط برنامهنویسی آردوینو نصبشده باشند.
عملکرد ساعت NTP
ساعت باید بلافاصله با بارگذاری و نصب شدن برنامه شروع به کار کند. شکل 3 نمایشگر ساعت را در اثنای اتصال آن به وایفای شبکه اینترنت محلی نشان میدهد. اگر این تصویر به ساعت نمایشگر نشان دادهشده در شکل 4 تغییر نکند، نشاندهندهی آن است که مشکلی در برقراری ارتباط با وایفای اینترنت وجود دارد. اگر چنین بود به برنامه مراجعه کرده، مقادیر WIFI_PASS و WIFI_SSID را بررسی و در صورت لزوم اصلاح نمایید تا وایفای شبکه به کار بیفتد.
همانطور که اشاره شد صفحهی اتصال به وایفای زمانی که ارتباط وایفای برقرار شد باید به صفحهی نمایش ساعت در شکل 4 تغییر کند. اگر ساعت برای استفاده از حالت DST برنامهریزی نشده باشد، کار تمام است. ساعت باید تا زمانی که تغذیه میشود به کار خود ادامه دهد و زمان خود را هر 5 دقیقه با سرور زمانی NTP هماهنگ و تنظیم خواهد کرد. این موضوع ساعت را کاملاً دقیق میکند.
اگر ساعت برای اعمال حالت DST تطبیق دادهشده باشد (USE_DST انتخابشده باشد) تنظیم آن بر روی حالت DST درصورتیکه در آن تاریخ DST در حال اجرا باشد (بین ماههای آوریل تا نوامبر در آمریکا)، به کاربر بستگی دارد. حالت DST جزء تنظیمات معمول و اولیهی ساعت نمیباشد، پس کاربر باید دکمه آن را تا زمانی که نوشتهی DST بر روی گوشهی سمت راست بالای صفحه ظاهر شود، فشار دهد. متوجه خواهید شد که ساعت در حال نمایش، وقتی حالت DST وارد عمل میشود تغییر خواهد کرد. فشار مجدد دکمهی DST ساعت را از حالت DST خارج میکند.
مادامیکه ساعت انرژی دریافت میکند، به کار خود ادامه خواهد داد. اگر اتصال اینترنت دچار مشکل شود، ساعت زمان خود را حفظ کرده و نمایش میدهد. اگر وایفای قطع شود، اما ساعت همچنان فعال باقیمانده باشد، زمانی که مشکل اینترنت حل شد نیاز به راهاندازی مجدد خواهد داشت و درنتیجه هماهنگسازی NTP از سر گرفته میشود. اگر هم ساعت و هم مودم اینترنت همزمان خاموش شوند، ساعت خودش راهاندازی مجدد شده منتظر برقراری اتصال اینترنت میماند و سپس خودکار به شبکه وصل میشود.
اگر ساعت در شرایط کاری و عملیاتی باشد، زمان و تاریخ هر یک دقیقه بهروزرسانی میشوند. در طول روز عکس خورشید در گوشهی سمت چپ بالای صفحه نمایش داده میشود. نماد خورشید بعد از حدود ساعت 8 عصر جای خود را به نماد ماه میدهد.
وقتی زمان DST رسید و گذشت، کاربر ملزم خواهد بود که با فشار دادن دکمهی DST که مخصوص خاموش و روشن کردن این حالت است، به ساعت اطلاع داده و آن را تنظیم کند. بهجز آن، مورد عملی تکرارشوندهی دیگری که از کاربر توقع رود، برای نگهداری و استفاده وجود ندارد.
// ********************************************** // Start of user configuration items // ********************************************** // Set your WiFi login credentials #define WIFI_SSID “xxxxxxxx” #define WIFI_PASS “xxxxxxxxxxxxx” #define TIMEZONE_OFFSET -7 // Set your timezone offset (-7 is mountain // time) #define USE_DST true // Set to false to disable DST mode #define HOUR_FORMAT_12 true // Set to false for 24 hour time mode // ********************************************** // End of user configuration items // **********************************************
بهعنوان آخرین نکته، وضعیت فعال DST هر بار با فشار داده شدن میکروسویچ DST در حافظهی EEPROM ماژول ESP8266 ثبت شد. برگرداندن ساعت به وضعیت صحیح، حالت DST بعد از هر بار قطع و وصل شدن یا خاموش و روشن شدن آن ضروری است.
فایل Misc.h را برای کدهای خواندن و نوشتن بر روی حافظهی EEPROM مطالعه کنید.
امیدوارم از زمانی که با من اینجا گذراندید، لذت برده باشید و ساختن یک ساعت دیگر با طراحی خودتان را متصور شده، در دستور کار قرار داده باشید.
- توجه داشته باشید: وقتی زمان صرفه جویی در تابستان روشن است (DST)نمایش داده میشود.
- آیکون خورشید در طول روز نمایش داده شده میشود.