WebClient 和 MotionDetector 会在一段时间后停止

WebClient and MotionDetector stops after a while

本文关键字:一段时间 MotionDetector WebClient      更新时间:2023-10-16

我已经挖掘了大约一个星期,没有任何办法解决这个问题。我的Arduino代码工作了一段时间(几次/几天),然后突然停止。我正在尝试在Arduino中实现一个WebClient,当检测到运动/运动停止时,每次(定期 - 每90秒)都会将HTTP GET请求发送到其他服务器。

您可以在下面找到代码。谁能帮忙?

#include <Ethernet2.h>
#include <SPI.h>
byte mac[] = { 0x90, 0xA2, 0xDA, 0x10, 0x73, 0x88 };
IPAddress ip(192,168,20,84);
IPAddress server(192,168,50,93); // Google
IPAddress myDns(8, 8, 8, 8);
EthernetClient client;
//getMovement - sends a GET request when motion is detected
void getMovement() {
client.stop();
if (client.connect(server, 8080)) {
client.println("GET /GetARoomMaven/motion?roomId=1&movement=1");
client.println();
Serial.println("Movement Request Sent");
} else {
Serial.println("connection failed");
}
}
//getNoMovement - sends a GET request when motion had stopped
void getNoMovement() {
client.stop();
if (client.connect(server, 8080)) {
client.println("GET /GetARoomMaven/motion?roomId=1&movement=0");
client.println();
Serial.println("Movement Request Sent");
} else {
Serial.println("connection failed");
}
}
//VARS
//the time we give the sensor to calibrate (10-60 secs according to the datasheet)
int calibrationTime = 10;        
//the time when the sensor outputs a low impulse
long unsigned int lowIn;         

//the amount of milliseconds the sensor has to be low 
//before we assume all motion has stopped
long unsigned int pause = 90000;  
//
boolean lockLow = true;
boolean takeLowTime;  
int pirPin = 2;    //the digital pin connected to the PIR sensor's output
int ledPin = 13;

/////////////////////////////
//SETUP
void setup(){
Serial.begin(9600);
pinMode(pirPin, INPUT);
pinMode(ledPin, OUTPUT);
digitalWrite(pirPin, LOW);
Ethernet.begin(mac);
//give the sensor some time to calibrate
Serial.print("calibrating sensor ");
for(int i = 0; i < calibrationTime; i++){
Serial.print(".");
delay(1000);
}
Serial.println(" done");
Serial.println("SENSOR ACTIVE");
delay(50);
loop();
}
////////////////////////////
//LOOP
void loop(){
if(digitalRead(pirPin) == HIGH){
digitalWrite(ledPin, HIGH);   //the led visualizes the sensors output pin state
if(lockLow){  
//makes sure we wait for a transition to LOW before any further output is made:
lockLow = false;     
Serial.print("motion detected at ");
Serial.print(millis()/1000);
Serial.println(" sec"); 
getMovement();
}         
takeLowTime = true;
}
if(digitalRead(pirPin) == LOW){       
digitalWrite(ledPin, LOW);  //the led visualizes the sensors output pin state
if(takeLowTime){
lowIn = millis();          //save the time of the transition from high to LOW
takeLowTime = false;       //make sure this is only done at the start of a LOW phase
}
//if the sensor is low for more than the given pause, 
//we assume that no more motion is going to happen
if(!lockLow && millis() - lowIn > pause){  
//makes sure this block of code is only executed again after 
//a new motion sequence has been detected
lockLow = true; 
Serial.print("motion ended at ");      //output
Serial.print((millis() - pause)/1000);
Serial.println(" sec");
getNoMovement();
}
}
}

如果没有更好的症状描述,很难说。 指示灯是否仍在闪烁?

如果是,套接字代码对我来说似乎是错误的:

void getMovement() {
client.stop();

您必须记住,TCP需要连接跟踪,因此您不能立即停止套接字,它必须徘徊一下以确认发送的数据包。

如果您查看实现:

void EthernetClient::stop() {
if (_sock == MAX_SOCK_NUM)
return;
[...]
}

如果一次打开超过MAX_SOCK_NUM(在您的平台上为 4 个),stop()将失败。这能发生吗?

在所有情况下,您应该尽可能避免动态分配,您应该有一个sendMovement(bool detected)写入检测到的值的函数(getMovementgetNoMovement是相同的函数,因此请分解它们)。您应该尽可能多地重用客户端(避免关闭套接字并重新打开它,除非您从任何套接字函数中收到错误)。最后,您可能希望在数字输入引脚上设置一个中断(使用一些软件去抖动),以避免轮询,这将释放CPU,并且根据配置,可能会释放更多时间来处理SPI消息。

如果 LED 不闪烁,请尝试注释掉 SPI 相关代码(EthernetClient的代码)并检查它是否正常工作(在这种情况下,我会检查硬件是否有错误,一些套接字代码正忙于循环(socket::send这样做)永远不会完成并阻止您的loop功能继续。在这种情况下,如果你使用JTAG暂停CPU,它将处于client.connectclient.println方法中。

如果仍然不工作(LED不闪烁,没有SPI代码),那么问题可能是硬件,检查电压/温度/JTAG连接到电路板以中断CPU以找出它被击中的位置。

顺便说一句,如果您正在执行HTTP,则请求是错误的,应该是:

GET url HTTP/1.1rn
Host: yourserverhost.comrn
Connection: Keep-Alivern
rn

即使对于HTTP/1.0,GET url之后HTTP/1.x的部分也是绝对必需的。除非你已经编写了自己的服务器(在这种情况下,没有必要模仿HTTP),否则它根本不应该工作,甚至一次都不能工作。