通过 SPI 从 arduino 发送 uint16 数据(288 个值)缓冲区到 RPI(快速)
Send a buffer of uint16 data (288 values) over SPI from arduino to RPI (quickly)
我有一个用于进行光谱仪测量的设备。 raspberry Pi 用作 GUI 的 shell,并通过串行 (USB) 与 Arduino 通信以读取光谱仪值。 RPi 向 Arduino 发送一个字符串,告诉它读取光谱仪。在每次测量期间,所有光谱仪像素值 (288) 都存储到 uint16 缓冲区,然后通过串口发送回 Pi,等待至少 3 秒从串口读取数据。现在一次测量大约需要 0.3 秒(包括 RPi 告诉 Arduino 进行测量的时间,实际读取光谱仪所需的时间,然后通过串行将所有光谱仪值发送回 Pi)。我曾尝试使用 I2C 来实现它,但速度并不快(我必须逐字节发送每个值)。我正在尝试使用 SPI 来实现它(希望它会更快但没有使用此接口的任何经验)。有没有一种简单的方法告诉 Arduino 何时读取然后将大量数据缓冲区发送回 Pi? (而不是一件一件地寄过来?)
(这是我代码中最重要的部分,还有更多内容,但希望这能说明问题)
Arduino:
#define SPEC_CHANNELS 288 // New Spec Channel
uint16_t data[SPEC_CHANNELS];
void read_value()
{
//Read from SPEC_VIDEO
//analogReadResolution(16);
for(int i = 0; i < SPEC_CHANNELS; i++){
uint16_t readvalue = read_adc();
data[i] = readvalue;
// pulse the spectrometer clock to switch pixels
digitalWriteFast(SPEC_CLK, HIGH);
delayMicroseconds(delayTime);
digitalWriteFast(SPEC_CLK, LOW);
delayMicroseconds(delayTime);
}
// send the buffer info over serial (with some formatting)
for (int i = 0; i < SPEC_CHANNELS-1; i++){
Serial.print(data[i]);
Serial.print(',');
}
Serial.print(data[SPEC_CHANNELS - 1]);
Serial.print("\n");
}
树莓派:
self.ser.write(b"read\n") #tell arduino to read spectrometer
data_read = self.ser.readline() #read a full line of serial data
data_temp = np.array([int(p) for p in data_read.split(b",")]) #parse the info by ","
更新代码:
阿杜诺:
void setup() {
Serial.begin(115200);
}
#define SPEC_CHANNELS 288 // New Spec Channel
uint8_t data[SPEC_CHANNELS*2];
void read_value()
{
for(int i = 0; i < SPEC_CHANNELS*2; i+=2){
uint16_t readvalue = read_adc();
data[i] = readvalue & 255;
data[i+1] = (readvalue >> 8) & 255;
digitalWriteFast(SPEC_CLK, HIGH);
delay62ns();
digitalWriteFast(SPEC_CLK, LOW);
delay62ns();
}
Serial.write(data, SPEC_CHANNELS*2);
}
void delay62ns() {
asm("nop");
}
树莓派:
self.ser = serial.Serial(port, baudrate = 115200, timeout = 3)
self.ser.write(b"read\n") #tell arduino to read spectrometer
data_read = self.ser.read(288*2) #read a full line of serial data
new_data = []
for x in range(0,288*2,2):
new_data += [256*data_read[x] + data_read[x+1]]
data_plot = np.array(new)
print(data_plot)
arduino 串行监视器的输出:
g ⸮Og⸮⸮⸮ %⸮b⸮ ⸮'p⸮om⸮o ⸮⸮:p`ʏW⸮BOW⸮%�⸮ڊPX⸮z⸮b ⸮r⸮zB
b⸮⸮_⸮⸮ B⸮ ⸮ ⸮ ⸮R⸮rz⸮
7⸮⸮oxJϕ M0⸮% ⸮⸮ ⸮ /⸮ w⸮ ⸮ ⸮?U⸮W⸮%⸮ էW⸮⸮X⸮⸮⸮"⸮H ⸮⸮⸮R⸮⸮J⸮o7`z⸮ ⸮⸮*⸮5bB _⸮⸮Z⸮U U ⸮E⸮⸮⸮⸮ O⸮*⸮ ⸮2x*⸮b⸮o⸮z⸮}⸮_⸮⸮⸮⸮⸮
⸮⸮
=⸮:Ϛ⸮hW/�O-⸮`j⸮⸮
*⸮J⸮woB⸮⸮] ⸮⸮⸮w⸮⸮-⸮ (⸮ ⸮⸮⸮J:⸮eߗ_]⸮
Pi 的输出(上面的工作代码):
1586 1344, 1444, 1560 ...
我在评论中的建议是将数据作为二进制而不是 ASCII 字符串发送,因为如果您想象 16 位样本 10,000 它需要传输 2 个字节,而如果您将其设为 ASCII 字符串,如果包含将其与下一个示例分隔所需的逗号,则需要 6 个字节:
10000,
很高兴看到它提高了性能。
另一个想法,如果你想最大化每秒读取,可能是在预期 Raspberry Pi 要求数据的情况下不断读取光谱仪,然后在被要求时将其移交。所以,而不是:
do forever
sit around idly wasting time till RPi asks for data
read spectrometer
send spectrometer readings to RPi
done
也许这样做:
do forever
read spectrometer
if there are serial bytes available (check in NON-BLOCKING way)
send latest spectrometer readings (which we already have) to RPi
end if
done
另一个观察...虽然您提到在代码中延迟 62ns(对应于 16MHz 时钟上的一个周期),但您应该知道调用子程序可能需要 4 个以上的时钟周期,并且需要 4 个以上的时钟周期循环到 return 所以你实际上每次阅读比你预期的要多 16+ 个循环。它在伟大的计划中并不重要,你的编译器可能会内联你的函数调用......但希望你明白我的意思。
想象一下您的 Arduino 从 0..287 收集并发送 288 个 16 位值。您可以像这样合成 serial.read()
上可能收到的字节缓冲区:
import numpy as np
buf = np.arange(288, dtype=np.uint16).tobytes()
b'\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\t\x00\n\x00\x0b\x00\x0c\x00\r\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00 \x00!\x00"\x00#\x00$\x00%\x00&\x00\'\x00(\x00)\x00*\x00+\x00,\x00-\x00.\x00/\x000\x001\x002\x003\x004\x005\x006\x007\x008\x009\x00:\x00;\x00<\x00=\x00>\x00?\x00@\x00A\x00B\x00C\x00D\x00E\x00F\x00G\x00H\x00I\x00J\x00K\x00L\x00M\x00N\x00O\x00P\x00Q\x00R\x00S\x00T\x00U\x00V\x00W\x00X\x00Y\x00Z\x00[\x00\\x00]\x00^\x00_\x00`\x00a\x00b\x00c\x00d\x00e\x00f\x00g\x00h\x00i\x00j\x00k\x00l\x00m\x00n\x00o\x00p\x00q\x00r\x00s\x00t\x00u\x00v\x00w\x00x\x00y\x00z\x00{\x00|\x00}\x00~\x00\x7f\x00\x80\x00\x81\x00\x82\x00\x83\x00\x84\x00\x85\x00\x86\x00\x87\x00\x88\x00\x89\x00\x8a\x00\x8b\x00\x8c\x00\x8d\x00\x8e\x00\x8f\x00\x90\x00\x91\x00\x92\x00\x93\x00\x94\x00\x95\x00\x96\x00\x97\x00\x98\x00\x99\x00\x9a\x00\x9b\x00\x9c\x00\x9d\x00\x9e\x00\x9f\x00\xa0\x00\xa1\x00\xa2\x00\xa3\x00\xa4\x00\xa5\x00\xa6\x00\xa7\x00\xa8\x00\xa9\x00\xaa\x00\xab\x00\xac\x00\xad\x00\xae\x00\xaf\x00\xb0\x00\xb1\x00\xb2\x00\xb3\x00\xb4\x00\xb5\x00\xb6\x00\xb7\x00\xb8\x00\xb9\x00\xba\x00\xbb\x00\xbc\x00\xbd\x00\xbe\x00\xbf\x00\xc0\x00\xc1\x00\xc2\x00\xc3\x00\xc4\x00\xc5\x00\xc6\x00\xc7\x00\xc8\x00\xc9\x00\xca\x00\xcb\x00\xcc\x00\xcd\x00\xce\x00\xcf\x00\xd0\x00\xd1\x00\xd2\x00\xd3\x00\xd4\x00\xd5\x00\xd6\x00\xd7\x00\xd8\x00\xd9\x00\xda\x00\xdb\x00\xdc\x00\xdd\x00\xde\x00\xdf\x00\xe0\x00\xe1\x00\xe2\x00\xe3\x00\xe4\x00\xe5\x00\xe6\x00\xe7\x00\xe8\x00\xe9\x00\xea\x00\xeb\x00\xec\x00\xed\x00\xee\x00\xef\x00\xf0\x00\xf1\x00\xf2\x00\xf3\x00\xf4\x00\xf5\x00\xf6\x00\xf7\x00\xf8\x00\xf9\x00\xfa\x00\xfb\x00\xfc\x00\xfd\x00\xfe\x00\xff\x00\x00\x01\x01\x01\x02\x01\x03\x01\x04\x01\x05\x01\x06\x01\x07\x01\x08\x01\t\x01\n\x01\x0b\x01\x0c\x01\r\x01\x0e\x01\x0f\x01\x10\x01\x11\x01\x12\x01\x13\x01\x14\x01\x15\x01\x16\x01\x17\x01\x18\x01\x19\x01\x1a\x01\x1b\x01\x1c\x01\x1d\x01\x1e\x01\x1f\x01'
然后将其转换为 Numpy 数组,您只需要:
data = np.frombuffer(buf, dtype=np.uint16)
根据您的字节顺序,您可能需要像这样设置 dtype
:
dt = np.dtype(np.uint16)
dt = dt.newbyteorder('>') # You may need '<'
data = np.frombuffer(buf, dtype=dt)
data
现在看起来像这样:
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,
104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181,
182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194,
195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220,
221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233,
234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246,
247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259,
260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272,
273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285,
286, 287], dtype=uint16)
在我的机器上,这比构建列表的代码快 140 倍。
关键字: Python, serial, transfer, efficient, efficiency, performance, high performance, Raspberry Pi, Arduino, binary, ASCII, Numpy, ADC、光谱仪。
我有一个用于进行光谱仪测量的设备。 raspberry Pi 用作 GUI 的 shell,并通过串行 (USB) 与 Arduino 通信以读取光谱仪值。 RPi 向 Arduino 发送一个字符串,告诉它读取光谱仪。在每次测量期间,所有光谱仪像素值 (288) 都存储到 uint16 缓冲区,然后通过串口发送回 Pi,等待至少 3 秒从串口读取数据。现在一次测量大约需要 0.3 秒(包括 RPi 告诉 Arduino 进行测量的时间,实际读取光谱仪所需的时间,然后通过串行将所有光谱仪值发送回 Pi)。我曾尝试使用 I2C 来实现它,但速度并不快(我必须逐字节发送每个值)。我正在尝试使用 SPI 来实现它(希望它会更快但没有使用此接口的任何经验)。有没有一种简单的方法告诉 Arduino 何时读取然后将大量数据缓冲区发送回 Pi? (而不是一件一件地寄过来?)
(这是我代码中最重要的部分,还有更多内容,但希望这能说明问题)
Arduino:
#define SPEC_CHANNELS 288 // New Spec Channel
uint16_t data[SPEC_CHANNELS];
void read_value()
{
//Read from SPEC_VIDEO
//analogReadResolution(16);
for(int i = 0; i < SPEC_CHANNELS; i++){
uint16_t readvalue = read_adc();
data[i] = readvalue;
// pulse the spectrometer clock to switch pixels
digitalWriteFast(SPEC_CLK, HIGH);
delayMicroseconds(delayTime);
digitalWriteFast(SPEC_CLK, LOW);
delayMicroseconds(delayTime);
}
// send the buffer info over serial (with some formatting)
for (int i = 0; i < SPEC_CHANNELS-1; i++){
Serial.print(data[i]);
Serial.print(',');
}
Serial.print(data[SPEC_CHANNELS - 1]);
Serial.print("\n");
}
树莓派:
self.ser.write(b"read\n") #tell arduino to read spectrometer
data_read = self.ser.readline() #read a full line of serial data
data_temp = np.array([int(p) for p in data_read.split(b",")]) #parse the info by ","
更新代码: 阿杜诺:
void setup() {
Serial.begin(115200);
}
#define SPEC_CHANNELS 288 // New Spec Channel
uint8_t data[SPEC_CHANNELS*2];
void read_value()
{
for(int i = 0; i < SPEC_CHANNELS*2; i+=2){
uint16_t readvalue = read_adc();
data[i] = readvalue & 255;
data[i+1] = (readvalue >> 8) & 255;
digitalWriteFast(SPEC_CLK, HIGH);
delay62ns();
digitalWriteFast(SPEC_CLK, LOW);
delay62ns();
}
Serial.write(data, SPEC_CHANNELS*2);
}
void delay62ns() {
asm("nop");
}
树莓派:
self.ser = serial.Serial(port, baudrate = 115200, timeout = 3)
self.ser.write(b"read\n") #tell arduino to read spectrometer
data_read = self.ser.read(288*2) #read a full line of serial data
new_data = []
for x in range(0,288*2,2):
new_data += [256*data_read[x] + data_read[x+1]]
data_plot = np.array(new)
print(data_plot)
arduino 串行监视器的输出:
g ⸮Og⸮⸮⸮ %⸮b⸮ ⸮'p⸮om⸮o ⸮⸮:p`ʏW⸮BOW⸮%�⸮ڊPX⸮z⸮b ⸮r⸮zB
b⸮⸮_⸮⸮ B⸮ ⸮ ⸮ ⸮R⸮rz⸮
7⸮⸮oxJϕ M0⸮% ⸮⸮ ⸮ /⸮ w⸮ ⸮ ⸮?U⸮W⸮%⸮ էW⸮⸮X⸮⸮⸮"⸮H ⸮⸮⸮R⸮⸮J⸮o7`z⸮ ⸮⸮*⸮5bB _⸮⸮Z⸮U U ⸮E⸮⸮⸮⸮ O⸮*⸮ ⸮2x*⸮b⸮o⸮z⸮}⸮_⸮⸮⸮⸮⸮
⸮⸮
=⸮:Ϛ⸮hW/�O-⸮`j⸮⸮
*⸮J⸮woB⸮⸮] ⸮⸮⸮w⸮⸮-⸮ (⸮ ⸮⸮⸮J:⸮eߗ_]⸮
Pi 的输出(上面的工作代码):
1586 1344, 1444, 1560 ...
我在评论中的建议是将数据作为二进制而不是 ASCII 字符串发送,因为如果您想象 16 位样本 10,000 它需要传输 2 个字节,而如果您将其设为 ASCII 字符串,如果包含将其与下一个示例分隔所需的逗号,则需要 6 个字节:
10000,
很高兴看到它提高了性能。
另一个想法,如果你想最大化每秒读取,可能是在预期 Raspberry Pi 要求数据的情况下不断读取光谱仪,然后在被要求时将其移交。所以,而不是:
do forever
sit around idly wasting time till RPi asks for data
read spectrometer
send spectrometer readings to RPi
done
也许这样做:
do forever
read spectrometer
if there are serial bytes available (check in NON-BLOCKING way)
send latest spectrometer readings (which we already have) to RPi
end if
done
另一个观察...虽然您提到在代码中延迟 62ns(对应于 16MHz 时钟上的一个周期),但您应该知道调用子程序可能需要 4 个以上的时钟周期,并且需要 4 个以上的时钟周期循环到 return 所以你实际上每次阅读比你预期的要多 16+ 个循环。它在伟大的计划中并不重要,你的编译器可能会内联你的函数调用......但希望你明白我的意思。
想象一下您的 Arduino 从 0..287 收集并发送 288 个 16 位值。您可以像这样合成 serial.read()
上可能收到的字节缓冲区:
import numpy as np
buf = np.arange(288, dtype=np.uint16).tobytes()
b'\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\t\x00\n\x00\x0b\x00\x0c\x00\r\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00 \x00!\x00"\x00#\x00$\x00%\x00&\x00\'\x00(\x00)\x00*\x00+\x00,\x00-\x00.\x00/\x000\x001\x002\x003\x004\x005\x006\x007\x008\x009\x00:\x00;\x00<\x00=\x00>\x00?\x00@\x00A\x00B\x00C\x00D\x00E\x00F\x00G\x00H\x00I\x00J\x00K\x00L\x00M\x00N\x00O\x00P\x00Q\x00R\x00S\x00T\x00U\x00V\x00W\x00X\x00Y\x00Z\x00[\x00\\x00]\x00^\x00_\x00`\x00a\x00b\x00c\x00d\x00e\x00f\x00g\x00h\x00i\x00j\x00k\x00l\x00m\x00n\x00o\x00p\x00q\x00r\x00s\x00t\x00u\x00v\x00w\x00x\x00y\x00z\x00{\x00|\x00}\x00~\x00\x7f\x00\x80\x00\x81\x00\x82\x00\x83\x00\x84\x00\x85\x00\x86\x00\x87\x00\x88\x00\x89\x00\x8a\x00\x8b\x00\x8c\x00\x8d\x00\x8e\x00\x8f\x00\x90\x00\x91\x00\x92\x00\x93\x00\x94\x00\x95\x00\x96\x00\x97\x00\x98\x00\x99\x00\x9a\x00\x9b\x00\x9c\x00\x9d\x00\x9e\x00\x9f\x00\xa0\x00\xa1\x00\xa2\x00\xa3\x00\xa4\x00\xa5\x00\xa6\x00\xa7\x00\xa8\x00\xa9\x00\xaa\x00\xab\x00\xac\x00\xad\x00\xae\x00\xaf\x00\xb0\x00\xb1\x00\xb2\x00\xb3\x00\xb4\x00\xb5\x00\xb6\x00\xb7\x00\xb8\x00\xb9\x00\xba\x00\xbb\x00\xbc\x00\xbd\x00\xbe\x00\xbf\x00\xc0\x00\xc1\x00\xc2\x00\xc3\x00\xc4\x00\xc5\x00\xc6\x00\xc7\x00\xc8\x00\xc9\x00\xca\x00\xcb\x00\xcc\x00\xcd\x00\xce\x00\xcf\x00\xd0\x00\xd1\x00\xd2\x00\xd3\x00\xd4\x00\xd5\x00\xd6\x00\xd7\x00\xd8\x00\xd9\x00\xda\x00\xdb\x00\xdc\x00\xdd\x00\xde\x00\xdf\x00\xe0\x00\xe1\x00\xe2\x00\xe3\x00\xe4\x00\xe5\x00\xe6\x00\xe7\x00\xe8\x00\xe9\x00\xea\x00\xeb\x00\xec\x00\xed\x00\xee\x00\xef\x00\xf0\x00\xf1\x00\xf2\x00\xf3\x00\xf4\x00\xf5\x00\xf6\x00\xf7\x00\xf8\x00\xf9\x00\xfa\x00\xfb\x00\xfc\x00\xfd\x00\xfe\x00\xff\x00\x00\x01\x01\x01\x02\x01\x03\x01\x04\x01\x05\x01\x06\x01\x07\x01\x08\x01\t\x01\n\x01\x0b\x01\x0c\x01\r\x01\x0e\x01\x0f\x01\x10\x01\x11\x01\x12\x01\x13\x01\x14\x01\x15\x01\x16\x01\x17\x01\x18\x01\x19\x01\x1a\x01\x1b\x01\x1c\x01\x1d\x01\x1e\x01\x1f\x01'
然后将其转换为 Numpy 数组,您只需要:
data = np.frombuffer(buf, dtype=np.uint16)
根据您的字节顺序,您可能需要像这样设置 dtype
:
dt = np.dtype(np.uint16)
dt = dt.newbyteorder('>') # You may need '<'
data = np.frombuffer(buf, dtype=dt)
data
现在看起来像这样:
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,
104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181,
182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194,
195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220,
221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233,
234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246,
247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259,
260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272,
273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285,
286, 287], dtype=uint16)
在我的机器上,这比构建列表的代码快 140 倍。
关键字: Python, serial, transfer, efficient, efficiency, performance, high performance, Raspberry Pi, Arduino, binary, ASCII, Numpy, ADC、光谱仪。