1. シリアルポート
Arduino、マイコンボードやUSBシリアル変換器をUSBポートに差し込むと、シリアルポートにそれぞれ現れます。
% alias lsu
lsu='ls /dev/cu.*'
% lsu
/dev/cu.Bluetooth-Incoming-Port /dev/cu.usbserial-0001
/dev/cu.usbmodem1101 /dev/cu.usbserial-2120
/dev/cu.usbmodem13301 /dev/cu.wchusbserial2120
/dev/cu.usbmodemHIDEF1 /dev/cu.wlan-debug
一部ですが、↓ざっとこんな感じです。
- マイコン系
シリアルポート | 内容 |
---|---|
/dev/cu.usbmodemHIDEF1 | 自作プログラマブルテンキー(ATMega32U4 ネイティブUSB)常時接続 |
/dev/cu.usbmodemC7FD1ADFA7491 | 自作ボード(ESP32-S3 ネイティブUSB) CircuitPython REPL |
/dev/cu.usbmodem0000000000001 | RP2040 Dev Board (USB CDC) |
/dev/cu.usbmodem13201 | Raspberry Pi Pico Micropython REPL |
/dev/cu.usbmodem12401 | Seeed Studio XIAO RP2040 |
/dev/cu.usbmodem21201 | Adafruit Feather nRF52840 |
- Arduino系
シリアルポート | 内容 |
---|---|
/dev/cu.usbmodem11101 | Arduino Uno R3 |
/dev/cu.usbmodem11201 | Arduino Uno R4 Minia |
/dev/cu.usbserial-1140 | Arduino Nano 互換機(Atmega328p、CH340C) |
- USBシリアル変換器
シリアルポート | 内容 |
---|---|
/dev/cu.wchusbserial53250003491 | ESP32ダウンローダ(WCH CH9102F) |
/dev/cu.usbmodemBC5C61321D8E2 | Wch-Link(旧式)(WCH CH549G) |
/dev/cu.usbmodem8D568F0612342 | Wch-LinkE-R0-1v3(WCH CH32V305FBP6) |
/dev/cu.usbmodem05581 | USB Console Stub(HOLTEK HT43B534-2) |
/dev/cu.usbserial-120 | USB-TTL変換モジュール(WCH CH340C) |
もちろんですが、接続するUSBポートを変えると、数字部分が変化します。
WindowsOS
の COMxx
が、短くてうらやましい。。。
2. 複数あるシリアルポートを簡単に選びたい
screen
コマンドや、esptool
、mpremote
、ampy
などのコマンドで、接続しているマイコンのシリアルポートを指定する必要があるが、毎回ls
コマンドを叩いてシリアルポートを確認して入力するのが面倒なので、一覧から選択できるchooserial
コマンド(choose serial)を作成した。
% chooserial
1: /dev/cu.usbmodem1101
2: /dev/cu.usbmodem13301
3: /dev/cu.usbserial-0001
4: /dev/cu.usbserial-2120
5: /dev/cu.wchusbserial2120
Choose device number (1-5);5<enter>
/dev/cu.wchusbserial2120
プロンプトは、stderr
に出力し、番号入力で選ばれたシリアルポートをstdout
に(改行無しで)出力します。
選択可能なシリアルポートが1つしかない場合は、プロンプトせず、そのポートを返します。
また、write
モードでダミーopen
することで、他で使用中のシリアルポートを選択肢から除外します。
% esptool.py --chip auto --port `chooserial` flash_id
1: /dev/cu.usbmodem1101
2: /dev/cu.usbmodem13301
3: /dev/cu.usbserial-0001
4: /dev/cu.usbserial-2120
5: /dev/cu.wchusbserial2120
Choose device number (1-5);2
esptool.py v4.6.2
Serial port /dev/cu.usbmodem13301
Connecting...
Detecting chip type... ESP32-S3
Chip is ESP32-S3 (revision v0.1)
Features: WiFi, BLE
Crystal is 40MHz
MAC: xx:xx:xx:xx:xx:xx
Uploading stub...
Running stub...
Stub running...
Manufacturer: c8
Device: 4018
Detected flash size: 16MB
Flash type set in eFuse: quad (4 data lines)
Hard resetting via RTS pin...
% screen `chooserial` 115200
1: /dev/cu.usbmodem1101
2: /dev/cu.usbmodem13301
3: /dev/cu.usbserial-0001
4: /dev/cu.usbserial-2120
5: /dev/cu.wchusbserial2120
Choose device number (1-5);6
Choose device number (1-5);x
Choose device number (1-5);?
1: /dev/cu.usbmodem1101
2: /dev/cu.usbmodem13301
3: /dev/cu.usbserial-0001
4: /dev/cu.usbserial-2120
5: /dev/cu.wchusbserial2120
Choose device number (1-5);2
ESP-NOW Recv Ready!
(Ctrl-A Ctrl-K)
[screen is terminating]
%
シェルの機能でtab
キーによるパス名補完があるが、それでもchooserial
コマンドに慣れると、圧倒的に楽です。
3. ソースコード
C++
で作りました。
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
vector<string> lsu;
void promptN() {
fprintf(stderr, "Choose device number (1-%d);", lsu.size());
}
void prompt() {
int n = 1;
for (const auto& s: lsu) {
cerr << n++ << ": " << s << endl;
}
promptN();
}
const int BUF = 256;
char buf[BUF];
int run(string cmd) {
FILE *fp;
fp = popen(cmd.c_str(), "r");
if (!fp) {
cerr << "popen error" << endl;
return -1;
}
while (fgets(buf, BUF, fp)) {
buf[strlen(buf) - 1] = '\0'; //remove last '\n'
lsu.push_back(string(buf));
}
pclose(fp);
for (auto it = lsu.begin(); it != lsu.end();) {
//filter starts_with("cu.")
if (it->substr(0, 3).compare("cu."))
it = lsu.erase(it);
else {
*it = "/dev/" + *it;
//dummy open
FILE *fp = fopen(it->c_str(), "w");
if (fp) ++it, fclose(fp);
else it = lsu.erase(it);
}
}
//for (const auto& s: lsu) cout << s << endl; //for debug
return lsu.size();
}
int strToi(const string s, int defaultValue = 0) {
int result;
try {
result = stoi(s);
} catch (invalid_argument& e) {
return defaultValue;
}
return result;
}
int main(void) {
switch (run("ls /dev")) {
case -1: //fallthrough
case 0: cout << "NO_DEVICES"; return -1;
case 1: cout << lsu[0]; return 0;
default: break;
}
prompt();
int n = -1;
do {
if (fgets(buf, BUF, stdin)) {
if (buf[0] == '?') { prompt(); continue; }
if ((n = strToi(string(buf), -1)) >= 0) {
if (n < 1 || lsu.size() < n) n = -1;
}
}
if (n == -1) promptN();
} while (n == -1);
cout << lsu[n - 1];
return 0;
}
% c++-13 chooserial.cpp -o chooserial
コマンド名chooserial
が長いと思う貴方は、どうぞ短い名前を付けてご利用ください。
関連リンク;
以上