Arduino阅读大量序列数据而没有损失
在Arduino系列中,我需要阅读这类行< 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16>
尽可能地不阻止。 目标是在不延迟的情况下设置数组补偿的值[]。 在此示例中损失为96%,然后是95%……因此,我需要我的代码每次显示1000(100%)。
这就是我已经拥有的:
static int compensastion[64];
int passage=1;
const byte numChars = 1000;
char receivedChars[numChars];
boolean newData = false;
int score = 0;
int mal_score = 0;
void setup() {
Serial.begin(115200);
Serial.println();
}
void loop() {
read_inputs();
// get the percentage of success for this simple message from 1 to 16
Serial.print(double(double(score) / double(mal_score+score))*10000);
Serial.println();
}
void read_inputs(){
recvWithStartEndMarkers();
check();
}
// Get the full line <1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16>
void recvWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
if (Serial.available() > 0 && newData == false) {
rc = Serial.read();
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0';
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
// Parse the line in digits
void check(){
if (newData == true) {
newData = false;
int marge = 0;
passage=1;
for(int j = 0; j < numChars; j=j+1){
int my_int = -1;
char buf[4];
if(isDigit(receivedChars[j]) &&marge == 0 ){
if(!isDigit(receivedChars[j+1])){
my_int = receivedChars[j] - '0';
marge=marge+1;
}
if(isDigit(receivedChars[j+1]) && !isDigit(receivedChars[j+2]) ){
my_int = receivedChars[j] - '0';
my_int = my_int*10 + (receivedChars[j+1] - '0');
marge=marge+2;
}
if(isDigit(receivedChars[j+1]) && isDigit(receivedChars[j+2]) && !isDigit(receivedChars[j+3]) ){
my_int = receivedChars[j] - '0';
my_int = my_int*10 + (receivedChars[j+1] - '0');
my_int = my_int*10 + (receivedChars[j+2] - '0');
marge=marge+3;
}
}
if (isDigit(receivedChars[j]) && my_int != -1){
if(passage == my_int){
score=score+1;
}else{
mal_score= mal_score+1;
}
compensastion[(passage-1)*2] = my_int;
passage=passage+1;
if(passage+1 >= 16+2){
passage=1;
}
}
if(marge > 0){
marge=marge-1;
}
}
}
}
In Arduino Serial I need to read those kind of lines <1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16>
As fast
as possible, without blocking.
The goal is to set values of array compensation[] without delay.
In this example <1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16>
Would display 1000 (as 100% have been read) But I don't get 100% but periodique losses at 96% and then 95% … So I need my code to display 1000 (for 100%) every time.
This is what I have already :
static int compensastion[64];
int passage=1;
const byte numChars = 1000;
char receivedChars[numChars];
boolean newData = false;
int score = 0;
int mal_score = 0;
void setup() {
Serial.begin(115200);
Serial.println();
}
void loop() {
read_inputs();
// get the percentage of success for this simple message from 1 to 16
Serial.print(double(double(score) / double(mal_score+score))*10000);
Serial.println();
}
void read_inputs(){
recvWithStartEndMarkers();
check();
}
// Get the full line <1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16>
void recvWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
if (Serial.available() > 0 && newData == false) {
rc = Serial.read();
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0';
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
// Parse the line in digits
void check(){
if (newData == true) {
newData = false;
int marge = 0;
passage=1;
for(int j = 0; j < numChars; j=j+1){
int my_int = -1;
char buf[4];
if(isDigit(receivedChars[j]) &&marge == 0 ){
if(!isDigit(receivedChars[j+1])){
my_int = receivedChars[j] - '0';
marge=marge+1;
}
if(isDigit(receivedChars[j+1]) && !isDigit(receivedChars[j+2]) ){
my_int = receivedChars[j] - '0';
my_int = my_int*10 + (receivedChars[j+1] - '0');
marge=marge+2;
}
if(isDigit(receivedChars[j+1]) && isDigit(receivedChars[j+2]) && !isDigit(receivedChars[j+3]) ){
my_int = receivedChars[j] - '0';
my_int = my_int*10 + (receivedChars[j+1] - '0');
my_int = my_int*10 + (receivedChars[j+2] - '0');
marge=marge+3;
}
}
if (isDigit(receivedChars[j]) && my_int != -1){
if(passage == my_int){
score=score+1;
}else{
mal_score= mal_score+1;
}
compensastion[(passage-1)*2] = my_int;
passage=passage+1;
if(passage+1 >= 16+2){
passage=1;
}
}
if(marge > 0){
marge=marge-1;
}
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
根据我的经验,处理大量串行数据的最有效方法之一是使用中断和有限状态机器(FSM)。
请仔细阅读这是惊人的尼克·加蒙(Nick Gammon)的指南。在处理密集处理任务时,FSM是最通用的方法。 (不要与 rtos )
关于串行通信,我将通过
serialevent()
沿着沿着以下示例的行:
最后,尝试将单用函数中的所有必要数据处理划分。这样,您的代码将具有适当的流量,您将降低用繁重的任务阻止系统的风险。
编辑:我忘了提到
serial.available()
被视为一种高度不可靠且耗时的轮询方法。坚持中断,您不会遇到巨大的问题In my experience, one of the most effective ways to handle huge amounts of serial data is using Interrupts and Finite State Machines (FSM).
Please carefully read this guide by the amazing Nick Gammon. FSMs are the most versatile approach when dealing with intensive processing tasks. (Not to be confused with RTOS, though)
Regarding the serial communication, I would implement the serial reading through the
serialEvent()
interrupt along the lines of the following example:Finally, try to compartmentalize all the necessary data processing in single-purpose functions. This way your code will have a proper flow and you will reduce the risk of blocking the system with heavy tasks.
EDIT: I forgot to mention that the
Serial.available()
is regarded as a polling method which is highly unreliable and time-consuming. Stick to interrupts and you won't have massive issues