C 蓝牙通信中的大延迟
我曾尝试使用两块arduino nano v3板和两个bluetooth 4.0模块编写无线伺服控制。第一个代码是发射机。这很简单。它读取PPM信号并进行转换,以分离每个通道的PWM值。我使用硬件串口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
#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代码中的初学者。你们可以发布更好的解决方案,若可行,我将其标记为答案。你可以帮助很多人我不是故意对你太苛刻的,对不起。我打算写一个答案。我希望你觉得它有用。