我尝试使用两个arduino nano v3板和两个蓝牙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);
}
接收器也很简单。它从蓝牙读取值并将其解析为整数值,并通过第7针发送到伺服。我再次使用了硬件串行端口。
#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秒左右。可能在“垃圾邮件”串行端口中出现问题?
答案 0 :(得分:0)
在实现设备到设备通信时,您需要问自己的第一件事是我应该以多快的速度发送?并且如果我以该速率发送:接收方是否能够跟上步伐(阅读,进行处理或执行其需要做的任何事情并回复)?
这显然与波特率无关,而与循环的作用有关。您正在使用两个不同的库: 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);
}
}
我真的不知道执行每一行代码要花多长时间(请看here上的一些注释),但是您不能真正期望两个循环都能神奇地自我同步。考虑到它们在处理不同的硬件方面做的事情非常不同(省去了串行部分),我希望其中一个比另一个花费更长的时间。想想如果是这样的话。
正如我所说,我不知道调用ppm.latestValidChannelValue(1, 0)
会花费多长时间,但是出于我的观点,我们假设它花费0.1毫秒。要估算完成循环一次迭代所需的时间,您需要添加使用Serial.println(value1)
将一个(或两个)字节打印到端口所花费的时间,但这更容易,也许在{{3左右}}是个不错的人物。通过这些估计,您最终每秒读取5000次。如果您不满意或不信任我的估计,我建议您使用计数器或计时器进行自己的测试。如果对链接的另一端进行相同的练习,并且假设它的速度快一倍,则每秒运行10000次,您如何看待通信?是的,没错:它将被阻塞并以蜗牛的速度运行。
在这里,您应该仔细考虑您是否真的需要那么多阅读材料(您没有详细说明自己在做什么,所以我不知道,但我倾向于认为您不需要)。如果不这样做,只需在发送方增加延迟,以将其降低到合理的速度(可能是每秒10-20次迭代)。
您的代码还有其他需要改进的地方:应在读取缓冲区之前(而不是之后)检查缓冲区中是否已接收到数据。而且您需要小心使用Serial.parseInt()
,它有时会导致意外的结果,但是这个答案已经太长了,我不想进一步扩展它。
答案 1 :(得分:-1)
我发现了问题。这是在串行端口垃圾邮件中。我添加了检查当前值是否不等于上一个值,并且它已经开始工作并且下一个小问题在接收器中。我在价值可用之前就读过它。
#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);
}
}