He investigado las opciones de sueño del ATmega328, y leí algunos artículos al respecto, y me gustaría entender si hay más opciones.
Por lo tanto, me gustaría obtener la corriente más baja posible, de modo que cualquier cosa menor a 100uA sería buena, siempre que pueda escuchar uart e interrumpir por despertar.
Estoy usando una PCB personalizada (no la UNO), con ATmega328p.
Configurar el chip para dormir profundamente:
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_cpu ();
De acuerdo con esto , no lo despertaría con la comunicación en serie .
Necesitará ponerlo en IDLE
modo, para escuchar el serial, pero esto consumiría unos pocos mA -bad.
He encontrado este enlace donde puede conectar en hardware la serie a la interrupción, lo cual es peligroso para que pueda perder datos y, además, necesito estos 2 pines de interrupción.
También leí este artículo de Gammon , donde puedes desactivar algunas cosas, para que puedas dormir inactivo con una potencia mucho menor, pero no mencionó cómo exactamente obtienes esto:
power_adc_disable();
power_spi_disable();
power_timer0_disable();
power_timer1_disable();
power_timer2_disable();
power_twi_disable();
Entonces, en resumen, ¿hay alguna opción por ahí, para obtener menos de 0.25mA al menos, y también escuchar el puerto serie, sin ninguna manipulación de hardware? Por ejemplo, ¿despertarse con una entrada de datos en serie larga ?
Respuestas:
Un tablero que hacemos hace esto.
En suspensión, la interrupción INT0 de bajo nivel está habilitada
La rutina de servicio de interrupción INT0 establece un indicador y desactiva la interrupción
Al despertar, verificamos la marca (hay otras fuentes de interrupción)
En el lado de las comunicaciones, usamos un protocolo de mensaje que tiene un carácter inicial
>
y un carácter final\r
. por ej>setrtc,2015,07,05,20,58,09\r
. Esto brinda cierta protección básica contra la pérdida de mensajes, ya que los caracteres entrantes no se procesan hasta que>
se recibe un. Para activar el dispositivo, enviamos un mensaje ficticio antes de la transmisión. Un solo personaje lo haría, pero enviamos>wakeup\r
jeje.El dispositivo permanece despierto durante 30 segundos después de recibir el último mensaje en caso de nuevos mensajes. Si se recibe un nuevo mensaje, el temporizador de 30 segundos se reinicia. El software de interfaz de la PC envía un mensaje ficticio cada segundo para mantener el dispositivo despierto mientras el usuario lo tiene conectado para la configuración, etc.
Este método no ofrece absolutamente ningún problema. La placa con algunos periféricos usa aproximadamente 40 uA cuando duerme. La corriente real consumida por el ATMega328P es probablemente de alrededor de 4uA.
Actualizar
Al mirar la hoja de datos, se muestra que el pin RX también es el pin 16 de interrupción de cambio de pin (PCINT16)
Por lo tanto, otro método sin cables puede ser
Antes de dormir: configure el bit de máscara de interrupción de cambio de puerto en PCMSK2 para PCINT16, borre la bandera del puerto 2 de cambio de pin en PCIFR, active la interrupción del puerto 2 de cambio de pin (PCINT16-PCINT23) configurando PCIE2 en PCICR.
Configure un ISR para la interrupción del puerto de cambio de pin 2 y continúe como antes.
La única advertencia con la interrupción de cambio de puerto es que la interrupción se comparte entre todos los 8 pines que están habilitados para ese puerto. Entonces, si tiene más de un cambio de pin habilitado para el puerto, debe determinar qué activó la interrupción en el ISR. Esto no es un problema si no está utilizando ninguna otra interrupción de cambio de pin en ese puerto (PCINT16-PCINT23 en este caso)
Idealmente, así es como habría diseñado nuestra placa, pero lo que tenemos funciona.
fuente
El siguiente código logra lo que está pidiendo:
Usé una interrupción de cambio de pin en el pin Rx para notar cuándo llegan los datos en serie. En esta prueba, la placa se duerme si no hay actividad después de 5 segundos (el LED "despierto" se apaga). Los datos seriales entrantes provocan que la interrupción de cambio de clavija active la placa. Busca un número y parpadea el LED "verde" esa cantidad de veces.
Corriente medida
Corriendo a 5 V, medí aproximadamente 120 nA de corriente cuando estaba dormido (0.120 µA).
Mensaje de despertar
Sin embargo, un problema es que el primer byte de llegada se pierde debido al hecho de que el hardware en serie espera un nivel descendente en Rx (el bit de inicio) que ya ha llegado cuando está completamente despierto.
Sugiero (como en la respuesta de geometrikal) que primero envíe un mensaje "despierto", y luego haga una pausa por un corto tiempo. La pausa es asegurarse de que el hardware no interprete el siguiente byte como parte del mensaje despierto. Después de eso debería funcionar bien.
Dado que esto utiliza una interrupción de cambio de pin, no se requiere ningún otro hardware.
Versión modificada usando SoftwareSerial
La siguiente versión procesa con éxito el primer byte recibido en serie. Hace esto por:
Usando SoftwareSerial que usa interrupciones de cambio de pin. La interrupción causada por el bit de inicio del primer byte en serie también activa el procesador.
Configurando los fusibles para que usemos:
Inspirado por FarO en un comentario, esto permite que el procesador se active en 6 ciclos de reloj (750 ns). A 9600 baudios, cada tiempo de bit es 1/9600 (104.2 µs), por lo que el retraso adicional es insignificante.
El consumo de energía cuando estaba dormido se midió como 260 nA (0.260 µA), por lo que es un consumo muy bajo cuando no se necesita.
Tenga en cuenta que con los fusibles configurados así, el procesador funciona a 8 MHz. Por lo tanto, debe informarle al IDE sobre eso (por ejemplo, seleccione "Lilypad" como tipo de placa). De esa forma, los retrasos y SoftwareSerial funcionarán a la velocidad correcta.
fuente