我已经挖掘了大约一个星期,没有任何办法解决这个问题。我的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)
写入检测到的值的函数(getMovement
和getNoMovement
是相同的函数,因此请分解它们)。您应该尽可能多地重用客户端(避免关闭套接字并重新打开它,除非您从任何套接字函数中收到错误)。最后,您可能希望在数字输入引脚上设置一个中断(使用一些软件去抖动),以避免轮询,这将释放CPU,并且根据配置,可能会释放更多时间来处理SPI消息。
如果 LED 不闪烁,请尝试注释掉 SPI 相关代码(EthernetClient
的代码)并检查它是否正常工作(在这种情况下,我会检查硬件是否有错误,一些套接字代码正忙于循环(socket::send
这样做)永远不会完成并阻止您的loop
功能继续。在这种情况下,如果你使用JTAG暂停CPU,它将处于client.connect
或client.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),否则它根本不应该工作,甚至一次都不能工作。