Reinicio manual de la tarjeta Arduino Ethernet.

Saludos, soy nuevo tanto en esto de los foros como en la utilización de los microcontroladores Arduino (o cualquier otro), se me presenta un problema al que no le encuentro solución a pesar de haber mareado el google y su traductor (no se me da bien el inglés), parece que no pasa muy a menudo, por lo que pienso que la solución debe ser simple. La cuestión es que cada vez que alimento la tarjeta Arduino directamente (no a través del puerto serie), debo pulsar el botón del Reset manual para que el programa empiece a funcionar. Hardware: Tarjeta Arduino Ethernet, tarjeta HA7S, red 1-Wire (6 termómetros DS18B20) y fuente de alimentación casera. Softwere: Sketch Arduino (IDE 1.5.2), algo de Java, algo de Microsoft Access. En resumen, lo que pretendo es hacer un "data logger" y rellenar una base de datos con las temperaturas leídas por los DS18B20, la 1-wire (Maxim Integrated) es controlada mediante un HA7S, que a su vez recibe las órdenes desde un puerto serie creado para su control en la Arduino. Aparentemente el Sketch funciona correctamente, la base de datos se va llenando correctamente, pero: cada vez que alimento la tarjeta Arduino tengo que darle al botón del Reset para que empiece a funcionar, o sea que si la luz se va, no volvería a funcionar hasta que fuera a presionar el pulsador.

Gracias y perdón si no he sabido expresarme correctamente o faltan datos para evaluar la respuesta.

Has probado con otro scketch? De los que vienen en los ejemplos? Deberias poner el scketch para tener mas info...

Gracias por responder.
Con sketchs más simples funciona bien, o sea, al conectar alimentación directa (con el adaptador USB de serie Light desconectado) el programa simple empieza a funcionar sin problemas.
En cuanto al sketch, me da un poco de vergüenza, pues lo he ido haciendo a mi aire y siguiendo muchos ejemplos encontrados por Internet, pero bueno, ahí va.

TemperaturasArduino.ino (7.28 KB)

Bueno, no sabía como insertar código en el post y me salió un archivo adjunto, a ver si así es más cómodo.

//#include <Dhcp.h>//Librerías que se descargan al importar la Ethernet.
//#include <Dns.h>
#include <Ethernet.h>
//#include <EthernetClient.h>
//#include <EthernetServer.h>
//#include <EthernetUdp.h>
//#include <util.h>

#include <SPI.h>//La librería SD.h (para la microSD), exige la SPI.
#include <SD.h>

#include <Time.h>//Para manejar los tiempos.

#include <SoftwareSerial.h>//Librería para poder crear puerto serie en cualquier Pin.

SoftwareSerial PtoHA7S(6,7);//(6->Rx)(7->Tx)Puerto exclusivo para no liarse con el puerto de la "pantalla" o "monitor".

char Disp[20][17];//Dispositivos, hay 6 de 16 caract. con un caract. y disp. más para manejar la matriz(pueden ser hasta 20).
char Med[20][8];//Guarda respuesta del HA7S cuando un dispositivo da su medida de temperatura.
int i=0;//Auxiliar, para no declararlo muchas veces.
int n=0;//Numero de dispositivos.
char delCli;//Variable recibida desde el cliente.

byte mac[] = { 
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,1, 177);//Dirección ip del Servidor Arduino dentro de la LAN
byte subnet[]  = { 255, 255, 255, 0 };
EthernetServer servArduino(8989);//Declara que el Servidor arduino se comunica por el puerto 8989/tcp HTTP HyperText Transfer Protocol (Protocolo de Transferencia de HiperTexto) (WWW)

const int chipSelect = 4;//"Pone en marcha" la microSD.




void setup() {
  Serial.begin(9600);//Inicializa el "monitor" para ver resultados en pantalla (finalmente SE DESACTIVARÁ).
  PtoHA7S.begin(9600);//Inicializa el puerto para conectarse con el HA7S.
  NombDisp();//¿Función? que busca los nombres de los dispositivos.
  for(int i=0;i<=20;i++){//Para ver los nombres de los dispositivos en el monitor (se quitará al final).
    Serial.println(Disp[i]);
  }
  Ethernet.begin(mac, ip);
  servArduino.begin();
  //ActHora();//Convendría actualizar la hora al arrancar Arduino ¿por servidor NTP?(el reloj del Arduino...).
  SD.begin(chipSelect);//Inicializa la microSD (es lo último del void setup, obligatoriamente, o se bloquea).
}




void loop() {
  MideTemp();
  ServRedArduino();
}




void NombDisp(){
  PtoHA7S.write('R');//Por si acaso reseteo el 1 wire.
  PtoHA7S.flush();//Espero a que se hayan enviado todos los 0 y 1s por si acaso.
  delay(2);//Sin este retardo se queda bloqueado (imagino que lo necesita el 1 wire).

  PtoHA7S.write('S');//Envío "S" mayúscula al HA7S, me buscará el primer dispositivo.
  PtoHA7S.flush();//Espero a que se hayan enviado todos los 0 y 1s por si acaso.

  int m=millis();
  while(PtoHA7S.available()<=16){//Espera llegada de 16 caracteres(en realidad 17,un return creo).
      if(millis()-m>=50){//Si pasan 50 ms sin llegar datos, pues no hay dispositivos.
        //Serial.println("Si no hay dispositivos en el 1 wire, estamos jodidos");
        return;
      }
  }

  for(i=0;i<=16;i++){//de cero a 16 son 17 caracteres que guardo en Disp[1].
    Disp[1][i]=PtoHA7S.read();//Se guardan los 16 caracteres del primer dispositivo.
  }
  Disp[1][16]='\0';//el último caracter se pone nulo por si acaso.
  n=1;
  
  for(int j=2;j<=20;j++){//de 2 a 6 (inclusives) van los 5 dispositivos que tengo.
    delayMicroseconds(200);//Necesarios. NI ME IMAGINO, NI SE POR QUE.
    PtoHA7S.write('s');//Envío "s" minúscula al HA7S, buscará los siguientes disp. cada vez (for).
    PtoHA7S.flush();//Espero a que se hayan enviado todos los 0 y 1s por si acaso.
    int m=millis();
    while(PtoHA7S.available()<=16){//Espera llegada de 16 caracteres(en realidad 17,un return creo).
      if(millis()-m>=50){//Si pasan 50 ms sin llegar datos, pues se acabo esperar, no hay mas dispositivos.
        return;
      }
    }
    for(i=0;i<=16;i++){//de cero a 16 son 17 caracteres que guardo en Disp[j].
      Disp[j][i]=PtoHA7S.read();
    }
    Disp[j][16]='\0';
    n=j;
  }
}




void MideTemp(){
  delay(2);  
  PtoHA7S.write('R');
  PtoHA7S.flush();
  delay(3);

  PtoHA7S.println("W01CC");//Poniendo "CC" en 1Wire, los dispositivos recibirán una orden simultanea (solo con alimentación directa, sin alimentación parásita).
  PtoHA7S.flush();
  delay(100);  

  PtoHA7S.println("W0144");//Dá la orden para que cada dispositivo mida y guarde en su memoria la temperatura.
  PtoHA7S.flush();
  delay(60);

  for(int t=1;t<=n;t++){//Seleccionar cada dispositivo individualmente y guardar valores de su temperatura en matriz.
    PtoHA7S.write('A');
    PtoHA7S.println(Disp[t]);
    PtoHA7S.flush();
    delay(60);

    PtoHA7S.println("W03BEFFFF");//Ordena al dispositivo seleccionado que me envíe su temperatura almacenada en memoria.
    PtoHA7S.flush();
    while(PtoHA7S.available()<=6){
    }

    for(i=0;i<=5;i++){//Guarda en matriz, la temperatura enviada por el dispositivo seleccionado en cada for.
      Med[t][i]=PtoHA7S.read();
    }
    delay(60);

    GuarTempSD();//Para guardar dia hora y temperatura de cada dispositivo/termómetro en la microSD.
  }
}




void ServRedArduino(){//Comprueba si se conectó algún "cliente" y que carácter le envía.
  EthernetClient cliente = servArduino.available();
  if (cliente) {
    while (cliente.connected()) {
      if (cliente.available()) {
        delCli = cliente.read();

        switch (delCli) {

        case 'h'://Poner el reloj Arduino en hora (setTime(hr,min,sec,day,month,yr)); 

          char t[15];//Variable para ir recibiendo los caracteres desde el cliente.
          i=0;
          {
            while(cliente.available()>0){//Lee tiempo enviado por Java (Netbeans)(parece que envía un caracter nulo entre caracteres).
              t[i]=cliente.read();
              if (t[i]=='\0'){
                i=i--;
              }
              i++;
            }
          }
          t[14]='\0';
          //Para poner dia y hora pasamos código ASCII como un número, asi abrevio.
          setTime(((t[0]-48)*10)+t[1]-48,((t[2]-48)*10)+t[3]-48,((t[4]-48)*10)+t[5]-48,
          ((t[6]-48)*10)+t[7]-48,((t[8]-48)*10)+t[9]-48,
          ((t[10]-48)*1000)+((t[11]-48)*100)+((t[12]-48)*10)+(t[13]-48));
          cliente.stop();
          break;

        case 't'://ver fecha, horas y temp. (enviarlas al clientecomo un solo "párrafo").
          //quiza sea mejor enviar el último guardado en la microSD ???.
          cliente.print(day()); 
          cliente.print('/');
          cliente.print(month()); 
          cliente.print('/');
          cliente.print(year());
          cliente.print(' ');
          cliente.print(hour());
          cliente.print(':');
          cliente.print(minute());
          cliente.print(':');
          cliente.print(second());
          cliente.print("*");
          for(i=1;i<=n;i++){
            cliente.print(Disp[i]);
            cliente.print(Med[i]);
          }
          cliente.println();
          cliente.stop();
          break;
          
          //case 'd'://Sacar y enviar los datos solicitados a la microSD.
                    
          cliente.stop();
          break;
        }
      }
    }
  }
}




void GuarTempSD(){//Guarda temperaturas medidas en tarjeta microSD.
  File Tmps = SD.open("Temp.txt", FILE_WRITE);
  Tmps.print(day());
  Tmps.print('/');
  Tmps.print(month()); 
  Tmps.print('/');
  Tmps.print(year());
  Tmps.print(' ');
  Tmps.print(hour());
  Tmps.print(':');
  Tmps.print(minute());
  Tmps.print(':');
  Tmps.print(second());
  Tmps.print('*');
  for(i=1;i<=n;i++){
    Tmps.print(Disp[i]);
    Tmps.print(Med[i]);
  }
  Tmps.println();
  Tmps.close();
}

Para empezar, probaría a compilar usando la version del IDE 1.0.5 ya que se supone que es la última versiós estable, la 1.5 es una beta... Yo he tenido problemas en algunas pruebas al compilar...

Y también probaría, si tu problema está al usar el puerto serie,( y ya no lo necesitas) a eliminarlo de la ecuación... El serial.begin y todos los serial.print....podrías tener algún conflicto al iniciarlo...

Pues en su momento me descargué el IDE 1.5.2 y luego olvidé que era Beta. He seguido sus consejos, quité los Serial.begin ..., descargué y usé el IDE 1.0.5 (quité las sentencias Time... Day... porque parece ser que el IDE 1.0.5 no las entiende), compilé y descargué el sketch en el Arduino ethernet, pero el problema persiste en las mismas condiciones. Mirando por Internet voy notando que este problema es más común de lo que pensaba en principio, parece ser que lo resuelven poniendo condensadores, resistencias,... he probado algunos pero no me dan resultado, estoy pensando en algún circuito electrónico externo que me ponga a tierra (GND) el pin de RESET durante unos milisegundos después de 1 segundo (por ejemplo) desde la puesta en tensión de la tarjeta Arduino. No es una solución que me guste (hubiera preferido algo de software), pero no veo alternativas. Imagino que durante el tiempo de carga del C3 (patilla 29 -RESET- del Atmega 328) el microcontrolador decide si "recibe" un nuevo sketch o "corre" con el que ya tiene grabado (la descarga del condensador se hace pulsando manualmente el RESET o cuando el IDE le envía un "nivel bajo" por la patilla 5 del ICPS), de alguna forma mi sketch entra en conflicto con este sistema durante la primera puesta en tensión y no pone en funcionamiento el programa que tiene en memoria. Perdón por el rollo y gracias por su paciencia.

Bueno, he encontrado una mediosolución hard y soft para que el sketch corra sin muchos cambios. Resulta que el problema se centra en que (imagino que por el primer arranque del Atmega) no se "inicia" la comunicación por el puerto serie creado en pines 2 y 3 para el HA7S, pero todo lo demás funciona correctamente, así pues puenteé un pin (el 7) con el pin de RESET, al recibir tensión el Arduino el sketch no declara el pin 7 de ninguna manera, por lo que no le afecta al pin del RESET (eso fue una casualidad afortunada). Cuando abro la ventana del Java, lo primero que hace es decirle a Arduino que ejecute una ¿subrutina? que declara al pin 7 como salida poniendo automáticamente a cero (gnd) dicho pin lo que provoca un RESET y a partir de ese momento todo el Sketch funciona correctamente. Ahora tengo una manera de resetar el Arduino a través de la red LAN mediante Java.

Lisergio, quedo muy agradecido por tu atención, si encontrases otras soluciones, cuéntame. Muchas gracias.