Panduan · 14 mnt baca

Komunikasi Serial Arduino dan Python: pyserial, CSV, dan Grafik Langsung

Komunikasi serial Arduino dan Python dengan pyserial: instal, temukan port, catat data sensor ke CSV, kirim perintah, dan gambar grafik langsung dengan matplotlib.

Komunikasi serial Arduino dan Python berarti program Python yang berjalan di komputermu bertukar data dengan Arduino lewat kabel USB. Arduino mengukur sensor dan menulis hasilnya ke port serial; Python membaca baris-baris itu dengan library pyserial, menyimpannya ke file CSV, menampilkannya sebagai grafik, atau mengambil keputusan lalu mengirim perintah balik ke Arduino. Dengan begitu kamu menggabungkan kendali hardware Arduino yang presisi dengan kekuatan Python untuk pengolahan data, grafik, AI, dan otomasi. Kamu juga tidak butuh modul tambahan: kabel USB yang kamu pakai untuk meng-upload sketch sudah cukup.

Di panduan ini kamu akan belajar langkah demi langkah cara menginstal pyserial, menemukan port Arduino secara otomatis, mencatat data sensor beserta timestamp ke file CSV, mengirim perintah LED dan PWM dari Python ke Arduino, dan menggambar grafik langsung dengan matplotlib. Setelah itu kita bahas cara memilih format data dan akhir baris, dua masalah yang paling membingungkan (error port sibuk dan board yang reset ketika port dibuka), serta apa bedanya kalau pekerjaan yang sama dilakukan dengan MicroPython di Raspberry Pi Pico. Contoh-contohnya ditulis untuk Arduino Uno; perubahan yang dibutuhkan untuk ESP32 dan Pico dijelaskan terpisah.

Board Arduino Uno R3 dan soket USB-nya
Arduino Uno: soket USB dipakai untuk meng-upload kode sekaligus untuk komunikasi serial dengan Python; LED TX dan RX berkedip selama data mengalir.

Bagaimana Arduino berkomunikasi dengan Python?

Chip USB-ke-serial di Arduino Uno (ATmega16U2 di board asli, biasanya CH340 di board klon) muncul di komputermu sebagai port serial virtual: COM3, COM4, dan seterusnya di Windows; /dev/cu.usbmodem… atau /dev/cu.usbserial-… di macOS; /dev/ttyACM0 atau /dev/ttyUSB0 di Linux. Setiap karakter yang ditulis Arduino dengan Serial.print() mengalir ke komputer lewat port ini sebagai byte; di sisi Python, pyserial membuka port seperti membuka file, lalu membaca dan menulis ke sana. Ada satu perbedaan penting: Arduino Uno tidak menjalankan kode Python. Board menjalankan kode Arduino yang ditulis dalam C++, komputer menjalankan Python, dan keduanya hanya berbicara lewat jalur serial. Supaya kedua sisi berbicara dalam bahasa yang sama, pengaturan berikut harus cocok:

PengaturanSisi ArduinoSisi PythonPerhatikan
PortTerbentuk otomatis lewat USBserial.Serial("COM3", ...)Nama port tergantung sistem operasi
Kecepatan (baud)Serial.begin(115200)serial.Serial(port, 115200)Kalau berbeda, yang muncul karakter acak
Frame8 bit data, tanpa paritas, 1 stop bit (8N1)Default pyserial juga 8N1Jarang perlu diubah
Akhir barisSerial.println() menambahkan \r\nreadline() membaca sampai menemukan \nJangan lupa menambahkan \n ketika mengirim dari Python
TimeoutSerial.setTimeout(), default 1000 mstimeout=1 (detik)Dengan timeout=None, readline() menunggu selamanya

Menginstal pyserial (Windows, macOS, Linux)

  1. Pastikan Python 3 sudah terinstal. Di Windows, centang kotak Add python.exe to PATH di layar pertama installer dari situs resmi Python; di macOS dan Linux, Python 3 biasanya sudah terpasang.
  2. Buka terminal (Command Prompt atau PowerShell di Windows) lalu ketik python -m pip install pyserial. Kalau Windows tidak mengenali perintah python, coba py -m pip install pyserial; di macOS dan Linux perintahnya mungkin python3 -m pip install pyserial.
  3. Cek instalasinya: python -c "import serial; print(serial.__version__)" harus menampilkan nomor versi seperti 3.5.
  4. Bagian grafik langsung juga membutuhkan matplotlib: python -m pip install matplotlib.
  5. Di Linux, tambahkan user-mu ke grup dialout supaya bisa membuka port: sudo usermod -a -G dialout $USER, lalu logout dan login lagi. Kalau pip menampilkan error externally-managed-environment di Raspberry Pi OS atau rilis Ubuntu terbaru, pakai sudo apt install python3-serial atau buat virtual environment dengan python3 -m venv dan jalankan pip di dalamnya.
Di PyPI ada paket lain bernama serial yang sama sekali tidak berhubungan dengan port serial. Kalau kamu mengetik pip install serial, kodemu melewati baris import serial, tetapi kemudian gagal dengan AttributeError: module 'serial' has no attribute 'Serial'. Paket yang benar adalah pyserial; hapus paket yang salah dengan pip uninstall serial lalu instal ulang pyserial. Error yang sama muncul kalau kamu menamai file-mu sendiri serial.py, karena Python lalu mengimpor file-mu, bukan library-nya.

Arduino ada di port mana? Menemukan port dengan Python

Cara termudah adalah melihat menu Tools > Port di Arduino IDE, tetapi Python juga bisa mendaftar port sendiri. Ketik python -m serial.tools.list_ports -v di terminal dan kamu akan melihat nama, deskripsi, dan ID hardware (VID:PID) setiap port. Kalau kamu tidak bisa membedakan baris mana yang Arduino, cabut board-nya, jalankan perintah itu lagi, dan catat port yang hilang. Di macOS, board yang sama muncul sebagai /dev/tty… sekaligus /dev/cu…; di Python, pakai yang diawali cu.

Modul konverter USB-TTL CH340
Chip CH340: di sebagian besar board Arduino klon, chip inilah yang menjembatani USB dan port serial; vendor ID-nya (VID) adalah 1A86.
Chip USBAda di manaVID:PIDNama yang tampil di WindowsNama port di Linux
ATmega16U2Uno R3 asli, Mega 25602341:0043 (Uno)Arduino Uno (COMx)/dev/ttyACM0
CH340Board klon Uno, Nano, dan Mega1A86:7523USB-SERIAL CH340 (COMx)/dev/ttyUSB0
CP2102ESP32 DevKit, NodeMCU10C4:EA60Silicon Labs CP210x USB to UART Bridge (COMx)/dev/ttyUSB0
FT232RNano lama, kabel FTDI0403:6001USB Serial Port (COMx)/dev/ttyUSB0
RP2040 (USB bawaan)Raspberry Pi Pico dengan MicroPython2E8A:0005USB Serial Device (COMx)/dev/ttyACM0

Fungsi di bawah mendaftar semua port dan, kalau mengenali sebuah board dari VID-nya, mengembalikan nama port board tersebut. Simpan kodenya sebagai port_bul.py, lalu di skrip lain kamu cukup menulis from port_bul import port_bul dan PORT = port_bul(), tanpa perlu mengubah nama port secara manual setiap kali.

Python
1import serial.tools.list_ports
2
3# Bilinen USB yongalarının üretici kimlikleri (VID) / Vendor IDs of common USB chips
4BILINEN = {
5    0x2341: "Arduino (orijinal / genuine)",
6    0x2A03: "Arduino (orijinal / genuine)",
7    0x1A86: "CH340 (klon / clone)",
8    0x10C4: "CP210x (ESP32, NodeMCU)",
9    0x0403: "FTDI",
10    0x2E8A: "Raspberry Pi Pico",
11}
12
13
14def port_bul():
15    portlar = sorted(serial.tools.list_ports.comports())
16    for p in portlar:
17        print(p.device, "|", p.description, "|", p.hwid)   # tüm portları listele / list every port
18    for p in portlar:
19        if p.vid in BILINEN:
20            print("Bulundu / found:", p.device, "->", BILINEN[p.vid])
21            return p.device
22    return None
23
24
25if __name__ == "__main__":
26    if port_bul() is None:
27        print("Kart yok: kabloyu ve surucuyu kontrol et / no board: check cable and driver")

Mengirim data dari Arduino: sketch pertama

Contoh-contohnya memakai potensiometer yang terhubung ke pin A0: kaki tengah ke A0, satu kaki luar ke 5V, dan kaki lainnya ke GND. Sebagai pengganti potensiometer, kamu juga bisa merangkai LDR dengan resistor 10 kΩ sebagai pembagi tegangan. Sketch-nya mengambil pembacaan setiap 200 ms dan mengirim hasilnya sebagai satu baris dengan format waktu,nilai:

C++ (Arduino IDE)
1// A0 değerini "millis,deger" CSV satırı olarak gönderir / Sends the A0 reading as a "millis,value" CSV line
2const int SENSOR_PIN = A0;            // potansiyometrenin orta ucu / potentiometer wiper
3const unsigned long ARALIK = 200;     // gönderim aralığı, ms / send interval, ms
4unsigned long sonGonderim = 0;
5
6void setup() {
7  Serial.begin(115200);               // Python'daki hızla aynı olmalı / must match the baud rate in Python
8}
9
10void loop() {
11  if (millis() - sonGonderim >= ARALIK) {   // delay() olmadan zamanlama / timing without delay()
12    sonGonderim = millis();
13    int deger = analogRead(SENSOR_PIN);     // 0-1023
14    Serial.print(sonGonderim);              // zaman damgası / timestamp
15    Serial.print(',');                      // ayırıcı / separator
16    Serial.println(deger);                  // sonuna \r\n ekler / appends \r\n
17  }
18}

Memakai millis() alih-alih delay() memudahkanmu menambahkan pembacaan perintah dari Python ke loop yang sama nanti; detailnya ada di millis vs delay. Setelah meng-upload, buka Serial Monitor di 115200 baud dan kamu akan melihat baris seperti 2573,512 terus bergulir. Ini hanya pengecekan: selalu tutup Serial Monitor sebelum menjalankan skrip Python, kalau tidak port-nya akan sibuk. Kalau kamu baru mengenal Serial Monitor, panduan Serial Monitor Arduino akan membantu.

Membaca data Arduino dengan Python dan menyimpannya ke CSV

Python
1import csv
2import time
3from datetime import datetime
4
5import serial
6
7PORT = "COM3"     # macOS: /dev/cu.usbmodem14101, Linux: /dev/ttyACM0
8BAUD = 115200     # Arduino'daki Serial.begin ile aynı / same as Serial.begin on the Arduino
9
10with serial.Serial(PORT, BAUD, timeout=1) as ser, \
11        open("olcumler.csv", "w", newline="", encoding="utf-8") as dosya:
12    time.sleep(2)               # Uno port açılınca resetlenir / the Uno resets when the port opens
13    ser.reset_input_buffer()    # yarım kalmış eski veriyi at / drop stale, partial data
14    yazici = csv.writer(dosya)
15    yazici.writerow(["tarih", "zaman_ms", "deger", "volt"])   # başlık satırı / header row
16    print("Kayit basladi, durdurmak icin Ctrl+C / logging, press Ctrl+C to stop")
17    try:
18        while True:
19            satir = ser.readline().decode("utf-8", errors="ignore").strip()
20            parcalar = satir.split(",")
21            if len(parcalar) != 2:
22                continue                    # boş ya da beklenmeyen satır / empty or unexpected line
23            try:
24                zaman_ms, deger = int(parcalar[0]), int(parcalar[1])
25            except ValueError:
26                continue                    # bozuk satır / corrupted line
27            volt = deger * 5.0 / 1023       # Uno ADC: 0-1023 -> 0-5 V
28            yazici.writerow([datetime.now().isoformat(timespec="seconds"),
29                             zaman_ms, deger, round(volt, 3)])
30            dosya.flush()                   # satırı hemen diske yaz / write the row to disk now
31            print(zaman_ms, deger, f"{volt:.2f} V")
32    except KeyboardInterrupt:
33        print("Durduruldu / stopped")

Skrip ini membuka port dengan timeout=1: readline() menunggu akhir baris paling lama 1 detik, mengembalikan objek bytes kosong kalau tidak ada yang datang, dan loop tidak pernah macet. Data yang masuk bertipe bytes; decode() mengubahnya menjadi teks, strip() membuang \r\n di ujungnya, dan split(",") memecah baris menjadi kolom. time.sleep(2) dan reset_input_buffer() setelah port dibuka berfungsi membuang potongan baris yang datang selama Uno memulai ulang; alasannya akan kamu lihat di bawah. Membuka file dengan newline="" mencegah baris kosong di Windows, dan flush() memastikan pembacaan yang sudah tercatat tetap tersimpan di disk walaupun program tertutup tiba-tiba. Tekan Ctrl+C di terminal untuk menghentikan pencatatan.

Kalau file CSV terbuka di Excel sebagai satu kolom, penyebabnya adalah pengaturan regional: dengan pengaturan regional Indonesia dan banyak negara Eropa, Excel mengharapkan titik koma sebagai pemisah daftar dan koma sebagai pemisah desimal. Pakai csv.writer(dosya, delimiter=";") dan tulis tegangan dengan str(round(volt, 3)).replace(".", ","), atau impor file di Excel lewat Data > From Text/CSV dan pilih pemisahnya sendiri. Untuk cara lain memasukkan data ke Excel, lihat mengirim data Arduino ke Excel.

Mengirim perintah dari Python ke Arduino

Komunikasinya berjalan dua arah. Sketch Arduino di bawah menunggu perintah yang datang baris demi baris: LED ON dan LED OFF menyalakan dan mematikan LED bawaan, PWM 128 mengatur kecerahan LED di pin 9, dan READ mengirim balik nilai di A0. Setiap perintah mendapat balasan singkat, jadi Python tahu perintah itu benar-benar diproses. Nilai resistor yang tepat untuk LED di pin 9 bisa kamu cari dengan kalkulator resistor LED; Apa Itu PWM? menjelaskan cara kerja PWM.

C++ (Arduino IDE)
1// Python'dan gelen satır komutlarını işler / Handles line-based commands from Python
2const int LED_PIN = LED_BUILTIN;      // Uno'da pin 13 / pin 13 on the Uno
3const int PWM_PIN = 9;                // 220 ohm dirençli LED / LED with a 220 ohm resistor
4
5void setup() {
6  pinMode(LED_PIN, OUTPUT);
7  pinMode(PWM_PIN, OUTPUT);
8  Serial.begin(115200);
9  Serial.setTimeout(50);              // readStringUntil en fazla 50 ms bekler / waits at most 50 ms
10  Serial.println("HAZIR");            // Python bu satırı bekler / Python waits for this line
11}
12
13void loop() {
14  if (Serial.available() > 0) {
15    String komut = Serial.readStringUntil('\n');   // satır sonuna kadar oku / read up to the newline
16    komut.trim();                                  // \r ve boşlukları sil / strip \r and spaces
17
18    if (komut == "LED ON") {
19      digitalWrite(LED_PIN, HIGH);
20      Serial.println("OK LED ON");
21    } else if (komut == "LED OFF") {
22      digitalWrite(LED_PIN, LOW);
23      Serial.println("OK LED OFF");
24    } else if (komut.startsWith("PWM ")) {
25      int deger = komut.substring(4).toInt();     // "PWM 128" -> 128
26      deger = constrain(deger, 0, 255);           // 0-255 aralığında tut / keep it within 0-255
27      analogWrite(PWM_PIN, deger);
28      Serial.print("OK PWM ");
29      Serial.println(deger);
30    } else if (komut == "READ") {
31      Serial.println(analogRead(A0));              // A0 ölçümünü gönder / send the A0 reading
32    } else if (komut.length() > 0) {
33      Serial.print("ERR ");                        // bilinmeyen komut / unknown command
34      Serial.println(komut);
35    }
36  }
37}
Python
1import time
2
3import serial
4
5
6def komut_gonder(ser, komut):
7    ser.write((komut + "\n").encode("ascii"))       # satır sonu şart / the newline is required
8    return ser.readline().decode("ascii", errors="ignore").strip()   # cevabı bekle / wait for the reply
9
10
11with serial.Serial("COM3", 115200, timeout=2) as ser:
12    bitis = time.time() + 3                         # en fazla 3 sn bekle / wait at most 3 s
13    while time.time() < bitis:
14        if ser.readline().strip() == b"HAZIR":      # Arduino açıldı / the Arduino is up
15            break
16    print(komut_gonder(ser, "LED ON"))              # OK LED ON
17    time.sleep(1)
18    print(komut_gonder(ser, "PWM 128"))             # OK PWM 128
19    print("A0 =", komut_gonder(ser, "READ"))        # A0 = 512
20    print(komut_gonder(ser, "LED OFF"))             # OK LED OFF

Kesalahan paling umum di sisi Python adalah lupa menambahkan \n di akhir perintah: ketika readStringUntil('\n') tidak menemukan akhir baris, Arduino menunggu selama waktu yang diatur dengan Serial.setTimeout() dan baru setelah itu memproses perintahnya. Di sketch ini waktunya 50 ms; dengan default 1000 ms, setiap perintah akan tertunda satu detik. write() hanya menerima bytes, jadi kamu perlu mengubah teks dengan encode() atau dengan menaruh b di depannya (b"LED ON\n"). Skrip ini pertama-tama menunggu baris HAZIR (artinya “siap”) paling lama 3 detik: karena Uno memulai ulang ketika port dibuka, perintah yang langsung dikirim akan masuk ke bootloader dan hilang. Membaca balasan setelah setiap perintah, yaitu pola permintaan dan respons, menjaga kedua sisi tetap sinkron dan mencegah buffer penuh; buffer penerima Uno hanya 64 byte.

Format data dan akhir baris: mana yang sebaiknya dipilih?

Jalur serial hanya memberimu aliran byte; kamulah yang harus menandai di mana satu pembacaan berakhir dan pembacaan berikutnya dimulai. Cara paling andal adalah menulis setiap pembacaan di barisnya sendiri dan mengakhiri setiap baris dengan \n. Format yang kamu pakai di dalam baris tergantung pada besar kecilnya proyekmu:

FormatContoh barisKelebihanKekurangan
Satu nilai512Format paling sederhana; Serial Plotter Arduino bisa langsung menggambarnyaKalau ada beberapa nilai, tidak jelas mana yang mana
CSV2573,512,23.5Singkat; Excel dan pandas bisa langsung membacanyaUrutan kolom harus sama di kedua sisi
Kunci:nilaisuhu:23.5,lembap:41Mudah dibaca; Serial Plotter menampilkan labelnyaLebih panjang dan sedikit lebih repot di-parse
JSON{"t":23.5,"h":41}Di Python cukup satu baris dengan json.loads()Format paling panjang; membebani RAM Uno yang terbatas
Biner (binary)2 byte: 0x02 0x00Pilihan paling cepat dan paling ringkasTidak bisa dibaca manusia; butuh modul struct dan byte awal

Akhir baris juga sering membingungkan. Serial.println() menambahkan dua karakter di akhir setiap baris: carriage return (\r, CR) dan line feed (\n, LF). readline() di Python hanya menunggu \n, jadi \r tertinggal di ujung baris; strip() membuang keduanya. Daftar akhir baris di Serial Monitor Arduino IDE menawarkan No Line Ending, New Line, Carriage Return, dan Both NL & CR; ketika kamu menguji sketch Arduino di Serial Monitor sebelum memakai Python, pilih New Line supaya karakter yang terkirim sama dengan yang dikirim Python. Untuk angka desimal, tentukan jumlah digitnya seperti di Serial.print(temperature, 1); di Uno, sprintf tidak mendukung format floating-point (%f), jadi mencoba mencetak desimal dengan sprintf akan menghasilkan tanda tanya, bukan angkanya.

Baud rateByte per detik (8N1)Baris 12 byte per detikKapan dipakai
960096080Sensor lambat, kabel panjang, contoh sketch lama
576005.760480Pengukuran berkecepatan sedang
11520011.520960Grafik langsung, ESP32, dan sebagian besar proyek baru

Di jalur serial, setiap byte dikirim sebagai 10 bit termasuk start bit dan stop bit, jadi 115200 baud berarti sekitar 11.520 byte per detik. Untuk baris 12 byte yang terdiri dari 25730,1023 ditambah akhir baris (\r\n), ada ruang hingga 960 baris per detik. Kalau kecepatan di kedua sisi berbeda, karakter acak mengalir di jalur dan Python memunculkan UnicodeDecodeError. Antara 5 dan 20 pembacaan per detik sudah lebih dari cukup untuk mata manusia dan sebagian besar sensor; mengirim jauh lebih sering daripada yang dibutuhkan hanya memperlambat grafik dan membuat file membengkak.

Menggambar grafik langsung dengan matplotlib

Python
1from collections import deque
2
3import matplotlib.pyplot as plt
4import serial
5from matplotlib.animation import FuncAnimation
6
7ser = serial.Serial("COM3", 115200, timeout=0.1)
8N = 200                                          # ekrandaki ölçüm sayısı / readings on screen
9veri = deque([0] * N, maxlen=N)                  # eskiler kendiliğinden düşer / old values drop out
10
11fig, ax = plt.subplots()
12cizgi, = ax.plot(range(N), list(veri))
13ax.set_ylim(0, 1023)                             # Uno ADC aralığı / Uno ADC range
14ax.set_xlabel("Ornek / sample")
15ax.set_ylabel("A0")
16
17
18def guncelle(_):
19    while ser.in_waiting:                        # biriken bütün satırları oku / read every queued line
20        parca = ser.readline().decode("utf-8", errors="ignore").strip().split(",")
21        if len(parca) == 2 and parca[1].isdigit():
22            veri.append(int(parca[1]))
23    cizgi.set_ydata(list(veri))
24    return (cizgi,)
25
26
27ani = FuncAnimation(fig, guncelle, interval=50, blit=True, cache_frame_data=False)   # ani silinmemeli / keep ani
28plt.show()
29ser.close()

Grafiknya dibangun di atas deque yang menyimpan 200 pembacaan terakhir: setiap nilai baru ditambahkan di kanan dan nilai tertua otomatis terbuang dari kiri. FuncAnimation memanggil fungsi guncelle (artinya “perbarui”) setiap 50 ms. Loop while ser.in_waiting di dalam fungsi itu penting: sekarang Arduino mengirim 5 baris per detik, tetapi begitu kamu menaikkan lajunya, membaca hanya satu baris per frame membuat grafik tertinggal dari waktu nyata; loop ini membaca semua baris yang mengantre dan menjaga grafik tetap mutakhir. Jangan hapus variabel ani: kalau tidak ada variabel yang merujuk ke objek animasi, Python membuangnya lewat garbage collection dan jendelanya membeku. Pakai set_ylim(0, 4095) untuk ESP32 dan set_ylim(0, 65535) untuk Pico. Kalau kamu cuma ingin melihat sekilas, Serial Plotter di Arduino IDE sudah cukup; kelebihan Python adalah kamu bisa menyimpan grafiknya, menggabungkan beberapa sumber, dan mengolah datanya sekaligus.

Error port sibuk dan masalah auto-reset

Sebuah port serial hanya bisa dibuka oleh satu program dalam satu waktu. Kalau Serial Monitor atau Serial Plotter Arduino IDE terbuka ketika skrip Python-mu berjalan, ada skrip Python lain yang memegang port, atau software yang memindai port, seperti program printer 3D, berjalan di latar belakang, kamu akan mendapat could not open port 'COM3': PermissionError(13, 'Access is denied.', None, 5) di Windows dan Resource busy atau Device or resource busy di macOS dan Linux. Berlaku juga sebaliknya: selama skrip Python membiarkan port terbuka, Arduino IDE tidak bisa meng-upload kode. Karena itu, pakai konstruksi with serial.Serial(...) as ser: di skripmu; port akan tertutup otomatis ketika blok selesai atau terjadi error. Biasakan menghentikan skrip dengan Ctrl+C sebelum meng-upload.

Masalah kedua lebih licin: di Arduino Uno, Nano, dan Mega, jalur DTR dari chip USB terhubung ke pin RESET prosesor melalui kapasitor 100 nF. Rangkaian ini ada supaya IDE bisa me-restart board secara otomatis ketika meng-upload, tetapi setiap kali pyserial membuka port, DTR juga berubah dan board ikut reset. Board pertama-tama menunggu satu atau dua detik di bootloader, lalu menjalankan sketch-mu dari awal. Perintah yang kamu kirim selama waktu itu hilang, dan kamu bisa melewatkan baris-baris pertama yang dicetak Arduino di setup(). Solusinya adalah menunggu dengan time.sleep(2) setelah membuka port atau, yang lebih andal, menunggu Arduino mengirim baris seperti HAZIR; contoh perintah di atas melakukan persis itu. Buka port sekali di awal program dan biarkan terbuka sampai akhir: loop yang membuka dan menutup port untuk setiap pembacaan akan me-reset board berulang-ulang.

Kalau ingin mencegah reset sepenuhnya, ada dua cara. Lewat software: buat port dalam keadaan tertutup dengan ser = serial.Serial(), atur ser.port dan ser.baudrate, tulis ser.dtr = False, lalu panggil ser.open(). Cara ini biasanya berhasil di Windows; di Linux dan macOS, sistem operasi mungkin tetap mengubah DTR ketika port dibuka. Lewat hardware: pasang kapasitor 10 µF di antara pin RESET dan GND Uno, dengan kaki positif di RESET. Board dengan USB bawaan seperti Leonardo, Micro, dan Raspberry Pi Pico tidak me-restart ketika port dibuka; di board ini, baris yang dicetak kodemu sebelum Python terhubung bisa hilang, jadi lebih aman mengirim pesan penting ketika sebuah perintah datang.

Selama kapasitor 10 µF terpasang, Arduino IDE tidak bisa meng-upload kode, karena proses upload bergantung pada rangkaian auto-reset yang sama; lepaskan kapasitornya sebelum meng-upload. Kalau Python memunculkan device reports readiness to read but returned no data, board kehilangan koneksi atau ada dua program yang memakai port bersamaan. Kalau board reset sendiri ketika sedang berjalan, penyebabnya biasanya daya yang kurang; beri daya servo dan motor dari sumber terpisah, bukan dari 5V USB.

Komunikasi serial Python dengan ESP32

Semua kode Python di sini juga bekerja dengan ESP32; kamu hanya perlu mengubah beberapa hal di sisi Arduino. Untuk input analog, pakai salah satu pin ADC1 (misalnya GPIO 34). ADC ESP32 beresolusi 12 bit dan memetakan 0–3,3 V ke 0–4095, jadi hitung tegangannya di Python dengan deger * 3.3 / 4095. Ketika menyala, ESP32 mencetak pesan startup-nya sendiri di 115200 baud, seperti rst:0x1 (POWERON_RESET),boot:0x13; skrip di atas melewati baris yang tidak bisa diubah menjadi angka, jadi pesan ini tidak menimbulkan masalah. Tergantung rangkaian auto-reset board dan sistem operasinya, ESP32 juga bisa me-restart ketika port dibuka, jadi jeda tunggu dan baris HAZIR juga membantu di sini. Chip USB-nya biasanya CP2102 atau CH340. Kalau kamu lebih suka tanpa kabel, ESP32 bisa mengirim data yang sama lewat Wi-Fi; lihat panduan WebSocket ESP32 dan mencatat data ESP32 ke Google Sheets. Kalau ini ESP32 pertamamu, baca dulu Apa Itu ESP32?.

Raspberry Pi Pico dan MicroPython: apa bedanya?

Board pengembangan Raspberry Pi Pico
Raspberry Pi Pico: berkat periferal USB bawaan RP2040, board ini tidak butuh chip USB-ke-serial terpisah; dengan MicroPython terinstal, board ini langsung muncul di komputer sebagai port serial.

Cara lain untuk mempertemukan Python dan hardware adalah menjalankan Python langsung di board. Raspberry Pi Pico bisa diprogram dengan MicroPython: membaca sensor, mengendalikan LED, dan pengaturan waktu semuanya dikerjakan di dalam Pico dengan sintaks Python. Namun, MicroPython adalah versi ramping dari Python desktop; matplotlib, pandas, dan OpenCV tidak berjalan di Pico. Jadi kalau kamu ingin mencatat data, menggambar grafik, atau mengolahnya dengan AI, Pico pun tetap kamu hubungkan ke Python di komputermu. Kode pyserial di artikel ini juga bekerja dengan Pico; kamu hanya perlu menyesuaikan nama port, rentang nilai, dan cara membaca balasan perintah, seperti dijelaskan di bawah.

FiturArduino + Python di PCPico + MicroPython (mandiri)Pico + Python di PC
Di mana Python berjalan?Hanya di komputer; board menjalankan C++Di dalam PicoDi kedua sisi: MicroPython di Pico, Python di komputer
Perlu komputer?Ya, data diolah di komputerTidak, berjalan dari daya USB atau bateraiYa
Library yang tersediapyserial, matplotlib, pandas, numpy, OpenCV (library Python desktop)Modul terbatas seperti machine dan timeSemua library di komputer
Baud ratePenting, harus sama di kedua sisiTidak memakai port serialTidak berpengaruh, data mengalir dengan kecepatan USB
Reset ketika port dibukaYa di Uno, Nano, dan MegaTidak adaTidak
Kapan dipilihKamu sudah punya Arduino dan butuh library siap pakaiPerangkat mandiri yang sederhanaKamu ingin satu bahasa (Python) di kedua sisi

Kode MicroPython di bawah adalah versi Pico dari contoh Arduino di atas: kode ini membaca potensiometer di GP26 setiap 200 ms, mengirim hasilnya dengan format waktu,nilai yang sama, dan menerima perintah LED yang sama. Di sini, padanan Serial di Arduino adalah print() dan sys.stdin; berkat select.poll(), loop pengukuran tetap berjalan selama menunggu perintah.

MicroPython
1# Pico'ya main.py adıyla kaydet / save it on the Pico as main.py
2import sys
3import select
4import time
5from machine import ADC, Pin
6
7led = Pin("LED", Pin.OUT)          # Pico ve Pico W dahili LED / onboard LED on Pico and Pico W
8pot = ADC(26)                      # GP26 = ADC0, potansiyometre orta ucu / potentiometer wiper
9okuyucu = select.poll()
10okuyucu.register(sys.stdin, select.POLLIN)   # USB'den veri gelince haber ver / notify when USB data arrives
11
12son = time.ticks_ms()
13while True:
14    if okuyucu.poll(0):                       # bekleyen komut var mı? / is a command waiting?
15        komut = sys.stdin.readline().strip()
16        if komut == "LED ON":
17            led.on()
18            print("OK LED ON")
19        elif komut == "LED OFF":
20            led.off()
21            print("OK LED OFF")
22    if time.ticks_diff(time.ticks_ms(), son) >= 200:   # 200 ms'de bir ölçüm / one reading every 200 ms
23        son = time.ticks_ms()
24        print("{},{}".format(son, pot.read_u16()))     # zaman,değer (0-65535) / time,value (0-65535)

Simpan kodenya ke Pico sebagai main.py dengan Thonny, lalu tutup Thonny, cabut kabel USB Pico, dan colokkan lagi: Thonny memakai port serial Pico sendiri, jadi selama Thonny terhubung skrip Python-mu tidak bisa membuka port, dan Thonny juga menghentikan program yang sedang berjalan ketika terhubung; setelah board menyala ulang, main.py berjalan otomatis. Baud rate tidak berpengaruh di port USB Pico; berapa pun nilai yang kamu tulis di Python, data mengalir dengan kecepatan USB. read_u16() mengembalikan nilai dari 0 sampai 65535, jadi hitung tegangannya dengan deger * 3.3 / 65535. Karena Pico mengirim baris pengukuran tanpa henti, readline() di skrip perintah di atas bisa mengembalikan baris pengukuran, bukan balasan; dengan Pico, teruslah membaca sampai kamu mendapat baris yang diawali OK. Contoh ini tidak punya baris HAZIR maupun perintah PWM dan READ; tambahkan ke kode Pico kalau kamu membutuhkannya. Hati-hati kalau kamu mengirim data biner dari komputer: byte 0x03 berarti Ctrl+C di MicroPython dan menghentikan programmu; kamu bisa menonaktifkannya dengan micropython.kbd_intr(-1). Kalau kamu baru mengenal Pico, Apa Itu Raspberry Pi Pico? dan dasar-dasar MicroPython adalah awal yang bagus.

Ide proyek dengan Arduino dan Python

  • Pencatat suhu dan kelembapan: tulis hasil pembacaan DHT11 ke CSV sekali per menit, lalu buat grafik iklim kamarmu selama seminggu di Excel atau dengan pandas.
  • Kendali lampu dari komputer: kendalikan modul relay dengan perintah ON dan OFF yang dikirim dari Python, lalu gabungkan dengan timer atau perintah suara.
  • Grafik jarak langsung: gambar grafik jarak yang diukur HC-SR04 dengan matplotlib. Kalau sensornya kamu putar dengan servo, cara yang sama bisa dipakai untuk menggambar layar radar.
  • Layar status PC: biarkan Python membaca penggunaan CPU dan memori dengan library psutil lalu mengirimnya ke Arduino, yang menampilkannya di layar OLED.
  • Kamera pelacak wajah: OpenCV menemukan posisi wajah di gambar, Python mengubahnya menjadi sudut lalu mengirimkannya, dan Arduino memutar kamera dengan motor servo.
  • Keyboard shortcut buatanmu sendiri: biarkan tombol di Arduino mengirim satu baris ketika ditekan, lalu Python membacanya dan membuka program atau menjalankan shortcut di komputer.

Kesalahan umum dan cara mengatasinya

Error atau gejalaPenyebabSolusi
“ModuleNotFoundError: No module named 'serial'”pyserial tidak terinstal untuk interpreter Python yang menjalankan skrip; VS Code atau Thonny mungkin memakai Python yang berbedaJalankan python -m pip install pyserial dengan interpreter yang sama dan pilih interpreter yang benar di editormu
“AttributeError: module 'serial' has no attribute 'Serial'”Paket serial yang salah terinstal atau file-mu bernama serial.pypip uninstall serial lalu pip install pyserial; ganti nama file-mu
“could not open port 'COM3': PermissionError(13, 'Access is denied.', None, 5)”Port sedang terbuka di program lain: Serial Monitor, Serial Plotter, atau skrip keduaTutup program lain itu; pakai konstruksi with di skripmu
“could not open port 'COM5': FileNotFoundError(2, 'The system cannot find the file specified.', None, 2)”Nama port salah atau board tidak terpasangCari nama yang benar dengan python -m serial.tools.list_ports -v
“[Errno 13] Permission denied: '/dev/ttyACM0'”User Linux-mu tidak punya izin mengakses port serialsudo usermod -a -G dialout $USER, lalu logout dan login lagi
Karakter acak atau UnicodeDecodeErrorBaud rate berbeda, atau noise ketika startupPakai kecepatan yang sama di kedua sisi; tambahkan decode(errors="ignore") dan reset_input_buffer()
readline() selalu mengembalikan b''Arduino tidak mengirim akhir baris (print, bukan println), port salah, atau board masih bootingPakai println, cek port dan kecepatannya, perbesar timeout
“ValueError: invalid literal for int() with base 10”Baris yang terpotong, kosong, atau tidak terduga diubah menjadi angkaBungkus konversinya dengan try/except dan cek jumlah kolom
Perintah pertama diabaikanUno reset ketika port dibuka dan perintahnya masuk ke bootloaderTunggu baris HAZIR atau tunggu 2 detik setelah membuka port
Grafik tertinggal dari waktu nyataHanya satu baris yang dibaca per frame, jadi data menumpuk di bufferBaca semua baris dengan loop in_waiting dan kirim lebih jarang
Kode tidak bisa di-upload selama skrip berjalanPython sedang memegang portHentikan skrip dengan Ctrl+C, lalu upload
Kalau ada yang tidak beres, keluarkan dulu Python dari persamaan dan uji sketch Arduino di Serial Monitor dengan baud rate yang sama. Kalau baris-barisnya terlihat normal di sana, masalahnya ada di sisi Python (nama port, kecepatan, akhir baris, atau parsing); kalau di sana juga kacau, perbaiki sketch Arduino lebih dulu. Kalau kodenya sama sekali tidak mau ter-upload, ikuti langkah-langkah di panduan kode Arduino gagal di-upload. Kalau kamu penasaran dengan sisi hardware komunikasi serial, yaitu TX, RX, dan UART, lihat komunikasi serial UART.

Membuat Arduino dan Python berbicara lewat port serial adalah cara tercepat untuk mengubah proyek sensor sederhana menjadi sistem yang mencatat data, menggambar grafik, dan bisa dikendalikan dari komputermu. Mulailah dengan membaca satu nilai dan mencetaknya, lalu simpan ke CSV, dan tambahkan perintah serta grafik paling akhir; di setiap langkah, pastikan baud rate dan akhir baris cocok di kedua sisi. Di aplikasi BlueGrays kamu akan menemukan proyek langkah demi langkah lengkap dengan skema rangkaian dan kode untuk mengukur cahaya dengan LDR, suhu dan kelembapan dengan DHT11, jarak dengan HC-SR04, serta komunikasi serial antara dua Arduino, jadi kamu bisa cepat membangun sumber data yang akan kamu baca dengan Python.

Pertanyaan umum

Apakah Arduino bisa diprogram dengan Python?

Python tidak berjalan di dalam Arduino Uno, Nano, atau Mega; board ini diprogram dengan bahasa Arduino berbasis C++ di Arduino IDE. Python berjalan di komputer dan berbicara dengan board lewat port serial menggunakan pyserial; kamu juga bisa meng-upload contoh StandardFirmata dan mengendalikan pin langsung dari Python dengan library seperti pyFirmata2. Kalau kamu ingin Python berjalan di board itu sendiri, pilih Raspberry Pi Pico atau ESP32, yang mendukung MicroPython.

Bagaimana cara menginstal pyserial?

Jalankan python -m pip install pyserial di terminal dan tulis import serial di kodemu. Nama paketnya pyserial, tetapi modul yang kamu impor bernama serial; pip install serial menginstal paket yang sama sekali berbeda dan berujung pada AttributeError. Di Linux, kamu juga perlu menambahkan user-mu ke grup dialout.

Bagaimana cara mengetahui Arduino-ku ada di port COM mana?

Lihat Tools > Port di Arduino IDE atau jalankan python -m serial.tools.list_ports -v di terminal. Di Windows, bagian Ports (COM & LPT) di Device Manager juga menampilkan port-nya. Kalau ragu, cabut board-nya lalu tampilkan daftar port lagi; port yang hilang adalah milik Arduino.

Bagaimana cara mengirim data dari Python ke Arduino?

Buka port dengan serial.Serial dan kirim byte seperti ser.write(b"LED ON\n"); jangan lupa mengubah teks dengan encode() dan menambahkan akhir baris. Di sisi Arduino, cek data yang masuk dengan Serial.available() dan baca barisnya dengan Serial.readStringUntil('\n'). Karena Uno reset ketika port dibuka, tunggu sekitar 2 detik sebelum mengirim perintah pertama.

Bisakah Serial Monitor Arduino dan Python dipakai bersamaan?

Tidak, sebuah port serial hanya bisa dibuka oleh satu program dalam satu waktu; program kedua akan mendapat error Access is denied atau Resource busy. Kamu bisa mengolah data yang masuk di Python sekaligus mencetaknya ke layar. Kalau kamu butuh dua kanal terpisah, hubungkan konverter USB-TTL kedua ke Arduino dan buat port serial kedua dengan SoftwareSerial.

Kenapa Arduino-ku reset ketika Python membuka port?

Di Uno, Nano, dan Mega, jalur DTR chip USB terhubung ke pin RESET melalui kapasitor, sehingga board memulai ulang setiap kali port dibuka; rangkaian ini dibutuhkan supaya IDE bisa meng-upload kode. Tunggu 2 detik setelah membuka port, atau tunggu baris dari Arduino yang memberi tahu bahwa ia sudah siap. Untuk mencegah reset sepenuhnya, kamu bisa memasang kapasitor 10 µF di antara RESET dan GND, tetapi kapasitor itu harus dilepas sebelum meng-upload.

Lihat semua proyek
Mengukur Intensitas Cahaya dengan LDR
#11Pemula

Mengukur Intensitas Cahaya dengan LDR

Ingin melihat seberapa terang kamarmu dalam bentuk angka? LDR, komponen kecil yang bereaksi terhadap cahaya, mengukur cahaya di sekitarnya, dan Arduino menulis nilainya ke layar komputermu setiap sete

4.6(81)
139
Pengukuran Jarak HC-SR04 (Tampilan Serial)
#27Pemula

Pengukuran Jarak HC-SR04 (Tampilan Serial)

Sensor HC-SR04 bekerja persis seperti kelelawar yang mencari jalan dalam gelap: ia mengirim suara yang tidak bisa kamu dengar, mendengarkan pantulannya, dan mengukur seberapa jauh benda di depannya. A

4.6(46)
71
Suhu dan Kelembapan dengan DHT11
#55Menengah

Suhu dan Kelembapan dengan DHT11

Seberapa hangat kamarmu, dan apakah udaranya lembap atau kering? Sensor DHT11 mengukur suhu dan kelembapan, dan Arduino menulis nilainya di layar LCD dua baris, diperbarui setiap beberapa detik. Jika

4.7(47)
73
Membaca Intensitas Cahaya dengan Modul LDR ESP32
#113Pemula

Membaca Intensitas Cahaya dengan Modul LDR ESP32

Memantau secara real-time di Serial Monitor nilai ADC mentah modul LDR dan persentase cahaya relatif yang dihitung dari nilai acuan gelap dan terang. Persentase ini bukan pengukuran lux. Mengajarkan logika kalibrasi modul. Ideal dikerjakan sebelum Proyek 10, karena dipakai untuk menentukan nilai ambang.

4.6(36)
55
Komunikasi Satu Arah Antara 2 Arduino
#57Menengah
Premium

Komunikasi Satu Arah Antara 2 Arduino

Kamu membuat dua Arduino berbicara lewat satu kabel: tekan tombol di satu board dan LED di board lain menyala, tekan lagi dan LED mati. Board pengirim melaporkan tekanan tombol dengan pesan singkat, d

4.4(37)
50
Komunikasi Dua Arah Antara 2 Arduino
#58Menengah
Premium

Komunikasi Dua Arah Antara 2 Arduino

Dua Arduino disambung dengan kabel dan saling berbicara: tekan tombol di satu board dan lampu di board lain menyala, tekan lagi dan lampunya mati. Kedua board menjalankan program yang sama, jadi masin

4.5(20)
26
Kendalikan LED dari Ponselmu lewat Bluetooth
#34Pemula
Premium

Kendalikan LED dari Ponselmu lewat Bluetooth

Latihan kecil untuk menyalakan dan mematikan lampu kamarmu dari ponsel. Modul Bluetooth meneruskan huruf yang dikirim dari ponselmu ke Arduino; satu huruf menyalakan LED merah, huruf lain menyalakan L

4.8(68)
89
Pencatat Data Suhu ESP32 (DHT22 + RTC DS1307 + microSD + OLED)
#144Mahir
Premium

Pencatat Data Suhu ESP32 (DHT22 + RTC DS1307 + microSD + OLED)

Buat pencatat suhu bercap waktu dengan ESP32! Baca suhu/kelembapan DHT22 setiap menit, ambil waktu sebenarnya dari RTC DS1307, dan catat ke kartu microSD sebagai CSV. OLED menampilkan suhu langsung (font besar), kelembapan, cap waktu, dan penghitung catatan. File /temp_log.csv bisa dibuka di Excel, Google Sheets, atau Python pandas; cocok untuk rumah kaca, suhu kamar, data laboratorium, penyimpanan makanan, atau sarang lebah.

4.7(7)
12