Atmega328P: ¿cómo se supone que funciona la detección de caída de tensión?

[SOLUCIONADO][ACTUALIZAR]:

El problema estaba en los fusibles. De alguna manera, los fusibles se escribieron incorrectamente como 0xFE en lugar de 0xFD. FE corresponde a 1,8 V y, por lo tanto, la placa arduino funcionaba hasta 1,8 V. Reinstalé Arduino y comencé todo desde cero y con el código Show Info sugerido por bigjosh, pude verificar los bits del fusible. Configuré el nivel de DBO en 2,7 V y ahora funciona como se esperaba. Microcontrolador que reanuda todas las operaciones una vez que hay suficiente voltaje disponible.

Otra actualización: estaba viendo configuraciones de fusibles extendidas para 1.8V debido a los permisos de escritura de archivos en C:\ en Windows. Aparentemente, el archivo de tableros era de solo lectura y las ventanas no generan errores cuando presiono Ctrl+S. Me hizo pensar que el archivo de las placas se estaba actualizando mientras aún estaba atascado en el nivel predeterminado de BOD de 1,8 V. La segunda vez, elegí instalar en D:\ y todo funciona perfectamente.


Estoy tratando de descubrir cómo usar BOD para hacer que mi proyecto arduino sea más robusto, pero parece ser otro problema. Mi sistema funciona con 3,3 V, por lo que elegí establecer el nivel de DBO en 2,7 V (fusibles extendidos = 0x05).

Solo como prueba de banco, cargué un código de impresión en serie que imprime "Iniciado" cuando el microcontrolador se inicia por primera vez y luego "Trabajando" después de cada medio segundo.

El experimento fue encender el atmega usando una fuente de alimentación de banco y monitorear el texto en serie en una PC. Esperaba que sucediera algo extraño una vez que el voltaje baje de 2.7V. No pasó nada hasta 2.2V. Por debajo de 2.2V, había múltiples escenarios:

(Configuración experimental: no utilicé la placa arduino. Lo construí en una placa de prueba separada y el voltaje se alimentaba directamente mediante el uso de una fuente de alimentación de banco. Había tapas de filtro: 300 uF 16V cerca de los pines IC. El serial estaba conectado a la PC. directamente sin aislamiento óptico. También se hizo GND común.)

Caso 1: el microcontrolador se restableció varias veces y siguió funcionando normalmente a 2,1 V aproximadamente. Al reducir aún más, dejó de imprimir. Al aumentar el voltaje, nunca volvió a un estado de funcionamiento normal. El reinicio externo lo llevó al estado normal.

Caso 2: Siguió imprimiendo algunas cosas aleatorias en serie hasta que bajé aún más el voltaje, momento en el que dejó de imprimir. No reanudó la impresión incluso después de que el voltaje se elevara a niveles normales. El reinicio externo lo llevó al estado normal.

Caso 3: Se reinició varias veces y siguió imprimiendo "Wmrkmng". En ese momento, comencé a elevar el voltaje a niveles normales (3,3 V), pero seguía imprimiendo texto incorrecto. El reinicio externo lo llevó al estado normal.

Mi expectativa era que cuando se detecta un apagón, el microcontrolador se apagaría (todos los GPIO BAJOS y UART no imprimían nada, similar al microcontrolador apagado) y tan pronto como el voltaje se normalizara, actuaría como si se hubiera encendido. desde un estado APAGADO. Sin embargo, los resultados son totalmente diferentes. Como tal, si lo uso en un producto y, por alguna razón, se produce un apagón, la única forma conveniente de ponerlo en condiciones de funcionamiento es apagarlo y volver a encenderlo para que reciba la señal de encendido y reinicio. Definitivamente tal procedimiento no será aceptable en muchos casos (incluido el mío). Como tal, ¿qué debo hacer para evitar tal estado de bloqueo? No estoy seguro de que incluso el perro guardián sea de mucha ayuda (considere el caso 3: la mayor parte del código funcionaba. ¿Qué pasa si WDT no ve ningún problema y deja que el microcontrolador funcione de la manera en que lo está haciendo?).

(Editar: WDT falló en algunos casos como se esperaba)

No pude encontrar mucho en la hoja de datos de Atmel, pero encontré una pregunta de intercambio de pila aquí que describe un problema similar para la familia PIC.

(Edición 2: mientras esperaba las respuestas a esta pregunta, realicé algunas otras pruebas que no involucraron ninguna conexión externa en absoluto. Eliminé la serie y cargué un código simple para hacer parpadear un LED a 1 Hz cuando un pin estaba ALTO y a 5 Hz cuando el pin pasó a nivel BAJO. Incluso este código no funcionó. Los resultados en este caso se pueden comparar con los casos 1, 2 y 3. También probé WDT. Sin beneficio. Una cosa extraña que noté. fue que a pesar de que estaba cambiando la configuración del cargador de arranque para establecer diferentes niveles de BOD: 1.8V, 2.7V y 4.5V, el código solía fallar en alrededor de 2.2V en todos los casos). Aquí está la definición de arduino:

uno.name=Arduino Uno

uno.vid.0=0x2341
uno.pid.0=0x0043
uno.vid.1=0x2341
uno.pid.1=0x0001
uno.vid.2=0x2A03
uno.pid.2=0x0043

uno.vid.0x2A03.warning=Uncertified

uno.upload.tool=avrdude
uno.upload.protocol=arduino
uno.upload.maximum_size=32256
uno.upload.maximum_data_size=2048
uno.upload.speed=115200

uno.bootloader.tool=avrdude
uno.bootloader.low_fuses=0xFF
uno.bootloader.high_fuses=0xDE
uno.bootloader.extended_fuses=0x05
uno.bootloader.unlock_bits=0x3F
uno.bootloader.lock_bits=0x0F
uno.bootloader.file=optiboot/optiboot_atmega328.hex

uno.build.mcu=atmega328p
uno.build.f_cpu=16000000L
uno.build.board=AVR_UNO
uno.build.core=arduino
uno.build.variant=standard

Cambié los bits de fusibles extendidos a 0x04, 0x05 y 0x06 para probar los tres niveles de DBO.

Código básico de parpadeo de LED utilizado para probar:

int ledPin = 17;
int inputPin = 2;


void setup() {
  // put your setup code here, to run once:
//  Serial.begin(115200);
//  Serial.println("BOOT");
  pinMode(ledPin,OUTPUT);
  pinMode(inputPin,INPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
//  delay(500);
//  Serial.println("XXXXXXXXXX");

  if (digitalRead(inputPin)==1)
  toggle(17,1000);
  else if (digitalRead(inputPin)==0)
  toggle(17,200);
}

void toggle(int pin_number, long int delay_time)
{
  digitalWrite(pin_number, HIGH);
  delay(delay_time);
  digitalWrite(pin_number, LOW);
  delay(delay_time);
}
¿Está utilizando una placa Arduino real? ¿Cuál? Estas placas suelen tener un regulador de voltaje. ¿Está alimentando el chip a través de ese regulador o directamente al pin Vcc?
¿Código? ¿Esquema (qué pin(es) conectado(s) a la alimentación/LED)?
¿Cómo estás quemando los fusibles en el chip de destino? ¿Usando avrdude directamente? ¿Quemar el gestor de arranque en el IDE de Arduino? ¿Tal vez intente ejecutar un pequeño programa de prueba que verifique los fusibles en tiempo de ejecución para verificar la suposición de que los fusibles se están configurando?
Esa parece una gran idea porque tengo algunas dudas sobre si los fusibles están funcionando como se esperaba. Idealmente a BOD = 4.5V, no debería haber podido bajar a 2.2V. ¿Funcionará esa muestra de código en el entorno arduino? Estoy cargando el cargador de arranque usando otro arduino Uno programado como Arduino ISP.
RE: ¿Funcionará ese ejemplo de código en el entorno arduino? Este boceto ShowInfo Arduino debería imprimir los bits de fusible actuales.

Respuestas (1)

El detector de caída de tensión pondrá el chip en modo de reinicio si el voltaje en el pin Vcc cae por debajo del umbral. Cuando se reinicia, todos los pines GPIO entran en modo de alta impedancia y no se ejecuta ningún código. Cuando el voltaje de suministro vuelve a subir por encima del umbral durante un período mínimo de tiempo, el chip saldrá del reinicio y comenzará a ejecutar el código en el vector de reinicio, similar a un inicio normal.

Tenga en cuenta que muchas placas Arduino tienen circuitos de alimentación adicionales como un regulador de voltaje. Esto significa que el voltaje que le suministre a la placa Arduino podría no ser el voltaje que el chip real ve en su pin Vcc. Puede usar un voltímetro para verificar el voltaje real que se ve en ese pin, así que vea si coincide con lo que espera.

También tenga en cuenta que los chips AVR tienen diodos de sujeción en sus entradas, por lo que si un pin GPIO está conectado a un voltaje más alto que el pin Vcc, entonces el chip puede continuar siendo alimentado desde el pin de entrada. Me encontré con un error muy interesante debido a esto...

https://wp.josh.com/2014/03/03/el-misterio-del-carnero-zombie/

¿Cómo estás haciendo tu conexión serial al chip? ¿Es posible que entre energía a través de esa conexión?

Solo para simplificar las cosas mientras resuelve esto, es posible que desee intentar sacar el chip del Arduino y ponerlo solo en una placa de prueba para que pueda controlar la energía directamente. También es posible que desee deshacerse de la conexión en serie y, en su lugar, usar un LED parpadeante para indicar si el programa se está ejecutando o está detenido.

Finalmente, verificaría la suposición de que los fusibles se configuran como se esperaba durante su proceso de programación. Puede usar avrdudepara leer los fusibles del chip programado para ver si son lo que desea, intente leer los fusibles en tiempo de ejecución a través del software , o simplemente intente cambiar la velocidad del reloj a través de los fusibles, programando el chip con su código parpadeante, y luego verificando que la tasa de parpadeo haya cambiado para ser consistente con la nueva configuración del fusible.

Una vez que obtenga el BOD esperado que funcione como se esperaba, puede comenzar a agregar complejidad nuevamente para encontrar el problema.

+1 para alimentación fantasma en serie: esto provoca todo tipo de errores extraños.
Gracias bigjosh por responder. He descrito la configuración experimental en la pregunta ahora. Chip estaba en una placa de prueba separada. No se estaban utilizando reguladores. Las mediciones de voltaje se estaban realizando en los pines del IC. La serie podría haber sido un problema, así que probé la configuración haciendo parpadear un LED. Mi microcontrolador tampoco se recuperó en este caso.
BOD definitivamente funciona, por lo que hay algo idiosincrásico en su configuración que está causando el problema. Con suficiente información, puedo volver a crear su configuración y ver si también vuelvo a crear el problema.
@bigjosh - Muchas gracias hombre. Con el código que sugirió, pude verificar dónde me estaba equivocando. Mis bits de fusibles correspondían a 1.8V a pesar de que probé diferentes niveles. Una nueva instalación de arduino y una nueva grabación del cargador de arranque seguida de una verificación simplificaron las cosas. Que tenga un lindo día. :)