2. Serial Monitor

Pada halaman ini kita akan membahas bagaimana menambahkan Serial Monitor ke Outseal, yaitu dengan menggunakan bantuan Arduino Nano (bisa juga menggunakan Arduino Uno atau Mega) dan library modbus-esp8266

Diinginkan dengan Serial Monitor ini, kita bisa melakukan beberapa hal berikut ini:
  1. Menampilkan data Coil di Serial Monitor
  2. Menampilkan data Input Diskrit di Serial Monitor
  3. Menampilkan data Input Register di Serial Monitor
  4. Menampilkan data Holding Register di Serial Monitor
  5. Mengirim data Coil dari Serial Monitor
  6. Mengirim data Holding Register dari Serial Monitor
Oya, sebelum menunjukkan langkah-langkah pembuatan keenam hal di atas, bagi rekan-rekan yang masih belum "kenal dekat" dengan modbus, saya akan memberikan sekedar ilustrasi singkat mengenai gambaran dari modbus. 

Bayangkan rekan-rekan sedang berada di sebuah perpustakaan dengan banyak buku di rak-rak yang diberi nomor tertentu sesuai posisinya. Anggap ada 4 rak buku. Keempat rak buku ini, kalau di protokol Modbus, merupakan tipe memori, yang juga terdiri dari 4 buah tipe, seperti terlihat pada tabel berikut (tabel ini saya kutip dari buku Panduan dasar Outseal PLC oleh Bpk. Agung Bakhtiar, yang dapat diunduh secara gratis di www.outseal.com):

Tabel 1. Tipe Memori Data di Protokol Modbus

Terlihat pada Tabel di atas, 4 tipe memori tersebut adalah Coil, Input Diskrit, Input Register dan Holding Register. Untuk tipe memori Coil dan Input Diskrit, ukuran setiap memorinya adalah 1 bit (sering disebut sebagai data digital), sedangkan untuk Input Register dan Holding Register, ukuran setiap memorinya adalah 16 bit (sering disebut sebagai data analog). 

Berikutnya, untuk membaca beberapa buku di rak tertentu, teman-teman harus meminta kepada petugas perpustakaan. Dalam ilustrasi ini, teman-teman berperan sebagai Master di Modbus, sedangkan petugas perpustakaan berperan sebagai Slave di Modbus. Ternyata di perpustakaan ini, teman-teman tidak hanya bisa membaca buku saja, tetapi diperbolehkan juga untuk menulis buku. Sesuai aturan Modbus, semua buku di keempat rak dapat dibaca, tetapi untuk buku-buku yang bisa ditulis, hanyalah buku-buku yang diletakkan di rak pertama (Coil), dan rak keempat (Holding Register). Baik untuk membaca maupun menulis, protokol Modbus menetapkan kode permintaan atau kode fungsi sesuai tabel berikut:

Tabel 2. Kode Fungsi di Protokol Modbus

Berikutnya, karena tidak hanya 1 perpustakaan (Slave) yang bisa diakses (dibaca dan ditulis) bukunya, maka setiap perpustakaan (Slave) harus memiliki nomor ID Slave tertentu. Jadi agar Master dapat membaca/menulis buku di Slave tertentu, Master harus mengirimkan kode permintaan dalam bentuk angka, dengan urutan sebagai berikut:
  1. No ID Slave
  2. Kode fungsi
  3. Alamat awal data
  4. Jumlah data/Nilai data
Untuk kode permintaan yang nomor 4, isinya tergantung pada kode fungsi. Apabila kode fungsinya membaca, maka nomor 4 haruslah jumlah atau banyaknya data yang ingin dibaca. Apabila kode fungsinya menulis, maka nomor 4 haruslah nilai data yang akan dituliskan.

Dengan membuat urutan kode permintaan di atas di-"baku"-kan, membuat penerapan protokol Modbus ini menjadi hal yang menarik, karena kita bisa mengakses banyak data, tidak hanya data di satu Slave, tetapi bisa hingga 247 Slave. 

Hal menarik berikutnya, yang membuat saya suka produk Outseal adalah, secara default, 5 buah variabel di Outseal, telah dialokasikan pada keempat tipe memori Modbus. Berikut ini nama-nama variabel di Outseal dan alamatnya di memori Modbus:

Tabel 3. Alokasi variabel Outseal di memori Modbus

Keterangan:
  • S = Switch, R = Relay, A = Analog, B = Binary, I = Integer.
  • Jumlah variabel pada tabel di atas adalah jumlah ideal. Pada prakteknya, jumlah variabel tersebut dibatasi dengan jumlah kaki I/O dan memori yang tersedia pada hardware. 
  • Sebagai contoh untuk hardware Outseal Nano, jumlah variabel Input Digital = 8 (S.1 - S.8), jumlah variabel Output Digital = 8 (R.1 - R.8), dan jumlah variabel Input Analog = 2 (A.1 - A.2). Sedangkan jumlah memori digital dan analog tergantung pada ukuran memori yang masih tersedia pada memori program.
Demikian info singkat tentang Modbus dan Outseal. Apabila rekan-rekan masih belum jelas, saya sarankan sebaiknya teman-teman mengunjungi sumber informasinya, yaitu di www.outseal.com. Di halaman web tersebut, teman-teman bisa mendapatkan panduan dan software yang gratis, serta banyak informasi mengenai penerapan Modbus pada Outseal.

Agar tidak terlalu panjang tulisannya, mari kita lanjutkan dengan langkah-langkah penambahan Serial Monitor.

1. Menampilkan data Coil di Serial Monitor 

Berhubung saat ini saya tidak memiliki Outseal, maka dalam penjelasan langkah-langkah di sini, saya akan menggunakan software simulator Proteus. Sekalipun hanya simulasi, namun hal yang menarik, hasilnya bisa sama dengan hasil pada hardware riilnya. Di samping hasil simulasinya yang bagus, juga gambar skematik yang dihasilkan dengan software Proteus lebih rapi dan mudah dipahami.

1.1 Kebutuhan 
Dibutuhkan beberapa hal berikut ini:
  1. Rangkaian Outseal Nano dengan 8 buah tombol (S.1 - S.8) dan 8 buah LED (R.1 - R.8).
  2. Rangkaian Arduino Nano yang terhubung dengan Outseal Nano secara modbus, sehingga dapat menampilkan data Outseal ke Serial Monitor.
  3. Ketika tombol S.1 ditekan, LED R.1 akan menyala. Ketika tombol S.2 dilepas, LED R.1 padam. Sama seperti tombol S.1, begitu pula tombol S.2 - S.8, masing-masing bisa menghidup matikan LED di R.2 - R.8, sesuai posisinya.
  4. Semua status R.1 - R.8 itu dapat ditampilkan datanya di Serial Monitor, yang disimulasikan dengan Virtual Terminal.

1.2 Rangkaian Outseal Nano dan Arduino Nano
Berikut ini gambar rangkaian untuk menjawab kebutuhan di atas. Baik Outseal Nano maupun Arduino Nano, keduanya menggunakan komponen ATmega328. Di sini Outseal Nano menjadi modbus Slave, dengan alamat modbus = 1, sedangkan Arduino Nano menjadi modbus Master.

Gambar 1. Rangkaian Outseal Nano dengan input outputnya, yang terhubung secara modbus dengan Arduino Nano (komunikasi RS232)

Rekan-rekan dapat mengunduh file Proteus Gambar 1 di atas di bagian terakhir dari materi di halaman ini.

Penggunaan komponen ATmega328P sebagai Arduino Nano, memiliki persamaan kaki seperti diperlihatkan pada gambar berikut:

Gambar 2. Persamaan kaki komponen ATmega328P dengan Arduino Nano

Catatan:
Agar Proteus bisa mensimulasikan Arduino dan juga Outseal, rekan-rekan perlu meng-klik 2 kali komponen ATmega328 tersebut, dan kemudian mengisi datanya mengikuti 4 isian berikut ini:

Gambar 3. Pengaturan isian komponen ATmega328 agar bisa disimulasikan

Keterangan:
  1. Program File harus diisi dengan direktori lokasi file Hex hasil kompilasi. 
    • Untuk file Hex Outseal, rekan-rekan bisa menemukan lokasinya di C:\Users\"nama user"\AppData\Local\Temp\Outseal\"nama file hex"
    • Sedangkan untuk file Hex Arduino, rekan-rekan bisa menemukan direktorinya di kotak Output (apabila lokasi file Hex tidak muncul di kotak Output, buka Preferences di menu File, beri centang pada pilihan Compile, di baris "Show verbose output during").
  2. CLKDIV8 (Divide clock by 8) = (1) Unprogrammed.
  3. CKSEL Fuses = (0000) Ext. Clock.
  4. Clock Frequency = 16 MHz.

1.3 Program Outseal Nano (sebagai Slave)
Berikut ini program Ladder Diagram Outseal Nano untuk membaca 8 buah tombol di S.1 - S.8, dan nilai pembacaannya digunakan untuk menghidup-matikan kedelapan LED di R.1 - R.8. Di jendela Settings, pilih Hardware = Nano V5, Baudrate = 9600, dan alamat modbus = 1 (slave address).

Gambar 4. Program Ladder Diagram Outseal Nano untuk menghidup-matikan 8 LED (R.1 - R.8) dengan 8 tombol (S.1 - S.8) 

Rekan-rekan dapat mengunduh file Ladder Diagram Gambar 4 di atas di bagian terakhir dari materi di halaman ini.

1.4 Program Arduino Nano (sebagai Master)
Ada 3 alternatif cara untuk menampilkan data Coil di Serial Monitor, yaitu:
a. Menampilkan data Coil secara periodik.
b. Menampilkan data Coil hanya ketika data tersebut berubah.
c. Menampilkan data Coil ketika tombol di Arduino Nano ditekan. 
 
1.4.a Menampilkan data Coil secara periodik: 
Berikut ini kode program Arduino Nano untuk menampilkan data Coil (variabel R) secara periodik:
  1. #include <ModbusRTU.h>
  2. #include <SoftwareSerial.h>
  3. SoftwareSerial mySerial(2, 3);  // RX, TX
  4. ModbusRTU mb;
  5. bool coil[10];  // variabel untuk menyimpan data coil
  6. unsigned long skr = 0;
  7. void setup() {
  8.   Serial.begin(9600);
  9.   mySerial.begin(9600);
  10.   mb.begin(&mySerial);
  11.   mb.setBaudrate(9600);
  12.   mb.master();
  13.   mb.readCoil(1, 0, coil, 8);  //hanya untuk trigger
  14.   while (mb.slave()) {
  15.     mb.task();
  16.     delay(10);
  17.   }
  18.   delay(1000);
  19. }
  20. void loop() {
  21.   if (millis() - skr > 5000) {  //setiap 5 detik
  22.     skr = millis();
  23.     mb.readCoil(1, 0, coil, 8);  //(id,alamat,variabel,jumlah);
  24.     while (mb.slave()) {
  25.       mb.task();
  26.       delay(10);
  27.     }
  28.     Serial.print("R.1-R.8 = ");
  29.     for (int i = 0; i < 8; i++) {
  30.       Serial.print(coil[i]);
  31.     }
  32.     Serial.println();
  33.   }
  34. }
Keterangan: 
Program di atas akan membuat Serial Monitor menampilkan data Coil (variabel R) secara periodik setiap 5 detik sekali. Kerugian dari cara ini adalah Serial Monitor akan dibuat bekerja terus-menerus menampilkan data, meskipun data yang ditampilkan sama dengan data sebelumnya. Rekan-rekan dapat mengunduh file program Arduino di atas di bagian terakhir dari materi di halaman ini.

Berikut ini tampilan hasil programnya:

 Gambar 5. Serial Monitor menampilkan data Coil (variabel R) secara periodik setiap 5 detik

1.4.b Menampilkan data Coil hanya ketika data berubah: 
Untuk mengatasi kekurangan cara pertama, maka di cara kedua ini dibuat agar Serial Monitor hanya menampilkan data apabila datanya berbeda dengan data sebelumnya. Berikut ini kode program Arduino Nano untuk menampilkan data Coil (variabel R) hanya ketika data berubah:
  1. #include <ModbusRTU.h>
  2. #include <SoftwareSerial.h>
  3. SoftwareSerial mySerial(2, 3);  // RX, TX
  4. ModbusRTU mb;
  5. bool coil[10];  // variabel untuk menyimpan data coil
  6. bool coilR[10];  
  7. bool tampil = false;
  8. unsigned long skr = 0;
  9. void setup() {
  10.   Serial.begin(9600);
  11.   mySerial.begin(9600);
  12.   mb.begin(&mySerial);
  13.   mb.setBaudrate(9600);
  14.   mb.master();
  15.   mb.readCoil(1, 0, coil, 8);  //hanya untuk trigger
  16.   while (mb.slave()) {
  17.     mb.task();
  18.     delay(10);
  19.   }
  20.   delay(1000);
  21. }
  22. void loop() {
  23.   if (millis() - skr > 100) {  //setiap 100milidetik
  24.     skr = millis();
  25.     mb.readCoil(1, 0, coil, 8);
  26.     while (mb.slave()) {
  27.       mb.task();
  28.       delay(10);
  29.     }
  30.     tampil = false;
  31.     for (int i = 0; i < 8; i++) {  //cek kesamaan
  32.       if (coil[i] != coilR[i]) {
  33.         tampil = true;
  34.         break;
  35.       }
  36.     }
  37.     if (tampil) {
  38.       Serial.print("R.1-R.8 = ");
  39.       for (int i = 0; i < 8; i++) {
  40.         Serial.print(coil[i]);
  41.         coilR[i] = coil[i];
  42.       }
  43.       Serial.println();
  44.     }
  45.   }
  46. }
Keterangan: 
Program di atas akan membuat Serial Monitor hanya menampilkan data apabila nilai data Coil (variabel R) berubah. Sekalipun Serial Monitor hanya menampilkan data yang berubah saja, tetapi cara ini masih memiliki kekurangan, yaitu jalur Modbus akan selalu terpakai oleh Arduino Nano yang menjadi Master. Sehingga penambahan Master RTU yang kedua tidak dimungkinkan, karena Arduino Nano selalu mengirimkan permintaan data. Rekan-rekan dapat mengunduh file program Arduino di atas di bagian terakhir dari materi di halaman ini.

Berikut ini tampilan hasil programnya:

 Gambar 6. Serial Monitor menampilkan data Coil hanya bila variabel R atau B berubah

1.4.c Menampilkan data Coil ketika tombol di Arduino Nano ditekan: 
Untuk mengatasi kekurangan cara kedua, cara ketiga ini menggunakan bantuan sebuah tombol yang terhubung dengan kaki D4 Arduino Nano, seperti gambar rangkaian berikut. 

Gambar 7. Menambahkan tombol untuk menampilkan data Coil di Serial Monitor

Rekan-rekan dapat mengunduh file Proteus Gambar 7 di atas di bagian terakhir dari materi di halaman ini.

Berikut ini kode program Arduino Nano untuk rangkaian pada Gambar 7 di atas:
  1. #include <ModbusRTU.h>
  2. #include <SoftwareSerial.h>
  3. SoftwareSerial mySerial(2, 3);  // RX, TX
  4. ModbusRTU mb;
  5. bool coil[10];
  6. int tampil = 0;
  7. int R = 0;
  8. void setup() {
  9.   Serial.begin(9600);
  10.   mySerial.begin(9600);
  11.   mb.begin(&mySerial);
  12.   mb.setBaudrate(9600);
  13.   mb.master();
  14.   pinMode(4, INPUT_PULLUP);
  15.   mb.readCoil(1, 0, coil, 8);  //hanya untuk trigger
  16.   while (mb.slave()) {
  17.     mb.task();
  18.     delay(10);
  19.   }
  20.   delay(1000);
  21. }
  22. void loop() {
  23.   tampil = !digitalRead(4);
  24.   if (tampil && tampil != R) {
  25.     mb.readCoil(1, 0, coil, 8);  //(id,alamat,variabel,jumlah)
  26.     while (mb.slave()) {
  27.       mb.task();
  28.       delay(10);
  29.     }
  30.     Serial.print("R.1-R.8 = ");
  31.     for (int i = 0; i < 8; i++) Serial.print(coil[i]);
  32.     Serial.println();
  33.   }
  34.   R = tampil;
  35. }
Keterangan:
Ketika tombol TAMPIL ditekan, maka Arduino Nano akan mengirimkan permintaan pembacaan data variabel R. Permintaan yang dilakukan oleh Arduino Nano ini tidak dilakukan terus-menerus, hanya sesaat ketika tombol ditekan. Dengan membuat permintaan data dilakukan hanya sesaat, memungkinkan dilakukan penambahan Master RTU lagi pada rangkaian, karena setiap Master RTU tersebut dapat dibuat bekerja secara sesaat dan bergiliran. Rekan-rekan dapat mengunduh file program Arduino di atas di bagian terakhir dari materi di halaman ini.

Berikut ini tampilan hasil program ketika tombol TAMPIL ditekan:

Gambar 8. Serial Monitor menampilkan data Coil (variabel R) setiap kali tombol TAMPIL ditekan 

Catatan:
Setelah berhasil menampilkan data Coil (variabel R) dengan beberapa alternatif cara, maka agar dapat menunjukkan bahwa protokol modbus ini dapat menghubungkan banyak perangkat, untuk selanjutnya, akan ditambahkan Outseal Mega. Berhubung di bagian ini hanya menggunakan 1 Master RTU, maka di bagian ini akan digunakan cara kedua, yaitu Serial Monitor hanya menampilkan data ketika data Coil tersebut berubah. Ketika ada penambahan Master RTU, sehingga Master RTU lebih dari 1, pada kondisi ini, barulah akan digunakan cara ketiga, yang bisa membuat permintaan data oleh Master RTU hanya sesaat ketika tombol ditekan. Cara ketiga ini akan diterapkan pada topik Penampil Data, yang menggunakan lebih dari 1 Master RTU. 

1.5 Rangkaian Outseal Nano, Outseal Mega dan Arduino Nano
Dibutuhkan penambahan hal-hal berikut ini:
  1. Pada rangkaian Gambar 1 di atas, tambahkan rangkaian Outseal Mega dengan 16 buah tombol dan 16 buah LED 
  2. Sama seperti Outseal Nano, buat ke-16 tombol di Outseal Mega dapat menghidup matikan ke-16 LED satu persatu. 
  3. Semua nilai atau status Coil (variabel R) di Outseal Nano dan Outseal Mega dapat ditampilkan datanya di Serial Monitor.
Gambar 9. Rangkaian Outseal Nano, Outseal Mega dan Arduino Nano (komunikasi RS485)

Catatan:
Berhubung label nama pin di Proteus harus berbeda untuk komponen yang berbeda, maka untuk pin input digital di Outseal Mega, yang harusnya S.1 - S.16, terpaksa harus diganti labelnya menjadi T.1 - T.16, karena label S.1 - S.8 sudah dipakai untuk pin input digital Outseal Nano. Begitu pula untuk pin output digital di Outseal Mega, yang harusnya R.1 - R.16, karena sudah dipakai labelnya oleh Outseal Nano, maka terpaksa harus diganti labelnya menjadi U.1 - U.16. Begitu pula untuk pin input analog, yang harusnya A.1 - A.2, karena sudah dipakai labelnya oleh Outseal Nano, maka terpaksa harus diganti labelnya menjadi E.1 - E.2. Penamaan label ini hanya sekedar agar Proteus bekerja. Untuk nama variabel sebenarnya di program Ladder Diagram Outseal, tetap menggunakan S untuk input digital, R untuk output digital, dan A untuk input analog. Rekan-rekan dapat mengunduh file Proteus Gambar 9 di atas di bagian terakhir dari materi di halaman ini.

1.6 Program Outseal Mega (sebagai Slave 2):
Berikut ini program Ladder Diagram Outseal Mega untuk membaca 16 buah tombol di S.1 - S.16, dan nilai pembacaannya digunakan untuk menghidup-matikan ke-16 LED di R.1 - R.16. Di jendela Settings, pilih Hardware = Mega V3, Baudrate = 9600, dan alamat modbus = 2 (slave address).

Gambar 10. Program Ladder Diagram Outseal Mega untuk rangkaian di Gambar 9

Rekan-rekan dapat mengunduh file program Ladder Diagram Gambar 10 di atas di bagian terakhir dari materi di halaman ini.

1.7 Program Arduino Nano (sebagai Master):
Berikut ini kode program Arduino Nano untuk menampilkan data Coil (variabel R) di Serial Monitor, baik data Coil di Outseal Nano maupun Outseal Mega. Serial Monitor akan menampilkan data setiap kali terjadi perubahan data Coil.
  1. #include <ModbusRTU.h>
  2. #include <SoftwareSerial.h>
  3. SoftwareSerial mySerial(2, 3);  // RX, TX
  4. ModbusRTU mb;
  5. bool coil[20];  // variabel untuk menyimpan data coil
  6. bool coilR1[10];
  7. bool coilR2[20];
  8. int urut = 0;
  9. int tampil = 0;
  10. unsigned long skr = 0;
  11. void setup() {
  12.   Serial.begin(9600);
  13.   mySerial.begin(9600);
  14.   mb.begin(&mySerial);
  15.   mb.setBaudrate(9600);
  16.   mb.master();
  17.   mb.readCoil(1, 0, coil, 8);  //hanya untuk trigger
  18.   while (mb.slave()) {
  19.     mb.task();
  20.     delay(10);
  21.   }
  22.   delay(1000);
  23. }
  24. void loop() {
  25.   if (millis() - skr > 100) {  //setiap 100milidetik
  26.     skr = millis();
  27.     urut++;
  28.     if (urut > 2) urut = 1;
  29.     switch (urut) {
  30.       case 1:
  31.         mb.readCoil(1, 0, coil, 8);
  32.         break;
  33.       case 2:
  34.         mb.readCoil(2, 0, coil, 16);
  35.         break;
  36.     }
  37.     while (mb.slave()) {
  38.       mb.task();
  39.       delay(10);
  40.     }
  41.     switch (urut) {
  42.       case 1:
  43.         for (int i = 0; i < 8; i++) {  //cek kesamaan
  44.           if (coil[i] != coilR1[i]) {
  45.             tampil = 1;
  46.             break;
  47.           }
  48.         }
  49.         break;
  50.       case 2:
  51.         for (int i = 0; i < 16; i++) {  //cek kesamaan
  52.           if (coil[i] != coilR2[i]) {
  53.             tampil = 2;
  54.             break;
  55.           }
  56.         }
  57.         break;
  58.     }
  59.     switch (tampil) {
  60.       case 1:
  61.         Serial.print("R.1-R.8 = ");
  62.         for (int i = 0; i < 8; i++) {
  63.           Serial.print(coil[i]);
  64.           coilR1[i] = coil[i];
  65.         }
  66.         Serial.println();
  67.         tampil = 0;
  68.         break;
  69.       case 2:
  70.         Serial.print("R.1-R.16 = ");
  71.         for (int i = 0; i < 16; i++) {
  72.           Serial.print(coil[i]);
  73.           coilR2[i] = coil[i];
  74.         }
  75.         Serial.println();
  76.         tampil = 0;
  77.         break;
  78.     }
  79.   }
  80. }
Keterangan
Setiap 100 milidetik, Arduino akan mengirimkan permintaan pembacaan data ke Slave 1 (Outseal Nano) dan Slave 2 (Outseal Mega) secara berurutan. Data Coil yang dibaca di Slave 1 berukuran 8 bit, sedangkan data Coil di Slave 2 berukuran 16 bit. Apabila data yang diberikan sama dengan data sebelumnya, Arduino tidak akan menampilkan datanya. Apabila datanya berbeda, Arduino akan menampilkan datanya di Serial Monitor. Rekan-rekan dapat mengunduh file program Arduino di atas di bagian terakhir dari materi di halaman ini.

Berikut ini tampilan hasil programnya:

Gambar 11. Serial Monitor menampilkan data Coil Slave1 dan Slave2 ketika data Coil tersebut berubah

2. Menampilkan data Input Diskrit di Serial Monitor

Diinginkan untuk bisa menampilkan data Coil dan Input Diskrit Outseal Nano dan Outseal Mega di Serial Monitor.

2.1 Rangkaian Pembacaan Input Diskrit

Menggunakan rangkaian yang sama dengan Gambar 9.

2.2 Program Outseal Nano (Slave 1)
Menggunakan program Ladder Diagram yang sama dengan Gambar 4.

2.3 Program Outseal Mega (Slave 2)
Menggunakan program Ladder Diagram yang sama dengan Gambar 10.

2.4 Program Arduino Nano (Master)

Berikut ini program Arduino Nano untuk menampilkan data Coil dan Input Diskrit Outseal Nano dan Outseal Mega di Serial Monitor.
  1. #include <ModbusRTU.h>
  2. #include <SoftwareSerial.h>
  3. SoftwareSerial mySerial(2, 3);  // RX, TX
  4. ModbusRTU mb;
  5. bool coil[20];  // variabel untuk menyimpan data coil
  6. bool coil1[10];
  7. bool coil2[20];
  8. bool disk[20];  // variabel untuk menyimpan data coil
  9. bool disk1[10];
  10. bool disk2[20];
  11. int urut = 0;
  12. int tampil = 0;
  13. unsigned long skr = 0;
  14. void setup() {
  15.   Serial.begin(9600);
  16.   mySerial.begin(9600);
  17.   mb.begin(&mySerial);
  18.   mb.setBaudrate(9600);
  19.   mb.master();
  20.   mb.readCoil(1, 0, coil, 8);  //hanya untuk trigger
  21.   while (mb.slave()) {
  22.     mb.task();
  23.     delay(10);
  24.   }
  25.   delay(1000);
  26. }
  27. void loop() {
  28.   if (millis() - skr > 100) {  //setiap 100milidetik
  29.     skr = millis();
  30.     urut++;
  31.     if (urut > 4) urut = 1;
  32.     switch (urut) {
  33.       case 1:
  34.         mb.readCoil(1, 0, coil, 8);
  35.         break;
  36.       case 2:
  37.         mb.readCoil(2, 0, coil, 16);
  38.         break;
  39.       case 3:
  40.         mb.readIsts(1, 0, disk, 8);
  41.         break;
  42.       case 4:
  43.         mb.readIsts(2, 0, disk, 16);
  44.         break;
  45.     }
  46.     while (mb.slave()) {
  47.       mb.task();
  48.       delay(10);
  49.     }
  50.     switch (urut) {
  51.       case 1:
  52.         for (int i = 0; i < 8; i++) {  //cek kesamaan
  53.           if (coil[i] != coil1[i]) {
  54.             tampil = 1;
  55.             break;
  56.           }
  57.         }
  58.         break;
  59.       case 2:
  60.         for (int i = 0; i < 16; i++) {  //cek kesamaan
  61.           if (coil[i] != coil2[i]) {
  62.             tampil = 2;
  63.             break;
  64.           }
  65.         }
  66.         break;
  67.       case 3:
  68.         for (int i = 0; i < 8; i++) {  //cek kesamaan
  69.           if (disk[i] != disk1[i]) {
  70.             tampil = 3;
  71.             break;
  72.           }
  73.         }
  74.         break;
  75.       case 4:
  76.         for (int i = 0; i < 16; i++) {  //cek kesamaan
  77.           if (disk[i] != disk2[i]) {
  78.             tampil = 4;
  79.             break;
  80.           }
  81.         }
  82.         break;
  83.     }
  84.     switch (tampil) {
  85.       case 1:
  86.         Serial.print("R.1-R.8 = ");
  87.         for (int i = 0; i < 8; i++) {
  88.           Serial.print(coil[i]);
  89.           coil1[i] = coil[i];
  90.         }
  91.         Serial.println();
  92.         tampil = 0;
  93.         break;
  94.       case 2:
  95.         Serial.print("R.1-R.16 = ");
  96.         for (int i = 0; i < 16; i++) {
  97.           Serial.print(coil[i]);
  98.           coil2[i] = coil[i];
  99.         }
  100.         Serial.println();
  101.         tampil = 0;
  102.         break;
  103.       case 3:
  104.         Serial.print("S.1-S.8 = ");
  105.         for (int i = 0; i < 8; i++) {
  106.           Serial.print(disk[i]);
  107.           disk1[i] = disk[i];
  108.         }
  109.         Serial.println();
  110.         tampil = 0;
  111.         break;
  112.       case 4:
  113.         Serial.print("S.1-S.16 = ");
  114.         for (int i = 0; i < 16; i++) {
  115.           Serial.print(disk[i]);
  116.           disk2[i] = disk[i];
  117.         }
  118.         Serial.println();
  119.         tampil = 0;
  120.         break;
  121.     }
  122.   }
  123. }

Berikut ini tampilan hasil programnya:

Gambar 12. Setiap kali tombol ditekan, maka Serial Monitor akan menampilkan data input diskrit (variabel S), dan juga Coil (variabel R)

Semua input digital (tombol) di Outseal merupakan variabel S, yang juga merupakan data modbus Input Diskrit. Berhubung di program Ladder Diagram Outseal Nano dan Outseal Mega, semua variabel S telah dihubungkan dengan variabel R, maka terlihat di Serial Monitor, data variabel S sama dengan data variabel R.

3. Menampilkan data Input Register di Serial Monitor

Diinginkan untuk bisa menampilkan data Coil, Input Diskrit dan Input Register di Serial Monitor. Data modbus Input Register ini terkait dengan variabel A di Outseal. Variabel A ini muncul sebagai kaki input analog di hardware Outseal. Agar bisa mengisi nilai variabel A ini, tambahkan 2 buah Potensio yang dihubungkan ke kaki A6 dan A7 di Outseal Nano, dan juga 2 buah Potensio di kaki PF0 dan PF1 Outseal Mega.

3.1 Rangkaian dengan tambahan 4 Potensio

Gambar 13. 2 buah Potensio di Outseal Nano dan Outseal Mega untuk pengaturan nilai Input Register

3.2 Program Outseal Nano (Slave 1)
Berikut ini program Ladder Diagram untuk pengaturan data Input Register (nilai analog) menggunakan 2 buah Potensio di Outseal Nano.

Gambar 14. Program Ladder Diagram untuk pembacaan Coil, Input Diskrit dan Input Regster di Outseal Nano

3.3 Program Outseal Mega (Slave 2)
Berikut ini program Ladder Diagram untuk pengaturan data Input Register (nilai analog) menggunakan 2 buah Potensio di Outseal Mega.

Gambar 15. Program Ladder Diagram untuk pembacaan Coil, Input Diskrit dan Input Regster di Outseal Mega

3.4 Program Arduino Nano (Master)
Berikut ini program Arduino Nano untuk menampilkan data Coil, Input Diskrit dan Input Register Outseal Nano dan Outseal Mega di Serial Monitor.

  1. #include <ModbusRTU.h>
  2. #include <SoftwareSerial.h>
  3. SoftwareSerial mySerial(2, 3);  // RX, TX
  4. ModbusRTU mb;
  5. bool coil[20];
  6. bool coil1[10];
  7. bool coil2[20];
  8. bool disk[20];
  9. bool disk1[10];
  10. bool disk2[20];
  11. uint16_t an[4];
  12. uint16_t an1[4];
  13. uint16_t an2[4];
  14. int urut = 0;
  15. int tampil = 0;
  16. unsigned long skr = 0;
  17. void setup() {
  18.   Serial.begin(9600);
  19.   mySerial.begin(9600);
  20.   mb.begin(&mySerial);
  21.   mb.setBaudrate(9600);
  22.   mb.master();
  23.   mb.readCoil(1, 0, coil, 8);  //hanya untuk trigger
  24.   while (mb.slave()) {
  25.     mb.task();
  26.     delay(10);
  27.   }
  28.   delay(1000);
  29. }
  30. void loop() {
  31.   if (millis() - skr > 100) {  //setiap 100milidetik
  32.     skr = millis();
  33.     urut++;
  34.     if (urut > 6) urut = 1;
  35.     switch (urut) {
  36.       case 1:
  37.         mb.readCoil(1, 0, coil, 8);
  38.         break;
  39.       case 2:
  40.         mb.readCoil(2, 0, coil, 16);
  41.         break;
  42.       case 3:
  43.         mb.readIsts(1, 0, disk, 8);
  44.         break;
  45.       case 4:
  46.         mb.readIsts(2, 0, disk, 16);
  47.         break;
  48.       case 5:
  49.         mb.readIreg(1, 0, an, 2);
  50.         break;
  51.       case 6:
  52.         mb.readIreg(2, 0, an, 2);
  53.         break;
  54.     }
  55.     while (mb.slave()) {
  56.       mb.task();
  57.       delay(10);
  58.     }
  59.     switch (urut) {
  60.       case 1:
  61.         for (int i = 0; i < 8; i++) {  //cek kesamaan
  62.           if (coil[i] != coil1[i]) {
  63.             tampil = 1;
  64.             break;
  65.           }
  66.         }
  67.         break;
  68.       case 2:
  69.         for (int i = 0; i < 16; i++) {  //cek kesamaan
  70.           if (coil[i] != coil2[i]) {
  71.             tampil = 2;
  72.             break;
  73.           }
  74.         }
  75.         break;
  76.       case 3:
  77.         for (int i = 0; i < 8; i++) {  //cek kesamaan
  78.           if (disk[i] != disk1[i]) {
  79.             tampil = 3;
  80.             break;
  81.           }
  82.         }
  83.         break;
  84.       case 4:
  85.         for (int i = 0; i < 16; i++) {  //cek kesamaan
  86.           if (disk[i] != disk2[i]) {
  87.             tampil = 4;
  88.             break;
  89.           }
  90.         }
  91.         break;
  92.       case 5:
  93.         for (int i = 0; i < 2; i++) {  //cek kesamaan
  94.           if (an[i] != an1[i]) {
  95.             tampil = 5;
  96.             break;
  97.           }
  98.         }
  99.         break;
  100.       case 6:
  101.         for (int i = 0; i < 2; i++) {  //cek kesamaan
  102.           if (an[i] != an2[i]) {
  103.             tampil = 6;
  104.             break;
  105.           }
  106.         }
  107.         break;
  108.     }
  109.     switch (tampil) {
  110.       case 1:
  111.         Serial.print("R.1-R.8 = ");
  112.         for (int i = 0; i < 8; i++) {
  113.           Serial.print(coil[i]);
  114.           coil1[i] = coil[i];
  115.         }
  116.         Serial.println();
  117.         tampil = 0;
  118.         break;
  119.       case 2:
  120.         Serial.print("R.1-R.16 = ");
  121.         for (int i = 0; i < 16; i++) {
  122.           Serial.print(coil[i]);
  123.           coil2[i] = coil[i];
  124.         }
  125.         Serial.println();
  126.         tampil = 0;
  127.         break;
  128.       case 3:
  129.         Serial.print("S.1-S.8 = ");
  130.         for (int i = 0; i < 8; i++) {
  131.           Serial.print(disk[i]);
  132.           disk1[i] = disk[i];
  133.         }
  134.         Serial.println();
  135.         tampil = 0;
  136.         break;
  137.       case 4:
  138.         Serial.print("S.1-S.16 = ");
  139.         for (int i = 0; i < 16; i++) {
  140.           Serial.print(disk[i]);
  141.           disk2[i] = disk[i];
  142.         }
  143.         Serial.println();
  144.         tampil = 0;
  145.         break;
  146.       case 5:
  147.         Serial.print("N:A.1-A.2 = ");
  148.         for (int i = 0; i < 2; i++) {
  149.           Serial.print(an[i]);
  150.           if (i == 0) Serial.print(',');
  151.           an1[i] = an[i];
  152.         }
  153.         Serial.println();
  154.         tampil = 0;
  155.         break;
  156.       case 6:
  157.         Serial.print("M:A.1-A.2 = ");
  158.         for (int i = 0; i < 2; i++) {
  159.           Serial.print(an[i]);
  160.           if (i == 0) Serial.print(',');
  161.           an2[i] = an[i];
  162.         }
  163.         Serial.println();
  164.         tampil = 0;
  165.         break;
  166.     }
  167.   }
  168. }


Berikut ini tampilan hasil programnya:

Gambar 14. Serial Monitor menampilkan data Coil (Relay), Input Diskrit (Tombol) dan Input Register (Potensio) yang terhubung dengan Outseal Nano dan Outseal Mega 


4. Menampilkan data Holding Register di Serial Monitor 

Diinginkan untuk bisa menampilkan data modbus Holding Register di Serial Monitor. Variabel di Outseal untuk data modbus Holding Register ini adalah variabel I (integer). Variabel I ini bisa dibaca dan ditulis (Read & Write). Karena bisa dibaca dan ditulis, maka kita dapat menggunakan variabel I ini untuk menampung data yang nantinya akan kita tampilkan di Serial Monitor. Sebagai contoh diinginkan untuk menampilkan data Counter (variabel C) di Serial Monitor. Menggunakan tombol pertama (S.1) di Outseal Nano, dan tombol pertama (T.1) di Outseal Mega, buat agar Serial Monitor bisa menampilkan banyaknya penekanan tombol S.1 dan T.1. Di samping ditampilkan di Serial Monitor, diinginkan agar nilai Counter (jumlah penekanan tombol) juga ditampilkan dengan nyala output digital LED. Untuk Outseal Nano, karena jumlah LED sebanyak 8, maka setelah Counter mencapai 8, akan me-reset kembali ke 0. Sedangkan untuk Outseal Mega, karena jumlah LED sebanyak 16, maka setelah Counter mencapai 16, akan me-reset kembali ke 0.

4.1 Gambar Rangkaian
Menggunakan rangkaian yang sama seperti Gambar 13.

4.2 Program Outseal Nano (Slave 1)
Berikut ini program Ladder Diagram Outseal Nano:


Gambar 15. Ladder Diagram Outseal Nano untuk menampilkan data Counter di Serial Monitor

Keterangan:
Program Ladder Diagram Outseal Nano di atas akan menyalakan LED sesuai dengan nilai Counter. Nilai Counter akan bertambah setiap kali tombol S.1 ditekan. Untuk mengurangi bouncing, ditambahkan instruksi OSF, yang membaca sisi turun dari pulsa input tombol. Ketika Counter telah mencapai 8, Counter akan di-reset kembali ke 0. Agar LED juga bisa dinyalakan dengan penekanan tombol S.1 - S.8, maka input dari Counter dan input dari tombol diparalel. Jangan lupa untuk mengatur Settings, pilih hardware = Nano V5Baudrate = 9600, alamat modbus Outseal Nano = 1. Rekan-rekan dapat mengunduh file program Ladder Diagram di atas di bagian terakhir dari materi di halaman ini.

4.3 Program Outseal Mega (Slave 2)
Berikut ini program Ladder Diagram Outseal Mega:


Gambar 16. Ladder Diagram Outseal Mega untuk menampilkan data Counter di Serial Monitor

Keterangan:
Program Ladder Diagram Outseal Mega ini akan menyalakan LED sesuai dengan nilai Counter. Nilai Counter akan bertambah setiap kali tombol S.1 ditekan. Untuk mengurangi bouncing, ditambahkan instruksi OSF, yang membaca sisi turun dari pulsa input tombol. Ketika Counter telah mencapai 16, Counter akan di-reset kembali ke 0. Agar LED juga bisa dinyalakan dengan penekanan tombol S.1 - S.16, maka input dari Counter dan input dari tombol diparalel. Jangan lupa untuk mengatur Settings, pilih hardware = Mega V3Baudrate = 9600, dan alamat modbus Outseal Mega = 2Rekan-rekan dapat mengunduh file program Ladder Diagram di atas di bagian terakhir dari materi di halaman ini.

4.4 Program Arduino Nano (Master)
Berikut ini program Arduino Nano untuk menampilkan data Coil, Input Diskrit, Input Register dan Holding Register di Serial Monitor. Data Holding Register yang dibaca di Outseal Nano dan Outseal Mega hanyalah 1 data, yang berisi nilai variabel Counter.

  1. #include <ModbusRTU.h>
  2. #include <SoftwareSerial.h>
  3. SoftwareSerial mySerial(2, 3);  // RX, TX
  4. ModbusRTU mb;
  5. bool coil[20];
  6. bool coil1[10];
  7. bool coil2[20];
  8. bool disk[20];
  9. bool disk1[10];
  10. bool disk2[20];
  11. uint16_t an[4];
  12. uint16_t an1[4];
  13. uint16_t an2[4];
  14. uint16_t hr[2];
  15. uint16_t hr1[2];
  16. uint16_t hr2[2];
  17. int urut = 0;
  18. int tampil = 0;
  19. unsigned long skr = 0;
  20. void setup() {
  21.   Serial.begin(9600);
  22.   mySerial.begin(9600);
  23.   mb.begin(&mySerial);
  24.   mb.setBaudrate(9600);
  25.   mb.master();
  26.   mb.readCoil(1, 0, coil, 8);  //hanya untuk trigger
  27.   while (mb.slave()) {
  28.     mb.task();
  29.     delay(10);
  30.   }
  31.   delay(1000);
  32. }
  33. void loop() {
  34.   if (millis() - skr > 100) {  //setiap 100milidetik
  35.     skr = millis();
  36.     urut++;
  37.     if (urut > 8) urut = 1;
  38.     switch (urut) {
  39.       case 1:
  40.         mb.readCoil(1, 0, coil, 8);
  41.         break;
  42.       case 2:
  43.         mb.readCoil(2, 0, coil, 16);
  44.         break;
  45.       case 3:
  46.         mb.readIsts(1, 0, disk, 8);
  47.         break;
  48.       case 4:
  49.         mb.readIsts(2, 0, disk, 16);
  50.         break;
  51.       case 5:
  52.         mb.readIreg(1, 0, an, 2);
  53.         break;
  54.       case 6:
  55.         mb.readIreg(2, 0, an, 2);
  56.         break;
  57.       case 7:
  58.         mb.readHreg(1, 0, hr, 1);
  59.         break;
  60.       case 8:
  61.         mb.readHreg(2, 0, hr, 1);
  62.         break;
  63.     }
  64.     while (mb.slave()) {
  65.       mb.task();
  66.       delay(10);
  67.     }
  68.     switch (urut) {
  69.       case 1:
  70.         for (int i = 0; i < 8; i++) {  //cek kesamaan
  71.           if (coil[i] != coil1[i]) {
  72.             tampil = 1;
  73.             break;
  74.           }
  75.         }
  76.         break;
  77.       case 2:
  78.         for (int i = 0; i < 16; i++) {  //cek kesamaan
  79.           if (coil[i] != coil2[i]) {
  80.             tampil = 2;
  81.             break;
  82.           }
  83.         }
  84.         break;
  85.       case 3:
  86.         for (int i = 0; i < 8; i++) {  //cek kesamaan
  87.           if (disk[i] != disk1[i]) {
  88.             tampil = 3;
  89.             break;
  90.           }
  91.         }
  92.         break;
  93.       case 4:
  94.         for (int i = 0; i < 16; i++) {  //cek kesamaan
  95.           if (disk[i] != disk2[i]) {
  96.             tampil = 4;
  97.             break;
  98.           }
  99.         }
  100.         break;
  101.       case 5:
  102.         for (int i = 0; i < 2; i++) {  //cek kesamaan
  103.           if (an[i] != an1[i]) {
  104.             tampil = 5;
  105.             break;
  106.           }
  107.         }
  108.         break;
  109.       case 6:
  110.         for (int i = 0; i < 2; i++) {  //cek kesamaan
  111.           if (an[i] != an2[i]) {
  112.             tampil = 6;
  113.             break;
  114.           }
  115.         }
  116.         break;
  117.       case 7:
  118.         if (hr[0] != hr1[0]) tampil = 7;
  119.         break;
  120.       case 8:
  121.         if (hr[0] != hr2[0]) tampil = 8;
  122.         break;
  123.     }
  124.     switch (tampil) {
  125.       case 1:
  126.         Serial.print("R.1-R.8 = ");
  127.         for (int i = 0; i < 8; i++) {
  128.           Serial.print(coil[i]);
  129.           coil1[i] = coil[i];
  130.         }
  131.         Serial.println();
  132.         tampil = 0;
  133.         break;
  134.       case 2:
  135.         Serial.print("R.1-R.16 = ");
  136.         for (int i = 0; i < 16; i++) {
  137.           Serial.print(coil[i]);
  138.           coil2[i] = coil[i];
  139.         }
  140.         Serial.println();
  141.         tampil = 0;
  142.         break;
  143.       case 3:
  144.         Serial.print("S.1-S.8 = ");
  145.         for (int i = 0; i < 8; i++) {
  146.           Serial.print(disk[i]);
  147.           disk1[i] = disk[i];
  148.         }
  149.         Serial.println();
  150.         tampil = 0;
  151.         break;
  152.       case 4:
  153.         Serial.print("S.1-S.16 = ");
  154.         for (int i = 0; i < 16; i++) {
  155.           Serial.print(disk[i]);
  156.           disk2[i] = disk[i];
  157.         }
  158.         Serial.println();
  159.         tampil = 0;
  160.         break;
  161.       case 5:
  162.         Serial.print("N:A.1-A.2 = ");
  163.         for (int i = 0; i < 2; i++) {
  164.           Serial.print(an[i]);
  165.           if (i == 0) Serial.print(',');
  166.           an1[i] = an[i];
  167.         }
  168.         Serial.println();
  169.         tampil = 0;
  170.         break;
  171.       case 6:
  172.         Serial.print("M:A.1-A.2 = ");
  173.         for (int i = 0; i < 2; i++) {
  174.           Serial.print(an[i]);
  175.           if (i == 0) Serial.print(',');
  176.           an2[i] = an[i];
  177.         }
  178.         Serial.println();
  179.         tampil = 0;
  180.         break;
  181.       case 7:
  182.         Serial.print("N:counter = ");
  183.         Serial.println(hr[0]);
  184.         hr1[0] = hr[0];
  185.         tampil = 0;
  186.         break;
  187.       case 8:
  188.         Serial.print("M:counter = ");
  189.         Serial.println(hr[0]);
  190.         hr2[0] = hr[0];
  191.         tampil = 0;
  192.         break;
  193.     }
  194.   }
  195. }


Berikut ini tampilan hasil programnya:

Gambar 17. Serial Monitor menampilkan data Coil (Relay), Input Diskrit (Tombol), Input Register (Potensio) dan Holding Register (nilai Counter)


Berhubung isi halaman ini sudah terlalu panjang, maka untuk penjelasan pengiriman data Coil dan pengiriman data Holding Register dari Master ke Slave melalui Serial Monitor, akan dibahas di halaman berikutnya.

Untuk memudahkan rekan-rekan dalam mempelajari materi di halaman ini, rekan-rekan bisa mengunduh semua file gambar dan program di link berikut ini:


Agar lebih jelas, berikut ini video pembuatan tampilan data Outseal di Serial Monitor yang dibuat mengikuti materi di halaman ini. 

Video pembuatan tampilan data Outseal di Serial Monitor

2 comments: