如何从Arduino捕获和存储传感器数据到C ++

时间:2019-06-04 07:50:37

标签: c++ arduino ubuntu-16.04

我正在编写代码以捕获从Arduino到C ++的串行读数

有没有一种方法可以逐行捕获读数,然后将其存储到数组中?我已经阅读了另一本与我类似的post,但仍然无法应用。

非常感谢您的帮助。

环境设置:

  • Arduino UNO
  • ADXL 335加速度计
  • Ubuntu 16.04
  • C ++

[更新] Bart的已应用解决方案

Cpp文件

我添加“带有打印和中断的for循环”的原因是为了分析数组内容。

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <unistd.h>

using namespace std;

char serialPortFilename[] = "/dev/ttyACM0";

int main()
{
    char readBuffer[1024];

    FILE *serPort = fopen(serialPortFilename, "r");

    if (serPort == NULL)
    {
        printf("ERROR");    
        return 0;
    }   

    while(1)
    {                           
        usleep(1000); //sync up Linux and Arduino       

        memset(readBuffer, 0, 1024);
        fread(readBuffer, sizeof(char),1024,serPort);       

        for(int i=0; i<1024; i++){
            printf("%c",readBuffer[i]);     
        }
        break;
    }

    return 0;
}

Ino文件

从加速度计获取数据

#include <stdio.h>

const int xPin = A0;
const int yPin = A1;
const int zPin = A2;

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

void loop() {
  int x = 0, y = 0, z = 0;

  x = analogRead(xPin);
  y = analogRead(yPin);
  z = analogRead(zPin);

  char buffer[16];
  int n;
  n = sprintf(buffer,"<%d,%d,%d>",x,y,z);

  Serial.write(buffer);
}

结果

运行代码三遍 Click Here

理想的输出应该是

<a,b,c><a,b,c><a,b,c>...

但是现在,某些输出的值在“ corrupted”(已损坏)内部(请see从顶部起第四行)。

即使使用开始和结束标记来确定正确的数据集,集合中的数据仍然是错误的。我怀疑问题出在C ++中的char数组,因为它与Arduino不同步。否则我需要从Arduino按字节发送(不确定如何发送)

1 个答案:

答案 0 :(得分:0)

当处理在不同处理器上运行的两个程序时,它们将永远不会同时开始发送/接收。您可能看到的不是结果合并错误,更可能是读取程序在数据中途启动和停止。

通过线路发送数据时,最好是:

在Arduino上:

  1. 首先对数据进行构图。
  2. 发送框架。

在Linux上:

  1. 读入缓冲区中的数据。
  2. 在缓冲区中搜索完整的帧和解帧。

1。构成数据

将数据成帧意味着我需要一个可以在接收端识别并验证的结构。例如,您可以在数据周围添加字符STX和ETX作为control characters。当数据长度变化时,也需要发送该数据。

在下面的示例中,我们认为数据数组永远不会超过255个字节。这意味着您可以将长度存储在单个字节中。在下面,您可以看到框架的伪代码:

STX LENGTH DATA_ARRAY ETX

将要发送的字节的总长度就是数据的长度加三。

2。正在发送

接下来,您不使用println,而是使用Serial.write(buf,len)。

3。接收

在接收方,您有一个缓冲区,所有接收到的数据都将附加在其中。

4。整理 接下来,每次添加新数据以搜索STX字符时,假定下一个字符为长度。使用长度+1,您应该找到一个ETX。如果是这样,您已经找到一个有效的框架并且可以使用该数据。接下来,将其从缓冲区中删除。

for(uint32_t i = 0; i < (buffer.size() - 2); ++i)
{
  if(STX == buffer[i])
  {
    uint8_t length = buffer[i+2];
    if(buffer.size() > (i + length + 3) && (ETX == buffer[i + length + 2]))  
    {
      // Do something with the data.

      // Clear the buffer from every thing before i + length + 3
      buffer.clear(0, i + length + 3);

      // Break the loop as by clearing the data the current index becomes invalid.
      break; 
    }
  }
}

有关还使用循环冗余校验(CRC)的示例,请参见here