Go Down

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

Antroid


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.

grande! sto leggendo il documento di le0S2 per riavviare la scheda..
Utilizzerò il tuo esempio
Code: [Select]
/*
This is a simple sketch to demonstrate the use of leOS2, a
<l>ittle <e>mbedded <O>perating <S>ystem 2

leOS2 is not a complete OS nor an RTOS as you usually know but it's a simple
scheduler to schedule little works in background, so that you can forget about
them.

This sketch tests the usage of the method reset() called by another task.

More info on the scheduler and the methods can be found into the README file.

Written by Leonardo Miliani <www.leonardomiliani.com>

This code and the leOS2 library are free software; you can redistribute
and/or modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3.0 of the License,
or (at your option) any later version.

The leOS2 library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

*/

#include "leOS2.h" //include the scheduler
leOS2 myOS; //create a new istance
const byte LED = 13; //LED on pin 13


//setup routine
void setup() {
   myOS.begin(); //initialize the scheduler
   pinMode(LED, OUTPUT); //pin as output
   myOS.addTask(reset, myOS.convertMs(10000)); //add a task to be executed after 10 seconds
   blink3times(); //blink 3 times the LED on pin 13
}


//main loop - it's empty
void loop() {
}


//reset the microcontroller
void reset() {
   myOS.reset();
}


//blink 3 times the LED on pin 13
void blink3times() {
   for (byte i=0; i<3; i++) {
       digitalWrite(LED, HIGH);
       delay(250);
       digitalWrite(LED, LOW);
       delay(250);
   }
}

ogni quanto mi consigli di riavviarla?
Grazie

leo72

Secondo me più che a tempo, dovresti resettare la scheda a necessità.
Metti una variabile globale che viene ad esempio incrementata oppure resettata dal codice posto subito dopo il punto in cui generalmente si blocca tutto. Se il task vede che questa variabile non è stata resettata o non è aumentata di valore, resetta tutto. Il check puoi farlo 1 volta al minuto oppure 1 volta all'ora ecc..

Antroid

il problema è quello... non so dove si blocca trattandosi di un problema dello shield ethernet.. al massimo posso metterlo quando effettuo la request HTTP...

leo72

Fai dei test, usando la seriale come monitor di debug e spedendo da codice  un pò di scritte varie. Esempio:
"leggo xxxx"
"ricevuta richiesta http"
"spedisco pagina"
ecc...

Antroid

ok perfetto, ad ogni modo ho applicato la tua leOS2 al mio progetto:
Ho creato un flag che ad inizio loop viene settato sempre a false, alla fine del loop invece a true.
Nel caso in cui rilevo lo stato del flag a false avvio il reset.
Guarda qui cosa ne pensi:
Code: [Select]
/*
My Lab Project
Programmed By Antonio Blescia
State: Alpha
2013-07-09
*/
/*Library Section*/
#include <SPI.h>
#include <Ethernet.h>
#include <leOS2.h> //include the scheduler

/*Sensor Section*/
#define LIGHT_SENSOR A0
#define TEMP_SENSOR A1
#define PIR_SENSOR 2

/*Network Settings*/
EthernetClient client;
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
/*ThingSpeak proprieties*/
String writeAPIKey = "KEY_HERE";    // Write API Key for a ThingSpeak Channel
byte server[]  = { 184, 106, 153, 149 }; // IP Address for the ThingSpeak API
const unsigned long postingInterval = 30*1000;  // delay between updates, in milliseconds

/*WatchDog Manager Section*/
bool allRight = false;
leOS2 Controller;

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

String stringLightValue;
String pirValue;

int tempC =0;
String tempcString;

void setup() {

  Serial.begin(9600);
  pinMode(PIR_SENSOR,INPUT); 
 
  delay(1000);
 
  Ethernet.begin(mac);
 
  Serial.print("My IP address: ");
  Serial.println(Ethernet.localIP());
  Controller.begin();
  Controller.addTask(reset, Controller.convertMs(10000)); //add a task to be executed after 10 seconds
}

void loop() {
  allRight = false;
  /*Pir Sensor Reading*/
  byte PirState =  digitalRead(PIR_SENSOR);
  PirState = 1-PirState; /*Invert the vale*/
  if(PirState > 0){
pirValue =  String(PirState,DEC);
  }
 
  /*Temperature Sensor Reading and Parsing*/
  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();
  allRight= true;
}

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

void reset() {
    if(!allRight)Controller.reset();
}

leo72

Il codice è giusto.
L'importante è che l'intervallo del controllo sia maggiore del tempo di esecuzione di tutto il loop.

Antroid

quindi in quel caso ho sbagliato.. controllo ogni 10 secondi ma effettuo l'invio dei dai ogni 30 secondi.
Sai cosa faccio... 5 minuti per il controllo del watchdog e 1.30 minuto per l'invio dei dati(non lo faccio arrotondato evitando,così, che si incrocino).
Cosa ne pensi?

leo72

Basta che il controllo tu lo faccia dopo almeno 1 invio  ;)

Antroid

ok perfetto... questa notte effettuo il flash del firmware e vediamo cosa succede!  ]:D
Ti ringrazio da parte di tutta la community per aver condiviso la tua leOS2.. evviva la community evviva l'open source! questo indipendentemente se il mio Arduino si blocchi o meno! 8)

leo72


evviva la community evviva l'open source! questo indipendentemente se il mio Arduino si blocchi o meno! 8)

ROTFL  :smiley-yell:

Antroid

leo... la board continua a riavviarsi e non riesco ad aggiornare il firmware
Mi da questo errore avrdude: stk500_recv(): programmer is not responding
Come posso fare?

leo72

Avrai sbagliato qualcosa nei tempi impostati?

Cmq, applica la manovra di emergenza:
http://forum.arduino.cc/index.php?topic=59668.msg429965#msg429965

Antroid

nn ci crederai ma ho fatto gli stessi passaggi involontariamente... ho letto solo ora il tuo messaggio! grazie cmq.. ora sta trasmettendo! 8)

Antroid

eccomi qui a ripostare codice sorgente simile ai precendenti ma con piccole accortezze...
Code: [Select]
/*
My Lab Project
Programmed By Antonio Blescia
State: Alpha
2013-07-09
*/
/*Library Section*/
#include <SPI.h>
#include <Ethernet.h>
#include <leOS2.h> //include the scheduler

/*Sensor Section*/
#define LIGHT_SENSOR A0
#define TEMP_SENSOR A1
#define PIR_SENSOR 2

/*Network Settings*/
EthernetClient client;
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
/*ThingSpeak proprieties*/
String writeAPIKey = "KEY_HERE";    // Write API Key for a ThingSpeak Channel
byte server[]  = { 184, 106, 153, 149 }; // IP Address for the ThingSpeak API
const unsigned long postingInterval = 30*1000;  // delay between updates, in milliseconds

/*WatchDog Manager Section*/
bool allRight = false;
leOS2 Controller;

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

String stringLightValue;
String pirValue;

int tempC =0;
String tempcString;
void(* resetFunc)(void)=0;

void setup() {

  Serial.begin(9600);
  pinMode(PIR_SENSOR,INPUT); 
 
  delay(1000);
 
  Ethernet.begin(mac);
 
  Serial.print("My IP address: ");
  Serial.println(Ethernet.localIP());
  Controller.begin();
  Controller.addTask(reset, Controller.convertMs(60000)); //add a task to be executed after 10 seconds
}

void loop() {
  allRight = false;
  /*Pir Sensor Reading*/
  byte PirState =  digitalRead(PIR_SENSOR);
  PirState = 1-PirState; /*Invert the vale*/
  if(PirState > 0){
pirValue =  String(PirState,DEC);
  }
 
  /*Temperature Sensor Reading and Parsing*/
  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();
  allRight= true;
}

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

void reset() {
    if(!allRight)
    {
      Serial.println("Resetting....");   
      resetFunc();
    }
}

Ho provato ad usare la funzione reset() della classe leOS2 ma il micro si resetta in maniera infinita... ho utilizzato la soluzione suggerita da Massimo Banzi e consigliata da Atmel e adesso sembra andare tutto bene... vediamo domani se ci saranno altri blocchi.. :smiley-eek:

leo72

La funzione che stai usando tu non è un reset, è solo un salto all'indirizzo $0000 della memoria: in pratica riavvii dall'inizio il firmware. Il reset con watchdog è un vero e proprio reset, ha gli effetti che avresti se premessi il pulsantino di reset.

Ora vediamo un pò, forse il bootloader della 2009 non disabilita subito il watchdog per cui entri in un loop infinito. Faccio una modifica al leOS e ti richiamo.. ;)

Go Up