Buona sera vi espongo il mio problema : ( premetto che non sono un gran esperto .. )
Ho la necessità che ARDUINO scriva su un DATABASE MYSQL il valore degli ingressi digitali e che recuperi da un altro DATABASE un valore BINARIO per pilotare le uscite
Ho sviluppato questo :
#include <Ethernet.h>
#include <SPI.h>
int in1 = 0;
int in2 = 1;
int in3 = 2;
int in4 = 3;
int in5 = 4;
int out1 = 5;
int out2 = 6;
int out3 = 7;
int out4 = 8;
int out5 = 9;
int read1;
int read2;
int read3;
int read4;
int read5;
byte server[] = { xxx, xxx, xxx , xxx };
String location = "/~xxxxxx/xxxxxxx.php?id=xxxxx HTTP/1.0";
byte mac[] = { 0xXY, 0xXY, 0xXY, 0xXY, 0xXY, 0xXY };
EthernetClient client;
char inString[32];
int stringPos = 0;
boolean startRead = false;
char charArray[10];
void setup(){
Ethernet.begin(mac);
Serial.begin(9600);
pinMode(in1, INPUT);
pinMode(in2, INPUT);
pinMode(in3, INPUT);
pinMode(in4, INPUT);
pinMode(in5, INPUT);
pinMode ( out1 , OUTPUT);
pinMode ( out2 , OUTPUT);
pinMode ( out3 , OUTPUT);
pinMode ( out4 , OUTPUT);
pinMode ( out5 , OUTPUT);
}
void loop(){
String pageValue = connectAndRead();
pageValue.toCharArray(charArray, 10);
unsigned long result = atoi(charArray);
// il valore num e un numero intero letto dal database
Serial.println(result);
digitalWrite(out5, result & B00001);
digitalWrite(out4, result & B00010);
digitalWrite(out3, result & B00100);
digitalWrite(out2, result & B01000);
digitalWrite(out1, result & B10000);
delay(2500);
}
String connectAndRead(){
if (client.connect(server, 80)) {
Serial.println("Leggo dal database il valore delle Uscite");
client.print("GET ");
client.println(location);
client.println();
return readPage();
}else{
return "connection failed";
}
}
String readPage(){
stringPos = 0;
memset( &inString, 0, 32 );
while(true){
if (client.available()) {
char c = client.read();
if (c == '<' ) {
startRead = true;
}else if(startRead){
if(c != '>'){
inString[stringPos] = c;
stringPos ++;
}else{
startRead = false;
client.stop();
client.flush();
Serial.println("disconnecting.");
return connectAndWrite();
}
}
}
}
}
String connectAndWrite(){
read1 = digitalRead(in1);
read2 = digitalRead(in2);
read3 = digitalRead(in3);
read4 = digitalRead(in4);
read5 = digitalRead(in5);
if (client.connect(server, 80)) {
Serial.println("Invio al database ingressi digitali");
client.print("GET /xxxxxx.php?xxxxx=xxxxxx");
client.print("&in1=");
client.print(read1);
client.print("&in2=");
client.print(read2);
client.print("&in3=");
client.print(read3);
client.print("&in4=");
client.print(read4);
client.print("&in5=");
client.print(read5);
client.println(" HTTP/1.0");
client.println("HOST: xxxxx.it");
client.println();
}
startRead = false;
client.stop();
client.flush();
delay(100);
return inString;
}
Funziona alla perfezione , ma ogni tanto si interrompe la comunicazione ed ARDUINO entra in un limbo dal quale non esce più ... per ristabilire la connessione al SERVER devo riavviare. Il codice lo ho scritto "scopiazzando" pezzi qua e la ma non trovo una via di uscita a questo problema
Ho 3 ARDUINO con relativi ETHERNET SHIELD ( premetto 3 indirizzi MAC diversi ) tutti e 3 con lo stessoprogramma che gira ( quello del post precedente )
ognuno comunica con il mio SERVER ma con ID univoco , il SERVER memorizza l'ultima esistenza in vita di ARDUINO ..
Assurdo ma vero.. tutte e tre smettono di funzionare alla stessa ora ( minuto e secondo ) anche se le accendo in tempi diversi
Quindi credo che il SERVER ogni tanto rifiuti la connessione eforo si impallano... infatti chiedevo se era possibile fare in modo che , se non trovano la connessione , il programma riparti da zero.
Ho provato con il WATCH DOG ma il problema e che , quando resetta , le uscite che avevo attive mi si spengono e ciò non posso farlo accadere !! ( controllano l'irrigazione penza che bordello )
Bhe quello che ti succede è proprio quello definito su quel link dove viene proposta una modifica alla libreria. Il testo tradotto da Vanzati dice:
Tra le situazioni in cui il chip sembra freezarsi e una delle cause potrebbe essere che quando si trova nella condizione di lasciare una connessione, si mette nello stato di CLOSE_WAIT, quindi sta lì ad aspettate una risposta che di fatto non riceve perchè qualcosa è andato storto nella trasmissione precedente.
L'importante in tutto questo è che la ethernet non si pianti, può cadere la connessione e la ethernet deve essere in grado di chiudersi in caso di mancata risposta. Visto che tu arduino lo usi come client ed è lui che chiama il server, potrebbe ristabilire la connessione da solo appena passato il disservizio.
quindi potresti provare, al massimo resta tutto come prima
soluzioni che potrebbero essere dei ripieghi sono:
Mandare al server l'ultimo status delle porte, in caso di riavvio arduino chiede al server "mi sono riavviato mandami l'ultimo stato!!"
Scrivere su SD i parametri ogni n secondi e caricarli con un file.ini al riavvio
OK per il PIN 1 , 2 effettivamente li ho usati in quanto non utilizzavo la seriale e volevo sfruttare tutte le risorse di ARDUINO ( MA LI POSSO CAMBIARE )
Il PIN 4 lo utilizzo in quanto non ho necessità della SD card ( NON SAPEVO ANDASSE LASCIATO LIBERO )
Il PIN10 non lo sto utilizzando !
risposta a pablos :
In realtà utilizzo già il SERVER per memorizzare lo stato delle uscite , infatti se lo riavvio le uscite tornano come erano... ma il problema e che si SPENGONO e poi RIACCENDONO e ciò non dovrebbe accadere
Serial.println(result);
digitalWrite(out5, result & B00001);
digitalWrite(out4, result & B00010);
digitalWrite(out3, result & B00100);
digitalWrite(out2, result & B01000);
digitalWrite(out1, result & B10000);
Come vedi dalla porzione di codice , leggo il numero dal DATABASE , lo converto in BINARIO e attivo le uscite !
L'ideale sarebbe "RIAVVIARE" a cicli regolari l'ETHERNET SHIELD sensa "RIAVVIARE" ARDUINO
Ho già provato a isolare i 2 pin di reset e resettare solo la ethernet in corsa, ma questa non riparte più, ha bisogno di essere resettato insieme ad arduino.
No, a me così non si pianta, la ethernet è a riposo e ogni tanto la chiamo.
Non ho esperienza diretta su una connessione continua, quindi non so dirti se c'e' una possibilità di schianto.
Hai una necessità di avere una comunicazione di 24h/24?
ogni 2 minuti ARDUINO legge lo stato di 5 ingressi , si collega ad un SERVER ed invia i dati ( tramite una pagina PHP ) a un DB MYSQL
contestualmente chiede al DB MYSQL come deve impostare le uscite ed esegue
E funziona tutto bene ( a parte il freeze )
Ho preferito questa soluzione per evitare di dover attivare servizi DDNS ( non devo cercarlo in rete ed inviargli richieste )
Si , ho la necessita di monitorare ingressi in modo continuo 24 ore su 24 ore
Grazie per l'interesse
P.S.
Nel frattempo ho modificato la libreria "libraries/Ethernet/EthernetClient.cpp" ( come da LINK postati da altri utenti ) e lo sto testando
for (int i = 0; i < MAX_SOCK_NUM; i++) {
uint8_t s = W5100.readSnSR(i);
// originale
if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT) {
// modificata
if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT || s == SnSR::CLOSE_WAIT) {
_sock = i;
break;
}
Ho connesso alla rete 3 moduli ARDUNO con la libreria modificata "libraries/Ethernet/EthernetClient.cpp" come da post precedente
In questo momento ( a 20 ore di connessione continua ) i tre moduli sono sempre connessi , li vedo dal database che aggiorna ogni 5 minuti lo stato trasmesso
In uno dei tre ho attivato le uscite digitali ( dove ci sono connessi dei LED ) tramite il codice
String pageValue = inString;
pageValue.toCharArray(charArray, 10);
unsigned long result = atoi(charArray);
//Serial.print("risultato letto ==> ");
//Serial.println(inString);
digitalWrite(out5, result & B00001);
digitalWrite(out4, result & B00010);
digitalWrite(out3, result & B00100);
digitalWrite(out2, result & B01000);
digitalWrite(out1, result & B10000);
dopo 20 minuti , il modulo in questione è andato in FREEZE... ora ho provato a mettere un ritardo tra l'attivazione delle uscite e la continuazione del programma
String pageValue = inString;
pageValue.toCharArray(charArray, 10);
unsigned long result = atoi(charArray);
//Serial.print("risultato letto ==> ");
//Serial.println(inString);
digitalWrite(out5, result & B00001);
digitalWrite(out4, result & B00010);
digitalWrite(out3, result & B00100);
digitalWrite(out2, result & B01000);
digitalWrite(out1, result & B10000);
delay (1000);
Ho appena ricevuto la mail dal server che mi comunica che la periferica n°1 ( quella senza OUTPUT collegati ) non è più raggiungibile !!!
Ora attendo di vedere se si riprende da sola ( ne dubito ) altrimenti stasera arrivo a casa e vedo
Mi dispiace, probabilmente la patch non basta, non è escluso però che ne tuo caso ci possa essere un problema software.
tutti i moduli hanno lo stesso software?
gli shield con l'enc28j60 di microchip non sembrano soffrire di problemi di blocco, ne ho in esecuzione da settimane senza particolari problemi... ho scritto anche un tutorial sul loro uso: http://www.lucadentella.it/category/enc28j60-arduino/
hai però altri limiti:
tutto lo stack TCP/IP è a carico di Arduino, il chip ENC28j60 si occupa "solo" della parte Ethernet... questo significa più carico e un diverso "approccio" alla programmazione (nel tuo loop devi prevedere esplicitamente chiamate al loop dei pacchetti);
anche il buffer di ricezione/trasmissione è in memoria Arduino (600-700bytes) quindi hai meno memoria disponibile per il tuo uso;
per ora le librerie non supportano la frammentazione del pacchetto TCP in più pacchetti IP, sei quindi limitato al valore MTU della rete (di solito 1500 bytes) come dimensione massima dei dati che puoi inviare...
Sempre in quel link che ti ho messo tempo fa http://arduino.cc/forum/index.php/topic,94572.0.html si parla anche di chip ethernet alternativi, mi sembra "legacy" abbia testimoniato come lucadentella qui sopra che non ha problemi con enc28j60, ripeto riguardo a me sulla mia shield con il 5100 ho un traffico di 1 MB circa al minuto e non si è mai freezata il massimo di tempo in test che ho fatto sono 10-12 ore circa, poi aggiungo modifico e quindi riavvio spesso.