【问题标题】:Serial communication: Sending data from C++ to Arduino串行通信:从 C++ 向 Arduino 发送数据
【发布时间】:2018-01-11 17:16:47
【问题描述】:

我正在尝试通过串行通信将数据从 C++ 程序发送到 Arduino。我形成了一个将数据作为对象发送的结构:

typedef struct
{
   double width;
   double height;
   bool passBoard;
} MachineParameters;

我正在使用这个串行库:http://wjwwood.github.com/serial/ 来发送这样的数据:

    MachineParameters mp;
    mp.width = 100;
    mp.height = 200;
    mp.passBoard = true;

    ser.write((const uint8_t *)&mp, sizeof(mp));

该库可以将数据作为 uint8_tstd::vectorstd::string 发送。

Arduino 确实接收到数据,但我不知道如何将数据解析到结构中。我使用与 cpp 代码中相同的结构。

// In Arduio

MachineParameters mp;
int byte_size = 24;

loop() {
   if(Serial.available() >= 24) {
     Serial.readBytes((char*) &mp , 24);
   } 
}

// Goal: Read received mp data just like
// mp.width or mp.height

经过几个小时的尝试,我仍然无法弄清楚如何成功地将这个结构发送到 arduino。有没有另一种方法可以将这些数据发送到 arduino?它可以将数据作为字符串发送,但这似乎不正确。

我是 C++ 编程的新手,所以请原谅任何明显的问题...

感谢您的帮助!


更新:下面的工作解决方案

在查看更多尝试并感谢您的提示后,我想通了。这是对我有用的代码。我发现我的问题是错误的字节大小,用于解析缓冲区。 C++ 中结构的大小是12,而在 arduino 上是9。在 Arduino 上使用原始大小 (12) 解析缓冲区,结构被正确解析。

/* --- C++ CODE --- */
typedef struct
{
   double width;
   double height;
   bool passBoard;
} MachineParameters;
// sizeof(MachineParameters) returns 12.


MachineParameters mp;
mp.width = 11.1;
mp.passBoard = false;
mp.height = 22.2;

ser.write((uint8_t *)&mp, sizeof(mp));
/* --- END OF C++ --- */



/* --- Arduino Code --- */
#define   BYTE_SIZE   12
char messageBuffer[BYTE_SIZE];

typedef struct
{
   double width;
   double height;
   bool passBoard;
} MachineParameters;

MachineParameters mp;

void setup() {
  Serial.begin(9600);
}

void loop() {

  if (Serial.available() >= BYTE_SIZE) {
    Serial.readBytes(messageBuffer , BYTE_SIZE);
    memcpy(&mp, &messageBuffer, BYTE_SIZE);

    // mp.width returns 11.1
    // Success :)
  }
}
/* --- END OF ARDUINO --- */

【问题讨论】:

  • 请向我们展示您是如何尝试发送数据的,而不仅仅是对其的描述。如果我们不知道您在做什么,我们就无法告诉您出了什么问题。
  • 您是逐字发送结构还是单独发送每个字段?你发送的是二进制还是文本?
  • 对不起,我写这个问题的时候很着急。我现在编辑了这个问题,希望你现在能理解我的问题。
  • 你怎么知道Arduino收到了数据?当您尝试在用于序列化数据的同一台机器上反序列化数据(即,将其解析回结构)时会发生什么,而不涉及 Arduino?您是否尝试过通过这种方法向 Arduino 发送更简单的数据?
  • 是的,我希望能更好地说明您认为代码不起作用的原因以及您为调试所做的工作。从计算机发送数据后,Serial.available() 返回什么?如果您读入所有可用字节并只查看这些字节的原始值,它们是什么?您的 Arduino 程序没有输出,那么您怎么知道它不起作用?两个系统上的sizeof(MachineParameters) 是什么?您可能需要对结构进行打包,这样任何一个编译器都不会添加填充。

标签: c++ arduino serial-port usb serial-communication


【解决方案1】:

在 arduino 上,您将缓冲区中的数据作为原始字节接收

现在你必须解析这个,你可以使用memcpy来复制struct中的数据

但是,为了做到这一点,数据必须对齐,这意味着您必须确切地知道它从哪里开始。所以你应该发送一个同步字节(开始/停止字节),以便能够修复数据开始的位置

那么你可以使用parsing buffer data into struct中的代码:

struct abc {
    char a;
    char b;
    char c;
    char d[2];
};

int main() {

    char arr[5] = { 'a', 'b', 'c', 'd', 'e' };
    struct abc sa;
    memcpy(&sa, arr, 5);


    return 0;
}

这里arr 是传入缓冲区,使用 memcpy 会正确复制所有内容。

ser.write((const uint8_t *)&mp, sizeof(mp));是正确的

您可以在 arduino 上创建一个相同的结构 mp_arduino 并使用

将接收缓冲区的内容复制到此结构中

memcpy ( &mp_arduino, receive_buffer+n, sizeof(mp_arduino) ); 其中n 表示receive_buffer 中数据开始的位置/字节,receive_buffer 定义为uint8_t receive_buffer[](或uint8_t* receive_buffer 相同...)

(http://www.cplusplus.com/reference/cstring/memcpy/)

这是 struct 在内存中的存储方式:How is a struct stored in memory?

在两个系统上,浮点数都应该是 32 位 https://www.arduino.cc/reference/en/language/variables/data-types/float/

【讨论】:

  • 那你觉得用ser.write((const uint8_t *)&mp, sizeof(mp));发送数据对吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多