WebClient и MotionDetector останавливается через некоторое время

Я копал это около недели, и у меня нет никакого способа решить этот вопрос. Мой код Arduino работает некоторое время (несколько раз / несколько дней), а затем внезапно останавливается. Я пытаюсь реализовать WebClient в Arduino, который отправляет HTTP-запросы GET на какой-либо другой сервер каждый раз (периодически — каждые 90 секунд), когда обнаруживается движение / когда движение прекращается.

Ниже вы можете найти код. Кто-нибудь может помочь?

#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();
}
}
}

0

Решение

Трудно сказать без лучшего описания симптомов.
Светодиод все еще мигает?

Если да, код сокета мне кажется неправильным:

void getMovement() {
client.stop();

Вы должны помнить, что TCP требует отслеживания соединения, поэтому вы не можете немедленно остановить сокет, он должен немного задержаться для подтверждения отправленных пакетов.

Если вы посмотрите на реализацию:

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

stop() потерпит неудачу, если у вас есть больше, чем MAX_SOCK_NUM (что на вашей платформе равно 4), открывается одновременно. Может ли это случиться?

В любом случае, вы должны избегать как можно больше динамических распределений, у вас должна быть одна функция sendMovement(bool detected) пишет записанное значение (getMovement а также getNoMovement являются одной и той же функцией, поэтому разложить их на множители). Вы должны использовать клиент как можно чаще (не закрывайте сокет и не открывайте его заново, если вы не получите ошибку от какой-либо функции сокета). Наконец, вы можете захотеть установить прерывание на выводе цифрового входа (с некоторым отладкой программного обеспечения), чтобы избежать опроса на нем, что приведет к освобождению ЦП и, в зависимости от конфигурации, может высвободить больше времени для обработки сообщений SPI.

Если светодиод не мигает, попробуйте закомментировать код, связанный с SPI (EthernetClientкод) и проверьте, работает ли он (в этом случае я бы проверил HW на наличие ошибок, часть кода сокета занята зацикливанием (socket::send делает это), что никогда не закончится и не остановит loop функция от прогресса. В этом случае, если вы используете JTAG для приостановки процессора, он будет в client.connect или же client.println метод.

Если это все еще не работает (светодиод не мигает без кода SPI), то проблема, вероятно, аппаратная, проверьте напряжение / температуру / JTAG, подключите к плате, чтобы прервать ЦП, чтобы выяснить, где он поражен.

Кстати, если вы делаете HTTP, запрос неверный и должен быть:

GET url HTTP/1.1\r\n
Host: yourserverhost.com\r\n
Connection: Keep-Alive\r\n
\r\n

Часть HTTP/1.x после GET url абсолютно необходимо даже для HTTP / 1.0. Если вы не написали свой собственный сервер (в этом случае нет необходимости имитировать HTTP), он не должен работать вообще, даже один раз.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]