Pada artikel ini, Anda akan mempelajari cara kerja Arduino Mega Server dari waktu ke waktu dan bagaimana Anda dapat membuat proyek di Arduino yang terhubung secara waktu-nyata, terlepas dari apakah mereka memiliki modul RTC berbasis besi yang diinstal atau tidak. Semua masalah bekerja dengan waktu nyata di Arduino akan dibahas secara rinci dan setelah membaca artikel ini Anda akan menjadi "pembuat jam" yang nyata.Esensi dari pertanyaan
Setiap proyek yang kurang lebih serius di Arduino harus memiliki gagasan tentang waktu nyata saat ini. Misalnya, pembacaan sensor harus terikat waktu (jika tidak, tidak mungkin untuk membuat statistik dan bahkan grafik dasar), pengontrol harus melakukan tindakan tertentu tergantung pada waktu saat ini hari, akhir pekan, liburan, dll. Jika pengontrol Anda tidak tahu tentang waktu nyata, itu berubah menjadi mesin sederhana yang hanya dapat melakukan tindakan dasar pada program yang didefinisikan dengan kaku.Sejak Arduino Mega Serverini adalah sistem yang kuat dan dikembangkan, maka keadaan ini (kurangnya pekerjaan dengan waktu nyata) tidak cocok untuk saya, dan semua pengguna sistem lainnya. Oleh karena itu, masalah integrasi ke dalam sistem RTC adalah salah satu yang pertama dalam agenda.Jam waktu nyata virtual
Semuanya akan baik-baik saja, tetapi baik saya, maupun sebagian besar pengguna AMS memiliki modul RTC "besi" yang sama, sehingga diputuskan untuk melakukan "menunggang kuda" dan, sebagai tindakan sementara, mengatur jam waktu nyata yang bekerja di dalam sistem, tanpa modul fisik nyata. Yang berhasil diimplementasikan.Jadi, bagaimana mengatur RTC virtual, tanpa modul nyata. Ada Perpustakaan Waktu yang luar biasa yang melakukan bagian terbesar dari pekerjaan menyediakan waktu yang akurat bagi kami. Untuk mulai bekerja dengannya, Anda perlu mengunduh, membuka ritsletingnya dan meletakkannya di lokasi standar semua perpustakaan di lingkungan Arduino, yaitu di folder:\rduino\libraries\
Setelah itu, semua kemungkinan bekerja dengan waktu yang disediakannya tersedia bagi kami.Bagaimana itu bekerja
Prinsipnya sangat sederhana. Perpustakaan "meluncurkan" jam virtual "di dalam" controller dan menyediakan kemampuan untuk menyinkronkannya dalam berbagai cara, untuk dipilih. Anda dapat memilih metode yang paling sesuai untuk Anda. Karena Arduino Mega Server adalah perangkat jaringan, opsi untuk menyinkronkan jam melalui jaringan dengan server waktu yang tepat dipilih. Ini bisa berupa server di Internet atau server di jaringan lokal tempat layanan terkait berjalan. Misalnya, dalam versi dasar AMS, jam disinkronkan dengan server MajorDoMo , dan Anda tidak perlu mengonfigurasi apa pun untuk ini, semuanya berfungsi di luar kotak.Jadi, agar ini berfungsi, Anda harus menghubungkan perpustakaan yang sesuai di awal sketsa.#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <Time.h>
File Time.h sebenarnya adalah sebuah perpustakaan untuk bekerja dengan waktu, dan sisa file diperlukan untuk bekerja dengan jaringan dan untuk menyinkronkan waktu menggunakan protokol NTP (perpustakaan Ethernet juga harus diinstal).Selanjutnya, Anda perlu menentukan alamat IP server yang ingin Anda selaraskan waktuIPAddress timeServer(192, 168, 2, 8);
dan port yang sesuaiunsigned int localPort = 8888;
tetapi ada satu titik: port 8888 cocok untuk sinkronisasi pada jaringan lokal, dan sebagian besar server di Internet tidak merespons, jadi jika Anda berencana untuk menyinkronkan waktu dengan server waktu yang tepat di Internet, lebih baik untuk mengatur port 123:unsigned int localPort = 123;
tetap hanya untuk menunjukkan zona waktuconst int timeZone = 4;
dan membuat objek EthernetUDPEthernetUDP Udp;
Mengenai hal ini, operasi persiapan dapat dianggap selesai dan Anda dapat menggambarkan fungsionalitas yang Anda perlukan untuk bekerja seiring waktu. Fungsi inisialisasi:void rtcInit() {
Udp.begin(localPort);
Serial.println("Waiting for NTP sync...");
setSyncProvider(getNtpTime);
}
Di sini Anda perlu memperhatikan fungsinyasetSyncProvider(getNtpTime);
Fungsi ini menetapkan sumber sinkronisasi waktu (dalam hal ini, sinkronisasi NTP melalui jaringan). Tetapi bisa juga sumber lain, misalnya, modul fisik RTC. Kinerja fungsi ini mengarah pada pemasangan sumber sinkronisasi (untuk masa depan) dan, pada saat yang sama, menuju sinkronisasi waktu melalui sumber ini. Pada saat melakukan fungsi ini maka waktu yang tepat "muncul" di sistem Anda.Perpustakaan itu sendiri memiliki fitur menarik lainnya,setSyncInterval(interval);
yang memungkinkan Anda untuk mengatur interval yang diinginkan antara sinkronisasi (diatur dalam detik, sinkronisasi itu sendiri terjadi secara otomatis, tanpa partisipasi Anda).
Sekarang Anda dapat menggunakan waktu yang tepat di dalam sketsa Arduino, misalnya, menampilkan acara di monitor Serial tidak mudah, tetapi terikat dengan waktu yang tepat. Ini dilakukan menggunakan fungsi timeStamp ():void timeStamp() {
serialRTC();
Serial.print(" ");
}
yang merupakan pembungkus untuk fungsi serialRTC ():void serialRTC() {
Serial.print(year());
Serial.print("-");
printDigits(month());
Serial.print("-");
printDigits(day());
Serial.print(" ");
printDigits(hour());
Serial.print(":");
printDigits(minute());
Serial.print(":");
printDigits(second());
}
Analisis mekanisme untuk mentransmisikan dan menampilkan waktu di antarmuka web AMS berada di luar cakupan cerita ini dan layak untuk artikel terpisah dan, jika ada minat, kita dapat menulis sekuel dan menjelaskan secara terperinci bagaimana "keajaiban" tampilan waktu di antarmuka web Arduino Mega Server
Sebenarnya itu saja. Ini adalah bagaimana jam real-time virtual diorganisasikan dalam AMS hingga versi 0.12 inklusif, dan Anda juga dapat mengatur kerja dengan waktu yang akurat dalam proyek Anda, bahkan jika Anda tidak memiliki modul fisik untuk jam real-time. Tapi ini bukan akhir dari cerita, melainkan hanya permulaan.Kode modul RTC penuh dari Arduino Mega Server 0.12/*
Modul Virtual RTC
part of Arduino Mega Server project
*/
// Virtual RTC
IPAddress timeServer(192, 168, 2, 8);
unsigned int localPort = 8888; // local port to listen for UDP packets
EthernetUDP Udp;
const int timeZone = 4;
time_t prevDisplay = 0; // when the digital clock was displayed
void rtcInit() {
Udp.begin(localPort);
Serialprint(«Waiting for NTP sync… \n»);
setSyncProvider(getNtpTime);
modulRtc = 1;
}
void rtcWorks() {
if (timeStatus() != timeNotSet) {
if (now() != prevDisplay) { // update the display only if time has changed
setLifer();
prevDisplay = now();
//digitalClockDisplay();
}
}
}
void printDigits(int digits) {
if(digits < 10) {
Serial.print('0');
}
Serial.print(digits);
}
void serialRTC() {
Serial.print(year());
Serial.print("-");
printDigits(month());
Serial.print("-");
printDigits(day());
Serial.print(" ");
printDigits(hour());
Serial.print(":");
printDigits(minute());
Serial.print(":");
printDigits(second());
}
void timeStamp() {
serialRTC();
Serial.print(" ");
}
void printRTC(){
serialRTC();
Serial.println();
}
// NTP code
const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets
#ifdef RTC_FEATURE
time_t getNtpTime() {
while (Udp.parsePacket() > 0); // discard any previously received packets
Serialprint(«Transmit NTP request\n»);
sendNTPpacket(timeServer);
uint32_t beginWait = millis();
while (millis() — beginWait < 1500) {
int size = Udp.parsePacket();
if (size >= NTP_PACKET_SIZE) {
Serialprint(«Receive NTP response\n»);
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];
return secsSince1900 — 2208988800UL + timeZone * SECS_PER_HOUR;
}
}
Serialprint(«No NTP response\n»);
return 0; // return 0 if unable to get the time
}
// send an NTP request to the time server at the given address
void sendNTPpacket(IPAddress &address) {
// set all bytes in the buffer to 0
memset(packetBuffer, 0, NTP_PACKET_SIZE);
// Initialize values needed to form NTP request
// (see URL above for details on the packets)
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();
}
#endif
// Duration
void showDuration(time_t duration) {
// prints the duration in days, hours, minutes and seconds
Serialprint(" (duration ");
if(duration >= SECS_PER_DAY){
Serial.print(duration / SECS_PER_DAY);
Serialprint(" day ");
duration = duration % SECS_PER_DAY;
}
if(duration >= SECS_PER_HOUR){
Serial.print(duration / SECS_PER_HOUR);
Serialprint(" hour ");
duration = duration % SECS_PER_HOUR;
}
if(duration >= SECS_PER_MIN){
Serial.print(duration / SECS_PER_MIN);
Serialprint(" min ");
duration = duration % SECS_PER_MIN;
}
Serial.print(duration);
Serialprint(" sec) \n");
}
void checkEvent(time_t* prevEvent) {
time_t duration = 0;
time_t timeNow = now();
if (*prevEvent > 0) {
duration = timeNow — *prevEvent;
}
if (duration > 0) {
showDuration(duration);
}
*prevEvent = timeNow;
}
Kejutan yang menyenangkan
Saya tidak akan sibuk mengintegrasikan modul RTC ke dalam sistem untuk waktu yang lama (ada juga cukup tugas mendesak lainnya), tetapi di sini, dalam rangka kerja sama teknologi dengan proyek kami, CHIPSTER menyediakan peralatan untuk pengujian dan integrasi ke dalam AMS, di antaranya terdapat modul Ethernet berdasarkan chip W5500 dan ... modul jam waktu nyata pada chip DS3231 , yang ternyata menjadi yang paling tepat dan berfungsi sebagai pendorong untuk integrasi modul RTC ke dalam sistem.Ternyata perusahaan CHIPSTER tidak hanya menjual peralatan elektronik, tetapi juga mengembangkan produknya sendiri untuk Arduino dan otomatisasi dengan merek Geegrowdan memiliki rencana besar untuk masa depan dalam arah ini, khususnya, ia memiliki proyek untuk rilis versi khusus dari Arduino Mega 2560 dengan fitur-fitur canggih dan "disesuaikan" khusus untuk Server Arduino Mega. Dan, jika papan ini dirilis, itu akan menjadi acara yang sangat menarik. Tetapi kembali ke jam waktu nyata.Jam waktu nyata
Karena modul RTC ada di ujung jari saya, akan menjadi dosa jika tidak mengintegrasikannya ke dalam sistem. Untungnya, ini menjadi sangat sederhana berkat Time Library yang sama. Tetapi hal pertama yang pertama.Bagi mereka yang tidak tahu, ada dua jenis modul waktu nyata - "biasa" (biasanya pada chip DS1307) dan "lanjutan" (pada chip DS3231, yang saya dapatkan). Perbedaan antara keduanya adalah bahwa yang pertama tidak terlalu akurat dan dapat "melarikan diri" dengan sangat cepat dan sangat kuat, dan yang kedua adalah arloji presisi tinggi dengan perawatan yang dinormalisasi tidak lebih dari dua menit setahun, yang sebenarnya berlaku dalam praktik. Dan akurasi dicapai berkat desain sirkuit yang lebih kompleks dan kompensasi termal bawaan.Namun secara pemrograman, kedua versi modul tersebut kompatibel dan keduanya akan bekerja dengan pustaka dan kode. Perbedaannya hanya pada akurasi.Dan tentu saja, salah satu sifat utama jam real-time adalah kemampuan untuk bekerja ketika daya dimatikan, karena baterai bawaan.Koneksi fisik
Sekarang mari kita bicara tentang bagaimana menghubungkan secara fisik modul RTC ke Arduino Mega Server atau ke proyek Arduino Anda. Saya harus mengatakan bahwa ini sangat sederhana dan Anda hanya perlu dua resistor dan beberapa kabel.Sambungan sepele: Anda perlu menemukan empat kontak pada modul Anda - GND (ground), VCC (tegangan suplai), SCL (signal clock), SDA (data). Kontak lain digunakan dalam kasus yang jarang dan spesifik dan Anda dapat mengabaikannya.
Jadi, kami menghubungkan pin GND ke ground, pin VCC ke tegangan suplai pengontrol. Semuanya sederhana di sini dan tidak ada pertanyaan yang muncul.Kesimpulan lainnya tidak jauh lebih rumit. Modul RTC berkomunikasi dengan controller melalui antarmuka I2C, yang hanya memiliki dua kabel: sinkronisasi dan data, dan pengontrol Arduino sudah memiliki kontak untuk menghubungkan antarmuka ini. Arduino Uno adalah A4 (SDA) dan A5 (SCL), sedangkan arduino Mega adalah D20 (SDA) dan D21 (SCL).Satu-satunya kehalusan adalah bahwa pin SCL dan SDA perlu "ditarik" ke sumber daya melalui resistor 4,7 kΩ. Jika Anda tidak memiliki peringkat ini secara tepat, maka Anda dapat menggunakan resistor dari kisaran 2 KOhm - 10 KOhm.
Dukungan perangkat lunak
Sekarang tinggal menambahkan dukungan untuk modul dalam kode AMS atau proyek Anda. Seperti yang saya katakan, itu akan sangat sederhana karena Perpustakaan Waktu yang sama akan bekerja dengan modul. Benar, kita perlu menambahkan perpustakaan lain, yaitu Perpustakaan DS1307RTC . Kami juga membongkar dan meletakkannya di folder perpustakaan standar:\rduino\libraries\
Tambahkan baris berikut ke kode sketsa Anda#include <Wire.h>
#include <DS1307RTC.h>
Sekarang kita sudah lengkap dan kita dapat mulai menulis kode untuk sketsa itu sendiri, bekerja dengan modul fisik RTC. Berfungsivoid rtcInit() {
Udp.begin(localPort);
Serial.println("Waiting for NTP sync...");
setSyncProvider(getNtpTime);
}
ganti stringsetSyncProvider(getNtpTime);
disetSyncProvider(RTC.get);
dan waktu internal Arduino Mega Server (atau pengontrol Anda) akan disinkronkan dengan pengontrol RTC "besi", dan bukan dengan server di Internet atau jaringan lokal. Jadi, dengan memanggil fungsi setSyncProvider (getNtpTime) dan setSyncProvider (RTC.get), Anda dapat memanipulasi sumber sinkronisasi waktu dan menyinkronkan waktu sesuai keinginan, tergantung pada berbagai kondisi.Fungsi lain yang perlu Anda ketahui adalahif (timeStatus() != timeNotSet) {
}
yang memungkinkan Anda untuk mengetahui apakah waktu disinkronkan dan, tergantung pada kondisi ini, mengambil tindakan yang diperlukan.Momen halus
Anda perlu membedakan antara dua hal: waktu yang ada di modul "besi" RTC dan waktu yang ada di controller Anda. Ini bukan hal yang sama. Yang "utama" bagi Anda adalah waktu di controller, dan waktu di modul hanyalah sumber untuk sinkronisasi.Tapi! karena waktu dalam RTC fisik juga secara bertahap “habis”, maka juga perlu disesuaikan dengan menyinkronkan dengan sumber yang lebih akurat, misalnya server di Internet.Oleh karena itu, algoritme yang optimal seharusnya adalah ini: jika memungkinkan, kemudian menyinkronkan semua jam dengan server di Internet, jika jaringan tidak tersedia, maka kami mulai menyinkronkan waktu dalam pengontrol dengan modul RTC, segera setelah jaringan muncul, kembali ke sinkronisasi melalui Internet.Jika Anda berada dalam kondisi ekstrem, tanpa akses ke sumber sinkronisasi apa pun, Anda dapat secara manual menyesuaikan arah jam besi dari waktu ke waktu.Sebagai contoh, mari kita perhatikan fungsi sinkronisasi jam internal controller dan modul RTC melalui jaringan:void rtcSync() {
setSyncProvider(getNtpTime);
Serial.println("...getNtpTime...");
if (timeStatus() != timeNotSet) {
Serial.println("...set!...");
time_t t = getNtpTime();
RTC.set(t);
setSyncProvider(RTC.get);
}
}
Di sini kita pertama kali mendapatkan waktu yang tepat melalui jaringan.setSyncProvider(getNtpTime);
kemudian, jika berhasil, pasang di modul RTCRTC.set(t);
dan kemudian dari modul ini kita atur waktu pengontrolsetSyncProvider(RTC.get);
Peluncuran awal
Tapi itu belum semuanya. Ada juga masalah start-up awal, ketika modul RTC hanya terhubung, tetapi waktu di dalamnya tidak diatur dan oleh karena itu tidak mungkin untuk melakukan sinkronisasi dengannya. Anda perlu entah bagaimana mengatur waktu yang tepat di dalamnya. Ada dua cara untuk mengatasi masalah ini di Server Arduino Mega: Anda dapat menyinkronkan RTC fisik melalui jaringan (jika server waktu tersedia) atau menggunakan utilitas Arduino Serial Commander.Untuk mengatur waktu dalam modul RTC, cukup ... klik pada tombol. Segala sesuatu yang lain akan dilakukan untuk Anda oleh dua pemuda bernama Arduino Mega Server dan Arduino Serial Commander. Jika Anda tidak menggunakan AMS, tetapi sedang mengembangkan proyek Anda sendiri, Anda dapat mengambil kode dari kit distribusi Arduino Mega Server (kode tersedia dan benar-benar gratis) atau mencari solusi untuk masalah ini di Internet (ada beberapa solusi).
Versi dengan dukungan RTC nyata
Arduino Mega Server, dimulai dengan versi 0.13, mendukung RTC "besi". Anda dapat mengunduh versi terbaru saat ini dari situs web resmi proyek , dan Anda dapat mengajukan pertanyaan di forum .Dan, tentu saja, saya mengucapkan terima kasih kepada CHIPSTER atas kerja sama dan peralatan yang disediakan untuk pengujian dan integrasi (saya akan memberi tahu Anda tentang modul W5500 dan percepatan operasi jaringan AMS di salah satu artikel berikut).Selain itu . Saluran Youtube terbuka dan berikut ini adalah video promo dari Arduino Mega Server, yang menunjukkan cara bekerja dengan sistem nyata.