如何从 Arduino 捕获传感器数据并将其存储到 C++ 中
How to capture and store sensor data from Arduino into C++
我正在编写代码以捕获从 Arduino 到 C++ 的串行读数
有没有办法逐行捕获读数,然后将其存储到数组中?我已经阅读了另一个与我的相似的post,但我仍然无法应用它。
非常感谢任何帮助,谢谢。
环境设置:
- Arduino UNO
- ADXL 335 加速度计
- Ubuntu 16.04
- C++
[更新] 应用了 Bart
的解决方案
Cpp 文件
之所以加上“for-loop with print and break”是为了分析数组内容。
#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>...
但现在,一些输出的值在“损坏”内(请 see 从顶部算起第四行)。
即使使用开始和结束标记来确定一个正确的数据集,该集中的数据仍然是错误的。我怀疑问题出在 C++ 的 char 数组上,因为它与 Arduino 不同步。否则我需要从 Arduino 发送字节(不太确定如何)
在不同处理器上处理两个程序 运行 时,它们永远不会同时启动 sending/receiving。您可能看到的不是结果合并错误,更有可能是读取程序在数据中途启动和停止。
通过线路发送数据时,您最好:
关于 Arduino:
- 第一帧数据。
- 发送帧。
在 Linux 上:
- 读入缓冲区中的数据。
- 在缓冲区中搜索完整的帧并解帧。
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
我正在编写代码以捕获从 Arduino 到 C++ 的串行读数
有没有办法逐行捕获读数,然后将其存储到数组中?我已经阅读了另一个与我的相似的post,但我仍然无法应用它。
非常感谢任何帮助,谢谢。
环境设置:
- Arduino UNO
- ADXL 335 加速度计
- Ubuntu 16.04
- C++
[更新] 应用了 Bart
的解决方案Cpp 文件
之所以加上“for-loop with print and break”是为了分析数组内容。
#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>...
但现在,一些输出的值在“损坏”内(请 see 从顶部算起第四行)。
即使使用开始和结束标记来确定一个正确的数据集,该集中的数据仍然是错误的。我怀疑问题出在 C++ 的 char 数组上,因为它与 Arduino 不同步。否则我需要从 Arduino 发送字节(不太确定如何)
在不同处理器上处理两个程序 运行 时,它们永远不会同时启动 sending/receiving。您可能看到的不是结果合并错误,更有可能是读取程序在数据中途启动和停止。
通过线路发送数据时,您最好:
关于 Arduino:
- 第一帧数据。
- 发送帧。
在 Linux 上:
- 读入缓冲区中的数据。
- 在缓冲区中搜索完整的帧并解帧。
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