通过串口在 Arduino 和 PC 之间传递变量的最佳方式?
Best way to pass variables between Arduino and PC over serial?
我写了一个 Arduino 草图,它从遥控接收器读取数据,returns 该通道的值介于 0 和 1023 之间。我基本上想将此数据(格式为 channel:value,例如,通道 1:1023,通道 2:511)发送到 PC 程序(我打算自己编写)。
我能想到的最有效的方法是使用两个字节的数据,前 6 位代表通道(2^6 = 64 个可能的通道,比我需要的多),最后一个十代表价值(2 ^ 10 = 1024,完美)。但我不确定用 C++ 实现它的最佳方式,或者这是否是最理想的方式。所以:
- 在 C++ 中制作单个字节和处理二进制数的最佳方法是什么?最好将值存储在内存中(即,没有 bool 数组,每个索引占用它自己的字节)。两个字节的数据足以满足我的需要
- 这是 easiest/simplest/most efficient/recommended 实现我想要实现的目标的方法吗?我基本上想在程序之间传递变量,还有其他方法吗?
这是针对你的号。 2 个问题。
OSC (OpenSoundControl) 是跨不同平台和设备发送消息的便捷方式。大多数平台都存在库。
您可以使用库 OSC for Arduino and implement your own solution to the specification 或使用适合您上下文的库。
您提到的消息可以发送为 /channel/1 /value/1023
您可以声明一个打包的 struct
来保存这两个值:
struct chan_value_t
{
uint8_t channel : 6;
uint16_t value : 10;
};
但是要将它作为两个字节发送,您需要 (1) "union" 它与一个双字节数组:
union chan_value_t
{
struct {
uint8_t channel : 6;
uint16_t value : 10;
};
uint8_t bytes[2];
};
chan_value_t cv;
void setup()
{
Serial.begin( 9600 );
cv.channel = 2;
cv.value = 800;
for (int i=0; i<sizeof(cv.bytes); i++) {
Serial.print( cv.bytes[i], HEX );
Serial.print( ' ' );
}
Serial.println();
}
void loop() {}
(struct
嵌套在此联合中时是匿名的;联合具有名称。)
或者 (2) 将指向结构的指针转换为指向字节的指针:
struct chan_value_t {
uint8_t channel : 6;
uint16_t value : 10;
};
chan_value_t cv;
void setup()
{
Serial.begin( 9600 );
cv.channel = 2;
cv.value = 800;
uint8_t *bytes = (uint8_t *) &cv; // cast &cv to a pointer to bytes
for (int i=0; i<sizeof(cv); i++) {
Serial.print( bytes[i], HEX );
Serial.print( ' ' );
}
Serial.println();
}
void loop() {}
它们都打印字节的十六进制值:0x02 和 0xC8。 800为0x320,左移6位为0xC800.
要将其发送到 PC,您可能需要以特殊字符序列开始并以某种校验和结束(Fletcher 校验和很容易)。这样就很容易丢掉垃圾字符,知道什么时候有传输错误。
我写了一个 Arduino 草图,它从遥控接收器读取数据,returns 该通道的值介于 0 和 1023 之间。我基本上想将此数据(格式为 channel:value,例如,通道 1:1023,通道 2:511)发送到 PC 程序(我打算自己编写)。
我能想到的最有效的方法是使用两个字节的数据,前 6 位代表通道(2^6 = 64 个可能的通道,比我需要的多),最后一个十代表价值(2 ^ 10 = 1024,完美)。但我不确定用 C++ 实现它的最佳方式,或者这是否是最理想的方式。所以:
- 在 C++ 中制作单个字节和处理二进制数的最佳方法是什么?最好将值存储在内存中(即,没有 bool 数组,每个索引占用它自己的字节)。两个字节的数据足以满足我的需要
- 这是 easiest/simplest/most efficient/recommended 实现我想要实现的目标的方法吗?我基本上想在程序之间传递变量,还有其他方法吗?
这是针对你的号。 2 个问题。
OSC (OpenSoundControl) 是跨不同平台和设备发送消息的便捷方式。大多数平台都存在库。
您可以使用库 OSC for Arduino and implement your own solution to the specification 或使用适合您上下文的库。
您提到的消息可以发送为 /channel/1 /value/1023
您可以声明一个打包的 struct
来保存这两个值:
struct chan_value_t
{
uint8_t channel : 6;
uint16_t value : 10;
};
但是要将它作为两个字节发送,您需要 (1) "union" 它与一个双字节数组:
union chan_value_t
{
struct {
uint8_t channel : 6;
uint16_t value : 10;
};
uint8_t bytes[2];
};
chan_value_t cv;
void setup()
{
Serial.begin( 9600 );
cv.channel = 2;
cv.value = 800;
for (int i=0; i<sizeof(cv.bytes); i++) {
Serial.print( cv.bytes[i], HEX );
Serial.print( ' ' );
}
Serial.println();
}
void loop() {}
(struct
嵌套在此联合中时是匿名的;联合具有名称。)
或者 (2) 将指向结构的指针转换为指向字节的指针:
struct chan_value_t {
uint8_t channel : 6;
uint16_t value : 10;
};
chan_value_t cv;
void setup()
{
Serial.begin( 9600 );
cv.channel = 2;
cv.value = 800;
uint8_t *bytes = (uint8_t *) &cv; // cast &cv to a pointer to bytes
for (int i=0; i<sizeof(cv); i++) {
Serial.print( bytes[i], HEX );
Serial.print( ' ' );
}
Serial.println();
}
void loop() {}
它们都打印字节的十六进制值:0x02 和 0xC8。 800为0x320,左移6位为0xC800.
要将其发送到 PC,您可能需要以特殊字符序列开始并以某种校验和结束(Fletcher 校验和很容易)。这样就很容易丢掉垃圾字符,知道什么时候有传输错误。