Go Down

Topic: Freeze Arduino Duemilanove (Read 15596 times) previous topic - next topic

Antroid

Salve a tutti ragazzi!
Ho scritto questo piccolo codice che permette di inserire in cloud le informazioni ricavate da un sensore pir e da una fotoresistenza.
Il tutto funziona correttamente per un paio di ore.. dopo si blocca la scheda non trasmettendo piu i dati... sapreste indicarmi una soluzione?
Code: [Select]
#include <SPI.h>
#include <Ethernet.h>
#include <SimpleTimer.h>

#define MOVEMENT_SENSOR 2
#define LIGHT_SENSOR A0
// Local Network Settings
byte mac[]     = { 0xD4, 0x28, 0xB2, 0xFF, 0xA0, 0xA1 };

// ThingSpeak Settings
byte server[]  = { 184, 106, 153, 149 }; // IP Address for the ThingSpeak API
String writeAPIKey = "KEY_HERE";    // Write API Key for a ThingSpeak Channel
EthernetClient client;
SimpleTimer timer;
boolean sended = false;
boolean lastConnected = false;

void setup()
{
        /*PIN settings*/
        pinMode(MOVEMENT_SENSOR,INPUT);
        /*------------------*/
        /*Timers Section*/
        timer.setInterval(60000,updateStats);
        /*------------------*/
        Serial.begin(9600);
        Serial.println(Ethernet.begin(mac));
        delay(1000);
}

void loop(){
        timer.run();
       
        updateMovementSensor();
       
        if (client.available()) {
                char c = client.read();
                Serial.print(c);
        }

        // if the server's disconnected, stop the client:
        if (!client.connected() &&lastConnected) {
                /*Serial.println();
                Serial.println("disconnecting.");*/
                client.stop();

   }
   lastConnected = client.connected();
       
}

void updateMovementSensor(){
        byte PirState =  digitalRead(MOVEMENT_SENSOR);
        PirState = 1-PirState; /*Invert the vale*/
        if(PirState > 0 && sended == false){
                String movementSensor = String(PirState,DEC);
                updateThingSpeak("field2="+movementSensor);
                sended = true;
        }else if(PirState == 0){
          sended = false;
        }
}

void updateStats(){
        String lightValue = String(analogRead(LIGHT_SENSOR),DEC);
        updateThingSpeak("field1="+lightValue+"&field2=0");
}

void updateThingSpeak(String tsData)
{
  if (client.connect(server, 80))
  {
    Serial.println("Connected to ThingSpeak...");
    Serial.println();
       
    client.print("POST /update HTTP/1.1\n");
    client.print("Host: api.thingspeak.com\n");
    client.print("Connection: close\n");
    client.print("X-THINGSPEAKAPIKEY: "+writeAPIKey+"\n");
    client.print("Content-Type: application/x-www-form-urlencoded\n");
    client.print("Content-Length: ");
    client.print(tsData.length());
    client.print("\n\n");

    client.print(tsData);
   
  }
  else
  {
    /*Serial.println("Connection Failed."); 
    Serial.println();*/
  }
}

leo72

Ci sono tantissime discussioni aperte sui problemi di freeze causati dalla scheda Ethernet o, a quanto pare, dalla libreria che la gestisce. Ti consiglio di cercarle e di leggertele per evitare di trattare argomenti già discussi ampiamente. Ce n'era anche una molto recente, a cui avevano contribuito in diversi.

PaoloP

La prima delle soluzioni è utilizzare l'ultima versione dell'IDE (1.0.5) che riunisce le modifiche alla libreria Ethernet fatte già dalla versione 1.0

Antroid

ciao e grazie per le risposte... sto utilizzando proprio quella versione per mac osx...
ho trovato questo link.. ma non so se può essermi davvero utile:
http://forum.arduino.cc/index.php?topic=68624.15

Antroid

Ho analizzato il file w5100.h ed effettivamente con la versione del mio compiler(1.0.5) è già contenuta la modifica citata nel link che ho postato.
Ci sono altre soluzione a questo problema?

Antroid

Ho appena applicato l'esempio "WebClientRepeating" prensente sul sito al mio caso.. ]:D
Code: [Select]
/*
  Repeating Web client

This sketch connects to a a web server and makes a request
using a Wiznet Ethernet shield. You can use the Arduino Ethernet shield, or
the Adafruit Ethernet shield, either one will work, as long as it's got
a Wiznet Ethernet module on board.

This example uses DNS, by assigning the Ethernet client with a MAC address,
IP address, and DNS address.

Circuit:
* Ethernet shield attached to pins 10, 11, 12, 13

created 19 Apr 2012
by Tom Igoe

http://arduino.cc/en/Tutorial/WebClientRepeating
This code is in the public domain.

*/

#include <SPI.h>
#include <Ethernet.h>
#define LIGHT_SENSOR A0

// assign a MAC address for the ethernet controller.
// fill in your address here:
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
// fill in an available IP address on your network here,
// for manual configuration:
IPAddress ip(10,0,0,20);

// fill in your Domain Name Server address here:
IPAddress myDns(1,1,1,1);

// initialize the library instance:
EthernetClient client;
String writeAPIKey = "KEY_HERE";    // Write API Key for a ThingSpeak Channel
byte server[]  = { 184, 106, 153, 149 }; // IP Address for the ThingSpeak API

unsigned long lastConnectionTime = 0;          // last time you connected to the server, in milliseconds
boolean lastConnected = false;                 // state of the connection last time through the main loop
const unsigned long postingInterval = 30*1000;  // delay between updates, in milliseconds
String stringLightValue;

void setup() {
  // start serial port:
  Serial.begin(9600);
  // give the ethernet module time to boot up:
  delay(1000);
  // start the Ethernet connection using a fixed IP address and DNS server:
  Ethernet.begin(mac, ip, myDns);
  // print the Ethernet board/shield's IP address:
  Serial.print("My IP address: ");
  Serial.println(Ethernet.localIP());
}

void loop() {
  // if there's incoming data from the net connection.
  // send it out the serial port.  This is for debugging
  // purposes only:
  if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }

  // if there's no net connection, but there was one last time
  // through the loop, then stop the client:
  if (!client.connected() && lastConnected) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
  }

  // if you're not connected, and ten seconds have passed since
  // your last connection, then connect again and send data:
  if(!client.connected() && (millis() - lastConnectionTime > postingInterval)) {
    stringLightValue = String(analogRead(A0),DEC);
updateThingSpeak("field1="+stringLightValue);
  }
  // store the state of the connection for next time through
  // the loop:
  lastConnected = client.connected();
}

// this method makes a HTTP connection to the server:
void updateThingSpeak(String tsData) {
  // if there's a successful connection:
  if (client.connect(server, 80)) {
     Serial.println("Connected to ThingSpeak...");
    Serial.println();
       
    client.print("POST /update HTTP/1.1\n");
    client.print("Host: api.thingspeak.com\n");
    client.print("Connection: close\n");
    client.print("X-THINGSPEAKAPIKEY: "+writeAPIKey+"\n");
    client.print("Content-Type: application/x-www-form-urlencoded\n");
    client.print("Content-Length: ");
    client.print(tsData.length());
    client.print("\n\n");

    client.print(tsData);

    // note the time that the connection was made:
    lastConnectionTime = millis();
  }
  else {
    // if you couldn't make a connection:
    Serial.println("connection failed");
    Serial.println("disconnecting.");
    client.stop();
  }
}

Stasera flasho e lascio in funzione per tutta la notte... speriamo... 8)

Antroid

Allora, dopo aver verificato anche sul mio secondo pc la prensenza della modifca sul file w5100 ho apportato una piccola modifica al firmware.
Salvo lo stato del sensore PIR in una variabile ed invio con una sola chiamata i dati in cloud.
Code: [Select]
/*
  Repeating Web client

This sketch connects to a a web server and makes a request
using a Wiznet Ethernet shield. You can use the Arduino Ethernet shield, or
the Adafruit Ethernet shield, either one will work, as long as it's got
a Wiznet Ethernet module on board.

This example uses DNS, by assigning the Ethernet client with a MAC address,
IP address, and DNS address.

Circuit:
* Ethernet shield attached to pins 10, 11, 12, 13

created 19 Apr 2012
by Tom Igoe

http://arduino.cc/en/Tutorial/WebClientRepeating
This code is in the public domain.

*/

#include <SPI.h>
#include <Ethernet.h>
#define LIGHT_SENSOR A0
#define PIR_SENSOR 2
// assign a MAC address for the ethernet controller.
// fill in your address here:
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
// fill in an available IP address on your network here,
// for manual configuration:
//IPAddress ip(1);

// fill in your Domain Name Server address here:
IPAddress myDns(1,1,1,1);

// initialize the library instance:
EthernetClient client;
String writeAPIKey = "KEY_HERE";    // Write API Key for a ThingSpeak Channel
byte server[]  = { 184, 106, 153, 149 }; // IP Address for the ThingSpeak API

unsigned long lastConnectionTime = 0;          // last time you connected to the server, in milliseconds
boolean lastConnected = false;                 // state of the connection last time through the main loop
const unsigned long postingInterval = 30*1000;  // delay between updates, in milliseconds
String stringLightValue;
String pirValue;

void setup() {
  // start serial port:
  Serial.begin(9600);
  pinMode(PIR_SENSOR,INPUT); 
  // give the ethernet module time to boot up:
  delay(1000);
  // start the Ethernet connection using a fixed IP address and DNS server:
  Ethernet.begin(mac);
  // print the Ethernet board/shield's IP address:
  Serial.print("My IP address: ");
  Serial.println(Ethernet.localIP());
}

void loop() {
  // if there's incoming data from the net connection.
  // send it out the serial port.  This is for debugging
  // purposes only:
 
  byte PirState =  digitalRead(PIR_SENSOR);
  PirState = 1-PirState; /*Invert the vale*/
 
  if(PirState > 0){
   pirValue =  String(PirState,DEC);
   Serial.println(pirValue);
  }
 
  if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }

  // if there's no net connection, but there was one last time
  // through the loop, then stop the client:
  if (!client.connected() && lastConnected) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
  }

  // if you're not connected, and ten seconds have passed since
  // your last connection, then connect again and send data:
  if(!client.connected() && (millis() - lastConnectionTime > postingInterval)) {
    stringLightValue = String(analogRead(A0),DEC);
updateThingSpeak("field1="+stringLightValue+"&field2="+pirValue);
        pirValue = "0";
  }
  // store the state of the connection for next time through
  // the loop:
  lastConnected = client.connected();
}

// this method makes a HTTP connection to the server:
void updateThingSpeak(String tsData) {
  // if there's a successful connection:
  if (client.connect(server, 80)) {
     Serial.println("Connected to ThingSpeak...");
    Serial.println();
       
    client.print("POST /update HTTP/1.1\n");
    client.print("Host: api.thingspeak.com\n");
    client.print("Connection: close\n");
    client.print("X-THINGSPEAKAPIKEY: "+writeAPIKey+"\n");
    client.print("Content-Type: application/x-www-form-urlencoded\n");
    client.print("Content-Length: ");
    client.print(tsData.length());
    client.print("\n\n");

    client.print(tsData);

    // note the time that the connection was made:
    lastConnectionTime = millis();
  }
  else {
    // if you couldn't make a connection:
    Serial.println("connection failed");
    Serial.println("disconnecting.");
    client.stop();
  }
}

Vediamo cosa succede da ora in poi.... :smiley-fat:

Antroid

ho aggiunto anche la temperatura per aumentare la mole di pacchetti..
Code: [Select]
/*
  Repeating Web client

This sketch connects to a a web server and makes a request
using a Wiznet Ethernet shield. You can use the Arduino Ethernet shield, or
the Adafruit Ethernet shield, either one will work, as long as it's got
a Wiznet Ethernet module on board.

This example uses DNS, by assigning the Ethernet client with a MAC address,
IP address, and DNS address.

Circuit:
* Ethernet shield attached to pins 10, 11, 12, 13

created 19 Apr 2012
by Tom Igoe

http://arduino.cc/en/Tutorial/WebClientRepeating
This code is in the public domain.

*/

#include <SPI.h>
#include <Ethernet.h>
#define LIGHT_SENSOR A0
#define TEMP_SENSOR A1
#define PIR_SENSOR 2

// assign a MAC address for the ethernet controller.
// fill in your address here:
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
// fill in an available IP address on your network here,
// for manual configuration:
//IPAddress ip(1);

// fill in your Domain Name Server address here:
IPAddress myDns(1,1,1,1);

// initialize the library instance:
EthernetClient client;
String writeAPIKey = "KEY_HERE";    // Write API Key for a ThingSpeak Channel
byte server[]  = { 184, 106, 153, 149 }; // IP Address for the ThingSpeak API

unsigned long lastConnectionTime = 0;          // last time you connected to the server, in milliseconds
boolean lastConnected = false;                 // state of the connection last time through the main loop
const unsigned long postingInterval = 30*1000;  // delay between updates, in milliseconds
String stringLightValue;
String pirValue;
int tempC =0;
String tempcString;

void setup() {
  // start serial port:
  Serial.begin(9600);
  pinMode(PIR_SENSOR,INPUT); 
  // give the ethernet module time to boot up:
  delay(1000);
  // start the Ethernet connection using a fixed IP address and DNS server:
  Ethernet.begin(mac);
  // print the Ethernet board/shield's IP address:
  Serial.print("My IP address: ");
  Serial.println(Ethernet.localIP());
}

void loop() {
  // if there's incoming data from the net connection.
  // send it out the serial port.  This is for debugging
  // purposes only:
 
  byte PirState =  digitalRead(PIR_SENSOR);
  PirState = 1-PirState; /*Invert the vale*/
 
  if(PirState > 0){
   pirValue =  String(PirState,DEC);
   //Serial.println(pirValue);
  }
 
  tempC = analogRead(TEMP_SENSOR);           //lettura valore del sensore
tempC =(int) (5.0 * tempC * 100.0)/1024.0;  //conversione del dato analogico
  tempcString = String(tempC,DEC);
 
  if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }

  // if there's no net connection, but there was one last time
  // through the loop, then stop the client:
  if (!client.connected() && lastConnected) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
  }

  // if you're not connected, and ten seconds have passed since
  // your last connection, then connect again and send data:
  if(!client.connected() && (millis() - lastConnectionTime > postingInterval)) {
    stringLightValue = String(analogRead(A0),DEC);
updateThingSpeak("field1="+stringLightValue+"&field2="+pirValue+"&field3="+tempcString);
        pirValue = "0";
  }
  // store the state of the connection for next time through
  // the loop:
  lastConnected = client.connected();
}

// this method makes a HTTP connection to the server:
void updateThingSpeak(String tsData) {
  // if there's a successful connection:
  if (client.connect(server, 80)) {
     Serial.println("Connected to ThingSpeak...");
    Serial.println();
       
    client.print("POST /update HTTP/1.1\n");
    client.print("Host: api.thingspeak.com\n");
    client.print("Connection: close\n");
    client.print("X-THINGSPEAKAPIKEY: "+writeAPIKey+"\n");
    client.print("Content-Type: application/x-www-form-urlencoded\n");
    client.print("Content-Length: ");
    client.print(tsData.length());
    client.print("\n\n");

    client.print(tsData);

    // note the time that the connection was made:
    lastConnectionTime = millis();
  }
  else {
    // if you couldn't make a connection:
    Serial.println("connection failed");
    Serial.println("disconnecting.");
    client.stop();
  }
}

Antroid

ragazzi sto trasmettendo da ieri sera alle 21 circa! sembra andare ancora tutto bene!

Antroid

Cattive notizie... mi ero gasato... =(... a questo punto credo che un reset della scheda sarebbe l'ideale..
ho trovato a questo link: http://forum.arduino.cc/index.php/topic,35155.0.html una risposta di Banzi in persona:
Quote
Ciao.

Ci sono 4 metodi:

1. Chiudere e riaprire la porta seriale , questo fa resettare il processore. e' la tecnica che usiamo per caricare i programmi sull'arduino quando premi "Upload to IO Board"

2. Collegare un piedino digitale al piedino "Reset" sulla scheda ma la Atmel non garantisce che funzioni (la spiegazione è abbastanza tecnica e rasenta la masturbazione mentale)

3. forzare il processore a fare "goto $00" però questo lascia la ram, i timer e gli interrupt sporchi... cioè non è garantito che il programma riparta bene.

4.  Raccomandato da Atmel. Attivare il "watchdog timer" e aspettare che si resetti.
Il "cane da guardia" è un timer che serve a resettare un processore che si sia incastrato per un problema software. Il timer, una volta attivato, resetta il processore a meno che non venga fatto ripartire... perciò in un'applicazione che deve mantenere un certo livello di affidabilità, il programma fa ripartire il timer regolarmente ... dovesse mai incepparsi allora dopo pochi millisecondi il processore si resetta. Aggiungi questo all'inizio tuo sketch Arduino
Code:
#include <avr/io.h>
#include <avr/wdt.h>

#define Reset_AVR() wdt_enable(WDTO_30MS); while(1) {}

mentre nel punto dove vuoi resettare scrivi:
Code:
Reset_AVR();

Nota: Apprezzo molto l'entusiasmo con cui molti si danno da fare per rispondere, senza di voi Arduino non esisterebbe. Però certe volte non sparate le risposte a caso perchè se chi ha fatto la domanda è un principiante poi si confonde e non capisce più   


Proverò a resettare seguendo quanto consigliato da Atmel...

leo72

L'autoreset mediante un piedino mandato a LOW non ti garantisce un tempo di tenuta del pin di reset a livello basso sufficiente per il reset. Meglio il watchdog.
Hai cercato quella discussione che ti dicevo?

Antroid

si leo... la modifica al file w5100.h era già presente...
proverò con il watchdog...

Antroid

che ne dici se resetto la board ogni 2 ore?
Imposto un timer con questa libreria http://playground.arduino.cc/code/timer
Cosa ne pensi? esiste un event handler che rileva il blocco o qualche soluzione migliore? :smiley-eek:

leo72

Non conosco bene quella lib ma mi pare che usi millis per schedulare i compiti, come fa anche il mio looper.
Se però il codice si blocca da qualche parte, quella lib non funziona più. Ti serve uno scheduler basato su un timer o sul watchdog. Io ho scritto il leOS basato sul timer 2 ed il leOS2 basato sul watchdog. Entrambe sono "immuni" ai blocchi del codice principale e possono anche resettare l'Arduino.

Ma non so se è conveniente un reset ogni 2 ore diciamo... preventivo.

PaoloP

Alternativamente potresti utilizzare una soluzione basata sul chip ENC28J60, ma si tratta di scrivere buona parte del codice da capo e  fare i conti con la libreria specifica che occupa più spazio di quella ufficiale.
Però non mi risulta che si blocchi.

Esempio http://www.open-electronics.org/low-cost-ethernet-shield-with-enc28j60/

Go Up