stefan
2017-11-24 20:56:52 UTC
No puedo usar PWM en el modo de ahorro de energía. La salida se comporta de forma errática. Esto debería ser posible, supongo. El siguiente es un ejemplo de trabajo mínimo:
/ * MWE: No se puede usar PWM en ningún modo de ahorro de energía. Un ejemplo de trabajo mínimo (MWE) que demuestra mi problema al usar PWM mientras se ahorra energía. Intención: Controlar que una carga esté encendida o apagada durante períodos de tiempo más largos (es decir, horas). El brillo de la carga lo establece PWM. Cableado: + 5V | + ------------------ + | + 5V --- | Vin | | | Arduino | C | Pro Mini 9 | ----- / \ / \ / ---- B | < PN2222 | compatible | 1k E | (ATmega328) | | GND --- | GND | | + + ------------------ + LED | - | > < 1k > | | Implementación GND: * Configure el perro guardián para causar una interrupción en intervalos regulares (en este MWE: 2s). Cuente los `ciclos` (MWE: 2 o 3) en cada interrupción del perro guardián. * Si `ciclos` es 0, alternar la salida, establecer un nuevo valor de` ciclos`. El programa real utiliza 7200 ciclos de 8 s durante 16 h antes del próximo cambio. * Vaya a SLEEP_MODE_PWR_DOWN. Esperado: la carga adjunta está encendida durante 4 segundos, atenuada a 32/256. Luego de 6 segundos. Luego repita. Observado: en la mayoría de los casos, no hay salida en el modo de suspensión, el LED solo parpadea antes de dormir. Pero a veces está encendido, así que
¡PWM parece ser posible mientras duerme! El programa real (del cual se deriva este MWE) usa brillo ajustable, se despierta de la suspensión por interrupciones externas, almacena brillo en EEPROM, ... * // * Al establecer lo siguiente en 0 se usa `digitalWrite` en lugar de` analogWrite` para Demuestre que la lógica de vigilancia y de interrupción realmente funcionan. * / # define USE_PWM 1 # incluye <avr / sleep.h> # incluye <avr / wdt.h> # define outputPin 9 // donde está conectada la carga PWM # define onCycles 2 // número de ciclos de vigilancia para permanecer en # define offCycles 3 / número de ciclos de vigilancia para permanecer fuera de brillo = 32; // Ciclo de trabajo de PWM en 1/256, si la carga está encendidaint toggle = 1; // estado actual de encendido / apagado de la carga PWM / * Número de ciclos de vigilancia hasta el próximo cambio. Esto se modificará en el controlador de interrupciones del perro guardián. * / volatile unsigned long wdt_cycles = onCycles; / * Se llama al manejador de interrupciones del perro guardián cuando el perro guardián expira, cuenta los ciclos restantes. No se desborda. * / ISR (WDT_vect) {if (wdt_cycles > 0) wdt_cycles -;} void setup (void) {/ * Configurar el perro guardián. Ver [1] p54, [2] * / cli (); // BEGIN inhabilita las interrupciones MCUSR & = ~ (1<<WDRF); // no se reinicia el sistema en el tiempo de espera de vigilancia WDTCSR | = 1<<WDCE | 1<<WDE; // permitir la configuración del perro guardián WDTCSR = 1<<WDIE // habilitar interrupciones | 1<<WDP2 | 1<<WDP1 | 1<<WDP0 // 2,0 segundos; wdt_reset (); // reiniciar el temporizador sei (); // FIN desactivar interrupciones / * Configurar pines de salida * / pinMode (outputPin, OUTPUT); # if USE_PWM analogWrite (outputPin, brillo); # else digitalWrite (outputPin, alternar? HIGH: LOW); # endif} bucle vacío (void) {if (wdt_cycles < 1) {toggle =! toggle; wdt_cycles = alternar? onCycles: offCycles; #if USE_PWM
analogWrite (outputPin, alternar? brillo: 0); # else digitalWrite (outputPin, alternar? HIGH: LOW); # endif} / * Heartbeat: Parpadeo corto del led incorporado. Esto verifica que realmente estamos durmiendo y despertando. * / digitalWrite (LED_BUILTIN, ALTO); retraso (50); digitalWrite (LED_BUILTIN, BAJO); / * Me dormí, ver [3]. Quiero `SLEEP_MODE_PWR_DOWN`, pero tampoco ninguno de los otros funciona. * / set_sleep_mode (// SLEEP_MODE_IDLE // SLEEP_MODE_ADC // SLEEP_MODE_PWR_SAVE // SLEEP_MODE_STANDBY SLEEP_MODE_PWR_DOWN); sleep_mode ();} / * Referencias [1] https://cdn.sparkfun.com/datasheets/Kits/doc8161.pdf [2] https://forum.arduino.cc/index.php?topic=63651.0 [3 ] https://playground.arduino.cc/Learning/ArduinoSleepCode * /