Riset PID-iTCLab GUI
Riset iTCLab: Pemrograman Kendali PID-iTCLab GUI dengan Menggunakan Bahasa Pemrograman Arduino+Python
Pengaturan File - Preferences:
Kit iTCLab menggunakan Mikrokontroller ESP32. Silahkan di-copy dan di-paste, di FIle - Preferences, alamat berikut ini:
https://dl.espressif.com/dl/package_esp32_index.json
Pengaturan Board.
Kit iTCLab menggunakan Mikrokontroller ESP32. Jika belum muncul. Untuk menggunakan pertama kali , silahkan diinstall ESP32 di Board Manager.
Pilihan Board.
Selanjutnya, silahkan dipilih Board: DOIT ESP32 DEVKIT V1.
File Program yang dibutuhkan
File-file yang dibutuhkan agar bisa dijalankan pengujian Kit iTCLab menggunakan Bahasa Pemrograman Python Jupyter Notebook, yaitu:
- Program yang harus diupload di Kit iTCLab (silahkan klik-kanan Save link as) (05-iTCLab_PID.ino).
- File Program Modul (silahkan klik-kanan Save link as) itclab.py.
- Silahkan Download Program PID-GUI yang digunakan oleh Kampus BYU (tclab_jupyter-master).
Masing-masing file program di atas dapat didownload dari link di atas. Program-program di atas merupakan pengembangan dari program yang telah dibuat oleh Kampus BYU.
Program yang harus diupload ke Kit iTCLab (05-iTCLab_PID.ino)
/* iTCLab Internet-Based Temperature Control Lab Firmware Jeffrey Kantor, Initial Version John Hedengren, Modified Oct 2017 Basuki Rahmat, Modified April 2022 This firmware is loaded into the Internet-Based Temperature Control Laboratory ESP32 to provide a high level interface to the Internet-Based Temperature Control Lab. The firmware scans the serial port looking for case-insensitive commands: Q1 set Heater 1, range 0 to 100% subject to limit (0-255 int) Q2 set Heater 2, range 0 to 100% subject to limit (0-255 int) T1 get Temperature T1, returns deg C as string T2 get Temperature T2, returns dec C as string VER get firmware version string X stop, enter sleep mode Limits on the heater can be configured with the constants below. */ #include <Arduino.h> // constants const String vers = "1.04"; // version of this firmware const int baud = 115200; // serial baud rate const char sp = ' '; // command separator const char nl = '\n'; // command terminator // pin numbers corresponding to signals on the iTCLab Shield const int pinT1 = 34; // T1 const int pinT2 = 35; // T2 const int pinQ1 = 32; // Q1 const int pinQ2 = 33; // Q2 const int pinLED = 26; // LED // setting PWM properties const int freq = 5000; //5000 const int ledChannel = 0; const int Q1Channel = 1; const int Q2Channel = 2; const int resolutionLedChannel = 8; //Resolution 8, 10, 12, 15 const int resolutionQ1Channel = 8; //Resolution 8, 10, 12, 15 const int resolutionQ2Channel = 8; //Resolution 8, 10, 12, 15 const double batas_suhu_atas = 59; // global variables char Buffer[64]; // buffer for parsing serial input String cmd; // command double pv = 0; // pin value float level; // LED level (0-100%) double Q1 = 0; // value written to Q1 pin double Q2 = 0; // value written to Q2 pin int iwrite = 0; // integer value for writing float dwrite = 0; // float value for writing int n = 10; // number of samples for each temperature measurement void parseSerial(void) { int ByteCount = Serial.readBytesUntil(nl,Buffer,sizeof(Buffer)); String read_ = String(Buffer); memset(Buffer,0,sizeof(Buffer)); // separate command from associated data int idx = read_.indexOf(sp); cmd = read_.substring(0,idx); cmd.trim(); cmd.toUpperCase(); // extract data. toInt() returns 0 on error String data = read_.substring(idx+1); data.trim(); pv = data.toFloat(); } // Q1_max = 100% // Q2_max = 100% void dispatchCommand(void) { if (cmd == "Q1") { Q1 = max(0.0, min(25.0, pv)); iwrite = int(Q1 * 2.0); // 10.? max iwrite = max(0, min(255, iwrite)); ledcWrite(Q1Channel,iwrite); Serial.println(Q1); } else if (cmd == "Q2") { Q2 = max(0.0, min(25.0, pv)); iwrite = int(Q2 * 2.0); // 10.? max iwrite = max(0, min(255, iwrite)); ledcWrite(Q2Channel,iwrite); Serial.println(Q2); } else if (cmd == "T1") { float mV = 0.0; float degC = 0.0; for (int i = 0; i < n; i++) { mV = (float) analogRead(pinT1) * 0.322265625; degC = degC + mV/10.0; } degC = degC / float(n); Serial.println(degC); } else if (cmd == "T2") { float mV = 0.0; float degC = 0.0; for (int i = 0; i < n; i++) { mV = (float) analogRead(pinT2) * 0.322265625; degC = degC + mV/10.0; } degC = degC / float(n); Serial.println(degC); } else if ((cmd == "V") or (cmd == "VER")) { Serial.println("TCLab Firmware Version " + vers); } else if (cmd == "LED") { level = max(0.0, min(100.0, pv)); iwrite = int(level * 0.5); iwrite = max(0, min(50, iwrite)); ledcWrite(ledChannel, iwrite); Serial.println(level); } else if (cmd == "X") { ledcWrite(Q1Channel,0); ledcWrite(Q2Channel,0); Serial.println("Stop"); } } // check temperature and shut-off heaters if above high limit void checkTemp(void) { float mV = (float) analogRead(pinT1) * 0.322265625; //float degC = (mV - 500.0)/10.0; float degC = mV/10.0; if (degC >= batas_suhu_atas) { Q1 = 0.0; Q2 = 0.0; ledcWrite(Q1Channel,0); ledcWrite(Q2Channel,0); //Serial.println("High Temp 1 (> batas_suhu_atas): "); Serial.println(degC); } mV = (float) analogRead(pinT2) * 0.322265625; //degC = (mV - 500.0)/10.0; degC = mV/10.0; if (degC >= batas_suhu_atas) { Q1 = 0.0; Q2 = 0.0; ledcWrite(Q1Channel,0); ledcWrite(Q2Channel,0); //Serial.println("High Temp 2 (> batas_suhu_atas): "); Serial.println(degC); } } // arduino startup void setup() { //analogReference(EXTERNAL); Serial.begin(baud); while (!Serial) { ; // wait for serial port to connect. } // configure pinQ1 PWM functionalitites ledcSetup(Q1Channel, freq, resolutionQ1Channel); // attach the channel to the pinQ1 to be controlled ledcAttachPin(pinQ1, Q1Channel); // configure pinQ2 PWM functionalitites ledcSetup(Q2Channel, freq, resolutionQ2Channel); // attach the channel to the pinQ2 to be controlled ledcAttachPin(pinQ2, Q2Channel); // configure pinLED PWM functionalitites ledcSetup(ledChannel, freq, resolutionLedChannel); // attach the channel to the pinLED to be controlled ledcAttachPin(pinLED, ledChannel); ledcWrite(Q1Channel,0); ledcWrite(Q2Channel,0); } // arduino main event loop void loop() { parseSerial(); dispatchCommand(); checkTemp(); }
File Program Modul itclab.py
File Program Modul itclab.py, harus ada, dan diletakkan di folder kerja yang sama dengan Program tclab_jupyter-master. File modul itclab.py ini digunakan untuk menggantikan file modul tclab.py yang dikembangkan oleh Kampus BYU.
import sys import time import numpy as np try: import serial except: import pip pip.main(['install','pyserial']) import serial from serial.tools import list_ports class iTCLab(object): def __init__(self, port=None, baud=115200): port = self.findPort() print('Opening connection') self.sp = serial.Serial(port=port, baudrate=baud, timeout=2) self.sp.flushInput() self.sp.flushOutput() time.sleep(3) print('iTCLab connected via Arduino on port ' + port) def findPort(self): found = False for port in list(list_ports.comports()): # Arduino Uno if port[2].startswith('USB VID:PID=16D0:0613'): port = port[0] found = True # Arduino HDuino if port[2].startswith('USB VID:PID=1A86:7523'): port = port[0] found = True # Arduino Leonardo if port[2].startswith('USB VID:PID=2341:8036'): port = port[0] found = True # Arduino ESP32 if port[2].startswith('USB VID:PID=10C4:EA60'): port = port[0] found = True # Arduino ESP32 - Tipe yg berbeda if port[2].startswith('USB VID:PID=1A86:55D4'): port = port[0] found = True if (not found): print('Arduino COM port not found') print('Please ensure that the USB cable is connected') print('--- Printing Serial Ports ---') for port in list(serial.tools.list_ports.comports()): print(port[0] + ' ' + port[1] + ' ' + port[2]) print('For Windows:') print(' Open device manager, select "Ports (COM & LPT)"') print(' Look for COM port of Arduino such as COM4') print('For MacOS:') print(' Open terminal and type: ls /dev/*.') print(' Search for /dev/tty.usbmodem* or /dev/tty.usbserial*. The port number is *.') print('For Linux') print(' Open terminal and type: ls /dev/tty*') print(' Search for /dev/ttyUSB* or /dev/ttyACM*. The port number is *.') print('') port = input('Input port: ') # or hard-code it here #port = 'COM3' # for Windows #port = '/dev/tty.wchusbserial1410' # for MacOS return port def stop(self): return self.read('X') def version(self): return self.read('VER') @property def T1(self): self._T1 = float(self.read('T1')) return self._T1 @property def T2(self): self._T2 = float(self.read('T2')) return self._T2 def LED(self,pwm): pwm = max(0.0,min(100.0,pwm))/2.0 self.write('LED',pwm) return pwm def Q1(self,pwm): pwm = max(0.0,min(100.0,pwm)) self.write('Q1',pwm) return pwm def Q2(self,pwm): pwm = max(0.0,min(100.0,pwm)) self.write('Q2',pwm) return pwm # save txt file with data and set point # t = time # u1,u2 = heaters # y1,y2 = tempeatures # sp1,sp2 = setpoints def save_txt(self,t,u1,u2,y1,y2,sp1,sp2): data = np.vstack((t,u1,u2,y1,y2,sp1,sp2)) # vertical stack data = data.T # transpose data top = 'Time (sec), Heater 1 (%), Heater 2 (%), ' \ + 'Temperature 1 (degC), Temperature 2 (degC), ' \ + 'Set Point 1 (degC), Set Point 2 (degC)' np.savetxt('data.txt',data,delimiter=',',header=top,comments='') def read(self,cmd): cmd_str = self.build_cmd_str(cmd,'') try: self.sp.write(cmd_str.encode()) self.sp.flush() except Exception: return None return self.sp.readline().decode('UTF-8').replace("\r\n", "") def write(self,cmd,pwm): cmd_str = self.build_cmd_str(cmd,(pwm,)) try: self.sp.write(cmd_str.encode()) self.sp.flush() except: return None return self.sp.readline().decode('UTF-8').replace("\r\n", "") def build_cmd_str(self,cmd, args=None): """ Build a command string that can be sent to the arduino. Input: cmd (str): the command to send to the arduino, must not contain a % character args (iterable): the arguments to send to the command """ if args: args = ' '.join(map(str, args)) else: args = '' return "{cmd} {args}\n".format(cmd=cmd, args=args) def close(self): try: self.sp.close() print('Arduino disconnected successfully') except: print('Problems disconnecting from Arduino.') print('Please unplug and reconnect Arduino.') return True
Program untuk PID-iTCLab GUI Demo
Setelah download dari https://github.com/evertoncolling/tclab_jupyter. Silahkan diekstrak. Kemudian file modul itclab.py silahkan dimasukkan kedalam folder hasil ekstrak tersebut. Bukalah program control_arduino.py, silahkan diedit misalnya menggunakan Notepad+. Silahkan ganti from tclab import TCLab dengan from itclab import iTCLab. Sehingga menjadi sebagai berikut:
Dan gantilah semua TCLab menjadi iTCLab, contohnya seperti terlihat pada gambar berikut ini.
Selanjutnya, silahkan buka file program demo.ipynb, menggunakan Python Jupyter Notebook. Maka akan tampil seperti gambar berikut ini.
Silahkan masing-masing program pada cell dijalankan. Jika misal ada error karena ada modul atau library yang belum diinstall, silahkan diinstall terlebih dahulu. Biasanya perintahnya dari Command Prompt dengan menggunakan hak akses Administrator, yaitu: pip install nama_modul. Selanjutnya jika tidak ada error. Silahkan jalankan setiap cell, dan arahkan Tab masing-masing ke Tab PID. Hasil tampilannya seharusnya terlihat seperti pada gambar berikut.
Gambaran tapilannya seperti terlihat pada video berikut.
Program untuk PID-iTCLab GUI dengan Menggunakan Kit iTCLab
Setelah berhasil pada program Demo di atas, selanjutnya, silahkan program Demo tersebut di-copy dan diberi nama lain. Misalnya PID_iTCLab.ipynb. Seperti terlihat pada gambar berikut.
Kemudian, silahkan ganti tulisan control_demo dengan control_arduino. Demikian juga, demo = cd.GUI() silahkan diganti dengan run_control = cd.GUI(), dan demo.app() silahkan diganti dengan run_control.app(), dan demo.config() silahkan diganti dengan run_control.config(). Seperti terlihat pada gambar berikut.
Kemudian, dalam posisi Kit iTCLab menggunakan kabel data ditancap ke USB laptop atau PC, dan kondisi Power Adaptor ditancap ke colokan listrik. Serta program arduino 05-iTCLab_PID.ino sudah diupload ke Kit iTCLab. Selanjutnya, silahkan jalankan masing-masing cell program di atas. Tab diarahkan posisinya pada PID. Jika berhasil maka tampilannya, seharusnya seperti terlihat pada gambar berikut.
Gambaran tapilannya seperti terlihat pada video berikut.