Question:
Comment puis-je utiliser PWM en mode économie d'énergie (ATmega328)?
stefan
2017-11-24 20:56:52 UTC
view on stackexchange narkive permalink

Je n'utilise pas PWM en mode d'économie d'énergie. La sortie se comporte de manière erratique. Cela devrait être possible, je suppose. Voici un exemple de fonctionnement minimal:

  / * MWE: Impossible d'utiliser PWM dans aucun mode d'économie d'énergie. Un exemple de travail minimal (MWE) démontrant mon problème dans l'utilisation de PWM tout en économisant de l'énergie. Intention: contrôler une charge pour qu'elle soit allumée ou éteinte pendant de plus longues périodes (des heures, c'est-à-dire). La luminosité de la charge est définie par PWM. Câblage: + 5V | + ------------------ + | + 5V --- | Vin | | | Arduino | C | Pro Mini 9 | ----- / \ / \ / ---- B | < PN2222 | compatible | 1k E | (ATmega328) | | GND --- | GND | | + + ------------------ + LED | - | > < 1k > | | Implémentation GND: * Réglez le chien de garde pour provoquer une interruption à intervalles réguliers (dans ce MWE: 2s). Décompte des «cycles» (MWE: 2 ou 3) à chaque interruption du chien de garde. * Si `cycles` est égal à 0, basculer la sortie, définir une nouvelle valeur` cycles`. Le programme réel utilise 7200 cycles 8s pendant 16h avant la prochaine bascule. * Accédez à SLEEP_MODE_PWR_DOWN. Attendu: la charge attachée est allumée pendant 4 s, atténuée à 32/256. Puis éteint pendant 6s. Puis répétez. Observé: Dans la plupart des cas, il n'y a pas de sortie en mode veille, la LED ne clignote qu'avant de dormir. Mais parfois c'est allumé, alors
PWM semble être possible pendant le sommeil! Le programme réel (à partir duquel ce MWE est dérivé) utilise la luminosité réglable, se réveille du sommeil par des interruptions externes, stocke les brightnes dans l'EEPROM, ... * // * La définition de ce qui suit à 0 utilise `digitalWrite` au lieu de` analogWrite` démontrer que le chien de garde et la logique d'interruption fonctionnent réellement. * / # define USE_PWM 1 # include <avr / sleep.h> # include <avr / wdt.h> # define outputPin 9 // où la charge PWM est connectée # define onCycles 2 // nombre de cycles de surveillance à rester actif # define offCycles 3 / / nombre de cycles de surveillance pour rester éteintint luminosité = 32; // Cycle de service PWM au 1/256, si la charge est activée toggle = 1; // état marche / arrêt actuel de la charge PWM / * nombre de cycles de surveillance jusqu'à la prochaine bascule. Cela sera modifié dans le gestionnaire d'interruption de surveillance. * / volatile unsigned long wdt_cycles = onCycles; / * Gestionnaire d'interruptions Watchdog appelé lorsque le chien de garde expire, compte à rebours des cycles restants. Ne déborde pas. * / ISR (WDT_vect) {if (wdt_cycles > 0) wdt_cycles -;} void setup (void) {/ * Setup watchdog. Voir [1] p54, [2] * / cli (); // BEGIN désactiver interrompt MCUSR & = ~ (1<<WDRF); // pas de réinitialisation du système à l'expiration du délai de surveillance WDTCSR | = 1<<WDCE | 1<<WDE; // autorise la configuration du chien de garde WDTCSR = 1<<WDIE // active les interruptions | 1<<WDP2 | 1<<WDP1 | 1<<WDP0 // 2,0 secondes; wdt_reset (); // réinitialise la minuterie sei (); // END désactiver les interruptions / * Configurer les broches de sortie * / pinMode (outputPin, OUTPUT); # if USE_PWM analogWrite (outputPin, luminosité); # else digitalWrite (outputPin, toggle? HIGH: LOW); # endif} void loop (void) {if (wdt_cycles < 1) {toggle =! toggle; wdt_cycles = basculer? onCycles: offCycles; #if USE_PWM
analogWrite (outputPin, basculer? Luminosité: 0); # else digitalWrite (outputPin, basculer? HIGH: LOW); # endif} / * Heartbeat: Clignotement court de la LED intégrée. Cela vérifie que nous dormons et nous nous réveillons réellement. * / digitalWrite (LED_BUILTIN, HIGH); retard (50); digitalWrite (LED_BUILTIN, LOW); / * Je me suis endormi, voir [3]. Je veux `SLEEP_MODE_PWR_DOWN`, mais aucun des autres ne fonctionne. * / set_sleep_mode (// SLEEP_MODE_IDLE // SLEEP_MODE_ADC // SLEEP_MODE_PWR_SAVE // SLEEP_MODE_STANDBY SLEEP_MODE_PWR_DOWN); sleep_mode ();} / * Références [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 * /  
Deux réponses:
Gerben
2017-11-24 22:46:03 UTC
view on stackexchange narkive permalink

Les minuteries sont désactivées pendant SLEEP_MODE_PWR_DOWN, donc PWM ne fonctionne pas pendant SLEEP_MODE_PWR_DOWN. Vous pouvez à la place utiliser SLEEP_MODE_IDLE , mais cela ne permet d'économiser qu'un peu de courant.

Lorsque vous mettez le MCU en veille, la LED conservera l'état dans lequel elle se trouvait pendant PWM. Donc environ 12,5% si la durée des leds sera allumée, et les autres fois elle sera éteinte (pendant ces périodes PWM de 2 s).

Votre deuxième commentaire explique pourquoi j'ai vu la lumière en mode veille, et aussi pourquoi cela est difficile à reproduire.
Edgar Bonet
2017-11-25 01:14:27 UTC
view on stackexchange narkive permalink

Juste pour compléter la réponse de Gerben:

  1. Vous pouvez utiliser SLEEP_MODE_PWR_DOWN pendant la période de repos, mais SLEEP_MODE_IDLE est le seul moyen pour faire PWM pendant le sommeil.
  2. Lorsque vous êtes dans SLEEP_MODE_IDLE , vous pouvez utiliser la fonction power _ * _ disable () définie dans <avr /power.h> afin de réduire davantage la consommation d'énergie.
Vraiment bonne info: "SLEEP_MODE_IDLE est * le seul moyen * de faire PWM pendant le sommeil". Je n'ai pas réussi à trouver cela dans la documentation ATmega. J'utilise ce que vous avez suggéré, merci!


Ce Q&R a été automatiquement traduit de la langue anglaise.Le contenu original est disponible sur stackexchange, que nous remercions pour la licence cc by-sa 3.0 sous laquelle il est distribué.
Loading...