Carga sketch Wenos D1 mini

Hola buenas noches, estoy utilizando wemos D1 mini y no consigo cargar los sketch sin tener que conectar el pin GND al D3, al intentar cargar sin unirlos siempre da error.
¿¿ Alguien puede ayudarme o indicarme como configurar el IDE de Arduino o que hacer para no tener que unir estos pines en la carga del sketch??

Muchas gracias.

De donde sacaste que el pin D3 debe ir a GND, porque no pudo ser inspiración divina?

Moderador:
Tu publicación fue MOVIDA a su ubicación actual porque es más adecuada.
¿Podría también tomarse unos minutos para aprender a usar el foro?
Puede encontrar más ayuda general y consejos para la resolución de problemas aquí.
Le ayudará a obtener lo mejor del foro en el futuro.

Como no conseguia cargar los sketchs, buscando información encontre esta solución en varios sitios, en unos dice que esa union provoca un reset de la memoria en tiempo de carga, otros reset de la eeprom, otros que entra en modo programación......

Siempre cuando leas, que sean fuentes valederas, si no sabes, simplementes te tomas el tiempo en el foro y buscas que se ha hecho con el dispostivo de tu interés. Te aseguro que alguien lo ha preguntado antes que tu.

Esta es una página seria, la de Luis Llamas. Siempre lo mencionamos como referente.

Si tuvieras una placa con un wemos SOLO entiendo que consideres hacer algo, pero cuando tienes una placa como la tuya, solo hay que configurar correctamente y tiene que funcionar. Si no lo hace, esta mal cargado el driver en el IDE.
Y aquí el resumen la tabla de resumen de los pines y su función principal.

Pin ESP-8266 Pin Función
TX TXD TXD
RX RXD RXD
A0 A0 Analog input (max 3.2V)
D0 GPIO16 IO
D1 GPIO5 IO, PWM, Interrupt, I2C, SCL
D2 GPIO4 IO, PWM, Interrupt, I2C, SDA
D3 GPIO0 IO 10k Pull-up, PWM, Interrupt, I2C
D4 GPIO2 IO 10k Pull-up, PWM, Interrupt, I2C, BUILTIN_LED
D5 GPIO14 IO, PWM, Interrupt, I2C, SCK
D6 GPIO12 IO, PWM, Interrupt, I2C,, MISO
D7 GPIO13 IO, PWM, Interrupt, I2C,, MOSI
D8 GPIO15 IO 10k Pull-down, PWM, Interrupt, I2C,, SS
G GND Ground
5V - 5V
3V3 3.3V 3.3V

image
Observa que abajo a la izquierda dice
On Boot/Reset/Wakeup keep GPIO15 o sea D8 LOW y GPIO2 D4 HIGH
Pero eso lo hace la placa, no deberías tener que hacerlo a menos que este mal soldada y en todo caso D3 no tiene nada que ver a menos que SI tengas algo mal soldado porque leo que es SPI_CS2 y podria tener que ver con una EEPROM que no se esta habilitando correctamente.
Este es el link que debe pegarse en preferencias.
http://arduino.esp8266.com/stable/package_esp8266com_index.json
Coincide con el tuyo?
SI no coincide cámbialo y sigue los pasos para restaurar las cosas debidamente.
Te aseguro que todo funciona como un reloj.

En cuanto al link de preferencias, si, es el que tengo, ademas tengo actualizada la librería para el esp 8266. Te aseguro que he buscado y no he encontrado solución ni respuesta, es por ello que aqui lo pregunto. En cuanto ha la página de Luis Llamas, suelo tomarla como referencia para resolver dudas y cualquier problema, pero si al leido la entrada que me indicas no dice nada de lo que intento solucionar. Lo de los pines y su función principal también lo he visto y utilizo porque al llevar poco tiempo con esta placa aun no estoy muy familiarizado con las funciones de los pines. Sospecho segun todo lo que he leido que debe ser algo de configuración, pero como no consigo dar con la tecla he decidido pedir ayuda.

Obviamente no tienes otro Wemos Mini no?

Otro wemos mini no tengo.
Como información (que creo que puede ser util) bajando la velocidad de subida he conseguido cargar alguna vez, otras no apareciendo el mismo error: compila y despues intenta conectar hasta que lanza el siguiente error: esptool.FatalError:Failed to connect to ESP 8266: Invalid jead of packet(0x01) (he buscado en Google ese error pero no he conseguido solucionar el problema).

Cuando hago la conexión D3-GND despues de terminar de cargar indica lo siguiente en la ultima linea: Hard resetting via RST pin...

Intuyo que ese puente D3-GND es el que provoca ese Hard resetting y me permite cargar siempre sin problemas....¿Como poder hacer ese hard resseting sin tener que conectar el cable??? O como puedo subir sketch sin tener que realizar ese hard resseting???

Gracias por toda la ayuda y tiempo dedicado.

Tu placa tiene algo mal.
Ese hard resetting lo tendria que hacer por su cuenta.
Revisa soldaduras con una lupa
Si ves alguna mal simplemente pon el cautin y repásala. De hecho hacerlo con cuidado no le hará ningun daño.

¿Que soldaduras? Yo no veo ninguna, ¿Te refieres a soldadura de componentes (resistencias, chips, etc.) Soldaduras solo tiene las de los pines y esas estan bien. Dices que tiene algo mal pero ¿Puedes sospechar que es? ¿o sabes que lo que esta mal es una soldadura seguro? ¿Si hay algo mal no debería de dar el error siempre y no dejar subir el sketch nunca??? ¿¿Porque ha veces si me permite subirlo sin error?

Entonces lo mejor que puedo decirte es que consigas otro y que hagas comparaciones.

Tengo mismo problema que el tuyo con el mio.
Pero peor , porque funciona bien cuando quiere. Y si el mio siempre que subo un sketch me tira diciendo a lo ultimo que haga el reset manual , pero en realidad si hace el reset automatico y arranca solito . Pense que era el arduino ide que por default te decia eso.
Bueno , lo que me paso es que deje ese D1 mini en un proyecto de una persinana , funciono lo mas bien por unas semanas y ayer murio. Lo saque y al querer subir de nuevo el sketch me saltaba todo el tiempo que no se podia comunicar . por ahi lo intentaba mil veces y en una lo subia pero despues se tildaba al arrancar . Lo que hice fue limpiarlo muy bien primero y despues darle aire caliente por un rato. volvi a conectarlo a la pc y perfecto subio el sketch . Lo puse en marcha , andaba toda la primer parte , pero se me tildaba cuando el servidor se conectaba a internet. Al otro dia volvi a encenderlo y perfecto. lleva mas de un dia funcionando con la persiana. Tenia otro arduino nano que me daba exacto mismo problema y lo revivia de la misma manera. Me parece que las placas estas chinas estas viniendo con problemas de soldadura.
Como te dijeron arriba hay que conseguir una buena lupa y mirar las soldaduras del Chip ESP a la placa , tal vez alguna de ellas estan con problemas.

Disculpad por subir este post. Uso bastante el esp8266 de diferentes fabricantes (muchos chinos). alguno que otro me hizo cosas raras pero yo siempre siempre utilizo OTA para subir los sketch. es muy rápido y me suele funcionar bien la subida del sketch por la wifi y creo que es más cómodo. Además suelo meterles las librerias para detectar problemas (ESPCrash, incluso página web para que vuelque el último "crash", etcetc)
Saludos

@DanX3 hacete si podés un tuto de ESPCrash, aunque si lo busco claramente lo encuentro. Interesante aporte!!

que interesante.
Estaria genial tener algunos ejemplos.

Esta librería esta bastante buena

Hola,
Os paso un ejemplo así como preliminares de qué hay que instalar en Arduino IDE:
Necesitamos 2 cosas instaladas en el IDE:

El primero sirve para poder decodificar el error y que te diga en qué linea ha sido. Lo guarda en la EEPROM.

El segundo sirve para poder enviar el programa (sketch) por la WiFi pero también puede enviar otros datos como imágenes, ficheros html, etc directamente a la wemos. Si queremos enviar ficheros, dentro de nuestra carpeta de proyecto donde tengamos el .ino deberemos tener una carpeta "data" donde meteremos diferentes cositas que necesitamos. por ejemplo yo la uso para poner el index.html, favicon.ico, etc etc aunque en el ejemplo que os paso no hago uso de estas funcionalidades.
Tened en cuenta que yo suelo usar la ESP8266 incluso como servidor FTP donde guardo ficheros de logs etc.

Una vez que lo tengamos instalados los dos plugins, en el menú del Arduino IDE debe aparecer en Herramientas así:


Observad que están los dos instalados, el ESP Exception Decoder y el ESP8266 Sketch Data Upload.

Para el .ino que os paso, hago uso de watchdog por lo que si no lo conocéis aquí paso un link que sin mirar mucho he encontrado en internet: watchdog

Lo primero que hacemos es pasar este .ino de ejemplo a la wemos por su cable usb (puerto serie) como cualquier otro.
La primera vez hemos de hacerlo así, después ya podemos usar OTA:

Perdón, antes de pasarlo hay que cambiar los datos de la WiFi así como la IP y puerta de enlace por alguna vuestra. para este ejemplo NO he usado DHCP, lo siento: no es mi cometido enseñar aqui sobre esp y wifi o redes.

Una vez pasado, en el monitor serie aparecerá que ya está funcionando:
2

ahora abriremos la página según la IP con /index al final.
En mi caso abro http://10.0.0.123/index.html
y aparecerá esto:


Habrá que "formatear" la eeprom por lo que daremos al link que dice "borrar o inicializar la eeprom para guardar crash".
Esto lo tendremos que hacer la primera vez y siempre que nos de un error es conveniente hacerlo para que pueda guardar otro nuevo dado que no suele tener espacio para más de 1 error (a veces me ha guardado más pero no os lo recomiendo).


Le daremos atrás al navegador para ir otra vez a index.html.

¿cómo subir un nuevo sketch?
Fácil, ahora cuando lo modifiquemos, por ejemplo he añadido esta línea en el index.html (linea 199 aprox):

  clienteWeb.print(F("<H1>Test ESP SaveCrash y otros</H1>"));  ///añadida!

Si queremos subir el sketch por la wifi daremos buscaremos el nombre que tiene. más o menos en la línea 64:

    //activar el actualizador OTA (over the air)
    ArduinoOTA.setHostname("testOTA"); //mi nombre que mostrará el IDE de Arduino

En el Arduino IDE aparece un nuevo puerto así:

Y ya tendremos siempre ese puerto (cuando la wemos esté activa, claro).
Una vez transmitido, operar como siempre.

¿como usar savecrash?
pues si accedemos a la web index.html (ver anteriores capturas), tenemos dos ejemplos.
Si fuerzo el de nullpointer, la Wemos se resetea y en la web index.html cambia el mensaje inicial que decía que era "external system" por este otro:

Y si damos sobre "ver reporte último crash":

Seleccionamos y cortamos el texto que aparece en el recuadro rojo.
Vamos al arduino IDE (si lo teníamos cerrado hemos de abrir el .INO y compilarlo primero).
Y damos a ESP Exception Decoder que está en el menú Herramientas:

y pegamos con Control+V el texto recortado de la página web:

Vemos el volcado de la pila de llamadas donde el primero es el Loop del fichero otaespsavecrash.ino en la línea 245 que en mi caso es esta:

*b=a; //esto nos dará una excepción al escribir en la zona de memoria reservada

El .INO de ejemplo que he realizado (lo he llamado otaespsavecrash.ino) se puede mejorar pero no tengo mucho tiempo:

/* OTA ESPSaveCrash test -  Dan_X3 
 *  
 *  Descripción de proyecto:
 *  Este proyecto es unicamente para poder realizar pruebas de: 
 *  OTA (Over The Air) actualizar por la wifi el sketch
 *  ESPSaveCrash Para poder probar la funcionalidad
 *  
 * Creado con Arduino 1.8.16
 * Sobre placa Wemos D1 mini
 * Compilar, en mi caso, como Generic ESP8266 Module, 
 * Upload speed: 115200
 * Cpu freq.: 80mhz
 * Cristal freq.: 25mhz
 * Flash size: 4M (3M LittleFS)          ///atencion!!! si no se utiliza 4M/3MLittleFS, no subirá por OTA !!!
 * Flash mode: DOUT (compatible)
 * Flash freq.: 40mhz
 * Reset Method: "ck"
 * Debug port: disable
 * Debug level: none
 * IwIP Variant: v2 lower memory 
 * VTables: flash
 * Exceptions: disabled
 * Build in led: 2
 * Erase flash: only sketch
 * Espressif FW: nonos sdk 2.2.1 (legacy)
 * SSL support: all ssl chipers (most compatible)
 * 
 * Revisiones:  
 * 26/09/2022 - Versión inicial
 * 
 */
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <EEPROM.h>
#include <ArduinoOTA.h>  //para poder actualizar el .ino del wemos sin conectar al usb (por la wifi)
#include <EspSaveCrash.h> //en caso de excepcion que se pueda recuperar el error de la EEPROM y trazarlo

const char* ssid = "el nombre de mi wifi";      //SSID de la WiFi a conectarse
const char* passwordwifi = "la contraseña de mi wifi"; //Password de la wifi
int mip[4]={10,0,0,110};                 //ip que tendrá la wemos (para las pruebas poner una ip fija mejor)
int mgateway[4]={10,0,0,1};              //puerta de enlace(IP del router)
int msubnet[4]={255,0,0,0};              //máscara de red de la wemos (normalmente 255.255.255.0, en mi caso uso clase A, 255.0.0.0)
int mdns[4]={10,0,0,1};                  //ip del servidor dns (normalmente la IP del router)
const unsigned int serverport=80;        //puerto TCP por donde se accederá por web a la placa Wemos
WiFiServer servidorWeb(serverport);      //servidor web de WeMos por el puerto 80
String peticionWeb ="";                  //cadena donde se guarda la petición web (url invocada)

int wstate=0; //estado de la WiFi (connected/failed,..)
int wifidisconnected=0;
int counter=0; //aqui llevamos el contador de reintentos de conexión que hace SETUP()
int counterb=0; //idem al anterior (usados para imprimir puntitos por el serial para ver la conexión

//savecrash para poder monitotizar excepciones por la web
 EspSaveCrash SaveCrash; //manejador del ESP SaveCrash donde se guardarán los errores

//establecer la configuración de pines, redes, etc...
void setup() 
{
    //Inicializar puerto serie   
    Serial.begin(115200);
    Serial.println("\n\n"); //limpiar salida serie
    
    //activar el actualizador OTA (over the air)
    ArduinoOTA.setHostname("testOTA"); //mi nombre que mostrará el IDE de Arduino
    //ArduinoOTA.setPassword((const char *)"w"); //si tiene password, no puede subir los ficheros al sketch (html, etc etc) por un bug, creo
    ArduinoOTA.onStart([]() { Serial.println(F("Comienzo OTA.")); }); //cuando empieza transmisión OTA (hacer las tareas necesarias)
    ArduinoOTA.onEnd([]() { Serial.println(F("\nFin OTA.")); }); //idem cuando finaliza OTA (por ejemplo formatear, guardar datos en EEPROM, etc)
    ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) 
    { 
      Serial.print(F("Progreso OTA: "));
      Serial.print((progress / (total / 100)));
      Serial.println("\n");  
    });
    ArduinoOTA.onError([](ota_error_t error)  //gestionar errores OTA
    {
        Serial.print(F("Error "));
        Serial.print(String(error));
        Serial.print(":");
        if (error == OTA_AUTH_ERROR) Serial.print(F("Error contraseña"));
        else if (error == OTA_BEGIN_ERROR) Serial.print(F("Fallo al iniciar"));
        else if (error == OTA_CONNECT_ERROR) Serial.print(F("Fallo al conectar"));
        else if (error == OTA_RECEIVE_ERROR) Serial.print(F("Fallo al recibir"));
        else if (error == OTA_END_ERROR) Serial.print(F("Fallo de finalización"));
    });
    
    ArduinoOTA.begin(); //activamos OTA: esto hace que desde Arduino IDE ya pueda aparecer el dispositivo

    //inicializar el watchdog
    ESP.wdtEnable(5000); // 5 segundos de watchdog. para Test es correcto, para productos finales hay que estudiar las necesidades
    ESP.wdtFeed();
    
    Serial.println(""); //limpiar la salida serie del wemos
    Serial.flush();
    Serial.println(F("Product:OTA ESP SaveCrash ejemplo v1.0"));
    Serial.println(F("Release:26/09/2022 Dan_X3"));
    Serial.flush();
    Serial.println("Mensaje anterior reset:"+ESP.getResetInfo()); //porqué se reinicó antes !!! muy útil para saber si fue por una excepción o no
    

  
    // Conectar WiFi
    char HostName[32];
    sprintf(HostName, "testOTAySC-%06X", ESP.getChipId()); //poner el nombre que tendrá en la red wifi (como ocurre con los PC's)
    wifi_station_set_hostname(HostName);
    WiFi.hostname(HostName);
  

    ESP.wdtFeed(); //watchdog para evitar reset
  
  // IP estatica si se necesita:
  IPAddress ip(mip[0],mip[1],mip[2],mip[3]);
  IPAddress gateway(mgateway[0],mgateway[1], mgateway[2], mgateway[3]);
  IPAddress subnet(msubnet[0], msubnet[1], msubnet[2],msubnet[3]);
  IPAddress dns(mdns[0],mdns[2],mdns[2],mdns[3]);
  IPAddress dns2('8','8','8','8'); //se necesita 2 DNS para el NTP, si no, no funciona con con ip estática (bug NTP)
  WiFi.config(ip, gateway, subnet,dns,dns2);  //configurar la WiFi

  
  WiFi.begin(ssid, passwordwifi); //conectar a la WiFi 
  counter=0;
  
  //esperamos a la WiFi que conecte
  wstate=WiFi.status();
  while (wstate != WL_CONNECTED) 
  {
    ESP.wdtFeed();
    delay(250);
    if (wstate==WL_NO_SHIELD) Serial.println("No tiene chip WiFi?");
    if (wstate==WL_IDLE_STATUS) Serial.println("Chip WiFi no responde?");
    if (wstate==WL_NO_SSID_AVAIL) Serial.println("WiFi no encuentra SSID?");
    if (wstate==WL_SCAN_COMPLETED) Serial.println("WiFi busqueda completada?");
    if (wstate==WL_CONNECT_FAILED) Serial.println("WiFi fallo de conexion?");
    if (wstate==WL_CONNECTION_LOST) Serial.println("WiFi perdida conexion?");
    //if (wstate==WL_DISCONNECTED) Serial.println("WiFi desconectada");
    ArduinoOTA.handle();
    counter++;
    if (counter==20)
    {
      counter=0;
      Serial.print(".");
      counterb++;
      if (counterb==8) 
      {
         ESP.restart(); //demasiados reintentos, reiniciamos ESP !!!
      }
    }
    wstate=WiFi.status();
    ESP.wdtFeed(); //watchdog que no se olvide
  }

  //comenzar servidor http:
  Serial.println(F("Activando servidor HTTP..."));
  servidorWeb.begin();

  
  //todo listo, finalizamos configuración
  ESP.wdtFeed();
  
  Serial.println(F("Configuración SETUP terminada. Servidores iniciados.")); 
} //fin setup()

/* loop principal */
void loop() 
{
    WiFiClient clienteWeb = servidorWeb.available(); //manejador del cliente web conectado

    //dar tiempo a los manejadores:
    yield();
    ESP.wdtFeed();    //watchdog !!! siempre en el loop
    yield();
    ArduinoOTA.handle();    //por si hay que actualizar por OTA
    yield();

    wstate=WiFi.status();    //asegurar que hay WiFi conectada:
    
    //comprobar que la WiFi siga conectada
    if  (wstate != WL_CONNECTED) 
    {
       Serial.println(F("WiFi desconectada?"));
       wifidisconnected++;
       if (wifidisconnected>100) ESP.restart(); //demasiado tiempo sin WiFi, reiniciar el ESP
    }
    else
    {
       wifidisconnected=0;
    }

    if (clienteWeb) 
    {
        peticionWeb = clienteWeb.readStringUntil('\r');  //guardamos la url invocada
        Serial.println(peticionWeb);
        if (peticionWeb.indexOf("index.htm")>0) //aparece index.html o index.htm?
        {
              clienteWeb.println(F("HTTP/1.1 200 OK"));
              clienteWeb.println(F("Content-Type: text/html"));
              clienteWeb.println(""); //no olvidar mandar una linea en blanco !
              clienteWeb.print(F("<!DOCTYPE HTML><html><head><title>Test ESP SaveCrash y otros</title></head><body>"));
              //clienteWeb.print(F("<script type=\"text/javascript\">setTimeout(function(){window.location=\"test.html\";}, 180000);</script>"));
              clienteWeb.print(F("<H1>Test ESP SaveCrash y otros</H1>"));  ///añadida!
              clienteWeb.print(F("<br><hr><br>"));
              clienteWeb.print(F("Memoria libre (bytes):<br>"));
              clienteWeb.print(ESP.getFreeHeap());
              clienteWeb.print(F("<br><hr><br>"));
              clienteWeb.print("Mensaje reset anterior:<br>"+ESP.getResetInfo());
              clienteWeb.print(F("<br><hr><br>"));
              clienteWeb.print(F("<a href='reporte.txt'>ver reporte del &uacute;ltimo crash</a>"));
              clienteWeb.print(F("<br><hr><br>"));
              clienteWeb.print(F("<a href='borrarcrash.txt'>borrar o inicializar la eeprom para guardar crash</a>"));
              clienteWeb.print(F("<br><hr><br>"));
              clienteWeb.print(F("<a href='forzarcrash1.txt'>forzar un 'crash' de puntero nulo</a>"));
              clienteWeb.print(F("<br><hr><br>"));
              clienteWeb.print(F("<a href='forzarcrash2.txt'>forzar un 'crash' por watchdog</a>"));
              clienteWeb.print(F("<br><hr><br>"));
              
              clienteWeb.println(""); //no olvidar mandar una linea en blanco
        } 
        if (peticionWeb.indexOf("reporte.txt")>0) //volcar el reporte
        {
              clienteWeb.println(F("HTTP/1.1 200 OK"));
              clienteWeb.println(F("Content-Type: text/plain"));
              clienteWeb.println(""); //no olvidar mandar una linea en blanco
              clienteWeb.println(F("Crash Report (cortar y pegar en el IDE desde el 'begin' al 'end'):"));              
              clienteWeb.println(F("===========begin"));
              clienteWeb.println(""); //no olvidar mandar una linea en blanco
              SaveCrash.print(clienteWeb);
              clienteWeb.println(""); //no olvidar mandar una linea en blanco
              clienteWeb.println(F("===========end"));
              clienteWeb.println(""); //no olvidar mandar una linea en blanco
        }      
        if (peticionWeb.indexOf("borrarcrash.txt")>0) //petición de borrado del último savecrash?
        {
            clienteWeb.println(F("HTTP/1.1 200 OK"));
            clienteWeb.println(F("Content-Type: text/plain"));
            clienteWeb.println(""); //no olvidar mandar una linea en blanco
            clienteWeb.println("Registro de excepciones borrado.");
            SaveCrash.clear();
            clienteWeb.println(""); //no olvidar mandar una linea en blanco
        }
        if (peticionWeb.indexOf("forzarcrash1.txt")>0) //petición de crash por división por cero?
        {
            clienteWeb.println(F("HTTP/1.1 200 OK"));
            clienteWeb.println(F("Content-Type: text/plain"));
            clienteWeb.println(""); //no olvidar mandar una linea en blanco
            clienteWeb.println("intentando realizar excepción...");
            clienteWeb.println(""); //no olvidar mandar una linea en blanco
            clienteWeb.flush(); //forzamos envío y cierre cliente
            int a=0;
            int *b;
            b=(int*)0;
            *b=a; //esto nos dará una excepción al escribir en la zona de memoria reservada
        }
        if (peticionWeb.indexOf("forzarcrash2.txt")>0) //petición de crash por no llamar al watchdog?
        {
            clienteWeb.println(F("HTTP/1.1 200 OK"));
            clienteWeb.println(F("Content-Type: text/plain"));
            clienteWeb.println(""); //no olvidar mandar una linea en blanco
            clienteWeb.println("intentando división por cero...");
            clienteWeb.println(""); //no olvidar mandar una linea en blanco
            clienteWeb.flush(); //forzamos envío y cierre cliente
            while (1){} //morir aqui
        }
        clienteWeb.flush(); //forzamos envío y cierre cliente
        Serial.println(F("Cliente WEB desconectado"));
    }
    
} //loop fin

Saludos.

Se me ha pasado comentar que las subidas por OTA, si hay buena WiFi, son bastantes más rápidas que por serie, pero claro, perdemos el monitor serie si no lo tenemos por USB conectado al PC.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.