non riesco a capire il problema

Rieccomi qua dopo 2 mesi a rompervi le scatole con il mio progetto!
Innanzitutto buongiorno!
Allora dopo varie peripezie sono riuscito a montare il mio progetto, si trata di un controllo remoto di una pompa di un pozzo. ve lo descrivo brevemente
in pratica devo controllare una pompa d'acqua ad 1 km di distanza dall'abitazione per riempire la cisterna. Quindi ho preso 2 arduino 2009 con le sheild ethernet, 2 access point in configurazione bridge point-point e ho scritto un piccolo codice che sfrutta il protocollo UDP
il primo arduino deve semplicemente inviare il comando di accensione della pompa del pozzo , oppure aprire la saracinesca dell'acquedotto (nel caso che non ci sia + acqua, si sia rotta la pompa, ecc), l'altro arduino invece deve inviare dei segnali di controllo (poma ON, acquedotto ON, Assenza energia elettrica, avaria pompa)

montanto a casa tutto funzionava, adesso no! cioè...funziona per qualche giorno...poi l'arduino si pianta! (ho pensato ad un problema di comunicazione tra gli access point, ma si pingano con 1ms di media! e poi ho messo contantore di pacchetti persi, non è quello il problema)! semplicemente smette di funzionare e non riconosce + gli ingressi...e devo andare con la macchina su per i campi a premere il tasto reset!
Quale è il problema secondo voi? devo inserire un watchdog?

ora posto il codice

Questo è quello che invia il comando di accensione pozzo/acquedotto e tramite led mostra lo stato del remoto!

//Arduino Casanova aggiornato al 7 Marzo 2011 - Versione senza serial print

#include <SPI.h>        
#include <Ethernet.h>
#include <Udp.h>         

byte mac[] = {  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEE };
byte ip[] = { 192,168,0,201 }; //Indirizzo IP
unsigned int localPort = 8888;   //Porta


byte remoteIp[] = { 192,168,0,202 };        // Ip arduino Capannacce
unsigned int remotePort = 8888 ; // Porta arduino capannacce

char packetBuffer[UDP_TX_PACKET_MAX_SIZE];
int timer =0;


int stati = 0;
int stato1 = 0;
int stato2 = 0;
int ricevuto = 0;
char invio[] = "0";
//unsigned int sentSize = 0;




void setup() {
  

  Ethernet.begin(mac,ip);
  Udp.begin(localPort);

  Serial.begin(9600);

  pinMode(2,INPUT); //pompa
  pinMode(3,INPUT); //Acquedott

  pinMode(4,OUTPUT);  //pompa
  pinMode(5,OUTPUT); //Acquedotto
  pinMode(6,OUTPUT); //Avaria
  pinMode(7,OUTPUT); //Assenza Energia
  pinMode(8,OUTPUT); //assenza rete access point


}

void loop() {
  
  
 stati = 0;
  
 stato1 = digitalRead(2);
 stato2 = digitalRead(3);
  
   if (stato1 == HIGH) { stati = stati+1;}
    
   if (stato2 == HIGH){  stati =stati+2; }
    
   itoa(stati,invio,10);

ket( invio, remoteIp, remotePort);
    

//char  packetBuffer[] = "0"; 
 
 

  int packetSize = Udp.available(); // note that this includes the UDP header
  if(packetSize)
  {  digitalWrite(8, LOW);
    timer = 0;
    
   Udp.readPacket(packetBuffer,UDP_TX_PACKET_MAX_SIZE, remoteIp, remotePort);
 
   ricevuto=atoi(packetBuffer);


  switch (ricevuto) {
    case 1:
      digitalWrite(4, HIGH);
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);
      break;
      
    case 2:
      digitalWrite(4, LOW);
      digitalWrite(5, HIGH);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);      
      break;
      
    case 3:
      digitalWrite(4, HIGH);
      digitalWrite(5, HIGH);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);

      break;
    
    case 4:
      digitalWrite(4, LOW);
      digitalWrite(5, LOW);              
      digitalWrite(6, HIGH);
      digitalWrite(7, LOW);
      break;
      
    case 5:
      digitalWrite(4, HIGH);
      digitalWrite(5, LOW);
      digitalWrite(6, HIGH);
      digitalWrite(7, LOW);
      break;
    
    case 6:
      digitalWrite(4, LOW);
      digitalWrite(5, HIGH);
      digitalWrite(6, HIGH);     
      digitalWrite(7, LOW);      
      break;
      
    case 7:
      digitalWrite(4, HIGH);
      digitalWrite(5, HIGH);
      digitalWrite(6, HIGH);
      digitalWrite(7, LOW);      
      break;
    
    case 8:
     digitalWrite(4, LOW);
     digitalWrite(5, LOW);
     digitalWrite(6, LOW);
     digitalWrite(7,  HIGH);
     break;
     
    case 9:
      digitalWrite(4, HIGH);
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);     
      digitalWrite(7, HIGH);
      break;
    
    case 10:
      digitalWrite(4, LOW);    
      digitalWrite(5, HIGH);
      digitalWrite(6, LOW);      
      digitalWrite(7, HIGH);
      break;
    
    case 11:
      digitalWrite(4, HIGH);
      digitalWrite(5, HIGH);
      digitalWrite(6, LOW);      
      digitalWrite(7, HIGH);
      break;
    
    case 12:
      digitalWrite(4, LOW);    
      digitalWrite(5, LOW);
      digitalWrite(6, HIGH);
      digitalWrite(7, HIGH);
      break;
    
    case 13:
      digitalWrite(4, HIGH);
      digitalWrite(5, LOW);
      digitalWrite(6, HIGH);
      digitalWrite(7, HIGH);
      break;
      
    case 14:
      digitalWrite(4, LOW);    
      digitalWrite(5, HIGH);
      digitalWrite(6, HIGH);
      digitalWrite(7, HIGH);      
      break;
      
    case 15:
      digitalWrite(4, HIGH);
      digitalWrite(5, HIGH);
      digitalWrite(6, HIGH);
      digitalWrite(7, HIGH);
      break;
    
    
    
    default: 
      digitalWrite(4, LOW);
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);
  }
}
else   { timer = timer+1;
if (timer > 20){
  //Serial.println("NESSUNA RISPOSTA");
 digitalWrite(4, LOW);
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);
  digitalWrite(8, HIGH);}
    


}
  
Serial.println(timer);
delay (500);
}

Questo è il remoto: accende pompa o pozzo e manda informazioni sugli stati

//aggiornato al 7 marzo 2011, versione senza serial print
#include <SPI.h>         
#include <Ethernet.h>
#include <Udp.h>         

byte mac[] = {  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192,168,0,202 };       //Indirizzo Ip
unsigned int localPort = 8888;      // Porta in ascolto


byte remoteIp[] = { 192,168,0,201 };        //Indirzzo IP Arduino Casanova
unsigned int remotePort = 8888; // Porta Arduino Casanova


char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet,


int arrivo;
char invio[] = "0";

int timer = 0;

int stato4 = 0;
int stato5 = 0;
int stato6 = 0;
int stato7 = 0;
int stati = 0;

void setup() {
  
  pinMode(2, OUTPUT); // Pompa 
  pinMode(3, OUTPUT); // Acquedotto
  pinMode(8, OUTPUT); //Assenza Energia Eleettrica
  
  pinMode(4,INPUT); // Pompa
  pinMode(5,INPUT); // Acquedotto
  pinMode(6,INPUT); // Avaria Pompa
  pinMode(7,INPUT); //Energia Elettrica
  
  // start the Ethernet and UDP:
  Ethernet.begin(mac,ip);
  Udp.begin(localPort);

  Serial.begin(9600);
}

void loop() {
  
  
   stati = 0;

  int packetSize = Udp.available(); 
  if(packetSize) //controlla se c'è un pacchetto UDP
  {     timer =0;

    // read the packet into packetBufffer and get the senders IP addr and port number
    Udp.readPacket(packetBuffer,UDP_TX_PACKET_MAX_SIZE, remoteIp, remotePort);
    arrivo=atoi(packetBuffer);
   


  switch (arrivo) {
    case 1:
      digitalWrite(2, HIGH);
      digitalWrite(3, LOW);
      break;
    
    case 2:
      digitalWrite(2, LOW);
      digitalWrite(3, HIGH);
      break;
      
    case 3:
      digitalWrite(2, HIGH);
      digitalWrite(3, HIGH);
      break;
    
    default: 
      digitalWrite(2, LOW);
      digitalWrite(3, LOW);
      
  }}
  else {
    timer= timer+1;
    if (timer >20){
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    //Serial.print("Nessun Collegamento");}
  
  }

   stato4 = digitalRead(4);
   stato5 = digitalRead(5);
   stato6 = digitalRead(6);
   stato7 = digitalRead(7);
    
   if (stato4 == HIGH) { (stati=stati+1);  }  
   if (stato5 == HIGH) { (stati=stati+2);  }   
   if (stato6 == HIGH) { (stati=stati+4);  }
   if (stato7 == LOW) { (stati=stati+8);
                        digitalWrite(8, HIGH); }   
   if (stato7 == HIGH) {digitalWrite(8, LOW);} 
itoa(stati,invio,10); 


    Udp.sendPacket( invio, remoteIp, remotePort);
  
  delay(500);
}

Dico una stupidaggine, se il tutto non e' alimentato a batteria, basta mettere una di quelle prese ad orologio per far spegne e riaccendere l'arduino una volta al giorno.

Piccola scappatoia dal costo di 5€ :stuck_out_tongue:

Non mi pare cosi' ad occhio che il codice contenga errori, a dire il vero pero' eviterei di utilizzare variabili come "timer" visto che mi pare siano usate dal sistema.

Mi chiedo... il sistema smette di funzionare a caso o con una cadenza precisa?
Smette di funzionare dopo qualche giorno anche a casa?

ps: sei il contadino piu' tecnologico del mondo ]:smiley:

Perchè non tiri un cavo da 1 KM dall'arduino a casa tua e ci metti un pulsante per resettarlo? :smiley: :smiley: :smiley:
Ovviamente scherzo, e complimenti per l'idea :slight_smile:

i rimedi barbari volevo lasciarli come estrema ratio :slight_smile:
la cadenza non è precisa (a occhio è capitato 1 volta a settimana) poi quando ho tolto una riga che scriveva 0 nel buffer ad ogni ciclo, si è piantato 2 volte in un giorno! ma non c'è un evento o qualcosa di preciso che lo fa bloccare.... anzi + lavora meno si blocca! (è dovuto al fatto che il contattore della pompa (3kw 380v) quando attacca anche se ha i condensatori fa un extratensione tale che resetta tutto! haah

volevo provare a mettere il watchdog ma l'ultima volta che k'ho fatto con un altro arduino ho sbagliato e mi si resettava di continuo (ho dovuto usare un altro arduino per riprogrammare l'atm :slight_smile: )

Tommaso:
è dovuto al fatto che il contattore della pompa (3kw 380v) quando attacca anche se ha i condensatori fa un extratensione tale che resetta tutto! haah

Ma è un'affermazione o un'ipotesi?

a parte un fattore esterno, potrebbe essere:

  1. un errore di trasmissione del pacchetto UDP... prova a usare il TCP!

  2. un errore nella libreria dell'ethernet shield

in "locale"

ket( invio, remoteIp, remotePort);

che è sta funzione? dov'è dichiarata? che fa?

argh!
sia in remoto che in "locale":

char invio[] = "0";
[...]
itoa(stati,invio,10);

cos'è sta cosa?
quando tu fai char invio[] = "0"; crei un'array di char che però ha dimensione 2 (carattere '0'+ carattere fine stringa '\0')
in locale nessun problema, perchè tanto i numeri sono 0, 1, 2, 3 che occupano tutti due caratteri (numero + stringa).

ma che succede in remoto? ehhehehe, quì i numeri vanno da 0 a 15.... quindi succede che quando scrivi da 10 in su il carattere '\0' buca l'array è va a sovrascrivere diosolosacosa... e quando sovrascrive la cosa sbagliata arduino si pianta

la soluzione più veloce è, nel remoto, fare char invio[] = "00"; così hai spazio per 2 caratteri oltre al fine stringa. Vedi se pianta ancora.

poi quando ho tolto una riga che scriveva 0 nel buffer ad ogni ciclo

dov'è questa istruzione? io non la vedo...

bel lavoro.....
mi sento tanto piccolo d'innanzi ad un codice così......... :frowning:

La butto lì.... on è più o meno il problema del quale discutevano su un altro post recente a proposito del reset dell'ethernet shield? che si risolveva eliminando una resistenza o un condensatore?

Allora...
quella funzione ket è parte del codice che il copia incolla non ha copiato...sarebbe
Udp.sendPacket( invio, remoteIp, remotePort); :wink:

la striga che ho tolto scriveva nel packetbuffer ad ogni loop 0
cioè

char  packetBuffer[] = "0";

ma il bello è che normalmente funziona! va tutto...tranquillissimo (anche perchè quando faccio itoa da numero a lettera mi viene sempre una lettera sola, no? anche se il numero è 40! perchè sono ascii, giusto??)... tutto funziona bene, tutte le combinazioni...a casa, sul tavolino tutte le combinazioni e tutti i casi anche improbabili funzionavano...funziona tutto per qualche giorno...poi senza motivo si pianta l'arduino

penso che l'unica soluzione sia il watchdog....ma avrei bisogno di un aiuto per sapere come e dove metterlo!

Tommaso:
anche perchè quando faccio itoa da numero a lettera mi viene sempre una lettera sola, no? anche se il numero è 40! perchè sono ascii, giusto??

ma cosa stai dicendo? proprio perché sono ascii usi due caratteri, anzi tre: il 4 il 0 e il '\n'... altrimenti che usi a fare gli array di char?
e comunque sono gli interi o gli altri valori numerici che usano byte fissi sia che salvi 1 o che salvi 6000, e infatti hanno limiti minimo e massimo, cosa che in ascii non hai

quindi ogni volta che usi un numero a 2 cifre rischi di andare a sovrascrivere un'altra variabile, in base a cosa c'è subito dopo l'indirizzo di packetBuffer... magari ti va di culo e di solito non c'è niente, ma la volta in cui lì c'è qualche variabile, può assume un valore che fa impallare tutto.
Oppure il valore che va in overflow (che è '\n') viene riscritto perché l'indirizzo è usato da un'altra variabile a cui è stato assegnato quello spazio, quando poi eseguirai atoa() non trova più '\n' e la funzione va avanti a trasformare in lettera ciò che trova dopo, che però sono valori a caso e incasinano tutto.... o meglio bloccano il programma.

Credimi, magari non è SOLO questo, ma di sicuro è uno dei motivi per cui si incasina tutto!

fammi sapere

si appunto! ne uso sempre 2! se io ci scrivessi "00" a questo punto ne userei 3, ti torna?
la conversione itoa mi restituisce un carattere, seguito da /n
quando converto 40, mi viene il 40 in ascii che è un carattaere, supponiamo la "a" e poi /n
itoa di 40 viene a/n
infatti provando con "00" fa casino ed uno "0" se lo tira sempre dietro!

mi seriverebbe una guida per inserire correttamente il watchdog...perhcè l'ultima volta ho fatto casino e mi si resettava di continuo

NO!
tu hai 40 che è un intero.
se fai atoa() NON ottieni 40 che corrisponde alla lettera '(' ma ottieni un array di char formato dalle lettere '4', '0', '\0' (quì mi son sbagliato prima, non è \n ma \0, carattere di fine stringa), quindi hai bisogno di spazio per 3 cifre.

Per ottenere '(', non serve la funzione atoa() ma basta sbattere il valore 40 direttamente in un char (e a questo punto non ti servirebbe nemmeno il carattere di fine stringa, perchè ogni stringa sarebbe di un solo byte, ovvero un solo char)

infatti provando con "00" fa casino ed uno "0" se lo tira sempre dietro!

infatti ti ho spiegato che perchè succeda il casino vero e proprio devono esserci delle coincidenze, come l'andare a scrivere in un'altra variabile o viceversa... e non è una cosa che capita spesso, e magari alle volte capita ma con variabili che sono già state usate e quindi non crea macello, ecc...

ah e comunque se quello \0 vagante nella ram va a riscrivere una variabile del watchdog (difficile, ma possibile) sei punto e a capo, perché sarà il watchdog a impazzire. kiss

mmmmm ero convinto che atoi mi facesse un cast !
quindi come posso cambiare il mio codice? a me basta trasformar un int in char e viceversa

è un cast no? quindi semplicemente
char invio = (char)stati;
Udp.sendPacket( invio, remoteIp, remotePort);

dunque anche in ricezione devi cambiare
ricevuto=atoi(packetBuffer); deve essere modificato in:
ricevuto = packetBuffer[0];

giusto! le cose + semplici sono anche le più efficaci...... come tutta questa storia dello switch...se mi facevo un bel vettore con 1 e 0 e poi lo scorrevo in 2 istruzioni avevo finito :slight_smile:

per il watchdog hai idee ? (ormai ti rompo le scatole per bene!)

P.S. non funziona.... ecco forse perchè non avevo seguito questa strada

home_FINE_v3_sp.cpp: In function 'void loop()':
home_FINE_v3_sp:63: error: invalid conversion from 'char' to 'const char*'
home_FINE_v3_sp:63: error: initializing argument 1 of 'uint16_t UdpClass::sendPacket(const char*, uint8_t*, uint16_t)'

risolvi così:

char invio[1];
invio[0] = (char)stati;
Udp.sendPacket( invio, remoteIp, remotePort);

edit: cazzata, molto meglio risolvere così (funziona lo stesso ma così il codice è più pulito):
char invio = (char)stati;
Udp.sendPacket( &invio, remoteIp, remotePort);

niente da fare, così non funziona.....
mmm cioè il cast lo fa, ma non invia per UDP, o cmq non lo riconosce un pacchetto valido...damn