TODOPIC
Microcontroladores PIC => Todo en microcontroladores PIC => Mensaje iniciado por: DarkVect en 19 de Febrero de 2007, 17:23:07
-
Hola,
A raíz de este post http://www.todopic.com.ar/foros/index.php?topic=13890.0 en el que se discute sobre la forma de realizar un reset completo del PIC, me ha entrado una duda acerca del uso o no del WATCHDOG.
¿Es realmente necesario proteger el sistema frente a un "cuelgue" del PIC? ¿Qué probabilidades hay de que se "cuelgue"? Hasta el momento siempre lo he dashabilitado y no he tenido ningún problema jamás de que una aplicación se quede colgada, pero me ha entrado el miedo!!
¿Es aconsejable ponerlo? ¿En qué casos?
Gracias a todos!!
-
Hablando en funcion de la corta experiencia que llevo haciedo "cacharros" profesionalmente puedo decirte que:
* En el laboratorio no hace falta el WachDog para nada.
* En el mundo real de las interferencias, los ruidos, las condiciones reales en las que tienen que funcionar si que hace falta.
Cuando un PIC, y toda la electrónica que lo rodea, se monta en entornos de motores,variadores de frecuencia, cargas reactivas, líneas de alimentación alterna, emisores de todo tipo de radiofrecuencias y campos electromagnéticos y hasta cargas estáticas, cuando el PIC se conecta a sensores, o a otros dispositivos electronicos, o incluso a su propia fuente de alimentación está rodeado de antenas que recogen absolutamente todo lo que pueda perturbarles.
En entornos de este tipo lo extraño es que funcione bien. Es imprescindible un diseño cuidadoso de nuestra PCB, con sus planos de masa, sus condensadores de desacoplo, (ver el magnifico articulo de Chaly sobre el tema), es imprescindible también afinar el firmware para que deseche o descarte los ruidos que puedan interferirlo, es imprescindible usar líneas con malla para evitar que las señales se contaminen de ruidos ...
y si todo falla es necesario disponer de un watchdog que vuelva a colocar al PIC en orden de marcha.
Al menos esa ha sido mi experiencia en dos de cada diez casos a los que me he enfrentado. Y según me dicen los fabricantes de otros equipos con los que integro los míos esto va e irá siempre a peor.
-
¿Es aconsejable ponerlo? ¿En qué casos?
Yo diría que desde que Murphy publicó sus leyes siempre es aconsejable. Al fin y al cabo no cuesta nada ponerlo y si nunca tiene porqué funcionar, pues no está de sobra.
-
Queda claro que es recomendable ponerlo por si acaso.
Lo he probado pero no me funciona bien.
El código es este:
#include <16LF84A.h> //pic a utilizar
#fuses XT, WDT, NOPROTECT, PUT //ordenes para el programador
#use delay (clock=3276800) //Fosc=3,2768Mhz
#use fast_io(a)
#use fast_io(b)
//Funciones de interrupción Timer0 e INT_EXT
void main(void)
{
disable_interrupts(GLOBAL); //deshabilitar interrupciones
ext_int_edge(H_TO_L); //interrupcion en flanco de bajada
setup_TIMER_0(RTCC_INTERNAL | RTCC_DIV_128); //preescaler=128 para 1seg
setup_wdt(wdt_18ms);
set_tris_a(0b00000000); //porta todo como salida
set_tris_b(0b11111111); //portb todo como entrada
enable_interrupts(INT_EXT); //interrupcion del reed del anemo
enable_interrupts(INT_TIMER0); //interrupcion del contador
enable_interrupts(GLOBAL); //interrupciones activadas
do
{
restart_wdt();
actividades();
}while(TRUE);
}
Actividades() lo forman pocas instrucciones que duran mucho menos que los 18ms del Watchdog pero el PIC se va reiniciando. Según he leído en el Datasheet no puedo escalar el Watchdog porque ya estoy usando el preescaler para el Timer0 y en el 16F84 es incompatible escalar ambos.
-
Me sumo a las sugerencias de los amigos Diego y Manolo de aconsejarte el uso del Watchdog. Vivimos a miles de km de distancia y aún así hemos llegado a las mismas conclusiones que no las relataré ya que el amigo Diego las expuso en forma breve y precisa.
Los tiempos del watchdog son bastante precisos, ¿qué tanto más pequeño que 18mseg es esa funcion actividades?
¿Acaso no tienes algún salto a interrupción que pueda demorar su tiempito? Ojo con esto. También si tienes algún delayms(20) bueno, esto es candidato a que ocurra un watchdog :)
El uso del watchdog preveé de cuelgues en el hardware por causas externas pero no evitará que tu software haga cualquier cosa si está mal hecho. Y depende donde pongas el reset del watchdog (por ej, si lo ubicas en un vector de interrupción activado por un timer) nunca se reseteará no importa qué cosas hagas en el código normalmente (excepto desactivar el GIE).
Saludos
-
Hola DarkVect!
Fíjate hasta donde llega mi nivel de paranoia con los cuelgues de los PIC´s que mira lo que hago en todos mis programas (los que ven la luz de forma comercial claro).
http://www.todopic.com.ar/foros/index.php?topic=12418.0
No me atrevo a sacar ningún equipo al mercado sin hacerle esto. Es muy paranoico poor mi parte pero... por las noches duermo a pierna suelta sabiendo que hardware/software es incolgable jeje.
PD: Núnca se sabe donde se van a colocar nuestros cacharros. Imagínate que alguien lo pone justo encima de una máquina de soldadura por arco o... en cualquier otro sitio peor :D
Un saludo desde Alicante.
-
do
{
restart_wdt();
actividades();
}while(TRUE);
}
Prueba lo siguiente en este fragmento de código, sustituye actividades(); por algo como encender y apagar un LED o hacer sonar un piezo, lo que te propongo es que compruebes si tu WD realmente está reseteando al PIC o eres tú el que se pasa de tiempo. Si actualmente estás simulando o tienes un debugger en caliente, entonces te darás cuenta rápidamente, sino es así te aconsejo poner una demora antes de activar el WD y correr el código que sustituye a actividades();
De todas formas creo que es muy probable que te estés pasando del tiempo de restart del WD. Por ejemplo si usas un printf(), es muy probable que te pases de ese tiempo, una función con demoras, pues también te pasas con facilidad de ese tiempo, 18ms no es mucho tiempo, así que tienes que hilar bien fino tu código para resetear el WD antes de que el sea el que te resetee al uC.
Lo esencial que debes conocer al trabajar con un WD, es que se parece al PacMan, (un juegito viejo que muchos foreros arcanos conocen y otro no tanto también). Pues en ese juego debes correr y correr...... y hacerlo muy bien, para que no te coman. En tu caso es lo mismo, si tu código no le da tiempo a la función que resetea el WD para que haga su trabajo, te aseguro que el WD no tendrá piedad y adiós.
Por ejemplo: pónte como meta que cada tarea que ejecutes lo haga en menos de 15ms antes de llamar a restart_wdt(), así le dejas tres a restart_wdt(), al do...while() para que compruebe la expresión lógica y te queden algunos us de respaldo para cualquier ruta crítica que demore un poquito la ejecución.
Otra cosa que puedes hacer es mover la temporización para otro Timer, así le dejas el preescalador al WD solito y puedes poner un período más largo para el reset. Si no te alcanzan los Timer para dejarle el preescalador al WD, entonces múdate para un uC con más Timers, Microchip tiene tal variedad que eso no será problema.
saludos Reinier
-
Me ha gustado mucho tu mecanismo anti-cosas-raras, Azicuetano.
Me apunto la idea; además también sirve para debuggear los programas.
-
Ivan:
Tengo una instalación que me está volviendo loco ... y tus "checkpoints" van a ser como agua bendita caída del cielo. :mrgreen:
-
Muy bueno el sitema Azicuetano!! lo voy a tener presente.
-
Gracias por las respuestas.
Mañana probaré con un ejemplo básico el funcionamiento del Watchdog a ver dónde me estoy equivocando.
Sólo tengo una duda. Programando en CCS, dónde se asigna el preescaler para el timer0 o para el watchdog? Como veis tengo la función setup_timer_0() en la que se asigna un preescaler para el timer0 pero luego utilizo la función setup_wdt() en la que asigno el periodo del watchdog. Supongo que si en esta última función no pones algo diferente de 18ms el CCS ya se encarga de mantener el preescaler para el timer0 y que si le pones algo diferente lo cambia. Es así? Es necesario poner setup_wdt() si vas a usarlo a 18ms?
Otra cosa que me me "choca" es que teniendo el timer0 preescalado no puedas prácticamente usar la función delay_ms() debido al "pequeño" periodo del watchdog. En un programa más o menos largo habría que refrescarlo cada varias líneas, en cada interrupción o función adicional, etc...
-
Hola gente!
Explicaré un poco mejor de que me han salvado mis 'checkpoints'. Además del caso que he comentado en el link que he puesto un poco más arriba tengo otra situación un tanto curiosa.
Teniamos un equipo que consta de varias PBA´s conectadas entre si. El caso es que una vez me llamó un operario diciendome que una de las PBA´s se reiniciaba cuando se enchufaba el equipo. Era una cosa que núnca me habia pasado y me puse a hacerle pruebas como un loco al cacharro.
Una o dos de cada 10 veces que encendíala el equipo la maldita PBA se reseteaba. Al final me di cuenta que el operario había cortado el cable de alimentación demasiado largo y... se paseaba por encima de la PBA que se reiniciaba (el cable de 220V de la red tocaba la PBA y el lomo del micro).
Mi compañero se estaba comiendo un bocata y... ni corto ni perezoso le pedí el papel de aluminio con el que tenía envuelto el bocadillo. Apantalle la PBA y todo fenomeno paranormal dejó de suceder. Quité el papel de aluminio y otra vez con los reinicios, es decir, era el cable de 220V seguro.
Muy bien... por que os he contado todo este rollazo?? Pues porque mi software tenía implementado el 'checkpoint securty system' jejej y gracias a el la PBA se daba cuenta del salto en el contador de programa debido al ruido y se autorreiniciaba. Cogí una versión del software sin los chequpoint y... puufff!!! como fallaba la cosa. Con el software sin checkpoints en lugar de reiniciarse se pegaba unas colgadas de escandalo.
Entonces fué cuando decidí incluir este sistema en todos mis programas. Así evitamos que el ruido, ya sea por un mal diseño, por una mala colocación del equipo, o por lo que sea que se nos escape del entendimiento electrónico cuadrado que tenemos, nos cuelgue nuestos queridos cacharros.
Otro proyecto en el que puedo contrastar la eficacia de los checkpoints es en una fuente de alimentación que implementé y que tenía unos cuantos relés. Antes de descubrir los truquillos para evitar el ruido de los relés hice un montón de prototipos que fallaban más que una escopeta de feria. Al final conseguí un diseño del cual nunca he detectado nungún cuelgue pero... despues del buen resultado que me dieron los checkpoints decidí implementarlos también en este diseño.
Lo que hize fue... coger el peor diseño que tenía (uno de los primeros que insolé y que tenía un índide de cuelgues sobrehumano) e implementé el checkpoint security system hasta que conseguí que el equipo no se me colgara núnca. Tenía muchísimo ruido por los relés pero lo detectaba y rearmaba la fuente (tan rápido que el usuario no se daba ni cuenta). Cuando el equipo con el diseño malo se paso una semana encendido y funcionando a la perfección, cogí ese software y lo metí en el diseño bueno.
Nunca detecté ningún cuelgue en el hardware final que hice pero ademas... con el nuevo software que ya tenía y que era capaz de soportar tantos cuelgues, mi seguridad en el equipo es total. Se puede colgar? Pues a lo mejor si, pero, la probabilidad es ínfima. Resultado?? Iván duerme a pierna suelta todas las noches sin ningún miedo a que llamen clientes furiosos jejej :D :D
Bueno, os invito a que lo probeis. A mi me da muy buenos resultados.
PD: Diego, intenta implementarlo que ya verás como te puedes evitar un monton de problemas. Puedes hacer 2 cosas:
Cosa 1 -> Cuando detectes que la cuenta de checkpoints no se ha hecho correctamente, llama a una función que se quede en un bucle infinito con algún parpadeo característico y con refresco de Watchdog. Así la próxima vez que veas el equipo podras saber si es por el motivo del ruido los cuelgues.
Cosa 2 -> Cuando detectes que la cuenta de checkpoints no se ha hecho correctamente, llama a una función que resetee el PIC pero antes guarda en la eeprom el número de cuelgues. Así tras unas semanas de funcionamiento podrás distinguir si los cuelgues son por el ruido y el índice de reseteos que ha tenido el equipo.
Ufff... que panzá de escribir jejeje. Un saludo desde Alicante!
-
Estas ideas geniales alegran mi vida :-)
saludos.
-
Azicuetano es probable que en caso ese de la interferencia de los 220V en realidad tuvieras problemas con el oscilador. Si usas un cristal metálico, prueba soldar su chasis a GND.
Saludos
-
COMPROBADO:
El preescaler común del watchdog y del timer0 de algunos PIC se asigna, como era de esperar, al que hace la llamada a su función setup en último lugar. Es decir, si ponemos:
setup_timer_0(...);
setup_wdt(...); //el preescaler es para el watchdog y viceversa para el caso contrario
Lo he comprobado con un led que se encendía al pulsar un botón y debía estar encendido durante 20 segundos temporizados con el timer0. En el main se refrescaba el watchdog constantemente.
Si el preescaler lo utilizaba el timer0 todo iva perfecto. Si éste era para el watchdog el led se encendía y apagaba de inmediato, ya que el timer sin el reescaler daba un periodo muy corto.
Además he añadido una rutina infinita: while(TRUE){} para ver si el watchdog actuaba y todo ha ido bien.
Una pregunta a los que hacéis programas "largos": ¿qué mecanismo usáis para ir refrescando el watchdog? Me refiero a cada cuánto lo hacéis, si lo hacéis también en las rutinas de interrupción, etc...
Gracias a todos!!
-
En mis programas largos, suelo tener un bucle principal del programa. Es ahí donde lo reseteo al watchdog.
No lo hago en el vector de interrupción porque como suelo usar timers para una base de tiempo, me lo estaría reseteando constantemente lo cual no significa que el pic no se haya desviado su rumbo, sino que simplemente cada n milisegundos se resetea el watchdog entonces termina no funcionando para lo que lo quiero hacer funcionar.
Ponerlo 'a cada rato' tampoco es buena idea porque deja de tener efecto. El watchdog es muy útil cuando el pic enloquece porque se cuelga el pic por alguna razón. Nunca me pasó lo que comenta Azicuetano así que no soy el más indicado para comentar su técnica.
Si me pasó por ej. es que teniendo algunos pines de A/D al aire, cada N minutos, se colgaba el pic! así sin más, reveldemente. Se ve que algo tildaba del hardware. El watchdog en esos casos me salvaba del problema.
Pero como te decia antes, no lo ejecuto a cada rato, sino solamente en el bucle principal.
-
Gracias Maunix.
Lo tengo funcionando en un programa más bien pequeño (30% en un PIC 16F84A) pero he puesto 4 restarts del watchdog. Uno en el bucle principal (while(TRUE)), otro en una rutina de inicialización de los parámetros que uso y luego otro en cada función de interrupción. Se que es exagerado, pero de momento ahora funciona, iré quitándolos a ver hasta cuando sigue funcionando.
De todas formas, el problema principal es que al usar el timer0 escalado, el watchdog lo tengo que usar a 18ms y me parecen muy pocos para lo que quiero hacer.
Seguiré informando de cómo va la cosa...
Gracias de nuevo!!
-
Coincido con maunix.
A mi me gusta refrescar el watcdog en el bucle principal (y si es posible sólo una vez) y no recomiendo el refresco en las interrupciones.
Lo que hago es seleccionar un determinado tiempo en el watchdog y pongo un refresco en el bucle principal. Si el micro se está reseteando continuamente lo que hago es aumentar el tiempo del watcdog hasta que el equipo me funciona bien (o viceversa).
Además de todo esto también me gusta hacer lo siguiente:
Si pasamos por el bucle principal cada 10 ms (aproximadamente) configuro el wdt con 18ms y en el bucle principal (si la aplicación me lo permite) hago un retardo de unos 6 o 7 ms para que mi bucle principal tenga una duración de 17 ms (más o menos). Lo que consigo así es ajustar al máximo el wdt. Parece una tontería pero... por no ajustar bien el wdt en varias ocasiones que he tenido problemas de ruido y el wdt no me los ha solventado (porque se me ha refrescado aún sufriendo un salto el contador de programa).
Un saludo desde Alicante!
-
Bueno pués ya funciona con un solo restart_wdt() en el bucle principal. He eliminado algunos delay_ms que tenía por en medio y he usado el timer para contar esos tiempos.
Una pregunta, supongo que un poco tonta pero... cómo mides más o menos lo que tarda en ejecutarse un fragmento?? Me refiero algo a vista, sin usar timers, ni nada más, una cosa aproximada viendo el código.
Gracias!!
-
DarkVect, son decisiones que uno debe tomar y no puedo opinar si está bien o mal sin conocer tu aplicación.
Como dije antes, nunca me pasó o al menos no noté que el program counter salte como loco, sí me pasó que el pic deje de funcionar o se quede "como tildado", lo cual como dije antes, atribuyo más a un tema de ruido que deje al pic tal vez en un estado de "semi reset" o bien que en realidad afectase al circuito del oscilador del pic y por tanto no siga el curso del programa hasta tanto no se reinicia el pic. Es entonces donde creo que reanuda el oscilador y por eso mi programa sigue funcionando.
Si tu programa no tiene más que hacer que siempre lo mismo y no importa tanto la secuencia cómo el hecho que lo haga, entonces poner muchos clrwdt no está mal. Me explico: si tu programa tiene que por ejemplo refrescar unos 7 segmentos entonces lo más importante ahí es que el pic siga su curso en la ejecución entonces funciona tu técnica. Ahora si se debe seguir cierta secuencia la cual se pierde por algún bug en el código o bien por algún problema externo, entonces si el vector de interrupciones se sigue llamando entonces tu pic no se reiniciará porque justamente es el vector de interrupciones el que lo resetea constantemente.
Cada diseñador embebido debe tomar estas decisiones y responden a tantas variables que es difícil en 2 líneas dar soluciones "generales" a estos problemas más allá de las antes mencionadas.
En mi opinión, hay ciertas cosas que son imprescindibles para un sistema que no deba falla:
- Un buen pcb: si uno la hace en pertinax, es candidato al óxido en unas semanas...
- Un buen circuito de masa: esto aumenta las chances de evitar que cualquier imprevisto de ruido nos afecte en la electrónica de nuestro circuito general
- Un circuito oscilador bien cuidado, tanto en sus conexiones a masa como en evitar las interferencias.
- Un shielding o protección, si es que tendremos o pensamos tener interferencias electromagnéticas, esto sobre todo es importante en el cristal.
- Un buen código: esto es inevitable y si todo lo anterior está bien y esto no, no nos salvaremos de nada :)
Si se me ocurre alguna otra, la agrego ;)
Saludos
-
Gracias por los consejos Maunix.
Me refería a algo así como lo que explicas, algunas pautas para poder decir que el "sistema no fallará". La aplicación es muy sencilla, se trata de un sistemita para medir la velocidad del viento, sin extremada exactitud, para ponerlo en casa y subir toldos, etc... cuando haga mucho viento.
Como digo funciona perfectamente con un solo reinicio del watchdog y creo que le sobra bastante tiempo. Probaré a añadir un delay al final del main para ver cuánto tiempo sobra de forma más exacta.
Un saludo!!