Arduino Burn Batch (*.bat zur Portsuche)

Hallo zusammen,

seit einiger Zeit verwende ich eine Batch-Datei, die ein Board von mir mit einem Bootloader und einem Sketch bespielt.
Eine Unzulänglichkeit habe ich dabei noch: Der Port muss manuell eingetragen werden!
Also muss man erstmal im Gerätemanager nachschauen und diesen dann eintragen.

Eleganter wäre es, die in Frage kommenden Ports aufgelistet zu bekommen. Bzw. gibt es nur einen, diesen automatisch auszuwählen.
Da enden aber meine Batch-Fähigkeiten…

Nach etwas Recherche habe ich zwei Möglichkeiten identifiziert, welche zum einen die Ports und zum anderen die Beschreibung ausgeben können:

set _key="HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM"
for /f "tokens=1,3 delims= " %%i in ('reg query !_key! ^| find /v "HKEY"') do (
   set "_device=%%i" & set "_com#=%%j" & echo/!_com#! !_device!

Ergibt:

COM3 \Device\Silabser0

Um die Beschreibung zu erhalten, gibt es folgenden Befehl:
wmic path win32_pnpentity get caption /format:table| find "COM"

Silicon Labs CP210x USB to UART Bridge (COM3)
Bluetooth Device (RFCOMM Protocol TDI)

Hierbei werden aber auch andere Geräte angezeigt, die keinem COM-Port zugeordnet wurden.

Also habe ich beides kombiniert und die Schleife so erweitert, dass wmic gefiltert auf den Port ausgeführt wird:

ECHO Available COM-Ports:
@echo off & setlocal enabledelayedexpansion 
set _key="HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM"
for /f "tokens=1,3 delims= " %%i in ('reg query !_key! ^| find /v "HKEY"') do (
   set "_device=%%i" & set "_com#=%%j" & (for /f "tokens=*" %%a in ('wmic path win32_pnpentity get caption /format:table^| find "!_com#!"') do (set _desc=%%a)) & echo/!_device! : !_desc!)
@ECHO,
SET /P P=Enter the ComPort Number and press ENTER:
SET ComPort=COM%P%

Available COM-Ports:
\Device\Silabser0 : Silicon Labs CP210x USB to UART Bridge (COM3)

Enter the ComPort Number and press ENTER:

Das ist ja nun schon mal mehr als die halbe Miete. Es fehlen aber noch zwei Punkte zur Perfektion:

  1. Ausgabe wenn kein COM-Port gefunden wurde
  2. Automatische Auswahl, wenn nur ein COM-Port verfügbar

Vielleicht haben wir hier ja einen Batch-Profi unter uns :slight_smile:

PS: Um an den integer zu kommen, ist vermutlich das hier noch hilfreich:

:: for get number only :: By using !_com_N:~3! to get [n]
for /f "tokens=3 delims= " %%c in ('reg query !_key! ^| find /v "HKEY"') do set "_com_N=%%c"&& echo/!_com_N:~3! = !_com_N!

Das sehe ich auch so.

Die Anzahl der Ports lassen sich doch zählen.
Mein letztes Batch ist 8 Jahre her, aber Addition ging mit

@echo off
set _num=0
:Start
Echo %_num%
SET /a _num=%_num% + 1
IF %_num% == 10 GOTO BYE

REM Hier mach was

GOTO Start
:BYE
Pause

Das SET … brauchst nur in den do () einbauen…

Damit kann ich leider nicht dienen!
Benutze kaum Batch Dateien.
Verwende lieber PHP.

Um allerdings die COM Ports herauszufinden verwende ich den GitHub - arduino/serial-discovery: An Arduino IDE pluggable-discovery for Serial ports aus der arduino-1.9.0-beta.

Der lieferts mir im JSON Format, welches man in PHP einfachst verwursten kann.

Zudem gibts noch den mdns-discovery, der kann ja auch mal interessant sein.

Auch Powershell wäre eine Möglichkeit.
Ich verwende PHP auch an einigen Stellen als lokale Scriptsprache.

Gruß Tommy

Hier gehts vermutlich komplett ohne

@echo off
set _num=0
set _numport=0
set _numstart=1
set _numend=10

:Start
SET /a _num=%_num% + 1
IF %_num% == %_numend% GOTO Bye
mode COM%_num%: | findstr "COM%_num%:" >>NULL
IF %ERRORLEVEL% == 0 call :Addport
GOTO Start

:Addport
SET _port=COM%_num%:
SET /a _numport=%_numport%+1
GOTO Start

:Bye
Echo gefundene Port: %_numport%
IF %_numport% GTR 0 Echo letzte Schnittstelle: %_port%

Das Batch liefert Dir in der Ausgabe die Anzahl der gefundenen COM-Ports und den letzten.
Wenn die Anzahl 1 ist, ist der Port in der Variablen %_port% auch die Einzige Schnittstelle.
Wenn Du wissen willst, wo die Ports liegen, wenn es mehrere sind, dann ">> NULL " entfernen.

Gute Nacht.

3 Likes

Sehr cool @my_xy_projekt :sunglasses:
Das war genau der Wink in die richtige Richtung, den ich gebraucht habe!

Habe das Ganze dann mit meinem Script verhackstückelt und nun drei Fälle:

  1. Kein ComPort → Rausspringen
  2. Ein ComPort → Vorbelegen
  3. Mehrere Ports → Ausgabe aller und Abfrage welcher gewählt werden soll
@echo off & setlocal enabledelayedexpansion 
set _ports=0
set _key="HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM"
for /f "tokens=3 delims= " %%i in ('reg query !_key! ^| find /v "HKEY"') do (
   set "ComPort=%%i" & set /a "_ports+=1")

IF %_ports% EQU 0 GOTO NoComAvailable
IF %_ports% EQU 1 GOTO PrintSelectedComPort
IF %_ports% GTR 1 GOTO SelectComPort

:NoComAvailable
ECHO No COM-Port found!
Pause
GOTO EXIT

:SelectComPort
ECHO Available COM-Ports:
@echo off & setlocal enabledelayedexpansion 
set _key="HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM"
for /f "tokens=1,3 delims= " %%i in ('reg query !_key! ^| find /v "HKEY"') do (
   set "_device=%%i" & set "_com#=%%j" & (for /f "tokens=*" %%a in ('wmic path win32_pnpentity get caption /format:table^| find "!_com#!"') do (set _desc=%%a)) & echo/!_device! : !_desc!)
@ECHO,
SET /P P=Enter the ComPort Number and press ENTER:
SET ComPort=COM%P%

:PrintSelectedComPort
ECHO Port %ComPort% selected!

Geht sicherlich schöner, aber für mich passt´s :+1:t3:
Wichtig war nur, dass die Variable _ports nicht mit % angegeben wird. Sonst wird sie lokal verwurstelt (bzw. preprocessed) und bleibt nur 0 oder 1.

Hintergrund ist es natürlich den avrdude fernzusteuern. Hätte mir auch eine C# Anwendung bauen können. Dann müsste man aber mit der Konsolen-Ausgabe vom Dude herumjonglieren.

1 Like

Ich schau heute Abend mal noch, ob ich das noch besser hinbekomme.
Kannst Du mal nachsehen, ob deine CP’s als VID 10C4 und als PID EA60 oder EA63 haben?
Danke

Aber sicher!
ESP32 WROOM

USB\VID_10C4&PID_EA60&REV_0100

Original Uno

USB\VID_0403&PID_6001&REV_0600

(China) Nano

USB\VID_1A86&PID_7523&REV_0254

Die hatte ich zumindest gerade zur Hand. Scheinen aber nicht einem von Dir erhofften Schema zu entsprechen :man_shrugging:t3:

Doch - steht doch da. 10C4 und EA60 für den WROOM.
Dann las mich mal heute Nachmittag drüber schauen - ich denke es wird noch einfacher zusätzlich vorhandene COM: auszublenden.

Vorausgesetzt, Du benutzt nicht mehrere ESP gleichzeitig…
Na las mich mal versuchen - ich bin schon länger raus.

Hallo,

wenn ich einen Nano Every und Mega2560 angesteckt habe bekomme ich

Available COM-Ports:
\Device\USBSER000 : Arduino Nano Every (COM7)
\Device\USBSER001 : Serielles USB-Gerät (COM3)

Wäre es denkbar für jeden ComPort das Arduino Modell mit anzuzeigen?

Ich kenne nur diesen Weg:

Kann man nicht das Board mit der IDE einmal auslesen und die Seriennummer in der Batch hinterlegen und damit irgendwie vergleichen um einen Namen anzuzeigen?

Ja.
Warte las mich mal kurz machen - ich brauch jetzt ein wenig Zeit.

Hallo,

ist mir schon bewusst das das Zeit benötigt. Wenn fertig dann fertig. Es sollte nur eine Anregung sein wenn jemand schon so nett ist und sich daran setzt. Falls das so überhaupt möglich ist. Bei dem for Schleifen Syntax blicke ich schon lange nicht mehr durch.

Ich auch nicht.

Hier mal ein ansatz - ich möchte wissen, was es macht.

Am Anfang muss das _vendor gesetzt werden!!!
[edit] in der Ausgabe fehlte nich was [/edit]

@echo off
setlocal EnableExtensions
REM aus den folgenden das Board auskommentieren (:: entfernen) oder neu eintragen
REM Arduino UNO
::SET "_vendor=VID_2A03&PID_0043"
REM Arduino MEGA
SET "_vendor=VID_2341&PID_0042"
REM Silab - Bitte eines aussuchen
:: SET "_vendor=VID_10C4&PID_EA60"
:: SET "_vendor=VID_10C4&PID_EA63"


set "RegistryPath=HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB"

for /F "delims=" %%I in ('reg.exe QUERY "%RegistryPath%\%_vendor%" 2^>nul') do call :setVar "%%I"
endlocal
pause
goto :EOF


:setVar
set "RegistryKey=%~1"
 for /F  "tokens=1,3* delims= " %%A in ('reg.exe QUERY "%RegistryKey%" /s') do (
    if /I "%%A" == "FriendlyName" set "BoardName=%%B" && set "BoardType=%%C"
)

for /F "skip=2 tokens=1,3" %%A in ('reg.exe QUERY "%RegistryKey%\Device Parameters" /v PortName 2^>nul') do (
    if /I "%%A" == "PortName" set "_port=%%B" && goto checkPort
)
goto :EOF

:CheckPort
mode %_port%: | findstr "%_port%:" >>NULL
if %ERRORLEVEL% GTR 0 SET _port=NUL 
goto printVar
goto :EOF

:printVar
echo gefunden: %BoardName% %BoardType% %_port%
goto :EOF

Es ist nur mal hingetackert - schön ist anders, aber da kommt das für TriB schon genau hin. Ich hab nur nicht mehrere Boards und gleich auch keinen Zugriff mehr auf einen Windowsrechner…

Denn ist der COM-Port nicht da, gibt es keine Ausgabe, das der an einem COM: vorhanden ist.

Ich verfeiner das morgen. Dann hab ich evtl. Rückmeldungen und auch einen Windowsrechner direkt dran.

1 Like

Hallo,

damit kann man immer gezielt nach genau einem Board suchen lassen. Je nachdem welches SET man freigegeben hat. Richtig?

Irgendwie müßte es machbar sein das alle erkannten COM Ports mit Board Namen aufgelistet werden. Ich möchte die Port Nummer selbst auswählen und eingeben. Damit weichen jedoch meine Wünsche vom TO ab.

Bei mir wird einzig der Name vom Nano Every angezeigt. Ich habe dann in die Registry geschaut, dort findet man unter den VID auch die S/Ns seiner Boards. Hier habe ich beim Mega2560 in der Zeile “FriendlyName” den Eintrag Serielles USB-Gerät durch Arduino Mega 2560 ersetzt. Damit erscheint vor der COM Port Nummer der richtige Name. Bei meinem Nano Every war das schon eingetragen. Ob das eine USB Buchse ändern überlebt habe ich noch nicht probiert, da das bei mir eigentlich nie geändert wird.

Edit:
Was mir jedoch durch die Birne sackt. Wenn man mit avrdude flasht, dann benötigt man doch den ComPort vom Programmer und nicht vom Arduino Board? Oder möchte TriB alle Informationen verknüpfen? Nur dazu müßte man den Port vom Programmer herausfischen und vom Arduino Board um dann mit den gewünschten Einstellungen avrdude bedienen zu können.

Wenn Du “immer” durch “aktuell” oder “derzeit” ersetzt. Ja.

Naja, wenn ich so den Thread lese, ist der TO “eigentlich” zufrieden… So zumindest in #8

Mein Gedanke war nur, das ich Ports die NICHT mit dem ESP verbunden sind ausklammere um dann schlussendlich sagen zu können, es gibt mehr als einen aktiven Port (z.b. auch einen mit einem every) aber nur einen nutzbaren mit einem WROOM und auch weiss, welcher es ist - und somit die automatische Auswahl ermögliche, auch wenn mehr Ports aktiv sind…
Das war die Ausgangssituation in

Damit wäre ich durch, denn ich mach das von hinten auf. Ich suche nicht nach der Anzahl der “aktiven” COM: Ports sondern nach den Aktiven, die dem Chip zuzuordnen sind.

Das geht natürlich auch noch weiter auszubauen - und genau da bin ich stehen geblieben.
Ich will zum Schluss nicht einen Chip/Port vorher wählen, sondern abfragen, welcher Chip/Port benutzt werden soll.
Dafür kann ich aber nicht alles allein machen und brauch ggfls. etwas Unterstützung, da ich nicht jeden Chip da anbasteln kann (davon abgesehen, das es die auch garnicht alle habe :wink: )

Für die Bastelei bräuchte ich den Registryzweig.
Wer mag, führt in der Konsole aus:

reg query "HKLM\SYSTEM\CurrentControlSet\Enum\USB" /s>> reg.txt

und schickt mir ne PM mit dem Text-File.
Gerne auch gekürzt!
Aber ALLES was zu den Boards drin steht brauch ich um ggfls. drauf zu reagieren.

Morgen schaun wa mal, wie das mit der Auswahl klappt…

Hallo,

ich glaube wir gehen in die gleiche Richtung. Und zwar habe ich mir Grundlagen gesucht um vorgegebene Werte zu vergleichen. Weit kam ich noch nicht, weil Arrays in dem Sinne in Batch nicht existieren. Aber man kann eine Datei erstellen und irgendwas eintragen. Diese kann man Zeilenweise auslesen.

batch programmierung

Das habe ich ausprobiert.
Batch.zip (1,0 KB)

CALL LeseZeilenEin.bat Line “ArduinoBoards.txt”

Jetzt sollte es irgendwie möglich sein, in der for Schleife die Registry abzuklappern und mit den Einträgen in der ArduinoBoards.txt zu vergleichen und bei einem Treffer auszugeben. Man müßte demnach 2 for Schleifen verschachteln … ‘grübel’

Edit:
PN an dich geht nicht, dein öffentliches Profil ist ausgeblendet

Funktioniert, wenn Du den Usernamen händisch einträgst/ rein kopierst.
Ist das versteckte Profil Voreinstellung? Also ist meins auch versteckt (ich habe nix in der Richtung eingestellt)?

Gruß Tommy