C 蓝牙通信中的大延迟

C 蓝牙通信中的大延迟,c,arduino,C,Arduino,我曾尝试使用两块arduino nano v3板和两个bluetooth 4.0模块编写无线伺服控制。第一个代码是发射机。这很简单。它读取PPM信号并进行转换,以分离每个通道的PWM值。我使用硬件串口 #include <PPMReader.h> #include <InterruptHandler.h> int ppmInputPin = 3; int channelAmount = 2; PPMReader ppm(ppmInputPin, channelAmo

我曾尝试使用两块arduino nano v3板和两个bluetooth 4.0模块编写无线伺服控制。第一个代码是发射机。这很简单。它读取PPM信号并进行转换,以分离每个通道的PWM值。我使用硬件串口

#include <PPMReader.h>
#include <InterruptHandler.h> 

int ppmInputPin = 3;
int channelAmount = 2;

PPMReader ppm(ppmInputPin, channelAmount);

void setup()
{
  Serial.begin(9600);
  Serial.write("AT\r\n");
  delay(10);
  Serial.write("AT\r\n");
  Serial.write("AT+INQ\r\n");
  delay(5000);
  Serial.write("AT+CONN1\r\n");
}

void loop()
{
  unsigned long value1 = ppm.latestValidChannelValue(1, 0);
  Serial.println(value1);
}
#include <Servo.h>

int PWM_OUTPUT = 7;

Servo servo;

void setup() {
  servo.attach(PWM_OUTPUT);
  Serial.begin(9600);
}

void loop() {
  int pwmValue = Serial.parseInt();

  if (Serial.available()) { 
    if(pwmValue > 900 && pwmValue < 2001) {
      servo.writeMicroseconds(pwmValue);
    }
  }
}

接收器也很简单。它从蓝牙读取值并解析为整数值,然后通过第7个引脚发送到伺服。我再次使用了硬件串行端口

#include <PPMReader.h>
#include <InterruptHandler.h> 

int ppmInputPin = 3;
int channelAmount = 2;

PPMReader ppm(ppmInputPin, channelAmount);

void setup()
{
  Serial.begin(9600);
  Serial.write("AT\r\n");
  delay(10);
  Serial.write("AT\r\n");
  Serial.write("AT+INQ\r\n");
  delay(5000);
  Serial.write("AT+CONN1\r\n");
}

void loop()
{
  unsigned long value1 = ppm.latestValidChannelValue(1, 0);
  Serial.println(value1);
}
#include <Servo.h>

int PWM_OUTPUT = 7;

Servo servo;

void setup() {
  servo.attach(PWM_OUTPUT);
  Serial.begin(9600);
}

void loop() {
  int pwmValue = Serial.parseInt();

  if (Serial.available()) { 
    if(pwmValue > 900 && pwmValue < 2001) {
      servo.writeMicroseconds(pwmValue);
    }
  }
}


这一切都有效。但它有大约2-3秒的延迟。滥发串口可能会有问题吗

我发现了问题。这是串行端口垃圾邮件。我已经添加了检查当前值是否和以前的值不相等,它是否已经开始工作,下一个小问题是接收器。我在它可用之前读取了值

#include <PPMReader.h>
#include <InterruptHandler.h> 

int ppmInputPin = 3;
int channelAmount = 2;

PPMReader ppm(ppmInputPin, channelAmount);

volatile unsigned long previousValue1 = 0;

void setup()
{
  Serial.begin(9600);
  Serial.write("AT\r\n");
  delay(10);
  Serial.write("AT\r\n");
  Serial.write("AT+INQ\r\n");
  delay(5000);
  Serial.write("AT+CONN1\r\n");
  Serial.println("Transmitter started");
}

void loop()
{
  unsigned long value1 = ppm.latestValidChannelValue(1, 0);

  if(previousValue1 != value1) {
    previousValue1 = value1;
    Serial.println(value1);
  }

}

在实现设备到设备的通信时,您需要问自己的第一件事是我应该以多快的速度发送?如果我以这样的速度发送:接收者是否能够跟上阅读、处理或任何需要做的事情的速度并回复

这显然不是波特率的问题,而是循环在做什么。您正在使用两个不同的库:PPMReader和Servo。现在,请注意每个设备在各自的循环中所做的工作:

//Sending
void loop() {
  unsigned long value1 = ppm.latestValidChannelValue(1, 0);
  Serial.println(value1);
}

//Receiving
void loop() {
  int pwmValue = Serial.parseInt();
  if(pwmValue > 900 && pwmValue < 2001) {
  servo.writeMicroseconds(pwmValue);
  }
}
我真的不知道执行每一行代码需要多长时间,请看一下上面的注释,但您不能指望两个循环都能神奇地同步。考虑到他们正在做非常不同的事情,忽略了处理不同硬件的串行部分,我预计其中一个要比另一个花费更长的时间。想想如果是这样会发生什么

正如我所说,我不知道调用ppm.latestValidChannel Value1,0需要多长时间,但是为了我的论证,让我们假设它需要0.1毫秒。要估计完成循环一次迭代所需的时间,您需要添加使用Serial.printlnvalue1将一个或两个字节打印到端口所需的时间,但这更简单,可能是一个大致的数字。根据这些估计,您最终每秒读取5000次。如果你不高兴或者不相信我的估计,我建议你自己用计数器或计时器做测试。如果你对链接的另一端做同样的练习,假设你得到的速度是原来的两倍,每秒运行10000次,你认为通信会发生什么?是的,这是正确的:它会被堵塞,以蜗牛般的速度运行

在这里,你应该仔细考虑如果你真的需要这么多的阅读,你没有详细说明你实际上在做什么,所以我不知道,但我倾向于认为你不这样做。如果您不这样做,只需在发送方添加一个延迟,将其降低到每秒10-20次迭代的合理速度


代码还有其他需要改进的地方:在读取数据之前,而不是之后,应该检查缓冲区中是否已接收到数据。您需要小心使用Serial.parseInt,这有时会导致意外的结果,但是这个答案已经太长了,我不想进一步扩展它。

所以您首先读取值,然后检查它是否可用?没有道理,你是对的。我会修好的。但这不是问题。问题在于滥发串口。我快速检查了当前pwmValue是否与以前的值不相等,并且它已经开始工作。您意外地修复了您的问题,但实际上您使代码的健壮性比您在问题中发布的更差,这是一项非常了不起的成就。您应该考虑阅读文档,特别是如何Serial.PARSETIN的工作以及它的局限性。在读取之前检查缓冲区中的数据是否可用是一种很好的做法,但必须以正确的方式执行。你应该考虑以某种方式计时你发送值的方式,而不是在全速下做它,而不让接收器暂停,这就是为什么你固定它来检查C代码中的初学者。你们可以发布更好的解决方案,若可行,我将其标记为答案。你可以帮助很多人我不是故意对你太苛刻的,对不起。我打算写一个答案。我希望你觉得它有用。