Arduino Mega con shields se relentiza

Muy buenas. desde hace un tiempo estoy con un proyecto, con el que tomo desde un lector de QR un codigo, verifico este codigo por red y, de ser aceptado, procedo con la accion (activar una bomba de agua). Para todo esto, uso un Arduino Mega (original), un modulo shield usb (adaptado para SS particular y para que el SPI pase del arduino a la pantalla), un modulo de red W5100 (no shield) y una pantalla de 3,2 con shield. Cuando arranco todo, todo funciona lo mas bien. pasado un tiempo, el sistema comienza a relentizarse hasta dejar de funcionar. no se si es mucho consumo con tantas placas, si el chip del arduino mega se recalienta, o que es lo que le ocurre. Si lo alimento con 9V y 2000mA al tiempo comienza a apagarse atenuandose la pantalla, hasta desaparecer. Si lo alimento por el USB que va a la PC, puede durar bastante mas. Ya no se por donde buscarle el problema para poder darle una solucion.
Desde ya muchas gracias

Xakko

Código??? usa etiquetas para postearlo. Si no entiendes tienes dos caminos:

  1. Lee las normas y observa como se postean los códigos y
  2. Mira otros hilos y vuelve a 1 para hacerlo adecuadamente.

Buenas. Les dejo el codigo. Es bastante largo, pero esta casi todo comentado en que es lo que hago (asi yo no me pierdo en la misma programacion)
el void loop espera actividad del lector de QR y, una vez tiene algo, va al bucle secuencial 'principal'
comprueba a traves de la conexion de red en un servidor web (que esta conectado a la base de datos) si lo ingresado es correcto o no. Si esta autorizado habilita la pantalla de carga. a traves de una botonera puedo bajar o subir lo que deseo cargar. una vez presionado cargar, comienza la carga hasta que termine, o pulse el boton cancelar durante medio segundo
lee los pulsos del caudalimetro de la bomba por interrupcion en el puerto 21 del arduino mega
una vez terminada la carga, registra la actividad y vuelve a la espera de otro ingreso por qr

//bus spi comun a casi todos los modulos (pantalla, red o usb)
#include <SPI.h>
//red
#include <Ethernet.h>
//usb
#include <usbhid.h>
#include <usbhub.h>
#include <hiduniversal.h>
#include <hidboot.h>
//pantalla
#include <Adafruit_GFX.h>//graficos en la pantalla
#include <MCUFRIEND_kbv.h>  //administracion de la pantalla tft SHIELD

#include <avr/wdt.h> // Incluir la librería que contiene el watchdog (wdt.h)

//VARIABLES O CONSTANTES

//variables para el shield de la pantalla
//constantes para los colores de la pantalla
#define SD_CS 10
#define BLACK 0
#define GREY 21845
#define BLUE 31
#define RED 63488
#define GREEN 2016
#define DARKGREEN 1472
#define CYAN 2047
#define MAGENTA 63519
#define YELLOW 65504
#define GOLD 56768
#define WHITE 65535

//Usar si se usa pantalla shield
MCUFRIEND_kbv tft;

//variables para el modulo de la RED

//Inicializar instancia de la libreria ethernet
EthernetClient client;


//Dirección IP del servidor con la página PHP
char serverip[] = "192.168.1.107";
//Asignamos una dirección IP local para las operaciones en red
char localip[] = "Host: 192.168.1.80";
//Asignar dirección IP para la conexion inicial del modulo (misma que la anterior)
IPAddress ip(192,168,1,80);
//Asignamos una dirección MAC local
byte mac[] = {  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};

String idjir = "1";

boolean fin = false;
boolean pregunta = true;
byte bFnd = 0;  //banderas de frenado. numeros que indican por que termino la carga



//puertos SS para el control del bus SPI de las distintas placas
//RED
byte ssr = 53;  //SS de la placa de red
//como los diseñadores de la placa de red son simpaticos, mandan siempre datos por el SPI, asi este seleccionada o no
//se debe inhabilitar al modulo (al chip directamente). hay q hacer una modificacion fisica y mandar este pin hacia alli:
byte sse = 49;  //SEN (SPI Enable) del chip w5100 del modulo de red para deshabilitarlo (OJO!!: desabilita con HIGH)
//USB
byte ssu = 43;  //SS del shield USB
byte inu = 42;  //INT del shield USB (no se usa)
//TFT-pantalla
byte sss = 10;  //SS del TFT - 10
byte dct = 8; //DC del tft - 8
byte rst = 9; //reset del TFT - 9



//variables de tiempo
unsigned int tact = 0;  //tiempo actual, leido con el pulso de entrada del caudalimetro
byte tdif = 30; //diferencia de tiempo sin tomar carga para cortar por no haber movimiento. En segundos
byte tapv = 10;  //tiempo que tarda la valvula en abrir. en segundos. 150 = 2min 30seg
byte tciv = 3;  //tiempo que tarda la valvula en cerrar. en segundos. 150 = 2min 30seg
unsigned long mapv = 0; //momento en el que se realizo la apertura de la valvula
unsigned long mciv = 0; //momento en el que se realizo el cierre de la valvula


//variables del proceso de carga
//cp esta en las interrupciones, por eso es 'volatile'
volatile unsigned int cp = 0;  //cantidad de pulsos leidos por interrupcion

unsigned long total = 10;  //lo que cargo en definitiva. cambia si se presiona el boton de frenado
unsigned long cargado = 0;  //lo que lleva ya cargado
boolean seguir = true;  //indicador que el boton de frenado fue presionado, o que se acabo la carga
unsigned int mult = 100;  //multiplicador para los pulsos, para que de cantidad de litros cargados
unsigned long maximo = 0;  //lo que va a cargar
unsigned long permitido = 0;  //lo maximo que puede cargar
unsigned int incremento = 500;  //lo que va a sumar o restar por cada pulsada de boton

byte estado = 0; // estado en que se encuentra en cada etapa de la carga
byte ef = 0; // estado final, en caso de corte por STOP, almacena el estado donde se interrumpio la carga
unsigned int longboton = 200; // delay en ms de la longitud de espera entre presiones de botones del tablero
unsigned int espera = 200;  //espera para mostar en pantalla los estados en el proceso de carga en general


//cargas maximas para cada una de las rampas de arranque
unsigned int max1 = 1000;
unsigned int max2 = 2000;
//cantidad de litros antes del maximo, para que comience el frenado
unsigned int sup = 500;

// PINES
//interrupciones
byte ixb = 20;  //interrupcion por boton rojo presionado (no usado)
byte ixp = 21;  //interrupcion por pulsos
//pulsadores
byte cmz = 22;  //pulsador arranque de bomba
byte inc = 23;  //pulsador incrementar
byte dec = 24;  //pulsador decrementar
byte frn = 25;  //pulsador frenado. no se usa, se usa solo del de corte, el 21
//switch selector bomba-tanque
byte swb = 31;  //switch selector de ingreso por bomba
byte swv = 32;  //switch selector de ingreso por tanque
//Pines bomba
byte ra1 = 28;  //salida rampa 1
byte ra2 = 29;  //salida rampa 2
byte ra3 = 30;  //salida rampa 3
byte arb = 36; //señal de arranque de bomba (no usado, arranca por rampa)
byte frb = 37; //señal de frenado de bomba
//Pines valvula
byte arv = 33;  //señal de arranque de la valvula del tanque
byte frv = 34;  //señal de frenado de la valvula del tanque

bool bv = false; //estado en el que se mantendra si es bomba o valvula. el estado del switch, desde el momento del arranque de la carga


//variables en comun que vamos a tomar desde el usb y desde la placa de red para su posterior decodificacion
//String LecturaUSB = "&0123456789!";  //Aqui se almacena el dato leido del QR
//byte LongUSB = 12;  //Aca guardamos la longitud del string leido del lector QR para ir recorriendolo
String LecturaUSB = "";  //Aqui se almacena el dato leido del QR
byte LongUSB = 0;  //Aca guardamos la longitud del string leido del lector QR para ir recorriendolo
boolean UltimoUSB = false;  //si el leido fue ultimo caracter leido para armar el string de la lectura del QR

String LecturaRED = "&01%15000!";        //Aquí se almacena la respuesta del servidor
byte LongRED = 39; //Aca guardamos la longitud del string recibido del servidor para ir recorriendolo
byte ubi = 0;  //Aca guardamos la ultima posicion leida en cada campo de la tabla, para arrancar a formar la que sigue a partir de donde termino la anterior


//Variables que vienen desde el servidor en el string 'codigo' por RED
String VerifRED = "";
unsigned long LitrosRED = 0;
String MensajeRED = "";
String ActivoRED = "";

//general
unsigned int Litros = 0;

// inicio shield USB

//Lecturas de Lector de Codigo de Barras o QR

//vectores con tipos de caracteres
const uint8_t numKeys[10] PROGMEM = {'!', '@', '#', '$', '%', '^', '&', '*', '(', ')'};
const uint8_t symKeysUp[12] PROGMEM = {'_', '+', '{', '}', '|', ' ', ':', '"', ' ', '<', '>', '?'};
const uint8_t symKeysLo[12] PROGMEM = {'-', '=', '[', ']', '\\', ' ', ';', '\'', '`', ',', '.', '/'};
const uint8_t padKeys[5] PROGMEM = {'/', '*', '-', '+', '\r'};
bool shift = false;

class MyParser : public HIDReportParser {
  public:
    MyParser();
    void Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);

  protected:
    //transforma lo leido a caracter ASCII
    uint8_t KeyToAscii(bool upper, uint8_t mod, uint8_t key);
    //lectura de caracteres normales
    virtual void OnKeyScanned(bool upper, uint8_t mod, uint8_t key);
    //lectura de ultimo caracter, para entregar el string completo armado
    virtual void OnScanFinished();
};

MyParser::MyParser() {}

void MyParser::Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
  // Si hay error o no hay lectura, salir
//  if (buf[2] == 1 || buf[2] == 0) {
//    return;
//  }

  if(buf[0] == 2)
      shift = true;
  for (uint8_t i = 7; i >= 2; i--) {  //entradas de 7 a 2
    // Si esta vacio el ingreso, salir de la lectura
    if (buf[i] == 0) continue;

    // si lo ingresado es señal de final ( UHS_HID_BOOT_KEY_ENTER ), ir a final del escaneo ( OnScanFinished )
    if (buf[i] == UHS_HID_BOOT_KEY_ENTER) {
      OnScanFinished();
    }

    // si no es el ultimo, seguir normalmente, armando el codigo ( OnKeyScanned )
    else {
      // If bit position not in 2, it's uppercase words
      OnKeyScanned(shift, buf, buf[i]);
      shift = false;
    }

    return;
  }
}

//Decodificacion de cada ingreso del lector a su codigo ASCII correspondiente
uint8_t MyParser::KeyToAscii(bool upper, uint8_t mod, uint8_t key) {
  // Letras
  if (VALUE_WITHIN(key, 0x04, 0x01d)) { //si el ingreso esta entre 04 y 1D (letras) que devuelva
    if (upper) return (key - 4 + 'A');  // letras en mayusculas
    else return (key - 4 + 'a');  // o letras en minusculas
  }

  // Numeros
  else if (VALUE_WITHIN(key, 0x1e, 0x27)) {
    if (shift)
      return ((uint8_t)pgm_read_byte(&numKeys[key - 0x1e]));
    else
      return ((key == UHS_HID_BOOT_KEY_ZERO) ? '0' : key - 0x1e + '1');
  }

  // Numeros del Keypad
  else if (VALUE_WITHIN(key, 0x59, 0x61)) {
    return (key - 0x59 + '1');
  } else if (VALUE_WITHIN(key, 0x2d, 0x38))
    return ((upper) ? (uint8_t)pgm_read_byte(&symKeysUp[key - 0x2d]) : (uint8_t)pgm_read_byte(&symKeysLo[key - 0x2d]));
  else if (VALUE_WITHIN(key, 0x54, 0x58))
    return (uint8_t)pgm_read_byte(&padKeys[key - 0x54]);
  else {
    switch (key) {
      case UHS_HID_BOOT_KEY_SPACE: return (0x20);
      case UHS_HID_BOOT_KEY_ENTER: return ('\r'); // salto de campo (0x0D)
    }
  }
  //Serial.println(key, HEX);
  return 0;
}


//va escribiendo lo ingresado y lo va acumulando en la variable de salida
void MyParser::OnKeyScanned(bool upper, uint8_t mod, uint8_t key) {
  //Serial.print(upper);
  uint8_t ascii = KeyToAscii(upper, mod, key);
  //Serial.print((char)ascii);
  LecturaUSB += (char)ascii;
  UltimoUSB = false;
}

// se ha ingresado el ultimo caracter del codigo. finalizar el string leido
void MyParser::OnScanFinished() {
  //Serial.println();
  //Serial.println(LecturaUSB);
  UltimoUSB = true;
}


USB          Usb;
USBHub       Hub(&Usb);
HIDUniversal Hid(&Usb);
MyParser     Parser;

//fin shield USB


//subrutina de arranque del sistema
void setup() {
  //Inicializar el Serial de salida en la PC
  Serial.begin(9600);
  Serial.println(F("Arrancando el sistema...."));

  wdt_disable(); // Desactivar el watchdog mientras se configura, para que no se resetee
  wdt_enable(WDTO_8S); // Configurar watchdog a cuatro segundos

  
  //interrupcion por ingreso de pulsos
  attachInterrupt(digitalPinToInterrupt(ixp), pulsos, RISING);
  
  //interrupcion por corte de emergencia
  //attachInterrupt(digitalPinToInterrupt(ixb), corte, RISING); //no usado

  //noInterrupts();

  //interrupciones
  pinMode(ixp, INPUT);  // interrupcion pulsos
  pinMode(ixb, INPUT);  // interrupcion por boton de corte emergencia

  //botonera
  pinMode(cmz, INPUT);  // comenzar la carga
  pinMode(inc, INPUT);  // incrementar 
  pinMode(dec, INPUT);  // descontar
  pinMode(frn, INPUT);  // frenado

  //swich selector bomba-valvula
  pinMode(swb, INPUT);  // ingreso por bomba seleccionado
  pinMode(swv, INPUT);  // ingreso por valvula seleccionado

  //salidas de arranque y frenado para carga por valvula (tanque)
  pinMode(arv, OUTPUT);  // arranque de carga por valvula
  pinMode(frv, OUTPUT);  // frenado de carga por valvula

  //salidas de estados de carga
  pinMode(ra1, OUTPUT);  // arranque de rampa 1
  pinMode(ra2, OUTPUT);  // arranque de rampa 2
  pinMode(ra3, OUTPUT);  // arranque de rampa 3
  pinMode(arb, OUTPUT);  // arranque de carga de bomba (no usado, arranca por rampa)
  pinMode(frb, OUTPUT);  // frenado de carga de bomba
    
  //Pines SS (slave select) para el bus ISP de distintos modulos: pantalla, red y usb
  pinMode(sss, OUTPUT);  // SS del shield de la pantalla ILI9341
  pinMode(ssr, OUTPUT);  // SS del modulo de RED W5100
  pinMode(sse, OUTPUT);  // habilita el modulo de red. va a la par del ssr, pero con estado opuesto
  pinMode(ssu, OUTPUT);  // SS del shield USB . Modificar shield y modificar tambien en la libreria "UsbCore.h" dentro de USB_Host_Shield_Library_2.0 : 



  //Inicializar el shield USB
  HabilitarSS(ssu);
  if (Usb.Init(ssu) == -1) {
    Serial.println("Modulo USB no conectado");
  }else{
    Serial.println("Modulo USB inicializado");
  }
  delay( 200 );
  Hid.SetReportParser(0, &Parser);



  //Inicializar modulo de RED
  HabilitarSS(ssr);
  // demora de arranque
  //delay(1000);
  //Iniciar la coneción de red
  Ethernet.init(ssr);
  Ethernet.begin(mac, ip);
  //if (Ethernet.begin(mac, ip) == 0) {
    //Serial println("No se puede conectar la red");   
  //} else {
    // Imprimir la dirección IP
    Serial.print("IP: ");
    Serial.println(Ethernet.localIP());
  //}



  //Inicializar la pantalla TFT
  HabilitarSS(sss);
  uint16_t ID = tft.readID();
  Serial.print("TFT ID: ");
  Serial.println(ID);
  if (ID == 0xD3D3) ID = 0x9341;  //para shield 3.5" , 0x9341 for 2.8" TFT LCD Shield
  if (ID == 0x9327) ID = 0x9327;
  if (ID == 0x9225) ID = 0x9225;
  if (ID == 0x9201) ID = 0x9201;
  tft.begin(ID);
  tft.fillScreen(0);
  tft.setRotation(1);//0-VERTICAL 1-APAISADO 2-VERTICAL INVERTIDO 3-APAISADO INVERTIDO
  
  //noInterrupts();
  
  PantallaInicio();
  delay(500);
  
  HabilitarSS(ssu);
}


//bucle principar luego del arranque
void loop() {
  wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
  //desde el USB
  //1) espera a que haya alguna actividad del usb
  Usb.Task();
  //Serial.println(millis()/100);
  //2) si leyo un string completo y estoy en el ultimo caracter
  if (UltimoUSB && LecturaUSB.length() > 0) {
    Principal();  //hago todo el proceso
    Reiniciar();
  }
  
}



//subrutina de seleccion de esclavo para las placas SPI
void HabilitarSS(byte ss) {
  //deshabilito con HIGH todos los esclavos
  digitalWrite(ssu, HIGH);
  digitalWrite(sss, HIGH);
  digitalWrite(ssr, HIGH);
  digitalWrite(sse, LOW);

  //habilito solo ss al requerido
  
  if (ss > 0) {//si hay ahgun esclavo seleccionado para activar
    if (ss == ssr) digitalWrite(sse, HIGH); //para la placa de red, habilito a la placa tambien (no al SS)
    digitalWrite(ss, LOW); //se habilita con estado LOW
  }
}


//   I  N  T  E  R  R  U  P  C  I  O  N  E  S 

//interrupcion por ingreso de pulso al pin 21 del Arduino Mega 2560
//se incrementara en uno la catidad de pulsos ingresados
//que iran marcando los litros que van pasando
//el pulso viene del caudalimetro
void pulsos(){
  if (estado > 0 && estado < 5) {
    cp++;//incremento los pulsos leidos
    Serial.println(cp);
    wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
    tact = millis();  //tomo el momento de la lectura para control de caudal de agua
  }
}


//subrutina para prueba de ingreso de ID del coche por pantalla si no esta el lector USB
void lecturaPC(){
    //Comprobamos si tenemos datos en el puerto serie
  if (pregunta == true) Serial.print("Escribe el identificador de la persona: ");
  pregunta = false;
  if (Serial.available()>0){
    //leemos el identificador
    byte identificador = Serial.read()-48;
    if (identificador == 218){
    } else {
      Serial.println(identificador);
      pregunta = true;
    }  
  }
}


//subrutina principal, donde se llama a las distintas subrutinas o funciones secuencialmente
void Principal(){
  //Serial.println(LecturaUSB);
  PantallaLeyendo();
  //3) Decodifico el string tomado del QR leido del celular con el lector
  HabilitarSS(0);
  DecodificarUSB();
  //4) Con el ID del coche y demas datos, busco en la base de datos a traves del web server
  ConsultaHTTP();
  //5) Decodifico el string de datos que vinieron desde la base de datos
  DatosDeLaConsulta();
  Serial.println(seguir);
  if (!seguir) return;
  //6) Espero a que se presione el boton de arranque.
  //   Mientras puede subir o bajar por botonera lo que va a cargar
  //   o cancelar la operancion
  EsperarArranque(); //estado 0
  Serial.println(seguir);
  if (!seguir) return;
  //interrupts(); //activo las interrupciones (pulsos y frenado)
  //8) Comienzo el arranque de la carga de agua
  Arranque(); //estado 1
  //9) SUBRUTINA PRINCIPAL LARGA MIENTRAS CARGA AGUA 
  //hasta que por alguna razon se frena
  Carga();  //estado 2
  //10) Comienzo de la secuencia de frenado de la carga de agua
  Frenado();  //estado 3
  //11) Contabilizar hasta la ultima gota, luego de terminada la carga mecanica de la bomba
  PostFrenado();  //estado 4
  //12) Registro en la base de datos la carga realizada
  RegistroHTTP();
  //13) fin del proceso
  GameOver();  
}



//    USB


//decodificacion de lo leido desde el USB. Almaceno en la variable global LecturaUSB el codigo leido por el lector USB
void DecodificarUSB(){
  wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
  //Serial.println(LecturaUSB);
  LecturaUSB = LecturaUSB.substring(2,LecturaUSB.length()); // saco caracteres molestos del principio
  Serial.print("LecturaUSB 1: ");
  Serial.println(LecturaUSB);
  LecturaUSB = LecturaUSB.substring(LecturaUSB.indexOf("&")+1,LecturaUSB.indexOf("!"));
  LongUSB = LecturaUSB.length(); //longitud
  Serial.print("LecturaUSB 2: ");
  Serial.println(LecturaUSB);
}


//subrutina de consulta de desglose de registros tomados de la lectura unica desde el usb
String RegistroUSB(String code,byte longitud) {
  String campo = "";
  String car = "";
  //Analizamos el código obtenido y almacenamos 'campo'
  for (int i = ubi+1; i < longitud; i ++){
    ubi = i;
    car = code.substring(i,i+1);
    //Serial.println(car);
    if (car == "%") i = longitud; //salgo de bucle si encuentro un separador de campos ("%") antes de que termine
    else campo += car; //sino, voy concatenando en campo los caracteres
  }
  return campo; //devuelvo el campo obtenido
}


//si se cancela la operacion, o reinicio del procedimiento. se re-inicializan las variables
void reiniciar(){
  
  wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
  //inicializacion
  seguir = true;
  LecturaUSB = "";
  UltimoUSB = false;
  PantallaInicio();
  delay(500);
  HabilitarSS(ssu);
}


//                RED

// Hacemos la conexion con el servidor
// Y tomamos los datos de la RED del codigo dado (leido por el USB)
// Y pasamos esos datos a un string
int ConsultaHTTP() {
  HabilitarSS(ssr);
  
  if (cnx()) {//si tengo conexion con el servidor (cnx() es la subrutina que hace la conexion)

    wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
    
    Serial.println("Conectado... ");

    String identificador = LecturaUSB;  //paso por red el codigo intresado por el lector USB
    Serial.println("");
    Serial.println("RED");
    Serial.print("identificador: ");
    Serial.println(identificador);
    // 1-CONSULTAMOS AL SERVER WEB con 'identificador' como ID (LecturaUSB)
    //Enviar la petición HTTP
    //Dirección del archivo php dentro del servidor
    client.print("GET /jirafa/consulta1.php?id=");
    client.print(identificador);
    client.println(" HTTP/1.0");
    
    //IP del servidor
    client.println(localip);
    client.println("User-Agent: arduino-ethernet");
    client.println("Connection: close");
    client.println();

    delay(500); //esperamos para que haya respuesta desde el servidor
    
    //2-LEEMOS BYTE POR BYTE LA RESPUESTA CON LOS DATOS OBTENIDOS DE LA CONSULTA
    //Comprobamos si tenemos respuesta del servidor y la
    //almacenamos en el string – --> codigo.
    LecturaRED = "";  //inicializamos la variable en la que se va a ir almacenando lo leido desde la red
    while (client.available()) {  //ingreso caracter por caracter hasta que no hayan mas
      char c = client.read(); //caracter leido
      //3-VAMOS FORMANDO EL STRING
      LecturaRED += c;  //armado del string LecturaRED concatenandole cada caracter que se va recibiendo en c
      //Habilitamos la comprobación del código recibido
      fin = true;
    }
    //solo la parte que me interesa, entre los signos de inicio & y de fin !
    LecturaRED = LecturaRED.substring(LecturaRED.indexOf("&") + 1,LecturaRED.indexOf("!"));
    
    Serial.println(LecturaRED);
    client.stop();
    seguir = true;
    return 1;
  
  } else {
    // ...si no se conecta
    Serial.println("Conexión fallida");
    Serial.println("Desconectando");
    client.stop();
    seguir = false;
    bFnd = 1;
    PantallaTermino("Sin RED");
    return 0;
    
  }
  HabilitarSS(0);

  wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
  
}



// Sacamos los datos del string recibido de la consulta al servidor (RED)
int DatosDeLaConsulta () {

  wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
    
  //Ubicacion del primer caracter a tomar en cada variable, para el pase entre variables
  ubi = 0;
  
  //Longitud del código recibido
  LongRED = LecturaRED.length();
  
  int posicion = 0;

  delay(500);
  //tomamos el primer registro leido desde lo tomado por la red. puede ser "Si" o "No"
  VerifRED = RegistroRED(LecturaRED,LongRED);
  
  Serial.println("Verificacion: " + VerifRED);

  if (VerifRED == "Si"){  // si es "Si", habilita la carga y toma los litros habilitados a cargar
    LitrosRED = RegistroRED(LecturaRED,LongRED).toInt() * 100;
    MensajeRED = "";
    Serial.println("Litros: " + String(LitrosRED));
    seguir = true;
    
  }else{  // si es "No", no habilita la carga y toma el mensaje del problma
    LitrosRED = 0;
    MensajeRED = RegistroRED(LecturaRED,LongRED);
    seguir = false;
    Serial.println("Mensaje: " + MensajeRED);
    Serial.println(seguir);
    bFnd = 2;
  }
  
  
  //Deshabilitamos el análisis del código
  fin = false;

  //Cerrar conexión
  Serial.println("Desconectar");
  Serial.println("");
  Serial.println("");
  client.stop();
  
  //Salir de la función

  wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio

  if (!seguir){
    PantallaTermino(MensajeRED);
  }
  return 1;
}



//subrutina de desglose de los registros tomados de la red en un solo string
String RegistroRED(String code, byte longitud) {
  String campo = "";
  //Analizamos el código completo obtenido y almacenamos 'campo'
  for (int i = ubi+1; i < longitud; i ++){
    ubi = i;
    if (code[i] == '%') i = longitud; //salgo de bucle si encuentro un separador de campos ("%") antes de que termine
    else campo += code[i]; //sino, voy concatenando en campo los caracteres
  }
  return campo; //devuelvo el campo obtenido
}



// Hacemos la conexion con el servidor
// Y enviamos los datos de la transaccion y la cantidad de litros cargados
// Y pasamos esos datos a un string
int RegistroHTTP() {
  HabilitarSS(ssr);
  
  if (cnx()) {//si tengo conexion con el servidor (cnx() es la subrutina que hace la conexion)
    
    wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
    
    Serial.println("Conectado... ");
    String identificador = LecturaUSB;
    Serial.println("");
    Serial.println("RED");
    Serial.print("identificador: ");
    Serial.println(identificador);

    // 1-ENVTAMOS AL SERVER WEB el 'identificador' como ID
    
    client.print("GET /jirafa/carga.php?id=");
    client.print(identificador);
    client.print("&jir=");
    client.print(idjir);
    client.print("&ltr=");
    client.print(cargado / 100);
    client.println(" HTTP/1.0");
    
    Serial.println(cargado / 100);
    
    //IP del servidor
    client.println(localip);
    client.println("User-Agent: arduino-ethernet");
    client.println("Connection: close");
    client.println();

    Serial.println("Transacción realizada");
    
    delay(500); //esperamos para que haya respuesta desde el servidor


    //2-LEEMOS BYTE POR BYTE LA RESPUESTA CON LOS DATOS OBTENIDOS DE LA CONSULTA
    //Comprobamos si tenemos respuesta del servidor y la
    //almacenamos en el string – --> codigo.
    LecturaRED = "";
    while (client.available()) {  //ingreso caracter por caracter hasta que no hayan mas
      char c = client.read(); //caracter leido
      //3-VAMOS FORMANDO EL STRING
      LecturaRED += c;  //armado del string que se va recibiendo
      //Habilitamos la comprobación del código recibido
      fin = true;
    }
    //solo la parte que me interesa, entre los signos de inicio & y de fin !
    LecturaRED = LecturaRED.substring(LecturaRED.indexOf("&") + 1,LecturaRED.indexOf("!"));
    
    Serial.println(LecturaRED);
    client.stop();


    return 1;

  } else {
    // ...si no se conecta
    Serial.println("Conexión fallida");
    Serial.println("Desconectando");
    client.stop();

    return 0;
  }
  HabilitarSS(0);

  wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
}


//subrutina de conexion a la RED
bool cnx(){
  // Comprobar si hay conexión
  //ci: cantidad de intenos de conexion
  byte ci = 10;
  bool si = false;
  for (int i = 0; i <= ci; i++) {//reintentos de conexion
    if (client.connect(serverip, 80)) {
      si = true;
      i = ci; //o continue
    } else {
      Serial.println("no... ");
      delay(1000);
      wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
    }
  }//intentos de reconeccion
  return si;
}

//  C  A  R  G  A 
// ya ingresados los datos desde el USB y de la RED, mostramos a los mismos en pantalla
// y damos la opcion de modificarlos por medio de los botones
// boton mas, boton menos, boton verde comenzar carga, boton rojo cancelar y arrancar TODO nuevamente
void EsperarArranque(){
  permitido = LitrosRED;
  maximo = long(LitrosRED);
  estado = 0;
  cargado = 0;
  total = 0;
  seguir = true;  //pasa a true si se presiona el boton cancelar
  //Muestro en pantalla
  PantallaDatos();
  boolean arr = true;
  //MostrarMx(maximo);
  Serial.println("Permitido: " + String(permitido));
  unsigned long tfue = millis();
  do {
    if (digitalRead(cmz) == HIGH) {  //se presiono el pulsador VERDE de arranque
      Serial.println("Comenzar");
      arr = false;
      delay(longboton);
    }
    if (digitalRead(frn) == HIGH) {  //se presiono el pulsador ROJO de cancelar
      Serial.println("Cancelar");
      arr = false;
      seguir = false;  //cancelo la operacion
      PantallaTermino("Cancelado");
      bFnd = 3;
      delay(longboton);
    }
    if (digitalRead(inc) == HIGH) {  //se presiono el pulsador de aumentar
      if (maximo + incremento <= permitido) {
        Serial.println("Sumar");
        maximo = maximo + incremento;
        //Serial.println(maximo);
        MostrarMx(String(maximo));
        Serial.println(String(maximo));
        tfue = millis();  //renuevo contador
        delay(longboton);
      }
    }
    if (digitalRead(dec) == HIGH) {  //se presiono el pulsador de disminuir
      if (maximo - incremento >= 0) {
        Serial.println("Restar");
        maximo = maximo - incremento;
        //Serial.println(maximo);
        MostrarMx(String(maximo));
        Serial.println(String(maximo));
        tfue = millis();  //renuevo contador
        delay(longboton);
      }
    }

    //Serial.println((millis()-tfue)/1000 > 30);
    if((millis()-tfue)/1000 > 30) { //controlo que no pase tiempo mureto de espera
      Serial.println("Tiempo Fuera");
      arr = false;
      seguir = false;  //cancelo la operacion
      PantallaTermino("Tiempo /fuera");
      bFnd = 6;
    }
    
    //Serial.println(String(maximo));

    wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
    
  } while (arr);

  //maximo = 2000;  //OJO!!! Solo para prueba, para que no sea mucho. sacarlo para el definitivo

}


// para las tres siguientes subrutinas (todo el proceso de carga)
// tener en cuenta que la variable cp (cantidad de pulsos) se va incrementando por interrupcion
// en la subrutina 'pulsos'

void Arranque(){
  estado = 1; //arranque
  PantallaCarga("A Cargar", String(maximo));
  Serial.println("Estado 1");
  cp = 0; //inicializo el contador de pulsos
  boolean ba = true;
  //if (digitalRead(swb) == HIGH) { //me fijo que el switch bomba-valvula este en bomba
  if (ba){//solo en la prueba. en el real hay que usar el if de arriba
    //dependiendo la cantidad de litros a cargar, utilizara deistintos arranques
    bv = true;
    
    if (maximo < max1) {
      disparo(ra1);
      Serial.println("Arranque rampa 1 ");
    }
  
    if (maximo < max2 && maximo >= max1) {
      disparo(ra2);
      Serial.println("Arranque rampa 2 ");
    }
  
    if (maximo >= max2) {
      disparo(ra3);
      Serial.println("Arranque rampa 3 ");
    }
  }

  //arranque por valvula
  //lleva su tiempo (2.5 minutos) abrirla y cerrarla
  //guardo el momento en que comenzo la apertura y mientras carga controlo su cierre 
  
  //if (digitalRead(swv) == HIGH) {//me fijo que el switch bomba-valvula este en valvula
    bv = false; //bandera boma-valvula en false. actua la valvula
    digitalWrite(arv,HIGH); //activo la apertura de la valvula
    mapv = millis();  //momento en el que se comenzo la apertura de la valvula
    Serial.println("Arranque Valvula ");
  //}
  
}

//subrutina de tiempo para matener un pulso en un pin ingresado durante un periodo corto "de pulso" 
void disparo(byte pin){
    digitalWrite(pin,HIGH); //activo el pulso
    delay (200);  //espero un poco
    digitalWrite(pin,LOW);  //desactivo el pulso
}


// subrutina 'va cargando'. AQUI TODO LO QUE OCURRA MIENTRAS VA CARGANDO AGUA
void Carga() {
  if (!seguir) return;  //controlo que no haya sido presionado el boton cancelar
  estado = 2; //cargando
  Serial.println("Estado 2");
  bFnd = 0;  //byte que notifica la causa de la salida del bucle de carga
  String MsgSal = ""; //mensaje de salida
  boolean arr = true; //bandera de salida del bucle activada
  unsigned int tiempo = 3000;
  boolean vla = true; //bandera de valvula abriendo. para treminar su apertura a los 2.5 minutoa
  if (bv) vla = false;  //si estamos por bomba, no ir a frenado de valvula
  do {
    for (unsigned int i = 0; i < tiempo; i ++){
      //delay(100);//pequeño delay para ayudar al bucle for
      cargado = cp * mult;  //cp se incrementa por interrupcion

      if (cargado > (maximo - sup)){  //SI LLEGO AL LIMITE PREVIO AL MAXIMO A CARGAR, para comenzar el proceso de frenado
        MsgSal = "Terminado";
        bFnd = 4;
        arr = false;
        break;
      }

      //desactivo el arranque de la valvula en el momento estipulado. 
      //OJO! no la apaga, solo deja de enviar el pulso de apertura
      if (vla){ //que lo haga solo una vez
        if ((millis() - mapv) / 1000 > tapv) {
           digitalWrite(arv,LOW); //desactivo la apertura de la valvula
           vla = false; //que no entre mas aqui
           Serial.println("Fin Apertura Valvula ");
        }
      }
      
      if (digitalRead(frn) == HIGH) {  //SE PRESIONO EL BOTON CANCELAR!!!
        bool bStp = Stopeado();
        if (bStp){
          MsgSal = "Frenado";
          bFnd = 5;
          arr = false;
          break;
        }
      }

      /*
      if (controlcaudal()){ //SI NO ESTA PASANDO AGUA POR EL CAUDALIMETRO
        MsgSal = "Sin Agua";
        bFnd = 6;
        arr = false;
        break;
      }
      */
  
    }
    
    Serial.println(cargado);
    MostrarCarga(String(cargado));
    wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio

  } while (arr);

  PantallaTermino(MsgSal);
  delay(1000);

}


void Frenado(){
  estado = 3; //frenado
  Serial.println("Estado 3");
  MostrarCarga("Frenando");
  if (bv) { //switch bomba-valvula en valvula
    disparo(frb);    //frenado de la boma 
  }else{  //frenado de bomba
    digitalWrite(frv,HIGH); //activo el cierre de la valvula
    mciv = millis();  //momento en el que se comenzo el cierre de la valvula
    Serial.println("Inicio frenado de Valvula ");
  }
}



//Aqui controlamos lo que pasa por el caudalimetro luego de terminado el proceso
//"hasta la ultima gota"
void PostFrenado(){
  PantallaCarga("Frenando: ", String(maximo));
  estado = 4; //post-frenado
  Serial.println("Estado 4");
  //bool arr = true;
  boolean vla = true; //bandera de valvula cerrando. para terminar su cierre a los 2.5 minutoa
  if (bv) vla = false;  //si estamos por bomba, no ir a frenado de valvula
  bool arr = false; //PONER EN TRUE CUANDO OCURRA DE VERDAD!!!!!!
  unsigned int tiempo = 5000;
  do {  //realizo el bucle hasta que deje de pasar agua por el caudalimetro
    for (unsigned int i = 0; i < tiempo; i ++){
      //delay(100);//pequeño delay para ayudar al bucle for
      cargado = cp * mult;  //cp se incrementa por interrupcion


      if (vla){ //que lo haga solo una vez
        if ((millis() - mciv) / 1000 > tciv) {
           digitalWrite(frv,LOW); //desactivo la apertura de la valvula
           vla = false; //que no entre mas aqui
           Serial.println("Fin Cierre Valvula ");
        }
      }
      
      //if (controlcaudal()){ //SI NO ESTA PASANDO AGUA POR EL CAUDALIMETRO
      if (tiempo > 500) {
        byte bFnd = 4;
        arr = false;
        break;
      }
      delay(1);
    }

    Serial.println(cargado);
    MostrarCarga(String(cargado));
    //wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
    wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio

  } while (arr);

}



//control de caudalimetro. si pasado un tiempo de la ultima lectura, no hay mas lecturas, entonces dejo de pasar agua
boolean controlcaudal() {
  boolean bcc = false;
  if ((millis() - tact)/1000 > tdif) bcc = true; 
  return bcc;
}



boolean Stopeado() {
  boolean arr = true;
  PantallaFrenado("STOP?"); //pantalla confirmacion
  Serial.println("STOP?");
  delay(100);

  //controlo por bucle q el boton siga apretado luego de medio segundo (efecto rebote mecanico)
  bool bsal = false;
  for (int i=0; i <= 1000; i++){
    if (digitalRead(frn) == HIGH){
      bsal = true;
      break;
    }
  }
  
  if (bsal) { //...si presiono el boton rojo durante 1/2 segundo, se confirmar el frenado
    PantallaFrenado("STOP!!");
    Serial.println("STOP!!");
    arr = true;
    total = cargado;  //total cargado en el momento de frenado
    ef = estado; //estado en el momento de frenado
  }
  return arr;
}



void GameOver(){
  if (seguir) total = cargado;
  estado = 5;
  Serial.print("Estado 5");
  PantallaFinal();
  delay(5000);
  
}


void Reiniciar(){
  cp = 0;
  estado = 0;
  seguir = true;
  PantallaInicio();
  LecturaUSB = "";
  LecturaRED = "";
}




//SUBRUTINAS DE PANTALLAS

//           TFT - Pantalla

void PantallaInicio(){
  HabilitarSS(sss);
  tft.fillScreen(BLACK);
  tft.setCursor(0, 30);
  tft.setTextSize(4);
  tft.setTextColor(WHITE, BLACK);
  tft.print("  Por favor ");
  tft.setCursor(0, 80);
  tft.print("   pase el");
  tft.setCursor(0, 130);
  tft.print("  codigo QR");
  tft.setCursor(0, 180);
  tft.print("por el lector");

  delay(1000);

  wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
  
}

void PantallaLeyendo(){
  HabilitarSS(sss);
  tft.fillScreen(BLACK);
  tft.setCursor(0, 30);
  tft.setTextSize(4);
  tft.setTextColor(WHITE, BLACK);
  tft.print("  Leyendo ");
  tft.setCursor(0, 80);
  tft.print("   datos");
  tft.setCursor(0, 130);
  tft.print("  Por favor ");
  tft.setCursor(0, 180);
  tft.print("   espere ");

  delay(1000);

  wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
  
}

void PantallaDatos(){
  HabilitarSS(sss);
  tft.fillScreen(BLUE);
  tft.setTextColor(WHITE, BLUE);
  tft.setTextSize(3);
  tft.setCursor(10, 10);
  tft.setTextColor(WHITE, BLUE);
  tft.print("Maximo permitido: ");
  tft.setTextSize(3);
  tft.setCursor(110, 50);
  tft.setTextColor(WHITE, BLUE);
  tft.print(LitrosRED);
  tft.setTextSize(3);
  tft.setCursor(250, 50);
  tft.setTextColor(WHITE, BLUE);
  tft.print("litros");
  tft.setTextSize(3);
  tft.setCursor(20, 90);
  tft.print("Total a cargar:");
  tft.setTextSize(6);
  tft.setCursor(226 - String(maximo).length()*36, 130);
  //tft.print("10000");
  tft.print(maximo);
  tft.setCursor(240, 130);
  tft.setTextSize(3);
  tft.print("litros");
  tft.setCursor(280, 130);
  tft.setTextSize(4);
  tft.setTextColor(WHITE, BLUE);
  tft.setCursor(0, 200);
  tft.print("Pulse");
  tft.setTextColor(WHITE, DARKGREEN);
  tft.setCursor(120, 200);
  tft.print(" CARGAR ");

  delay(1000);

  wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
  
}

void PantallaCarga(String msg, String mxm){
  HabilitarSS(sss);
  tft.fillScreen(MAGENTA);
  tft.setTextColor(WHITE, MAGENTA);
  tft.setTextSize(3);
  tft.setCursor(0, 35);
  tft.print(msg);
  tft.setCursor(170, 30);
  tft.setTextSize(4);
  tft.print(mxm);
  tft.setTextSize(3);
  tft.setCursor(10, 80);
  tft.print("Ya van cargados:");
  tft.setTextSize(6);
  tft.setTextColor(BLACK, MAGENTA);
  tft.setCursor(190, 130);
  tft.print("0");
  //tft.print(cargado);
  tft.setCursor(240, 140);
  tft.setTextSize(4);
  tft.print("litros");
  tft.setCursor(280, 130);


  delay(1000);

  wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
  
}

void PantallaFrenado(String texto){
  for (int i = 1; i < 3; i ++){
    HabilitarSS(sss);
    tft.fillScreen(RED);
    tft.setTextColor(WHITE, RED);
    tft.setTextSize(8);
    tft.setCursor(50, 90);
    tft.print(texto);   
    delay(300);
  }  
  wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
}

void PantallaTermino(String texto){
  byte ubi = texto.indexOf("/");
  for (int i = 1; i < 3; i ++){
    HabilitarSS(sss);
    //tft.fillScreen(DARKGREEN);
    //tft.setTextColor(BLACK, DARKGREEN);
    tft.fillScreen(BLACK);
    tft.setTextColor(WHITE, BLACK);
    tft.setTextSize(6);
    if (ubi == 0){
      tft.setCursor(200 - texto.length()*18, 100);
      tft.print(texto);
    } else {
      String t1 = texto.substring(0,ubi);     
      tft.setCursor(200 - t1.length()*18, 60);
      tft.print(t1);
      String t2 = texto.substring(ubi+1,texto.length());
      tft.setCursor(200 - t2.length()*18, 140);
      tft.print(t2);
    }
    delay(2000);
  }  
  wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
}

void PantallaFinal(){
  HabilitarSS(sss);
  tft.fillScreen(BLACK);
  tft.setCursor(0, 30);
  tft.setTextSize(4);
  tft.setTextColor(WHITE, BLACK);
  tft.print("  Proceso ");
  tft.setCursor(0, 80);
  tft.print(" Finalizado ");
  tft.setCursor(0, 130);
  tft.print("  cargados ");
  tft.setCursor(60, 180);
  tft.print(total);
  tft.setCursor(200, 180);
  tft.print("l");

  delay(1000);

  wdt_reset(); // Actualizar el watchdog para que no produzca un reinicio
  
}


//modificaciones en pantalla de numeros
void MostrarMx(String mxm){
  HabilitarSS(sss);
  tft.setTextColor(WHITE, BLUE);
  tft.setTextSize(6);
  tft.setCursor(20, 130);
  tft.print("      ");
  tft.setCursor(226 - String(mxm).length()*36, 130);
  tft.print(mxm);
}


void MostrarCarga(String crg){
  HabilitarSS(sss);
  tft.setTextColor(BLACK, MAGENTA);
  tft.setTextSize(6);
  tft.setCursor(226 - String(crg).length()*36, 130);
  tft.print(crg);  
}


Hay abuso de WatchDog y toda una secuencia que aunque esta documentada es rara de seguir.
Deberías tener alguna secuencia que te permita saber si ocurren reinicios reiterados o que esta demorando la operación de tu código.
Yo lo modificaría usando una máquina de estados pero no porque es la manera que me gusta hacer las cosas, sino porque de ese modo podría entender que esta pasando.
Para mi un programa que usa tanto wd es un programa que tiene fallas y que las muestra cuando quiere, por eso hay que detectarlas.

hola Surbyte. antes que nada gracias. Si fuese por mi ni uso el wd. Pero lo que menos quiero es que se me cuelgue el sistema. Ojala pudiese hacer un control cada minuto o mas. pero como es un sistema que de tanto en tanto debe estar "esperando" una respuesta, no me queda otra mas que usarlo para que no se cuelgue. Hasta ahora con lo que hago, yo estoy como para solucionar problemas. Pero en este proyecto debo instalar el Arduino y dejarlo funcionando 24 hs, constantemente, ya que en cualquier momento puede ser usado por cualquier cliente. No hay reinicios. Lo que le ocurre al sistema, es que, de una, estando todo bien, la pantalla (creo que como consecuencia del sistema) comienza a mostrar leeeentameeeente los textos, y todo comienza a tardar en realizar acciones.