samedi 19 avril 2014

Gestion d'énergie du Arduino Uno


Le projet que je réalise est construit autour d'un Arduino Uno et après avoir réalisé un premier proto je me retrouve confronté au problème de la consommation de ces petites bestioles qui ne sont pas, et c'est peu de le dire, véritablement économes en énergie. J'exposerais juste ici le résultat de certaines mesures ainsi que des liens vers les ressources qui m'auront étés utiles pour résoudre mes problèmes...en espérant qu'elles le soit également pour vous.



Entrons dans le vif du sujet, dans un premier temps donc j'ai mesuré la consommation d'un Arduino Uno V3 seul en branchant un ampèremètre en série avec la pile de 9v qui est censée alimenter le montage final. A vide le Arduino consomme tout de même la bagatelle de 45mA. Sachant que la pile rechargeable que j'utilise est capable de fournir 170mAh (soit 170mA pendant une heure ou encore 85mA pendant 2 heure...etc)  avant de rendre l'âme, cela signifie que je ne peux alimenter mon montage que pendant:

170 / 45 = 3.7 heures

ce qui est embêtant sachant que mon montage, qui est de type capteur, doit pouvoir dans l'idéal survivre plusieurs mois.

J'ai donc ici absolument besoin de trouver un moyen de limiter la consommation du montage. La première mesure que je vais prendre est bien sur de mettre en veille le montage entre deux lectures de capteur, la seconde sera d'espacer autant que possible les prises de mesure. Ceci devrait dans un premier temps bien allonger la durée de vie de la pile.

Pour apprendre à gérer les modes d'alimentation du Arduino je suis tout d'abord tombé sur cette page qui m'a appris qu'il existait une bibliothèque avr/sleep.h qui permettait d'appeler les fonctions suivantes pour désactiver certaines fonctionnalités inutilement énergivore pendant les phases d'inactivité:

set_sleep_mode(<mode>);
sleep_mode();

Après quelques tests voici les différentes consommations que j'ai relevée pour chacun des modes

  • SLEEP_MODE_IDLE           // 45.6mA
  • SLEEP_MODE_PWR_DOWN       // 30.3mA
  • SLEEP_MODE_PWR_SAVE       // 31.4mA
  • SLEEP_MODE_ADC            // 36.6mA
  • SLEEP_MODE_STANDBY        // 30.7mA
  • SLEEP_MODE_EXT_STANDBY    // 31.4mA


L'économie d'énergie est bien là mais certain éléments de la carte comme la conversion usb/série, le convertisseur de tension et les 2 leds (5mA à elles deux) ne semblent pas affectés par la bibliothèque avr/sleep.h ce qui rend la carte encore beaucoup trop gourmande dans son mode le plus économique à savoir SLEEP_MODE_PWR_DOWN. Néanmoins allons au bout de la logique de cette méthode car telle qu'elle est actuellement utilisée elle ne permet pas de réveiller l'avr autrement que par un reset de la carte.

Si nous voulons pouvoir réveiller la carte il nous faudra utiliser les interruptions et pour cela installer un gestionnaire d'interruption sur la pin 2, seulement voilà sleep_mode nous embête un peu car il ne nous permet pas d'installer le gestionnaire d'interruption au plus près de la fonction qui met réellement en sommeil le cpu de l'avr. Si nous y regardons de plus près nous nous apercevons que la fonction sleep_mode n'est en fait qu'un alias pour le code suivant :

do
{
    sleep_enable();
    sleep_cpu();
    sleep_disable();
} while (0);

Nous remplacerons donc sleep_mode  par sa version longue afin de pouvoir intercaler des appels pour désactiver les interruptions jusqu'au tout dernier moment juste avant l'appel à sleep_cpu qui est le moment à partir duquel même le cpu ne pourra plus rien faire et ou nous seront donc condamné à attendre l'arrivée d'un interruption. Il est important de fixer le gestionnaire d'interruption le plus tard possible afin d'éviter qu'une interruption qui surviendrait avant l'appel à sleep_cpu ne déclenche le gestionnaire trop tôt ce qui bloquerait cpu dans son état de veille jusqu'a l'interruption suivante (s'il y en a une).

Schema et code


Voici le code et le schéma que j'ai utilisé pour mes tests :




En conclusion


Cette méthode n'est pas la bonne car elle ne permet pas d'éteindre suffisamment d'éléments du Arduino. Je vois cependant deux voies de sortie :

  1. Soit je developpe un module d'alimentation externe qui pourra couper l'alimentation de toute la carte lorsque le capteur ne mesure rien. Cette méthode aura l'avantage de réellement couper toute alimentation entre deux mesures mais fait rebooter toute la carte ce qui prend du temps et une bonne quantité d'énergie pendant les quelques secondes du boot.
  2. Soit je ne garde du arduino que l'avr et le minimum vital autour de lui pour le faire fonctionner (clock et condos principalement) ce qui sera peut-être un peu plus chiant car il faudra programmer l'avr avec un programmateur. Peut-être qu'un module comme le Arduino Mini conviendrai il faut que je regarde.