Cours:TPS 2103 tp powerfuses

De troyesGEII
Révision datée du 25 mai 2020 à 07:57 par Bjacquot (discussion | contributions) ({{Rouge|Servomoteur}})
(diff) ← Version précédente | Voir la version actuelle (diff) | Version suivante → (diff)
Aller à : navigation, rechercher

Retour à la liste des Tps

Éléments de correction

IMPORTANT, à la fin du tp, remettre le µcontrôleur dans la configuration initiale à l'aide de la commande suivante :

avrdude -pm328p -cavrisp2 -Pusb -B 100 -u -Ulfuse:w:0xc2:m -Uhfuse:w:0xd9:m -Uefuse:w:0x7:m


Attention, suivant la source d'horloge, il peut être nécessaire d'ajouter l'option -B 100 pour avrdude, afin de réduire la vitesse de programmation.


Atmega328p.png

Nous utiliserons un atmega328p en format DIP, que nous placerons sur une plaque à essais(le µcontrôleur présent sur les cartes arduino).


Câblage

Alimentation

Il faut bien évidemment alimenter notre composant.

On prendra une alimentation 5V continue, sur laquelle vous relierez un ampèremètre qui nous permettra de faire des mesures de consommation.

Pensez à relier tous les GND, ainsi que la broche AVCC (tension pour le convertisseur analogique-numérique).

Programmation

Avr isp.jpg

Nous utiliserons un programmateur olimex avr-isp mkii, qu'il convient de relier correctement au µcontrôleur.

La figure ci-contre d'une part, et celle en début de document d'autre part, sont suffisante pour réaliser le câblage.

Attention, le connecteur ISP tel que représenté est une vue du connecteur mâle normalement soudé sur la carte électronique à programmer. Il faut de servir du bossage sur le connecteur qui indique le côté de la broche n°1.

On ne connectera pas le VCC/VTG du connecteur de programmation, le µcontrôleur étant déjà relié à une alimentation.

Vérification

Todo.jpg Vérifions que le µcontrôleur est bien connecté en exécutant l'instruction suivante qui permet de tester la communication avec le programmateur :

avrdude -c avrisp2 -P usb -p m328p -B 100

Remarque : si cela ne fonctionne pas, il peut être nécessaire d'ajouter un Quartz entre les broches XTAL1-XTAL2

Source d'horloge

Dans cette partie, nous allons modifier la configuration du µcontrôleur au travers de ces fusibles.

L'objectif est de comparer différentes horloges et d'étudier les conséquences en terme de consommation.

Attention, modifier les fusibles n'est pas sans conséquences, et une mauvaise manipulation peut entraîner un blocage irrémédiable du µcontrôleur. En cas de doute, faire vérifier votre configuration !

Signal périodique à 1kHz

Nous souhaitons générer un signal à 1kHz, en utilisant le module adapté : un timer.

L'objectif n'étant pas ici de consacrer notre temps à la configuration de ce timer, vous pouvez utiliser cette page de calcul libreoffice. Il va sans dire que le timer sera :

  • configuré en mode CTC
  • Fcomparaison = 2.Fsortie (Fréquence de comparaison et Fréquence du signal de sortie)
  • la sortie sera directement pilotée par le timer (configuration du module de sortie avec bits COMxxx)

Question.jpg Choisissez un timer, branchez un oscilloscope et observez signal et consommation pour :

  • Oscillateur interne 1MHz
  • Oscillateur interne 8MHz
  • Oscillateur interne 128kHz
  • Oscillateur externe 16MHz (Quartz)

La sélection de l'horloge s'effectue grâce aux fusibles.

La description est donnée partie 9 (page 27 et suivantes) de la datasheet atmel de l'atmega328p.

Todo.jpg Comparer les résultats pour les différentes horloges

Mode d'économie d'énergie

Passez à la suite si vous avez passé plus de 30 minutes sur la question précédente !

On souhaite aller un peu plus loin dans la gestion de la consommation.

Pour configurer ce mode d'économie d'énergie, vous utiliserez les fonctions du fichier avr/sleep.h, dont :

  • sleep_enable() : autorise l'entrée dans un mode d'économie d'énergie
  • set_sleep_mode(mode) : mode à utiliser tel qu'indiqué dans le tableau ci-dessous
  • sleep_mode() : passe le µcontrôleur dans le mode configuré
Sleep Mode valeur programme c
idle SLEEP_MODE_IDLE
ADC Noise Reduction SLEEP_MODE_ADC
Standby SLEEP_MODE_STANDBY
Power-Down SLEEP_MODE_PWR_DOWN

Remarque :

  • Les TIMERs utilisent (sauf cas particulier) l'horloge CLKio
  • Le registre PRR permet une gestion plus fine de l'économie d'énergie

Question.jpg Lire la datasheet pages 39 et suivantes (partie 10). Reprendre votre signal de 1kHz de la question précédente à l'aide du timer. Passer le µcontrôleur en mode IDLE d'économie d'énergie pour voir si l'ensemble fonctionne toujours. Puis essayer les autres modes. Conclusion.

Servomoteur

Les servomoteurs possèdent généralement un connecteur à 3 contacts qui sont :

  • rouge : VCC (ici et en général +5V)
  • noir : GND
  • jaune : signal de consigne/commande

Les servomoteurs utilisés ici sont commandés en position, c'est à dire que suivant la consigne, le moteur tourne jusqu'à la valeur désirée.

Il existe également des commandes en vitesse, et dans ce cas c'est la vitesse de rotation qui est fonction de la commande.

Le signal de consigne est tel qu'indiqué sur la figure ci-dessous : TiemposServo

MLI

On constate sur la figure qu'il est nécessaire de générer un signal MLI (ou PWM) dont la fréquence (ou période) est indiquée sur la figure.

Remarquons que le rapport cyclique ne devra varier que dans une certaine plage, et non de 0% à 100%.

Question.jpg Écrire un programme qui fait varier la position du servomoteur entre ses positions extrêmes.

Remarques

  • Vous devez choisir une source d'horloge (cf fuses)
  • Vous devez choisir un timer
  • Vous devez configurer ce timer
  • Il existe pour la plupart des TIMERs un mode PWM dont la valeur maximum du TIMER est réglable
    • mode 7 pour TIMER0/TIMER2
    • mode 14 pour TIMER1

Potentiomètre

Can atmega328.png

Nous souhaitons maintenant commander la position du servomoteur au travers d'un potentiomètre.

On reliera bien évidemment ce potentiomètre sur une entrée analogique du µcontrôleur.

Question.jpg Écrire un programme répondant au cahier des charges

Consommation

On souhaite bien évidemment réduire au maximum la consommation du µcontrôleur.

Attention à ne pas mesurer la consommation du servomoteur lors des mesures réalisées.

Question.jpg Faire en sorte de minimiser la consommation

Monostable

Face au faible coût des µcontrôleur, la facilité de programmation et la faible consommation, ils sont de plus en plus utilisés pour remplacer des composants spécialisés.

C'est le cas de la fonction monostable qui était souvent réalisée avec un NE555.

Il est bien évident que si le µcontrôleur utilisé aujourd'hui est un peu "gros" pour jouer ce rôle, il convient cependant pour illustrer le principe.

Nous relions à ce µcontrôleur 1 bouton et 1 led.

  • un appui sur le bouton allume la led
  • cette led reste allumée pendant un temps déterminé puis s'éteint
  • il faut attendre un nouvel appui pour que la led se rallume

monostable basique

Question.jpg Réalisez une telle fonction, en essayant toujours de minimiser la consommation :

  • il est judicieux d'utiliser un TIMER pour la gestion du temps de déclenchement
  • le bouton sera judicieusement connecté à une interruption
  • le mode d'économie d'énergie peut changer :
    • un mode pendant que la led est allumée dans lequel le TIMER fonctionne
    • un mode en attente d'une interruption associée au bouton, dans lequel tout (ou presque) est arrêté

monostable évolué

Ajoutons quelques fonctions à notre monostable :

  • il peut être :
    • redéclenchable : on relance le chronomètre à chaque appui sur le bouton
    • non-redéclenchable : on doit attendre la fin du chronomètre avant de pouvoir le redémarrer.
  • de durée de déclenchement modifiable, au choix :
    • avec un potentiomètre
    • avec 2 boutons (+ et -)

Todo.jpg codez !!

ANNEXE : Delay_ms avec économie d'énergie

Ce que l'on tente de réaliser est un peu moins ambitieux que ce que prétend le titre de cette section. Ceci est lié au fait que toutes les durées en millisecondes ne seront pas permises, contrairement à _delay_ms().

L'idée est de remplacer un "_delay_ms" qui n'arrête pas le processeur et donc consomme de l'énergie à exécuter un programme qui ne sert à rien. On va plutôt mettre le processeur en sommeil pendant le temps d'attente et le réveiller.

Passer un processeur en mode d'économie d'énergie impose de se poser au moins deux questions qui n'ont pas de réponse générale :

  1. quel mode d'économie d'énergie choisit-on ? On choira le mode SLEEP_MODE_IDLE.
  2. comment vais-je le réveiller ? on choisira le watchdog (ou chien de garde).

Le watchdog est un timer qui, en général, sert à vérifier qu'un programme n'est pas planté. Il peut générer une interruption ou tout simplement un reset général. Comme il n'a pas encore été utilisé, on utilisera les primitives liées au fichier <avr/wdt.h>.

Question.jpg A l'aide de la datasheet pages 39 et suivantes (partie 10), faites clignoter une LED en PB4 avec un basculement toutes les secondes. L'attente sera réalisée en passant le µcontrôleur en mode IDLE d'économie d'énergie et non pas avec le classique "_delay_ms()".

Indications

Indication 1 : Le passage en mode économie d'énergie est expliqué dans le TP précédent.

Indication 2 : L'allure générale du programme sera :

#define F_CPU 16000000UL  // 16 MHz
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/wdt.h>

#define LED PB4

void system_sleep(uint8_t duration) {
// a compéter ici pour éteindre le comparateur (bit PRADC du registre PRR)

// a compéter ici pour éteindre le comparateur (bit ACD du registre ACSR)

// Toutou sort de la niche : sauvez-vous au plus vite....
   wdt_enable(duration);
// set wdt to generate interrupt instead of reset 
   WDTCSR |= (1<<WDIE);
// entrée dans la micro sieste    
 
// Toutou rentre à la niche 
   wdt_disable();

// on remet comparateur et convertisseur en route


// wait for stabilization of internal voltage 
 _delay_ms(1);
}

/* Interrupt handler for Watchdog */
ISR(WDT_vect) {
   // this is set to 0 on each interrupt, so re-force it to 1
   // set wdt to generate interrupt instead of reset (see p47)
   WDTCSR |= (1<<WDIE);
}
 
/** MAIN  */
int main (void) {  
   DDRB |= (1<<LED); // PBx as output
   //reset watchdog
   wdt_reset();
   /** end of inits */
   sei(); // enable global interrupts 
   // main loop
   while (1) {
         PORTB ^= (1<<LED);
         system_sleep(WDTO_1S);
   }
   return (0);
} /* main */

Indication 3 :

Pour savoir s'il faut mettre 1 ou 0 dans les bits pour éteindre le convertisseur analogique numérique, chercher en page 45 pour le registre PRR. L'autre (le comparateur) est identique. Pour information, ce choix de périphérique à éteindre est purement arbitraire et d'ailleurs pas très opportun puisque ces périphériques ne sont pas utilisés. C'est donc seulement pour l'exemple.

Indication 4 :

Les seules valeurs qui peuvent être passées à votre sous-programme "system_sleep()" sont liés au fait qu'elles sont immédiatement passées à "wdt_enable()" et donc ne peuvent être que les constantes de cet extrait de fichier :

#define WDTO_15MS 0
#define WDTO_30MS 1
#define WDTO_60MS 2
#define WDTO_120MS 3
#define WDTO_250MS 4
#define WDTO_500MS 5
#define WDTO_1S 6
#define WDTO_2S 7
#define WDTO_4S 8
#define WDTO_8S 9