Arduino Identifier

I've posted here because of similar threads -hope that's correct

I've been "talking " to chat GPT an it has produced a working code to identify which Arduino device is plugged into which com port.

It has a an on/off toggle to turn on the on board led to further help you find your board.

It needs some code on the Arduino, but not too big. It could be improved to remove the "delay" and turn it into a tidy function.

String boardID = "ARDUINO_2";

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  Serial.println(boardID);  // keep announcing itself
  delay(2000);

  if (Serial.available()) {
    String cmd = Serial.readStringUntil('\n');

    if (cmd == "ON") {
      digitalWrite(LED_BUILTIN, HIGH);
    }
    else if (cmd == "OFF") {
      digitalWrite(LED_BUILTIN, LOW);
    }
  }
}

The code on the PC is written in python and produces this GUI.

This is the Python code: (need pyserial what ever that is..) and can be made into a single file "EXE"

import tkinter as tk
import serial
import serial.tools.list_ports
import threading
import time

devices = {}  # name -> {"ser": serial, "port": str, "connected": bool}
device_frames = {}

BG = "#1e1e1e"
CARD = "#2d2d2d"
TEXT = "#ffffff"
GREEN = "#4CAF50"
RED = "#f44336"

def scan_ports():
    while True:
        ports = serial.tools.list_ports.comports()

        for port in ports:
            try:
                ser = serial.Serial(port.device, 9600, timeout=1)
                time.sleep(2)

                for _ in range(3):
                    name = ser.readline().decode(errors='ignore').strip()

                    if name.startswith("ARDUINO"):
                        if name in devices:
                            # reconnect existing
                            devices[name]["ser"] = ser
                            devices[name]["port"] = port.device
                            devices[name]["connected"] = True
                            update_device_label(name)
                            set_status(name, True)
                        else:
                            # new device
                            devices[name] = {
                                "ser": ser,
                                "port": port.device,
                                "connected": True
                            }
                            add_device(name)

                        break

            except:
                pass

        time.sleep(2)

def monitor_devices():
    while True:
        for name, data in devices.items():
            if not data["connected"]:
                continue

            try:
                data["ser"].write(b"\n")
                set_status(name, True)
            except:
                data["connected"] = False
                set_status(name, False)

        time.sleep(2)

def send_command(name, cmd):
    try:
        if devices[name]["connected"]:
            devices[name]["ser"].write((cmd + "\n").encode())
    except:
        devices[name]["connected"] = False
        set_status(name, False)

def add_device(name):
    frame = tk.Frame(root, bg=CARD, padx=10, pady=10)
    frame.pack(padx=10, pady=8, fill="x")

    top = tk.Frame(frame, bg=CARD)
    top.pack(fill="x")

    label = tk.Label(top, text="", fg=TEXT, bg=CARD, font=("Arial", 12, "bold"))
    label.pack(side="left")

    status = tk.Label(top, text="●", fg=GREEN, bg=CARD, font=("Arial", 14))
    status.pack(side="right")

    btn_frame = tk.Frame(frame, bg=CARD)
    btn_frame.pack(pady=5)

    tk.Button(btn_frame, text="ON", width=8, bg=GREEN, fg="white",
              command=lambda: send_command(name, "ON")).pack(side="left", padx=5)

    tk.Button(btn_frame, text="OFF", width=8, bg=RED, fg="white",
              command=lambda: send_command(name, "OFF")).pack(side="left", padx=5)

    device_frames[name] = {"frame": frame, "label": label, "status": status}

    update_device_label(name)

def update_device_label(name):
    label = device_frames[name]["label"]
    port = devices[name]["port"]
    label.config(text=f"{name} ({port})")

def set_status(name, connected):
    status = device_frames[name]["status"]
    status.config(fg=GREEN if connected else RED)

root = tk.Tk()
root.title("Arduino Controller Pro+")
root.geometry("350x400")
root.configure(bg=BG)

title = tk.Label(root, text="Arduino Controller", fg=TEXT, bg=BG, font=("Arial", 16, "bold"))
title.pack(pady=10)

threading.Thread(target=scan_ports, daemon=True).start()
threading.Thread(target=monitor_devices, daemon=True).start()

root.mainloop()
String boardID = "260418a";

unsigned long msec0;

void loop ()
{
    unsigned long msec = millis ();
    if (msec - msec0 >= 2000)  {
        msec0 = msec;
        Serial.println(boardID);  // keep announcing itself
    }

    if (Serial.available()) {
        String cmd = Serial.readStringUntil('\n');

        digitalWrite(LED_BUILTIN, cmd == "ON" ? HIGH : LOW);
    }
}

void setup() {
    pinMode(LED_BUILTIN, OUTPUT);
    Serial.begin(9600);
}

In case it will be of interest to those who find this thread, I'll add a link to a related discussion where an alternative approach to identification of the serial port to board unit granularity was described:

Note that this is a very different approach from the one presented here. Each has distinct strengths and applicability. So I do not imply that the alternative approach obviates @hammy's solution.

Not mine fella, Credit to ChatGpt

...whose understanding of Arduino is likely significantly based on the content of Arduino Forum that was surely included in its training data, so I guess we can say: credit to the Arduino community :glowing_star: