<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr">
	<id>https://wiki-se.plil.fr/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jramesh</id>
	<title>wiki-se.plil.fr - Contributions [fr]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki-se.plil.fr/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jramesh"/>
	<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php/Sp%C3%A9cial:Contributions/Jramesh"/>
	<updated>2026-08-08T03:15:34Z</updated>
	<subtitle>Contributions</subtitle>
	<generator>MediaWiki 1.39.1</generator>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12965</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12965"/>
		<updated>2026-04-14T18:25:31Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /*  Comparaison théorie VS pratique  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 19h57 : Ajout des calculs pour l'estimation de la consommation théorique + rajout des photos de la consommation expérimentale + rajout des sources&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:all_plugged_none_switched.jpg|center|300px|0 arduinos allumées]]&lt;br /&gt;
'''3 arduinos branchées, aucune allumée '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'une seule, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:one_switched.jpg|center|300px]]&lt;br /&gt;
'''1 arduino allumée''', '''La consommation en blink est identique à celle en mode power down'''&amp;lt;br /&amp;gt;&lt;br /&gt;
la clé ne prend tout simplement pas en compte la consommation d'une arduino seule&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Petit résumé : '''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Résumé de la consommation des Arduinos&lt;br /&gt;
|-&lt;br /&gt;
! Nombre d'Arduinos !! Mode !! Courant (A) !! Tension (V) !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Power down / Blink || 0.00 || 5.11 || Consommation trop faible pour être détectée par la clé&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Power down || 0.07 || 5.08 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || Blink || 0.09 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Power down || 0.11 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Blink || 0.13 || 5.07 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Si mon code est optimisé pour limiter la consommation du microcontrôleur, une carte Arduino embarque pourtant d'autres composants qui restent toujours sous tension et consomment de l'énergie en permanence, même en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;Mode Actif (Blink) &amp;lt;/span&amp;gt; ====&lt;br /&gt;
Dans ce mode, tous les composants fonctionnent à plein régime.&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~15 à 20 mA &lt;br /&gt;
* '''Puce USB-vers-Série ''' : ~15 mA (toujours allumée).&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA.&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA (au repos).&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : ~3 mA (allumée durant blink).&lt;br /&gt;
* '''Total estimé : ~40 à 50 mA'''&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;Mode Veille (Power Down) &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~ 5 µA. ''grâce au mode power down + mes autres optimisations supplémentaires''&lt;br /&gt;
* '''Puce USB-vers-Série''' : ~15 mA. ''(Impossible à éteindre par code)''&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA. ''(Toujours allumée)''&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA. ''(Toujours actif)''&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : 0 mA. ''(Éteinte)''&lt;br /&gt;
* '''Total estimé : ~25 à 35 mA'''&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; Comparaison théorie VS pratique &amp;lt;/span&amp;gt; ====&lt;br /&gt;
En reprenant les données mesurées avec la clé USB sur le hub pour 3 Arduinos, on peut en déduire la consommation réelle d'une seule carte et la comparer à notre théorie :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Comparaison Consommation : Théorie vs Mesures (pour 1 Arduino Uno)&lt;br /&gt;
|-&lt;br /&gt;
! Mode !! Estimation Théorique !! Mesure Réelle Déduite !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| '''Blink''' || ~40 à 50 mA || ~43 mA ''(130 mA / 3)'' || Cohérent avec la théorie.&lt;br /&gt;
|-&lt;br /&gt;
| '''Power Down''' || ~25 à 35 mA || ~36 mA ''(110 mA / 3)'' || Cohérent. La très légère surconsommation s'explique (d'après mon hypothèse) par les composants des clones de l'arduino qui seraient un peu plus gourmands en consommation.&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Conclusion :'''&lt;br /&gt;
Le code fait bien son travail et permet d'économiser environ '''10 mA''' en endormant le microcôntroleur. Néanmoins, à cause des puces secondaires inhérentes à la carte, celle ci ne descend pas en dessous d'une trentaine de milliampères.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Média:Datasheet_arduino_uno.pdf|Datasheet arduino uno]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Média:Datasheet_AVR.pdf|Datasheet AVR]] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; pour l'estimation de ma consommation: &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.gammon.com.au/power &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.robot-maker.com/forum/blog/45/entry-41-tout-ce-que-vous-pourriez-vous-demander-sur-la-consommation-dune-puce-atmega328p-puce-darduino/ &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12964</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12964"/>
		<updated>2026-04-14T18:25:05Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /*  Nota Bene  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 19h57 : Ajout des calculs pour l'estimation de la consommation théorique + rajout des photos de la consommation expérimentale + rajout des sources&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:all_plugged_none_switched.jpg|center|300px|0 arduinos allumées]]&lt;br /&gt;
'''3 arduinos branchées, aucune allumée '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'une seule, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:one_switched.jpg|center|300px]]&lt;br /&gt;
'''1 arduino allumée''', '''La consommation en blink est identique à celle en mode power down'''&amp;lt;br /&amp;gt;&lt;br /&gt;
la clé ne prend tout simplement pas en compte la consommation d'une arduino seule&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Petit résumé : '''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Résumé de la consommation des Arduinos&lt;br /&gt;
|-&lt;br /&gt;
! Nombre d'Arduinos !! Mode !! Courant (A) !! Tension (V) !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Power down / Blink || 0.00 || 5.11 || Consommation trop faible pour être détectée par la clé&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Power down || 0.07 || 5.08 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || Blink || 0.09 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Power down || 0.11 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Blink || 0.13 || 5.07 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Si mon code est optimisé pour limiter la consommation du microcontrôleur, une carte Arduino embarque pourtant d'autres composants qui restent toujours sous tension et consomment de l'énergie en permanence, même en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;Mode Actif (Blink) &amp;lt;/span&amp;gt; ====&lt;br /&gt;
Dans ce mode, tous les composants fonctionnent à plein régime.&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~15 à 20 mA &lt;br /&gt;
* '''Puce USB-vers-Série ''' : ~15 mA (toujours allumée).&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA.&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA (au repos).&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : ~3 mA (allumée durant blink).&lt;br /&gt;
* '''Total estimé : ~40 à 50 mA'''&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;Mode Veille (Power Down) &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~ 5 µA. ''grâce au mode power down + mes autres optimisations supplémentaires''&lt;br /&gt;
* '''Puce USB-vers-Série''' : ~15 mA. ''(Impossible à éteindre par code)''&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA. ''(Toujours allumée)''&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA. ''(Toujours actif)''&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : 0 mA. ''(Éteinte)''&lt;br /&gt;
* '''Total estimé : ~25 à 35 mA'''&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; Comparaison théorie VS pratique &amp;lt;/span&amp;gt; ====&lt;br /&gt;
En reprenant les données mesurées avec la clé USB sur le hub pour 3 Arduinos, on peut en déduire la consommation réelle d'une seule carte et la comparer à notre théorie :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Comparaison Consommation : Théorie vs Mesures (pour 1 Arduino Uno)&lt;br /&gt;
|-&lt;br /&gt;
! Mode !! Estimation Théorique !! Mesure Réelle Déduite !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| '''Blink''' || ~40 à 50 mA || ~43 mA ''(130 mA / 3)'' || Cohérent avec la théorie.&lt;br /&gt;
|-&lt;br /&gt;
| '''Power Down''' || ~25 à 35 mA || ~36 mA ''(110 mA / 3)'' || Cohérent. La très légère surconsommation s'explique (d'après mon hypothèse) par les composants des clones de l'arduino qui seraient un peu plus gourmands en consommation.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Conclusion :'''&lt;br /&gt;
Le code fait bien son travail et permet d'économiser environ '''10 mA''' en endormant le microcôntroleur. Néanmoins, à cause des puces secondaires inhérentes à la carte, celle ci ne descend pas en dessous d'une trentaine de milliampères.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Média:Datasheet_arduino_uno.pdf|Datasheet arduino uno]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Média:Datasheet_AVR.pdf|Datasheet AVR]] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; pour l'estimation de ma consommation: &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.gammon.com.au/power &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.robot-maker.com/forum/blog/45/entry-41-tout-ce-que-vous-pourriez-vous-demander-sur-la-consommation-dune-puce-atmega328p-puce-darduino/ &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12963</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12963"/>
		<updated>2026-04-14T18:24:30Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /*  Nota Bene  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 19h57 : Ajout des calculs pour l'estimation de la consommation théorique + rajout des photos de la consommation expérimentale + rajout des sources&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:all_plugged_none_switched.jpg|center|300px|0 arduinos allumées]]&lt;br /&gt;
'''3 arduinos branchées, aucune allumée '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'une seule, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:one_switched.jpg|center|300px]]&lt;br /&gt;
'''1 arduino allumée''', '''La consommation en blink est identique à celle en mode power down'''&amp;lt;br /&amp;gt;&lt;br /&gt;
la clé ne prend tout simplement pas en compte la consommation d'une arduino seule&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Petit résumé : '''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Résumé de la consommation des Arduinos&lt;br /&gt;
|-&lt;br /&gt;
! Nombre d'Arduinos !! Mode !! Courant (A) !! Tension (V) !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Power down / Blink || 0.00 || 5.11 || Consommation trop faible pour être détectée par la clé&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Power down || 0.07 || 5.08 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || Blink || 0.09 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Power down || 0.11 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Blink || 0.13 || 5.07 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Si mon code est optimisé pour limiter la consommation du microcontrôleur, une carte Arduino embarque pourtant d'autres composants qui restent toujours sous tension et consomment de l'énergie en permanence, même en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;Mode Actif (Blink) &amp;lt;/span&amp;gt; ====&lt;br /&gt;
Dans ce mode, tous les composants fonctionnent à plein régime.&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~15 à 20 mA &lt;br /&gt;
* '''Puce USB-vers-Série ''' : ~15 mA (toujours allumée).&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA.&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA (au repos).&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : ~3 mA (allumée durant blink).&lt;br /&gt;
* '''Total estimé : ~40 à 50 mA'''&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;Mode Veille (Power Down) &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~ 5 µA. ''grâce au mode power down + mes autres optimisations supplémentaires''&lt;br /&gt;
* '''Puce USB-vers-Série''' : ~15 mA. ''(Impossible à éteindre par code)''&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA. ''(Toujours allumée)''&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA. ''(Toujours actif)''&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : 0 mA. ''(Éteinte)''&lt;br /&gt;
* '''Total estimé : ~25 à 35 mA'''&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; Comparaison théorie VS pratique &amp;lt;/span&amp;gt; ====&lt;br /&gt;
En reprenant les données mesurées avec la clé USB sur le hub pour 3 Arduinos, on peut en déduire la consommation réelle d'une seule carte et la comparer à notre théorie :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Comparaison Consommation : Théorie vs Mesures (pour 1 Arduino Uno)&lt;br /&gt;
|-&lt;br /&gt;
! Mode !! Estimation Théorique !! Mesure Réelle Déduite !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| '''Blink''' || ~40 à 50 mA || ~43 mA ''(130 mA / 3)'' || Cohérent avec la théorie.&lt;br /&gt;
|-&lt;br /&gt;
| '''Power Down''' || ~25 à 35 mA || ~36 mA ''(110 mA / 3)'' || Cohérent. La très légère surconsommation s'explique (d'après mon hypothèse) par les composants des clones de l'arduino qui seraient un peu plus gourmands en consommation.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Conclusion :'''&lt;br /&gt;
Le code fait bien son travail et permet d'économiser environ '''10 mA''' en endormant le microcôntroleur. Néanmoins, à cause des puces secondaires inhérentes à la carte, celle ci ne descend pas en dessous d'une trentaine de milliampères.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Média:Datasheet_arduino_uno.pdf|Datasheet arduino uno]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Média:Datasheet_AVR.pdf|Datasheet AVR]] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; pour l'estimation de ma consommation: &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.gammon.com.au/power&lt;br /&gt;
. https://www.robot-maker.com/forum/blog/45/entry-41-tout-ce-que-vous-pourriez-vous-demander-sur-la-consommation-dune-puce-atmega328p-puce-darduino/&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Datasheet_AVR.pdf&amp;diff=12962</id>
		<title>Fichier:Datasheet AVR.pdf</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Datasheet_AVR.pdf&amp;diff=12962"/>
		<updated>2026-04-14T18:18:25Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12961</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12961"/>
		<updated>2026-04-14T18:17:11Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /*  Documents utilisés  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 19h57 : Ajout des calculs pour l'estimation de la consommation théorique + rajout des photos de la consommation expérimentale + rajout des sources&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:all_plugged_none_switched.jpg|center|300px|0 arduinos allumées]]&lt;br /&gt;
'''3 arduinos branchées, aucune allumée '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'une seule, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:one_switched.jpg|center|300px]]&lt;br /&gt;
'''1 arduino allumée''', '''La consommation en blink est identique à celle en mode power down'''&amp;lt;br /&amp;gt;&lt;br /&gt;
la clé ne prend tout simplement pas en compte la consommation d'une arduino seule&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Petit résumé : '''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Résumé de la consommation des Arduinos&lt;br /&gt;
|-&lt;br /&gt;
! Nombre d'Arduinos !! Mode !! Courant (A) !! Tension (V) !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Power down / Blink || 0.00 || 5.11 || Consommation trop faible pour être détectée par la clé&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Power down || 0.07 || 5.08 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || Blink || 0.09 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Power down || 0.11 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Blink || 0.13 || 5.07 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Si mon code est optimisé pour limiter la consommation du microcontrôleur, une carte Arduino embarque pourtant d'autres composants qui restent toujours sous tension et consomment de l'énergie en permanence, même en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;Mode Actif (Blink) &amp;lt;/span&amp;gt; ====&lt;br /&gt;
Dans ce mode, tous les composants fonctionnent à plein régime.&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~15 à 20 mA &lt;br /&gt;
* '''Puce USB-vers-Série ''' : ~15 mA (toujours allumée).&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA.&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA (au repos).&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : ~3 mA (allumée durant blink).&lt;br /&gt;
* '''Total estimé : ~40 à 50 mA'''&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;Mode Veille (Power Down) &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~ 5 µA. ''grâce au mode power down + mes autres optimisations supplémentaires''&lt;br /&gt;
* '''Puce USB-vers-Série''' : ~15 mA. ''(Impossible à éteindre par code)''&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA. ''(Toujours allumée)''&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA. ''(Toujours actif)''&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : 0 mA. ''(Éteinte)''&lt;br /&gt;
* '''Total estimé : ~25 à 35 mA'''&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; Comparaison théorie VS pratique &amp;lt;/span&amp;gt; ====&lt;br /&gt;
En reprenant les données mesurées avec la clé USB sur le hub pour 3 Arduinos, on peut en déduire la consommation réelle d'une seule carte et la comparer à notre théorie :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Comparaison Consommation : Théorie vs Mesures (pour 1 Arduino Uno)&lt;br /&gt;
|-&lt;br /&gt;
! Mode !! Estimation Théorique !! Mesure Réelle Déduite !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| '''Blink''' || ~40 à 50 mA || ~43 mA ''(130 mA / 3)'' || Cohérent avec la théorie.&lt;br /&gt;
|-&lt;br /&gt;
| '''Power Down''' || ~25 à 35 mA || ~36 mA ''(110 mA / 3)'' || Cohérent. La très légère surconsommation s'explique (d'après mon hypothèse) par les composants des clones de l'arduino qui seraient un peu plus gourmands en consommation.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Conclusion :'''&lt;br /&gt;
Le code fait bien son travail et permet d'économiser environ '''10 mA''' en endormant le microcôntroleur. Néanmoins, à cause des puces secondaires inhérentes à la carte, celle ci ne descend pas en dessous d'une trentaine de milliampères.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Média:Datasheet_arduino_uno.pdf|Datasheet arduino uno]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Média:Datasheet_AVR.pdf|Datasheet AVR]] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12960</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12960"/>
		<updated>2026-04-14T18:14:50Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /*  Documents utilisés  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 19h57 : Ajout des calculs pour l'estimation de la consommation théorique + rajout des photos de la consommation expérimentale + rajout des sources&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:all_plugged_none_switched.jpg|center|300px|0 arduinos allumées]]&lt;br /&gt;
'''3 arduinos branchées, aucune allumée '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'une seule, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:one_switched.jpg|center|300px]]&lt;br /&gt;
'''1 arduino allumée''', '''La consommation en blink est identique à celle en mode power down'''&amp;lt;br /&amp;gt;&lt;br /&gt;
la clé ne prend tout simplement pas en compte la consommation d'une arduino seule&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Petit résumé : '''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Résumé de la consommation des Arduinos&lt;br /&gt;
|-&lt;br /&gt;
! Nombre d'Arduinos !! Mode !! Courant (A) !! Tension (V) !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Power down / Blink || 0.00 || 5.11 || Consommation trop faible pour être détectée par la clé&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Power down || 0.07 || 5.08 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || Blink || 0.09 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Power down || 0.11 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Blink || 0.13 || 5.07 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Si mon code est optimisé pour limiter la consommation du microcontrôleur, une carte Arduino embarque pourtant d'autres composants qui restent toujours sous tension et consomment de l'énergie en permanence, même en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;Mode Actif (Blink) &amp;lt;/span&amp;gt; ====&lt;br /&gt;
Dans ce mode, tous les composants fonctionnent à plein régime.&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~15 à 20 mA &lt;br /&gt;
* '''Puce USB-vers-Série ''' : ~15 mA (toujours allumée).&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA.&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA (au repos).&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : ~3 mA (allumée durant blink).&lt;br /&gt;
* '''Total estimé : ~40 à 50 mA'''&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;Mode Veille (Power Down) &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~ 5 µA. ''grâce au mode power down + mes autres optimisations supplémentaires''&lt;br /&gt;
* '''Puce USB-vers-Série''' : ~15 mA. ''(Impossible à éteindre par code)''&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA. ''(Toujours allumée)''&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA. ''(Toujours actif)''&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : 0 mA. ''(Éteinte)''&lt;br /&gt;
* '''Total estimé : ~25 à 35 mA'''&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; Comparaison théorie VS pratique &amp;lt;/span&amp;gt; ====&lt;br /&gt;
En reprenant les données mesurées avec la clé USB sur le hub pour 3 Arduinos, on peut en déduire la consommation réelle d'une seule carte et la comparer à notre théorie :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Comparaison Consommation : Théorie vs Mesures (pour 1 Arduino Uno)&lt;br /&gt;
|-&lt;br /&gt;
! Mode !! Estimation Théorique !! Mesure Réelle Déduite !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| '''Blink''' || ~40 à 50 mA || ~43 mA ''(130 mA / 3)'' || Cohérent avec la théorie.&lt;br /&gt;
|-&lt;br /&gt;
| '''Power Down''' || ~25 à 35 mA || ~36 mA ''(110 mA / 3)'' || Cohérent. La très légère surconsommation s'explique (d'après mon hypothèse) par les composants des clones de l'arduino qui seraient un peu plus gourmands en consommation.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Conclusion :'''&lt;br /&gt;
Le code fait bien son travail et permet d'économiser environ '''10 mA''' en endormant le microcôntroleur. Néanmoins, à cause des puces secondaires inhérentes à la carte, celle ci ne descend pas en dessous d'une trentaine de milliampères.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Média:Datasheet_arduino_uno.pdf|Datasheet arduino uno]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Média:Datasheet_AVR.ogg|Datasheet AVR]] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12959</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12959"/>
		<updated>2026-04-14T18:08:35Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /*  Documents utilisés  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 19h57 : Ajout des calculs pour l'estimation de la consommation théorique + rajout des photos de la consommation expérimentale + rajout des sources&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:all_plugged_none_switched.jpg|center|300px|0 arduinos allumées]]&lt;br /&gt;
'''3 arduinos branchées, aucune allumée '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'une seule, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:one_switched.jpg|center|300px]]&lt;br /&gt;
'''1 arduino allumée''', '''La consommation en blink est identique à celle en mode power down'''&amp;lt;br /&amp;gt;&lt;br /&gt;
la clé ne prend tout simplement pas en compte la consommation d'une arduino seule&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Petit résumé : '''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Résumé de la consommation des Arduinos&lt;br /&gt;
|-&lt;br /&gt;
! Nombre d'Arduinos !! Mode !! Courant (A) !! Tension (V) !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Power down / Blink || 0.00 || 5.11 || Consommation trop faible pour être détectée par la clé&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Power down || 0.07 || 5.08 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || Blink || 0.09 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Power down || 0.11 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Blink || 0.13 || 5.07 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Si mon code est optimisé pour limiter la consommation du microcontrôleur, une carte Arduino embarque pourtant d'autres composants qui restent toujours sous tension et consomment de l'énergie en permanence, même en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;Mode Actif (Blink) &amp;lt;/span&amp;gt; ====&lt;br /&gt;
Dans ce mode, tous les composants fonctionnent à plein régime.&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~15 à 20 mA &lt;br /&gt;
* '''Puce USB-vers-Série ''' : ~15 mA (toujours allumée).&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA.&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA (au repos).&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : ~3 mA (allumée durant blink).&lt;br /&gt;
* '''Total estimé : ~40 à 50 mA'''&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;Mode Veille (Power Down) &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~ 5 µA. ''grâce au mode power down + mes autres optimisations supplémentaires''&lt;br /&gt;
* '''Puce USB-vers-Série''' : ~15 mA. ''(Impossible à éteindre par code)''&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA. ''(Toujours allumée)''&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA. ''(Toujours actif)''&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : 0 mA. ''(Éteinte)''&lt;br /&gt;
* '''Total estimé : ~25 à 35 mA'''&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; Comparaison théorie VS pratique &amp;lt;/span&amp;gt; ====&lt;br /&gt;
En reprenant les données mesurées avec la clé USB sur le hub pour 3 Arduinos, on peut en déduire la consommation réelle d'une seule carte et la comparer à notre théorie :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Comparaison Consommation : Théorie vs Mesures (pour 1 Arduino Uno)&lt;br /&gt;
|-&lt;br /&gt;
! Mode !! Estimation Théorique !! Mesure Réelle Déduite !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| '''Blink''' || ~40 à 50 mA || ~43 mA ''(130 mA / 3)'' || Cohérent avec la théorie.&lt;br /&gt;
|-&lt;br /&gt;
| '''Power Down''' || ~25 à 35 mA || ~36 mA ''(110 mA / 3)'' || Cohérent. La très légère surconsommation s'explique (d'après mon hypothèse) par les composants des clones de l'arduino qui seraient un peu plus gourmands en consommation.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Conclusion :'''&lt;br /&gt;
Le code fait bien son travail et permet d'économiser environ '''10 mA''' en endormant le microcôntroleur. Néanmoins, à cause des puces secondaires inhérentes à la carte, celle ci ne descend pas en dessous d'une trentaine de milliampères.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Média:Datasheet_arduino_uno.ogg|Datasheet arduino uno]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Média:Datasheet_AVR.ogg|Datasheet AVR]] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12958</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12958"/>
		<updated>2026-04-14T18:05:29Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /*  Historique  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 19h57 : Ajout des calculs pour l'estimation de la consommation théorique + rajout des photos de la consommation expérimentale + rajout des sources&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:all_plugged_none_switched.jpg|center|300px|0 arduinos allumées]]&lt;br /&gt;
'''3 arduinos branchées, aucune allumée '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'une seule, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:one_switched.jpg|center|300px]]&lt;br /&gt;
'''1 arduino allumée''', '''La consommation en blink est identique à celle en mode power down'''&amp;lt;br /&amp;gt;&lt;br /&gt;
la clé ne prend tout simplement pas en compte la consommation d'une arduino seule&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Petit résumé : '''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Résumé de la consommation des Arduinos&lt;br /&gt;
|-&lt;br /&gt;
! Nombre d'Arduinos !! Mode !! Courant (A) !! Tension (V) !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Power down / Blink || 0.00 || 5.11 || Consommation trop faible pour être détectée par la clé&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Power down || 0.07 || 5.08 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || Blink || 0.09 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Power down || 0.11 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Blink || 0.13 || 5.07 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Si mon code est optimisé pour limiter la consommation du microcontrôleur, une carte Arduino embarque pourtant d'autres composants qui restent toujours sous tension et consomment de l'énergie en permanence, même en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;Mode Actif (Blink) &amp;lt;/span&amp;gt; ====&lt;br /&gt;
Dans ce mode, tous les composants fonctionnent à plein régime.&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~15 à 20 mA &lt;br /&gt;
* '''Puce USB-vers-Série ''' : ~15 mA (toujours allumée).&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA.&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA (au repos).&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : ~3 mA (allumée durant blink).&lt;br /&gt;
* '''Total estimé : ~40 à 50 mA'''&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;Mode Veille (Power Down) &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~ 5 µA. ''grâce au mode power down + mes autres optimisations supplémentaires''&lt;br /&gt;
* '''Puce USB-vers-Série''' : ~15 mA. ''(Impossible à éteindre par code)''&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA. ''(Toujours allumée)''&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA. ''(Toujours actif)''&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : 0 mA. ''(Éteinte)''&lt;br /&gt;
* '''Total estimé : ~25 à 35 mA'''&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; Comparaison théorie VS pratique &amp;lt;/span&amp;gt; ====&lt;br /&gt;
En reprenant les données mesurées avec la clé USB sur le hub pour 3 Arduinos, on peut en déduire la consommation réelle d'une seule carte et la comparer à notre théorie :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Comparaison Consommation : Théorie vs Mesures (pour 1 Arduino Uno)&lt;br /&gt;
|-&lt;br /&gt;
! Mode !! Estimation Théorique !! Mesure Réelle Déduite !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| '''Blink''' || ~40 à 50 mA || ~43 mA ''(130 mA / 3)'' || Cohérent avec la théorie.&lt;br /&gt;
|-&lt;br /&gt;
| '''Power Down''' || ~25 à 35 mA || ~36 mA ''(110 mA / 3)'' || Cohérent. La très légère surconsommation s'explique (d'après mon hypothèse) par les composants des clones de l'arduino qui seraient un peu plus gourmands en consommation.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Conclusion :'''&lt;br /&gt;
Le code fait bien son travail et permet d'économiser environ '''10 mA''' en endormant le microcôntroleur. Néanmoins, à cause des puces secondaires inhérentes à la carte, celle ci ne descend pas en dessous d'une trentaine de milliampères.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12957</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12957"/>
		<updated>2026-04-14T18:05:18Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /*  Historique  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout des calculs pour l'estimation de la consommation théorique + rajout des photos de la consommation expérimentale + rajout des sources&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:all_plugged_none_switched.jpg|center|300px|0 arduinos allumées]]&lt;br /&gt;
'''3 arduinos branchées, aucune allumée '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'une seule, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:one_switched.jpg|center|300px]]&lt;br /&gt;
'''1 arduino allumée''', '''La consommation en blink est identique à celle en mode power down'''&amp;lt;br /&amp;gt;&lt;br /&gt;
la clé ne prend tout simplement pas en compte la consommation d'une arduino seule&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Petit résumé : '''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Résumé de la consommation des Arduinos&lt;br /&gt;
|-&lt;br /&gt;
! Nombre d'Arduinos !! Mode !! Courant (A) !! Tension (V) !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Power down / Blink || 0.00 || 5.11 || Consommation trop faible pour être détectée par la clé&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Power down || 0.07 || 5.08 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || Blink || 0.09 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Power down || 0.11 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Blink || 0.13 || 5.07 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Si mon code est optimisé pour limiter la consommation du microcontrôleur, une carte Arduino embarque pourtant d'autres composants qui restent toujours sous tension et consomment de l'énergie en permanence, même en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;Mode Actif (Blink) &amp;lt;/span&amp;gt; ====&lt;br /&gt;
Dans ce mode, tous les composants fonctionnent à plein régime.&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~15 à 20 mA &lt;br /&gt;
* '''Puce USB-vers-Série ''' : ~15 mA (toujours allumée).&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA.&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA (au repos).&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : ~3 mA (allumée durant blink).&lt;br /&gt;
* '''Total estimé : ~40 à 50 mA'''&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;Mode Veille (Power Down) &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~ 5 µA. ''grâce au mode power down + mes autres optimisations supplémentaires''&lt;br /&gt;
* '''Puce USB-vers-Série''' : ~15 mA. ''(Impossible à éteindre par code)''&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA. ''(Toujours allumée)''&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA. ''(Toujours actif)''&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : 0 mA. ''(Éteinte)''&lt;br /&gt;
* '''Total estimé : ~25 à 35 mA'''&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; Comparaison théorie VS pratique &amp;lt;/span&amp;gt; ====&lt;br /&gt;
En reprenant les données mesurées avec la clé USB sur le hub pour 3 Arduinos, on peut en déduire la consommation réelle d'une seule carte et la comparer à notre théorie :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Comparaison Consommation : Théorie vs Mesures (pour 1 Arduino Uno)&lt;br /&gt;
|-&lt;br /&gt;
! Mode !! Estimation Théorique !! Mesure Réelle Déduite !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| '''Blink''' || ~40 à 50 mA || ~43 mA ''(130 mA / 3)'' || Cohérent avec la théorie.&lt;br /&gt;
|-&lt;br /&gt;
| '''Power Down''' || ~25 à 35 mA || ~36 mA ''(110 mA / 3)'' || Cohérent. La très légère surconsommation s'explique (d'après mon hypothèse) par les composants des clones de l'arduino qui seraient un peu plus gourmands en consommation.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Conclusion :'''&lt;br /&gt;
Le code fait bien son travail et permet d'économiser environ '''10 mA''' en endormant le microcôntroleur. Néanmoins, à cause des puces secondaires inhérentes à la carte, celle ci ne descend pas en dessous d'une trentaine de milliampères.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12956</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12956"/>
		<updated>2026-04-14T18:00:25Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /*  Comparaison théorie VS pratique  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie)&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:all_plugged_none_switched.jpg|center|300px|0 arduinos allumées]]&lt;br /&gt;
'''3 arduinos branchées, aucune allumée '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'une seule, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:one_switched.jpg|center|300px]]&lt;br /&gt;
'''1 arduino allumée''', '''La consommation en blink est identique à celle en mode power down'''&amp;lt;br /&amp;gt;&lt;br /&gt;
la clé ne prend tout simplement pas en compte la consommation d'une arduino seule&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Petit résumé : '''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Résumé de la consommation des Arduinos&lt;br /&gt;
|-&lt;br /&gt;
! Nombre d'Arduinos !! Mode !! Courant (A) !! Tension (V) !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Power down / Blink || 0.00 || 5.11 || Consommation trop faible pour être détectée par la clé&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Power down || 0.07 || 5.08 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || Blink || 0.09 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Power down || 0.11 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Blink || 0.13 || 5.07 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Si mon code est optimisé pour limiter la consommation du microcontrôleur, une carte Arduino embarque pourtant d'autres composants qui restent toujours sous tension et consomment de l'énergie en permanence, même en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;Mode Actif (Blink) &amp;lt;/span&amp;gt; ====&lt;br /&gt;
Dans ce mode, tous les composants fonctionnent à plein régime.&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~15 à 20 mA &lt;br /&gt;
* '''Puce USB-vers-Série ''' : ~15 mA (toujours allumée).&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA.&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA (au repos).&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : ~3 mA (allumée durant blink).&lt;br /&gt;
* '''Total estimé : ~40 à 50 mA'''&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;Mode Veille (Power Down) &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~ 5 µA. ''grâce au mode power down + mes autres optimisations supplémentaires''&lt;br /&gt;
* '''Puce USB-vers-Série''' : ~15 mA. ''(Impossible à éteindre par code)''&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA. ''(Toujours allumée)''&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA. ''(Toujours actif)''&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : 0 mA. ''(Éteinte)''&lt;br /&gt;
* '''Total estimé : ~25 à 35 mA'''&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; Comparaison théorie VS pratique &amp;lt;/span&amp;gt; ====&lt;br /&gt;
En reprenant les données mesurées avec la clé USB sur le hub pour 3 Arduinos, on peut en déduire la consommation réelle d'une seule carte et la comparer à notre théorie :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Comparaison Consommation : Théorie vs Mesures (pour 1 Arduino Uno)&lt;br /&gt;
|-&lt;br /&gt;
! Mode !! Estimation Théorique !! Mesure Réelle Déduite !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| '''Blink''' || ~40 à 50 mA || ~43 mA ''(130 mA / 3)'' || Cohérent avec la théorie.&lt;br /&gt;
|-&lt;br /&gt;
| '''Power Down''' || ~25 à 35 mA || ~36 mA ''(110 mA / 3)'' || Cohérent. La très légère surconsommation s'explique (d'après mon hypothèse) par les composants des clones de l'arduino qui seraient un peu plus gourmands en consommation.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Conclusion :'''&lt;br /&gt;
Le code fait bien son travail et permet d'économiser environ '''10 mA''' en endormant le microcôntroleur. Néanmoins, à cause des puces secondaires inhérentes à la carte, celle ci ne descend pas en dessous d'une trentaine de milliampères.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12955</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12955"/>
		<updated>2026-04-14T17:59:32Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /* 6. modélisation de la consommation théorique  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie)&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:all_plugged_none_switched.jpg|center|300px|0 arduinos allumées]]&lt;br /&gt;
'''3 arduinos branchées, aucune allumée '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'une seule, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:one_switched.jpg|center|300px]]&lt;br /&gt;
'''1 arduino allumée''', '''La consommation en blink est identique à celle en mode power down'''&amp;lt;br /&amp;gt;&lt;br /&gt;
la clé ne prend tout simplement pas en compte la consommation d'une arduino seule&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Petit résumé : '''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Résumé de la consommation des Arduinos&lt;br /&gt;
|-&lt;br /&gt;
! Nombre d'Arduinos !! Mode !! Courant (A) !! Tension (V) !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Power down / Blink || 0.00 || 5.11 || Consommation trop faible pour être détectée par la clé&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Power down || 0.07 || 5.08 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || Blink || 0.09 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Power down || 0.11 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Blink || 0.13 || 5.07 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Si mon code est optimisé pour limiter la consommation du microcontrôleur, une carte Arduino embarque pourtant d'autres composants qui restent toujours sous tension et consomment de l'énergie en permanence, même en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;Mode Actif (Blink) &amp;lt;/span&amp;gt; ====&lt;br /&gt;
Dans ce mode, tous les composants fonctionnent à plein régime.&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~15 à 20 mA &lt;br /&gt;
* '''Puce USB-vers-Série ''' : ~15 mA (toujours allumée).&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA.&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA (au repos).&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : ~3 mA (allumée durant blink).&lt;br /&gt;
* '''Total estimé : ~40 à 50 mA'''&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;Mode Veille (Power Down) &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~ 5 µA. ''grâce au mode power down + mes autres optimisations supplémentaires''&lt;br /&gt;
* '''Puce USB-vers-Série''' : ~15 mA. ''(Impossible à éteindre par code)''&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA. ''(Toujours allumée)''&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA. ''(Toujours actif)''&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : 0 mA. ''(Éteinte)''&lt;br /&gt;
* '''Total estimé : ~25 à 35 mA'''&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; Comparaison théorie VS pratique &amp;lt;/span&amp;gt; ====&lt;br /&gt;
En reprenant les données mesurées avec la clé USB sur le hub pour 3 Arduinos, on peut en déduire la consommation réelle d'une seule carte et la comparer à notre théorie :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Comparaison Consommation : Théorie vs Mesures (pour 1 Arduino Uno)&lt;br /&gt;
|-&lt;br /&gt;
! Mode !! Estimation Théorique !! Mesure Réelle Déduite !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| '''Blink''' || ~40 à 50 mA || ~43 mA ''(130 mA / 3)'' || Cohérent avec la théorie.&lt;br /&gt;
|-&lt;br /&gt;
| '''Power Down''' || ~25 à 35 mA || ~36 mA ''(110 mA / 3)'' || Cohérent. La très légère surconsommation s'explique (d'après mon hypothèse) des composants des clones de l'arduino qui seraient un peu plus gourmands en consommation.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Conclusion :'''&lt;br /&gt;
Le code fait bien son travail et permet d'économiser environ '''10 mA''' en endormant le microcôntroleur. Néanmoins, à cause des puces secondaires inhérentes à la carte, celle ci ne descend pas en dessous d'une trentaine de milliampères.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12954</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12954"/>
		<updated>2026-04-14T17:58:18Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /* 6. modélisation de la consommation théorique  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie)&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:all_plugged_none_switched.jpg|center|300px|0 arduinos allumées]]&lt;br /&gt;
'''3 arduinos branchées, aucune allumée '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'une seule, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:one_switched.jpg|center|300px]]&lt;br /&gt;
'''1 arduino allumée''', '''La consommation en blink est identique à celle en mode power down'''&amp;lt;br /&amp;gt;&lt;br /&gt;
la clé ne prend tout simplement pas en compte la consommation d'une arduino seule&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Petit résumé : '''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Résumé de la consommation des Arduinos&lt;br /&gt;
|-&lt;br /&gt;
! Nombre d'Arduinos !! Mode !! Courant (A) !! Tension (V) !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Power down / Blink || 0.00 || 5.11 || Consommation trop faible pour être détectée par la clé&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Power down || 0.07 || 5.08 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || Blink || 0.09 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Power down || 0.11 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Blink || 0.13 || 5.07 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Si mon code est optimisé pour limiter la consommation du microcontrôleur, une carte Arduino embarque pourtant d'autres composants qui restent toujours sous tension et consomment de l'énergie en permanence, même en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;Mode Actif (Blink) &amp;lt;/span&amp;gt; ====&lt;br /&gt;
Dans ce mode, tous les composants fonctionnent à plein régime.&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~15 à 20 mA &lt;br /&gt;
* '''Puce USB-vers-Série ''' : ~15 mA (toujours allumée).&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA.&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA (au repos).&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : ~3 mA (allumée durant blink).&lt;br /&gt;
* '''Total estimé : ~40 à 50 mA'''&lt;br /&gt;
&lt;br /&gt;
==== Mode Veille (Power Down) ====&lt;br /&gt;
&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~ 5 µA. ''grâce au mode power down + mes autres optimisations supplémentaires''&lt;br /&gt;
* '''Puce USB-vers-Série''' : ~15 mA. ''(Impossible à éteindre par code)''&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA. ''(Toujours allumée)''&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA. ''(Toujours actif)''&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : 0 mA. ''(Éteinte)''&lt;br /&gt;
* '''Total estimé : ~25 à 35 mA'''&lt;br /&gt;
&lt;br /&gt;
==== Comparaison Théorie vs Pratique ====&lt;br /&gt;
En reprenant les données mesurées avec la clé USB sur le hub pour 3 Arduinos, on peut en déduire la consommation réelle d'une seule carte et la comparer à notre théorie :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Comparaison Consommation : Théorie vs Mesures (pour 1 Arduino Uno)&lt;br /&gt;
|-&lt;br /&gt;
! Mode !! Estimation Théorique !! Mesure Réelle Déduite !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| '''Blink''' || ~40 à 50 mA || ~43 mA ''(130 mA / 3)'' || Cohérent avec la théorie.&lt;br /&gt;
|-&lt;br /&gt;
| '''Power Down''' || ~25 à 35 mA || ~36 mA ''(110 mA / 3)'' || Cohérent. La très légère surconsommation s'explique (d'après mon hypothèse) des composants des clones de l'arduino qui seraient un peu plus gourmands en consommation.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Conclusion :'''&lt;br /&gt;
Le code fait bien son travail et permet d'économiser environ '''10 mA''' en endormant le microcôntroleur. Néanmoins, à cause des puces secondaires inhérentes à la carte, celle ci ne descend pas en dessous d'une trentaine de milliampères.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12953</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12953"/>
		<updated>2026-04-14T17:56:20Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /* 5. Consommation expérimentale  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie)&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:all_plugged_none_switched.jpg|center|300px|0 arduinos allumées]]&lt;br /&gt;
'''3 arduinos branchées, aucune allumée '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'une seule, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:one_switched.jpg|center|300px]]&lt;br /&gt;
'''1 arduino allumée''', '''La consommation en blink est identique à celle en mode power down'''&amp;lt;br /&amp;gt;&lt;br /&gt;
la clé ne prend tout simplement pas en compte la consommation d'une arduino seule&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Petit résumé : '''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Résumé de la consommation des Arduinos&lt;br /&gt;
|-&lt;br /&gt;
! Nombre d'Arduinos !! Mode !! Courant (A) !! Tension (V) !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Power down / Blink || 0.00 || 5.11 || Consommation trop faible pour être détectée par la clé&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Power down || 0.07 || 5.08 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || Blink || 0.09 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Power down || 0.11 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Blink || 0.13 || 5.07 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Si mon code est optimisé pour limiter la consommation du microcontrôleur, une carte Arduino embarque pourtant d'autres composants qui restent toujours sous tension et consomment de l'énergie en permanence, même en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== Mode Actif (Blink) ====&lt;br /&gt;
Dans ce mode, tous les composants fonctionnent à plein régime.&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~15 à 20 mA &lt;br /&gt;
* '''Puce USB-vers-Série ''' : ~15 mA (toujours allumée).&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA.&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA (au repos).&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : ~3 mA (allumée durant blink).&lt;br /&gt;
* '''Total estimé : ~40 à 50 mA'''&lt;br /&gt;
&lt;br /&gt;
==== Mode Veille (Power Down) ====&lt;br /&gt;
&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~ 5 µA. ''grâce au mode power down + mes autres optimisations supplémentaires''&lt;br /&gt;
* '''Puce USB-vers-Série''' : ~15 mA. ''(Impossible à éteindre par code)''&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA. ''(Toujours allumée)''&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA. ''(Toujours actif)''&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : 0 mA. ''(Éteinte)''&lt;br /&gt;
* '''Total estimé : ~25 à 35 mA'''&lt;br /&gt;
&lt;br /&gt;
==== Comparaison Théorie vs Pratique ====&lt;br /&gt;
En reprenant les données mesurées avec la clé USB sur le hub pour 3 Arduinos, on peut en déduire la consommation réelle d'une seule carte et la comparer à notre théorie :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Comparaison Consommation : Théorie vs Mesures (pour 1 Arduino Uno)&lt;br /&gt;
|-&lt;br /&gt;
! Mode !! Estimation Théorique !! Mesure Réelle Déduite !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| '''Blink''' || ~40 à 50 mA || ~43 mA ''(130 mA / 3)'' || Cohérent avec la théorie.&lt;br /&gt;
|-&lt;br /&gt;
| '''Power Down''' || ~25 à 35 mA || ~36 mA ''(110 mA / 3)'' || Cohérent. La très légère surconsommation s'explique (d'après mon hypothèse) des composants des clones de l'arduino qui seraient un peu plus gourmands en consommation.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Conclusion :'''&lt;br /&gt;
Le code fait bien son travail et permet d'économiser environ '''10 mA''' en endormant le microcôntroleur. Néanmoins, à cause des puces secondaires inhérentes à la carte, celle ci ne descend pas en dessous d'une trentaine de milliampères.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12952</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12952"/>
		<updated>2026-04-14T17:54:36Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /* 5. Consommation expérimentale  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie)&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:all_plugged_none_switched.jpg|center|300px|0 arduinos allumées]]&lt;br /&gt;
'''3 arduinos branchées, aucune allumée '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'une seule, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:one_switched.jpg|center|300px]]&lt;br /&gt;
'''1 arduino allumée''', '''La consommation en blink est identique à celle en mode power down'''&amp;lt;br /&amp;gt;&lt;br /&gt;
la clé ne prend tout simplement pas en compte la consommation d'une arduino seule&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Petit résumé : '''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Résumé de la consommation des Arduinos&lt;br /&gt;
|-&lt;br /&gt;
! Nombre d'Arduinos !! Mode !! Courant (A) !! Tension (V) !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| 0 || éteintes || 0.00 || 5.11 || 3 branchées, aucune activée&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Power down / Blink || 0.00 || 5.11 || Consommation trop faible pour être détectée par la clé&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Power down || 0.07 || 5.08 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || Blink || 0.09 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Power down || 0.11 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Blink || 0.13 || 5.07 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Si mon code est optimisé pour limiter la consommation du microcontrôleur, une carte Arduino embarque pourtant d'autres composants qui restent toujours sous tension et consomment de l'énergie en permanence, même en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== Mode Actif (Blink) ====&lt;br /&gt;
Dans ce mode, tous les composants fonctionnent à plein régime.&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~15 à 20 mA &lt;br /&gt;
* '''Puce USB-vers-Série ''' : ~15 mA (toujours allumée).&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA.&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA (au repos).&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : ~3 mA (allumée durant blink).&lt;br /&gt;
* '''Total estimé : ~40 à 50 mA'''&lt;br /&gt;
&lt;br /&gt;
==== Mode Veille (Power Down) ====&lt;br /&gt;
&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~ 5 µA. ''grâce au mode power down + mes autres optimisations supplémentaires''&lt;br /&gt;
* '''Puce USB-vers-Série''' : ~15 mA. ''(Impossible à éteindre par code)''&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA. ''(Toujours allumée)''&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA. ''(Toujours actif)''&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : 0 mA. ''(Éteinte)''&lt;br /&gt;
* '''Total estimé : ~25 à 35 mA'''&lt;br /&gt;
&lt;br /&gt;
==== Comparaison Théorie vs Pratique ====&lt;br /&gt;
En reprenant les données mesurées avec la clé USB sur le hub pour 3 Arduinos, on peut en déduire la consommation réelle d'une seule carte et la comparer à notre théorie :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Comparaison Consommation : Théorie vs Mesures (pour 1 Arduino Uno)&lt;br /&gt;
|-&lt;br /&gt;
! Mode !! Estimation Théorique !! Mesure Réelle Déduite !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| '''Blink''' || ~40 à 50 mA || ~43 mA ''(130 mA / 3)'' || Cohérent avec la théorie.&lt;br /&gt;
|-&lt;br /&gt;
| '''Power Down''' || ~25 à 35 mA || ~36 mA ''(110 mA / 3)'' || Cohérent. La très légère surconsommation s'explique (d'après mon hypothèse) des composants des clones de l'arduino qui seraient un peu plus gourmands en consommation.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Conclusion :'''&lt;br /&gt;
Le code fait bien son travail et permet d'économiser environ '''10 mA''' en endormant le microcôntroleur. Néanmoins, à cause des puces secondaires inhérentes à la carte, celle ci ne descend pas en dessous d'une trentaine de milliampères.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12951</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12951"/>
		<updated>2026-04-14T17:54:03Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /*  Travail réalisé  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie)&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:all_plugged_none_switched.jpg|center|300px|0 arduinos allumées]]&lt;br /&gt;
'''3 arduinos branchées, aucune allumée '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'un seul, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:one_switched.jpg|center|300px]]&lt;br /&gt;
'''1 arduino allumée''', '''La consommation en blink est identique à celle en mode power down'''&amp;lt;br /&amp;gt;&lt;br /&gt;
la clé ne prend tout simplement pas en compte la consommation d'une arduino seule&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Petit résumé : '''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Résumé de la consommation des Arduinos&lt;br /&gt;
|-&lt;br /&gt;
! Nombre d'Arduinos !! Mode !! Courant (A) !! Tension (V) !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| 0 || éteintes || 0.00 || 5.11 || 3 branchées, aucune activée&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Power down / Blink || 0.00 || 5.11 || Consommation trop faible pour être détectée par la clé&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Power down || 0.07 || 5.08 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || Blink || 0.09 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Power down || 0.11 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Blink || 0.13 || 5.07 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Si mon code est optimisé pour limiter la consommation du microcontrôleur, une carte Arduino embarque pourtant d'autres composants qui restent toujours sous tension et consomment de l'énergie en permanence, même en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== Mode Actif (Blink) ====&lt;br /&gt;
Dans ce mode, tous les composants fonctionnent à plein régime.&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~15 à 20 mA &lt;br /&gt;
* '''Puce USB-vers-Série ''' : ~15 mA (toujours allumée).&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA.&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA (au repos).&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : ~3 mA (allumée durant blink).&lt;br /&gt;
* '''Total estimé : ~40 à 50 mA'''&lt;br /&gt;
&lt;br /&gt;
==== Mode Veille (Power Down) ====&lt;br /&gt;
&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~ 5 µA. ''grâce au mode power down + mes autres optimisations supplémentaires''&lt;br /&gt;
* '''Puce USB-vers-Série''' : ~15 mA. ''(Impossible à éteindre par code)''&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA. ''(Toujours allumée)''&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA. ''(Toujours actif)''&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : 0 mA. ''(Éteinte)''&lt;br /&gt;
* '''Total estimé : ~25 à 35 mA'''&lt;br /&gt;
&lt;br /&gt;
==== Comparaison Théorie vs Pratique ====&lt;br /&gt;
En reprenant les données mesurées avec la clé USB sur le hub pour 3 Arduinos, on peut en déduire la consommation réelle d'une seule carte et la comparer à notre théorie :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Comparaison Consommation : Théorie vs Mesures (pour 1 Arduino Uno)&lt;br /&gt;
|-&lt;br /&gt;
! Mode !! Estimation Théorique !! Mesure Réelle Déduite !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| '''Blink''' || ~40 à 50 mA || ~43 mA ''(130 mA / 3)'' || Cohérent avec la théorie.&lt;br /&gt;
|-&lt;br /&gt;
| '''Power Down''' || ~25 à 35 mA || ~36 mA ''(110 mA / 3)'' || Cohérent. La très légère surconsommation s'explique (d'après mon hypothèse) des composants des clones de l'arduino qui seraient un peu plus gourmands en consommation.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Conclusion :'''&lt;br /&gt;
Le code fait bien son travail et permet d'économiser environ '''10 mA''' en endormant le microcôntroleur. Néanmoins, à cause des puces secondaires inhérentes à la carte, celle ci ne descend pas en dessous d'une trentaine de milliampères.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12950</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12950"/>
		<updated>2026-04-14T17:50:30Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /* 5. modélisation de la consommation théorique  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie)&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Si mon code est optimisé pour limiter la consommation du microcontrôleur, une carte Arduino embarque pourtant d'autres composants qui restent toujours sous tension et consomment de l'énergie en permanence, même en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== Mode Actif (Blink) ====&lt;br /&gt;
Dans ce mode, tous les composants fonctionnent à plein régime.&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~15 à 20 mA &lt;br /&gt;
* '''Puce USB-vers-Série ''' : ~15 mA (toujours allumée).&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA.&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA (au repos).&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : ~3 mA (allumée durant blink).&lt;br /&gt;
* '''Total estimé : ~40 à 50 mA'''&lt;br /&gt;
&lt;br /&gt;
==== Mode Veille (Power Down) ====&lt;br /&gt;
&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~ 5 µA. ''grâce au mode power down + mes autres optimisations supplémentaires''&lt;br /&gt;
* '''Puce USB-vers-Série''' : ~15 mA. ''(Impossible à éteindre par code)''&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA. ''(Toujours allumée)''&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA. ''(Toujours actif)''&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : 0 mA. ''(Éteinte)''&lt;br /&gt;
* '''Total estimé : ~25 à 35 mA'''&lt;br /&gt;
&lt;br /&gt;
==== Comparaison Théorie vs Pratique ====&lt;br /&gt;
En reprenant les données mesurées avec la clé USB sur le hub pour 3 Arduinos, on peut en déduire la consommation réelle d'une seule carte et la comparer à notre théorie :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Comparaison Consommation : Théorie vs Mesures (pour 1 Arduino Uno)&lt;br /&gt;
|-&lt;br /&gt;
! Mode !! Estimation Théorique !! Mesure Réelle Déduite !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| '''Blink''' || ~40 à 50 mA || ~43 mA ''(130 mA / 3)'' || Cohérent avec la théorie.&lt;br /&gt;
|-&lt;br /&gt;
| '''Power Down''' || ~25 à 35 mA || ~36 mA ''(110 mA / 3)'' || Cohérent. La très légère surconsommation s'explique (d'après mon hypothèse) des composants des clones de l'arduino qui seraient un peu plus gourmands en consommation.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Conclusion :'''&lt;br /&gt;
Le code fait bien son travail et permet d'économiser environ '''10 mA''' en endormant le microcôntroleur. Néanmoins, à cause des puces secondaires inhérentes à la carte, celle ci ne descend pas en dessous d'une trentaine de milliampères.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:all_plugged_none_switched.jpg|center|300px|0 arduinos allumées]]&lt;br /&gt;
'''3 arduinos branchées, aucune allumée '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'un seul, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:one_switched.jpg|center|300px]]&lt;br /&gt;
'''1 arduino allumée''', '''La consommation en blink est identique à celle en mode power down'''&amp;lt;br /&amp;gt;&lt;br /&gt;
la clé ne prend tout simplement pas en compte la consommation d'une arduino seule&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Petit résumé : '''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Résumé de la consommation des Arduinos&lt;br /&gt;
|-&lt;br /&gt;
! Nombre d'Arduinos !! Mode !! Courant (A) !! Tension (V) !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| 0 || éteintes || 0.00 || 5.11 || 3 branchées, aucune activée&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Power down / Blink || 0.00 || 5.11 || Consommation trop faible pour être détectée par la clé&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Power down || 0.07 || 5.08 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || Blink || 0.09 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Power down || 0.11 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Blink || 0.13 || 5.07 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12949</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12949"/>
		<updated>2026-04-14T17:50:19Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /* 5. modélisation de la consommation théorique  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie)&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Si mon code est optimisé pour limiter la consommation du microcontrôleur, une carte Arduino embarque pourtant d'autres composants qui restent toujours sous tension et consomment de l'énergie en permanence, même en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== Mode Actif (Blink) ====&lt;br /&gt;
Dans ce mode, tous les composants fonctionnent à plein régime.&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~15 à 20 mA &lt;br /&gt;
* '''Puce USB-vers-Série ''' : ~15 mA (toujours allumée).&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA.&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA (au repos).&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : ~3 mA (allumée durant blink).&lt;br /&gt;
* '''Total estimé : ~40 à 50 mA'''&lt;br /&gt;
&lt;br /&gt;
==== Mode Veille (Power Down) ====&lt;br /&gt;
&lt;br /&gt;
* '''Microcontrôleur (ATmega328P)''' : ~ 5 µA. ''grâce au mode power down + mes autres optimisations supplémentaires''&lt;br /&gt;
* '''Puce USB-vers-Série''' : ~15 mA. ''(Impossible à éteindre par code)''&lt;br /&gt;
* '''LED de tension (Power)''' : ~3 à 5 mA. ''(Toujours allumée)''&lt;br /&gt;
* '''Régulateur de tension''' : ~2 à 5 mA. ''(Toujours actif)''&lt;br /&gt;
* '''LED &amp;quot;L&amp;quot; (Pin 13)''' : 0 mA. ''(Éteinte)''&lt;br /&gt;
* '''Total estimé : ~25 à 35 mA'''&lt;br /&gt;
&lt;br /&gt;
==== Comparaison Théorie vs Pratique ====&lt;br /&gt;
En reprenant les données mesurées avec la clé USB sur le hub pour 3 Arduinos, on peut en déduire la consommation réelle d'une seule carte et la comparer à notre théorie :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Comparaison Consommation : Théorie vs Mesures (pour 1 Arduino Uno)&lt;br /&gt;
|-&lt;br /&gt;
! Mode !! Estimation Théorique !! Mesure Réelle Déduite !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| '''Blink''' || ~40 à 50 mA || ~43 mA ''(130 mA / 3)'' || Cohérent avec la théorie.&lt;br /&gt;
|-&lt;br /&gt;
| '''Power Down''' || ~25 à 35 mA || ~36 mA ''(110 mA / 3)'' || Cohérent. La très légère surconsommation s'explique (d'après mon hypothèse) des composants des clones de l'arduino qui seraient un peu plus gourmands en consommation.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Conclusion :'''&lt;br /&gt;
Le code fait bien son travail et permet d'économiser environ '''10 mA''' en endormant le microcôntroleur. Néanmoins, à cause des puces secondaires inhérentes à la carte, celle ci ne descend pas en dessous d'une trentaine de milliampères.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:all_plugged_none_switched.jpg|center|300px|0 arduinos allumées]]&lt;br /&gt;
'''3 arduinos branchées, aucune allumée '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'un seul, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:one_switched.jpg|center|300px]]&lt;br /&gt;
'''1 arduino allumée''', '''La consommation en blink est identique à celle en mode power down'''&amp;lt;br /&amp;gt;&lt;br /&gt;
la clé ne prend tout simplement pas en compte la consommation d'une arduino seule&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Petit résumé : '''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Résumé de la consommation des Arduinos&lt;br /&gt;
|-&lt;br /&gt;
! Nombre d'Arduinos !! Mode !! Courant (A) !! Tension (V) !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| 0 || éteintes || 0.00 || 5.11 || 3 branchées, aucune activée&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Power down / Blink || 0.00 || 5.11 || Consommation trop faible pour être détectée par la clé&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Power down || 0.07 || 5.08 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || Blink || 0.09 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Power down || 0.11 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Blink || 0.13 || 5.07 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12948</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12948"/>
		<updated>2026-04-14T17:26:48Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /* 6. Consommation expérimentale  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie)&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:all_plugged_none_switched.jpg|center|300px|0 arduinos allumées]]&lt;br /&gt;
'''3 arduinos branchées, aucune allumée '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'un seul, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:one_switched.jpg|center|300px]]&lt;br /&gt;
'''1 arduino allumée''', '''La consommation en blink est identique à celle en mode power down'''&amp;lt;br /&amp;gt;&lt;br /&gt;
la clé ne prend tout simplement pas en compte la consommation d'une arduino seule&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Petit résumé : '''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Résumé de la consommation des Arduinos&lt;br /&gt;
|-&lt;br /&gt;
! Nombre d'Arduinos !! Mode !! Courant (A) !! Tension (V) !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| 0 || éteintes || 0.00 || 5.11 || 3 branchées, aucune activée&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Power down / Blink || 0.00 || 5.11 || Consommation trop faible pour être détectée par la clé&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Power down || 0.07 || 5.08 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || Blink || 0.09 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Power down || 0.11 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Blink || 0.13 || 5.07 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12947</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12947"/>
		<updated>2026-04-14T17:23:15Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /* 6. Consommation expérimentale  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie)&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:all_plugged_none_switched.jpg|center|300px|0 arduinos allumées]]&lt;br /&gt;
'''3 arduinos branchées, aucune allumée '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'un seul, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:one_switched.jpg|center|300px]]&lt;br /&gt;
'''1 arduino allumée''', '''La consommation en blink est identique à celle en mode power down'''&amp;lt;br /&amp;gt;&lt;br /&gt;
la clé ne prend tout simplement pas en compte la consommation d'une arduino seule&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Petit résumé : '''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center; margin: auto;&amp;quot;&lt;br /&gt;
|+ Résumé de la consommation des Arduinos&lt;br /&gt;
|-&lt;br /&gt;
! Nombre d'Arduinos !! Mode !! Courant (A) !! Tension (V) !! Remarques&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Aucune (éteintes) || 0.00 || 5.11 || 3 branchées, aucune activée&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Power down / Blink || 0.00 || 5.11 || Consommation trop faible pour être détectée par la clé&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Power down || 0.07 || 5.08 || &lt;br /&gt;
|-&lt;br /&gt;
| 2 || Blink || 0.09 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Power down || 0.11 || 5.07 || &lt;br /&gt;
|-&lt;br /&gt;
| 3 || Blink || 0.13 || 5.07 || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:3on_high.jpg&amp;diff=12946</id>
		<title>Fichier:3on high.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:3on_high.jpg&amp;diff=12946"/>
		<updated>2026-04-14T17:19:48Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:3on_low.jpg&amp;diff=12945</id>
		<title>Fichier:3on low.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:3on_low.jpg&amp;diff=12945"/>
		<updated>2026-04-14T17:18:24Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12944</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12944"/>
		<updated>2026-04-14T17:17:38Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /* 6. Consommation expérimentale  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie)&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:all_plugged_none_switched.jpg|center|300px|0 arduinos allumées]]&lt;br /&gt;
'''3 arduinos branchées, aucune allumée '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'un seul, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:one_switched.jpg|center|300px]]&lt;br /&gt;
'''1 arduino allumée''', '''La consommation en blink est identique à celle en mode power down'''&amp;lt;br /&amp;gt;&lt;br /&gt;
la clé ne prend tout simplement pas en compte la consommation d'une arduino seule&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:2on_1_off_high.jpg&amp;diff=12943</id>
		<title>Fichier:2on 1 off high.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:2on_1_off_high.jpg&amp;diff=12943"/>
		<updated>2026-04-14T17:14:21Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:2on_1_off_low.jpg&amp;diff=12942</id>
		<title>Fichier:2on 1 off low.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:2on_1_off_low.jpg&amp;diff=12942"/>
		<updated>2026-04-14T17:12:46Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12941</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12941"/>
		<updated>2026-04-14T17:12:24Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /* 6. Consommation expérimentale  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie)&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:all_plugged_none_switched.jpg|center|300px|0 arduinos allumées]]&lt;br /&gt;
'''3 arduinos branchées, aucune allumée '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'un seul, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:one_switched.jpg|center|300px]]&lt;br /&gt;
'''1 arduino allumée''', '''La consommation en blink est identique à celle en mode power down'''&amp;lt;br /&amp;gt;&lt;br /&gt;
la clé ne prend tout simplement pas en compte la consommation d'une arduino seule&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe que :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12940</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12940"/>
		<updated>2026-04-14T17:11:07Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /* 6. Consommation expérimentale  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie)&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:all_plugged_none_switched.jpg|center|300px|0 arduinos allumées]]&lt;br /&gt;
'''3 arduinos branchées, aucune allumée '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'un seul, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:one_switched.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''1 arduino allumée''', '''La consommation en blink est identique à celle en mode power down''' &amp;lt;br&amp;gt;&lt;br /&gt;
 la clé ne prend tout simplement pas en compte la consommation d'une arduino seule&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe que :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12939</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12939"/>
		<updated>2026-04-14T17:10:55Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /* 6. Consommation expérimentale  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie)&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:all_plugged_none_switched.jpg|center|300px|0 arduinos allumées]]&lt;br /&gt;
'''3 arduinos branchées, aucune allumée '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'un seul, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:one_switched.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''1 arduino allumée''', La '''consommation en blink est identique à celle en mode power down''' &amp;lt;br&amp;gt;&lt;br /&gt;
 la clé ne prend tout simplement pas en compte la consommation d'une arduino seule&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe que :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12938</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12938"/>
		<updated>2026-04-14T17:10:09Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /* 6. Consommation expérimentale  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie)&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:all_plugged_none_switched.jpg|center|300px|0 arduinos allumées]]&lt;br /&gt;
'''3 arduinos branchées, aucune allumée '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'un seul, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:one_switched.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''1 arduino allumée, La consommation en blink est identique à celle en mode power down''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' la clé ne prend tout simplement pas en compte la consommation d'une arduino seule&amp;quot;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe que :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12937</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12937"/>
		<updated>2026-04-14T17:09:57Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /* 6. Consommation expérimentale  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie)&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:all_plugged_none_switched.jpg|center|300px|0 arduinos allumées]]&lt;br /&gt;
'''3 arduinos branchées, aucune allumée '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'un seul, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:one_switched.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''1 arduino allumée, La consommation en blink est identique à celle en mode power down'''&lt;br /&gt;
''' la clé ne prend tout simplement pas en compte la consommation d'une arduino seule&amp;quot;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe que :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:One_switched.jpg&amp;diff=12936</id>
		<title>Fichier:One switched.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:One_switched.jpg&amp;diff=12936"/>
		<updated>2026-04-14T17:08:11Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12935</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12935"/>
		<updated>2026-04-14T17:06:21Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /* 6. Consommation expérimentale  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie)&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:all_plugged_none_switched.jpg|center|300px|0 arduinos allumées]]&lt;br /&gt;
'''3 arduinos branchées, aucune allumée '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'un seul, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:one_switched.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''1 arduino allumée, La consommation en blink est identique à celle en mode power down'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe que :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12934</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12934"/>
		<updated>2026-04-14T17:05:07Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /* 6. Consommation expérimentale  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie)&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:all_plugged_none_switched.jpg|center|300px|0 arduinos allumées]]&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'un seul, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:one_switched.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''1 arduino allumée, La consommation en blink est identique à celle en mode power down'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe que :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_high.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''2 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:3on_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:2on_1_off_low.jpg|center|300px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''3 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12933</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12933"/>
		<updated>2026-04-14T17:03:40Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /* 6. Consommation expérimentale  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie)&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:all_plugged_none_switched.jpg|center|300px|0 arduinos allumées]]&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'un seul, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:one_switched.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''1 arduino allumée, La consommation en blink est identique à celle en mode power down'''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe que :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:2on_1_off_low.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''2 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:2on_1_off_high.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''2 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:3on_low.jpg.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''3 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:2on_1_off_low.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''3 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12932</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12932"/>
		<updated>2026-04-14T17:02:58Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /* 6. Consommation expérimentale  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie)&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:all_plugged_none_switched.jpg|thumb|300px|0 arduinos allumées]]&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'un seul, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:one_switched.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''1 arduino allumée, La consommation en blink est identique à celle en mode power down'''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe que :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:2on_1_off_low.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''2 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:2on_1_off_high.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''2 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:3on_low.jpg.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''3 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:2on_1_off_low.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''3 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:All_plugged_none_switched.jpg&amp;diff=12931</id>
		<title>Fichier:All plugged none switched.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:All_plugged_none_switched.jpg&amp;diff=12931"/>
		<updated>2026-04-14T17:00:14Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12930</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12930"/>
		<updated>2026-04-14T16:58:32Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /* 6. Consommation expérimentale  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie)&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:all_plugged_none_switched.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''0 arduinos allumées'''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'un seul, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:one_switched.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''1 arduino allumée, La consommation en blink est identique à celle en mode power down'''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe que :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:2on_1_off_low.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''2 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:2on_1_off_high.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''2 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:3on_low.jpg.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''3 arduinos allumées, Consommation en mode power down '''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:2on_1_off_low.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''3 arduinos allumées, Consommation en mode blink '''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12929</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12929"/>
		<updated>2026-04-14T16:57:36Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /* 6. Consommation expérimentale  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie)&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant aucune : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:all_plugged_none_switched.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''0 arduinos ON'''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
J'ai ensuite branché les 3 arduinos sur le hub en n'en allumant qu'un seul, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:one_switched.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''1 arduino ON, La consommation en blink est identique à celle en mode power down'''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe que :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:2on_1_off_low.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''2 arduinos ON, Consommation en mode power down '''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:2on_1_off_high.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''2 arduinos ON, Consommation en mode blink '''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:3on_low.jpg.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''3 arduinos ON, Consommation en mode power down '''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:2on_1_off_low.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''3 arduinos ON, Consommation en mode blink '''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12928</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12928"/>
		<updated>2026-04-14T16:49:56Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /* 4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie)&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant qu'un seul, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:one_switched.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''1 arduino ON, La consommation en blink est identique à celle en mode power down'''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe que :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:2on_1_off_low.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''2 arduino ON, Consommation en mode power down '''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:2on_1_off_high.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''2 arduino ON, Consommation en mode blink '''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:3on_low.jpg.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''3 arduino ON, Consommation en mode power down '''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:2on_1_off_low.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''3 arduino ON, Consommation en mode blink '''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12927</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12927"/>
		<updated>2026-04-14T16:49:39Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /* 6. Consommation expérimentale  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie)&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down2.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down2.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant qu'un seul, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:one_switched.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''1 arduino ON, La consommation en blink est identique à celle en mode power down'''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe que :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:2on_1_off_low.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''2 arduino ON, Consommation en mode power down '''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:2on_1_off_high.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''2 arduino ON, Consommation en mode blink '''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:3on_low.jpg.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''3 arduino ON, Consommation en mode power down '''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:2on_1_off_low.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''3 arduino ON, Consommation en mode blink '''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12926</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12926"/>
		<updated>2026-04-14T16:46:55Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /* 6. mesure de la consommation totale  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie)&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down2.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down2.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. Consommation expérimentale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
J'ai d'abord branché les 3 arduinos sur le hub en n'en allumant qu'un seul, tout comme la dernière fois, les consommations en blink et en hibernation sont les mêmes : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:one_switched.jpg]] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''1 arduino ON, La consommation en blink est identique à celle en mode power down'''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En activant deux Arduino et en synchronisant leurs clignotements, on observe que :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:2on_1_off_low.jpg] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''2 arduino ON, Consommation en mode power down '''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:2on_1_off_high.jpg] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''2 arduino ON, Consommation en mode blink '''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enfin, en activant les 3 arduinos on obtient : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:3on_low.jpg.jpg] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''3 arduino ON, Consommation en mode power down '''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  [[Fichier:2on_1_off_low.jpg] &amp;lt;br /&amp;gt;&lt;br /&gt;
  '''3 arduino ON, Consommation en mode blink '''&lt;br /&gt;
 &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12925</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12925"/>
		<updated>2026-04-14T14:57:25Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /*  Travail réalisé  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie)&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down2.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down2.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;6. mesure de la consommation totale &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12893</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12893"/>
		<updated>2026-04-05T15:32:11Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /*  Historique  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16h16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C &amp;lt;br&amp;gt;&lt;br /&gt;
_ 05/04 17h23 : Ajout de la partie sur la modélisation théorique de consommation (non remplie)&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down2.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down2.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12892</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12892"/>
		<updated>2026-04-05T15:28:22Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /* 5. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16:16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down2.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down2.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. modélisation de la consommation théorique &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12891</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12891"/>
		<updated>2026-04-05T15:27:10Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /* 4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16:16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down2.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down2.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12890</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12890"/>
		<updated>2026-04-05T15:26:33Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /*  IV. Utilisation du WatchDog, registre WDTCSR  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16:16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci-dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog reglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down2.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down2.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12889</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12889"/>
		<updated>2026-04-05T15:26:13Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /*  IV. Utilisation du WatchDog, registre WDTCSR  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16:16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le réveiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog reglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down2.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down2.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12888</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12888"/>
		<updated>2026-04-05T15:25:46Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /*  III. Désactivation des Clocks des périphériques non utilisés  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16:16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déjà fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le révéiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog reglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down2.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down2.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12887</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12887"/>
		<updated>2026-04-05T15:25:24Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /*  III. Désactivation des Clocks des périphériques non utilisés  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16:16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le système ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déja fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le révéiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog reglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down2.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down2.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12886</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12886"/>
		<updated>2026-04-05T15:24:26Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /*  II. Désactivation des Interruptions, SREG, cli( ) et sei( )  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16:16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci-dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le sytème ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déja fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le révéiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog reglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down2.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down2.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12885</id>
		<title>SE3 2025/2026 EC1</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE3_2025/2026_EC1&amp;diff=12885"/>
		<updated>2026-04-05T15:23:58Z</updated>

		<summary type="html">&lt;p&gt;Jramesh : /*  I. registre SMCR et header sleep.h  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Objectifs &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Réaliser le programme d’économie d’énergie du cours/TP concernant la programmation sur microcontrôleur AVR :&lt;br /&gt;
&lt;br /&gt;
* le programme fait clignoter la LED de la carte plusieurs fois rapidement ;&lt;br /&gt;
* le programme entre alors en hibernation pendant plusieurs secondes ; &lt;br /&gt;
* évaluez la consommation dans deux implantations différentes :&lt;br /&gt;
**hibernation réalisée avec un simple &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
**hibernation réalisée avec une mise en sommeil de l’ATmega328p. &lt;br /&gt;
&lt;br /&gt;
Vous tenterez aussi de comprendre vos résultats empiriques :&lt;br /&gt;
* modélisez la consommation théorique en prenant en compte les principaux composants de l'Ardunio Uno ;&lt;br /&gt;
* comparez avec les mesures effectuées.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Matériel nécessaire &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Arduino Uno avec câble USB ;&lt;br /&gt;
* Dispositif de mesure de la consommation sur un port USB.&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Historique &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
_ 20/02 23h35 : première modification du wiki, rajout &amp;quot;Historique&amp;quot; + update &amp;quot;travaux réalisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 00h05 : Ajout de la datasheet de l'arduino uno + rajout &amp;quot;Documents utilisés&amp;quot; &amp;lt;br&amp;gt;&lt;br /&gt;
_ 22/02 02h40 : Ajout de blink.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
_ 24/02 23h46 : Ajout de blink.mp4 ( démonstration de blink.c ) &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 11h25 : Ajout veille_delay.c + instructions de compilations &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Problème Majeur : il me semble que la clé évaluant la consommation d'énegie de mon arduino ne marche pas. Cela se voit d'abord dans blink.mp4 où le compteur est immobile, &lt;br /&gt;
de même pour veille_delay.mp4 que je n'ai pas encore téléversé.&lt;br /&gt;
Ainsi, je vais continuer à travailler mes codes pour l'instant et je repasserai sur la partie consommation quand j'aurai les moyens de le faire.&lt;br /&gt;
&lt;br /&gt;
_ 26/02 14~15 : Modifications esthétiques &amp;lt;br&amp;gt;&lt;br /&gt;
_ 26/02 16h47 : Ajout de ma justification de méthode de veille de l'ATmega328P &amp;lt;br&amp;gt;&lt;br /&gt;
_ 27/02 15h-00h42 : Ajout des éléments I, II, III, IV dans la partie justification du code + Ajout de power_down.c + modifications mineures &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
_ 05/04 16:16 : gestion du sommeil et du watchdog à l'aide de registres et non de fonctions, comme demandé, au sein du nouveau code : power_down2.c + instruction de compilation + corrections de coquilles mineures &amp;lt;br&amp;gt; je teste la clé dès que je mets la main sur un câble usb-B usb-C&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Travail réalisé &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
Afin de se rendre la tâche plus facile nous allons nous découper le code en plusieurs morceaux,&lt;br /&gt;
* &amp;lt;code&amp;gt;blink.c&amp;lt;/code&amp;gt; -&amp;gt; pour faire clignoter la led,&lt;br /&gt;
* &amp;lt;code&amp;gt;veille_delay.c&amp;lt;/code&amp;gt; -&amp;gt; code pour mettre l'arduino en veille avec la méthode du &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;power_down.c&amp;lt;/code&amp;gt; -&amp;gt; pareil avec la deuxième méthode.&lt;br /&gt;
&lt;br /&gt;
Tout code disponible sur le Wiki : &lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;1. blink.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
  // configurer la led en sortie :&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
  for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
    // led on&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
    // led off&lt;br /&gt;
    PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
    _delay_ms(BLINK_DELAY);&lt;br /&gt;
  }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o blink.elf blink.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* pour mettre le code en flash :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:blink.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:blink.mp4.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration blink.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;2. veille_delay.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
Ce code permet de faire clignoter la led 5 fois avant d'entrer en hibernation par un _delay_ms de 3 secondes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#define BLINK_DELAY 500 // en milli secondes&lt;br /&gt;
#define VEILLE_DELAY 3000 // en ms&lt;br /&gt;
&lt;br /&gt;
int main (){&lt;br /&gt;
        while (1){&lt;br /&gt;
                 // configurer la led en sortie :&lt;br /&gt;
                 DDRB |= (1 &amp;lt;&amp;lt; 5); // PORTB 5e bit pour la led&lt;br /&gt;
&lt;br /&gt;
                 for(int i=0; i&amp;lt;5 ; i++){&lt;br /&gt;
                 // led on&lt;br /&gt;
                         PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
&lt;br /&gt;
                 // led off&lt;br /&gt;
                         PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                         _delay_ms(BLINK_DELAY);&lt;br /&gt;
                 }&lt;br /&gt;
                 // hibernation&lt;br /&gt;
                 _delay_ms(VEILLE_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o veille_delay.elf veille_delay.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex veille_delay.elf veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:veille_delay.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_veille_delay.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration veille_delay.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3. power_down.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.a) Justification de mon choix de méthode de veille &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
D'après la datasheet avr de l'atmega328P, il existe 6 modes différents de mise en veille : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:sleep_modes.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Tables des différentes méthodes de mise en Veille de l'ATmega32P''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La méthode utilisant le moins d'énergie serait par logique celle qui utilise le '''moins de ressources possibles''', c'est-à-dire qui désactive le plus de Clocks possible. &amp;lt;br&amp;gt;&lt;br /&gt;
Ici il semblerait que ce soit la méthode '''&amp;quot;Power Down&amp;quot;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais encore, mon choix s'affirme une seconde fois car il nous est pas demandé d'utiliser une interruption extérieure pour permettre à l'arduino de se réveiller, et plus il existe de manières de réveiller l'ATmega plus elle consommera d'énergie.&lt;br /&gt;
Nous partirons ainsi sur la méthode qui utilise le moins de Wake up sources : Power Down.&lt;br /&gt;
Le seul point à respecter étant que l'ATmega soit '''capable de se réveiller d'elle même''', c'est-à-dire en utilisant son WatchDog, condition qui est respectée. &amp;lt;br&amp;gt;&lt;br /&gt;
On utilise le timer du WatchDog car '''_delay_ms''' n'est '''pas utilisable''' en mode Power Down.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.b) Justification des éléments du code &amp;lt;/span&amp;gt; ====&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; I. registre SMCR et header sleep.h &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Afin de faire entrer l'ATmega en mode '''Power Down''' il suffit de modifier le registre SMCR (Sleep Mode Control Register)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SMCR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour entrer en mode '''Power Down''' spécifiquement : &lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:bit_order.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
''' Arrangement des bits SMCR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce qui ressemblerait à :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cependant, la procédure de mise en sommeil est plus complexe car elle nécessite aussi l'utilisation de l'instruction assembleur '''sleep''' &amp;lt;br&amp;gt;&lt;br /&gt;
Pour y pallier (même dans la documentation officielle du site Microchip sur les AVR), on utilise les fonctions &amp;lt;code&amp;gt;set_sleep_mode();&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;sleep_mode();&amp;lt;/code&amp;gt; toutes deux provenant du header '''&amp;lt;avr/sleep.h&amp;gt;'''. &amp;lt;br&amp;gt;&lt;br /&gt;
'''set_sleep_mode() :''' Cette fonction correspond exactement à notre ligne de code précédente quand on y passe l'argument SLEEP_MODE_PWR_DOWN &amp;lt;br&amp;gt; &lt;br /&gt;
'''sleep_mode() :''' C'est la partie &amp;quot;complexe&amp;quot; car elle s'occupe non seulement de l'instruction sleep mais aussi de mettre le bit SE (Sleep Enable) du SMCR à une valeur de 1 (Nécessaire pour plonger le MCU en mode sleep)... &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
En utilisant ces deux fonctions conformément à la documentation Microchip, on obtient : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
sleep_mode();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Attention !''' : en sleep_mode( ), l'ATmega ne répondra plus à rien, seul l'interruption du watchdog pourra la réveiller, donc toujours mettre cette instruction en fin de code lorsqu'il ne reste plus rien à faire.&lt;br /&gt;
&lt;br /&gt;
Pourtant, on peut aussi tout faire avec les registres :  &amp;lt;br&amp;gt;&lt;br /&gt;
en modifiant le bit '''SE ( sleep enable ) ''' de SMCR en le mettant à 1.&amp;lt;br&amp;gt;&lt;br /&gt;
Couplé à l'instruction : &amp;lt;code&amp;gt; asm(&amp;quot;SLEEP&amp;quot;) &amp;lt;/code&amp;gt; qui remplace la fonction &amp;quot;sleep()&amp;quot;. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; II. Désactivation des Interruptions, SREG, cli( ) et sei( ) &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même en mode '''Power Down''' il ne faut pas oublier de désactiver les interruptions globales. &amp;lt;br&amp;gt;&lt;br /&gt;
En effet, on a vu auparavant tous les types d'interruptions que le mode Power Down permet. Or, pour éviter d'interrompre le timer du watchdog, il faut manuellement les désactiver. &amp;lt;br&amp;gt;&lt;br /&gt;
Soit en utilisant le registre SREG et en travaillant avec le bit 7 comme indiqué ci dessous : &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:SREG.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre SREG''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit en utilisant directement la fonction &amp;quot;'''cli( )'''&amp;quot; puis en réactivant les interruptions à la fin du code avec &amp;quot;'''sei( )'''&amp;quot; contenus dans le header &amp;lt;avr/interrupt.h&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; III. Désactivation des Clocks des périphériques non utilisés &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
Même si le mode '''Power Down''' est activé, il est préférable de désactiver manuellement toutes les clocks qui ne nous sont pas utile afin d'économiser un maximum d'énergie. &amp;lt;br&amp;gt;&lt;br /&gt;
En sachant que nous n'utilisons que le watch dog, le reste peut être désactivé. &amp;lt;br&amp;gt;&lt;br /&gt;
Principalement le système &amp;quot;'''ADC'''&amp;quot; ( je n'ai pas réussi à parfaitement comprendre ce qu'il fait, mis à part assurer la capacité de l'ATmega à utiliser ses pins, mais j'ai compris qu'il était gourmand en énergie et je n'utilise pas de pins dans ce code, donc autant le désactiver pour gagner de l'énergie). &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis ensuite désactiver les clocks des périphériques non utilisés (SPI, timer...).&lt;br /&gt;
&lt;br /&gt;
Pour éteindre le sytème ADC il suffit de modifier la '''bit 7 du registre ADCSRA: '''&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:ADCSRA.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre ADCSRA''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soit : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; 7); &amp;lt;/code&amp;gt; ou pour plus de lisibilité : &amp;lt;code&amp;gt; ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN); &amp;lt;/code&amp;gt; avec EN pour &amp;quot;Enable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Puis, il faut désactiver les clocks, toutes sauf celle de la watchdog car c'est la seule que l'on utilisera. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
en important le header ''' &amp;lt;avr/interrupt.h&amp;gt; '''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
// power_adc_disable(); ( déja fait précédemment ) &lt;br /&gt;
power_usart0_disable();&lt;br /&gt;
power_spi_disable();&lt;br /&gt;
power_timer0_disable();&lt;br /&gt;
power_timer1_disable();&lt;br /&gt;
power_timer2_disable();&lt;br /&gt;
power_twi_disable();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ce qui peut être résumé par : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_disable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
évidemment il ne faut pas oublier de réactiver les clocks pour pouvoir utiliser delay_ms() pour faire clignoter la led après le réveil de l'ATmega. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
power_all_enable ();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt; IV. Utilisation du WatchDog, registre WDTCSR &amp;lt;/span&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
En sachant qu'en mode Power Down, nous n'avons pas accès à _delay_ms(), on utilisera le WatchDog. &amp;lt;br&amp;gt;&lt;br /&gt;
Pour cela supposons que l'on veut mettre l'ATmega en mode Power Down pendant 4 secondes ( temps de sommeil de l'ATmega ) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faudra alors établir un timer, en utilisant le registre WDTCSR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:WDTCSR.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Registre WDTCSR''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[Fichier:timer.png|centré|sans_cadre|900x900px]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Soit 512k cycle pour 4s ''' &amp;lt;br&amp;gt;&lt;br /&gt;
''' source : datasheet avr ATmega328P '''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Pour pouvoir modifier le timer WatchDog, il faut d'abord reset le WatchDog avec &amp;lt;code&amp;gt; wdt_reset(); &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Puis avant de pouvoir lui ordonner de compter nos 4 secondes il faut pouvoir le modifier, pour cela on utilise les bit WDCE et WDE. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDCE (Watchdog Change Enable) :''' Tant qu'il est à 0, toute écriture sur les bits de durée est ignorée par le hardware, donc il faut le mettre à 1. &amp;lt;br&amp;gt;&lt;br /&gt;
'''WDE (Watchdog System Reset Enable) : ''' Son rôle ne m'est pas vraiment clair mais la documentation de chez Microchip impose que WDE soit fixé à 1 pour modifier le timer. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aussi faut-il mettre à 1 le bit '''WDIE (Watchdog Interrupt Enable)''' qui permet au watchdog &amp;quot;d'interrompre&amp;quot; l'ATmega et ainsi de le révéiller. &amp;lt;br&amp;gt;&lt;br /&gt;
On met aussi le bit '''WDP3 à 1''' pour avoir un timer de '''4s''' comme indiqué ci dessus.&lt;br /&gt;
&lt;br /&gt;
Soit :  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
WDTCSR |= (1&amp;lt;&amp;lt;WDCE) | (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;3.c) Code power_down.c et instructions de compilation &amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                wdt_reset();&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog réglé on peut dormir&lt;br /&gt;
                sleep_mode();&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down.elf power_down.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down.elf power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;4. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/power.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
//#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BLINK_DELAY 320 // ms&lt;br /&gt;
&lt;br /&gt;
void blink_module(){&lt;br /&gt;
        for(int i=0; i &amp;lt;= 3; i++){&lt;br /&gt;
                //led ON&lt;br /&gt;
                PORTB |= (1 &amp;lt;&amp;lt; 5); // OR&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
                //led OFF&lt;br /&gt;
                PORTB &amp;amp;= ~ (1 &amp;lt;&amp;lt; 5); // AND + NOT&lt;br /&gt;
                _delay_ms(BLINK_DELAY);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
        // PB5 en sortie&lt;br /&gt;
        DDRB |= (1 &amp;lt;&amp;lt; 5);&lt;br /&gt;
        // désactivation de l'ADC&lt;br /&gt;
        ADCSRA &amp;amp;= ~(1 &amp;lt;&amp;lt; ADEN);&lt;br /&gt;
        while(1){&lt;br /&gt;
                // désactivation interruptions globales&lt;br /&gt;
                cli();&lt;br /&gt;
                // désactivations clocks inutiles&lt;br /&gt;
                power_all_disable();&lt;br /&gt;
                // call blink&lt;br /&gt;
                blink_module();&lt;br /&gt;
                // setting power down mode&lt;br /&gt;
                SMCR = (0 &amp;lt;&amp;lt; SM2) | (1 &amp;lt;&amp;lt; SM1) | (0 &amp;lt;&amp;lt; SM0);&lt;br /&gt;
                // reset watchdog timer&lt;br /&gt;
                asm( &amp;quot;WDR &amp;quot;);&lt;br /&gt;
                // WatchDog timer de 4s&lt;br /&gt;
                WDTCSR |= (1&amp;lt;&amp;lt;WDCE)| (1&amp;lt;&amp;lt;WDE);&lt;br /&gt;
                WDTCSR = (1 &amp;lt;&amp;lt; WDIE)| (1&amp;lt;&amp;lt;WDP3);&lt;br /&gt;
                // reactivation des interruptions&lt;br /&gt;
                sei();&lt;br /&gt;
                // une fois le watchdog reglé on peut dormir&lt;br /&gt;
                SMCR = (1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                asm(&amp;quot;SLEEP&amp;quot;);&lt;br /&gt;
                // une fois que 4s sont écoulés, sortie de veille:&lt;br /&gt;
                SMCR &amp;amp;= ~(1 &amp;lt;&amp;lt; SE);&lt;br /&gt;
                // reactivation des clocks (pour _delay_ms)&lt;br /&gt;
                power_all_enable();&lt;br /&gt;
        }&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour compiler : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avr-gcc -mmcu=atmega328p -Wall -Werror -I. -DF_CPU=16000000 -Os \&lt;br /&gt;
-o power_down2.elf power_down2.c&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex power_down2.elf power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour mettre le code en flash : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
avrdude -v -patmega328p -carduino -b115200 -P/dev/ttyACM0 \&lt;br /&gt;
-U flash:w:power_down2.hex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
[[2025_EC1_power_down2.mp4]] &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Démonstration power_down2.c'''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;span style=&amp;quot;color:#800020;font-weight: bold;&amp;quot;&amp;gt;5. Version avec registre pour la gestion du watchdog et de la mise en sommeil : power_down2.c &amp;lt;/span&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Documents utilisés &amp;lt;/span&amp;gt; =&lt;br /&gt;
[[Datasheet_arduino_uno.pdf]] &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datasheet_AVR.pdf]]&lt;br /&gt;
&lt;br /&gt;
= &amp;lt;span style=&amp;quot;color:#A45B3D;font-weight: bold;&amp;quot;&amp;gt; Nota Bene &amp;lt;/span&amp;gt; =&lt;br /&gt;
&lt;br /&gt;
* Problème majeur rencontré : dysfonctionnement de l'outil de mesure de consommation d'énergie &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Inspiration esthétique de ma page wiki prise de Kaoutar El Bachiri &amp;lt;br&amp;gt;&lt;br /&gt;
(https://wiki-se.plil.fr/mediawiki/index.php/SE5_IdO_s%C3%A9curit%C3%A9_des_objets_2025/2026_b2)&lt;br /&gt;
&lt;br /&gt;
* Sites utilisés : &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt; pour la justification du choix de mode de veille et la construction de mon code : &amp;lt;/u&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.ewskills.com/arduino/sleep-modes &amp;lt;br&amp;gt;&lt;br /&gt;
. https://circuitdigest.com/microcontroller-projects/arduino-sleep-modes-and-how-to-use-them-to-reduce-power-consumption &amp;lt;br&amp;gt;&lt;br /&gt;
. https://wolles-elektronikkiste.de/en/sleep-modes-and-power-management#Anker2 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://www.avrfreaks.net/s/topic/a5C3l000000UcdbEAC/t162315 &amp;lt;br&amp;gt;&lt;br /&gt;
. https://onlinedocs.microchip.com/oxy/GUID-EAD481FD-28E6-4CD5-87FB-5165E7687C12-en-US-5/GUID-3B54E66E-AE92-459F-99E6-EF5B8655258F.html &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jramesh</name></author>
	</entry>
</feed>