Certaines applications pour un réseau de trains miniatures ne requièrent pas toute la puissance d’un module Arduino/Genuino Uno et on peut trouver dommage de monopoliser un tel module pour si peu. La solution est de les confier à un microcontrôleur moins puissant, donc moins coûteux. Cette série d’articles vous présente le microcontrôleur ATtiny45 du constructeur Atmel et ses possibilités dans le domaine du modélisme ferroviaire.
Aujourd’hui, je vous propose de découvrir que l’ATtiny possède d’autres possibilités qui peuvent être mise en œuvre très facilement grâce au logiciel de programmation des cartes Arduino encore appelé IDE.
Le microcontrôleur ATtiny45
Le microcontrôleur ATtiny45 (8)
D’autres possibilités de l’ATtiny
.
Par :
DIFFICULTÉ :★★☆
Lorsque les ingénieurs conçoivent un microcontrôleur, ils cherchent à le rendre le plus polyvalent possible et le dotent de nombreuses interfaces pour que celui-ci puisse appréhender le mieux possible le monde extérieur. La série ATtiny25/45/85 n’échappe pas à cette règle et bien que la puce ne dispose que de 8 broches, nous allons retrouver des fonctions auxquelles nous étions habitués avec les cartes UNO. Dans l’article Le microcontrôleur ATtiny45 (1), nous avons démontré qu’il n’y a pas de grande différence de conception entre un ATtiny25/45/85 et un ATmega328 (celui qui équipe les cartes UNO), même s’il est vrai que ce dernier offre un plus grand nombre de broches d’entrée-sortie. On peut donc logiquement penser que notre ATtiny, malgré son nombre de broches restreint, offre des possibilités similaires à un ATmega328. Pour s’en convaincre, il suffit de regarder le brochage des ATtiny et les possibilités de chaque broche.
Entrées analogiques de l’ATtiny
La figure 1 a déjà été présentée dans l’article Le microcontrôleur ATtiny45 (1) et permet de voir que les broches sont multiplexées, ce qui signifie qu’elles peuvent servir à plusieurs choses. Nous pouvons voir qu’il existe une fonction ADC (pour Analog to Digital Converter) que nous avons soulignée en jaune.
Il s’agit d’un convertisseur analogique numérique, capable de lire une tension analogique pouvant varier continûment et la convertir en une valeur numérique comprise entre 0 et 1023. La tension à lire doit être comprise entre 0 et la tension de référence, qui par défaut est la tension d’alimentation Vcc mais peut aussi être une tension sur l’entrée AREF ou une des tensions générée par le chip 1,1 V ou 2,56V. Pour nos applications au train miniature, cette tension est souvent fournie par un capteur ou un diviseur de tension (par exemple, un simple potentiomètre). La valeur obtenue est comprise entre 0 et 1023 (soit 1024 possibilités) car l’échantillonnage se fait sur 10 bits (et 2 à la puissance 10 donne 1024). La carte UNO possède 6 entrées analogiques (ADC0 à ADC5), couramment appelées par l’IDE A0 à A5. Ici, nous voyons que notre ATtiny possède 4 entrées analogiques ADC0 à ADC3 :
ADC0 est sur la broche 1 qui sert de RESET ; nous éviterons donc de l’utiliser si nous voulons continuer à programmer facilement nos ATtiny avec notre carte Arduino UNO. Il nous reste donc 3 entrées analogiques disponibles, ce qui est bien suffisant pour la majorité des applications au train miniature. Les broches 7 (ADC1), 3 (ADC2) et 2 (ADC3) sont donc les entrées analogiques de notre microcontrôleur et l’IDE les appelle respectivement A1, A2 et A3, tout comme les entrées de la carte UNO étaient appelées A0 à A5. La mise en œuvre de ces entrées analogiques se fait très simplement avec la fonction analogRead()
du langage de programmation d’Arduino : cette fonction se charge des différentes opérations nécessaires pour que le microcontrôleur transforme la tension présente sur la broche en une valeur numérique. Voyons cela sur un exemple.
Ouvrez le programme « Analoginput » donné en exemple dans l’IDE : Fichier > Exemples > 03.Analog > AnalogInput comme le montre la figure 2.
Nous allons l’adapter à un microcontrôleur ATtiny25/45/85 en changeant dans la ligne 30 le A0 en A1 (notre entrée analogique sera donc sur la broche 7) et dans la ligne 31 int ledPin = 1 au lieu de 13 (la sortie LED sera donc la broche 6). Une fois ces deux lignes modifiées, téléversez le programme dans un µC ATtiny de la série 25/45/85, en suivant la procédure décrite dans l’article Le microcontrôleur ATtiny45 (2). Une fois la puce programmée, réalisez le montage donné par la figure 3.
Le mini-potentiomètre vaut au moins 10 kΩ : ses extrêmes sont reliés à la masse et au +5 V et la sortie (broche du milieu) est reliée à l’entrée analogique A1 sur la broche 7 de l’ATtiny. Le potentiomètre agit comme un diviseur de tension et sur sa broche du milieu, on retrouve une tension comprise entre 0 et 5 V en fonction de la position du curseur du potentiomètre. La sortie PB1 (broche 6 de l’ATtiny) est reliée à une LED par l’intermédiaire d’une résistance de 330 Ω. Le tout est alimenté en 5 V, prélevé par exemple sur une carte Arduino UNO. En tournant le bouton du potentiomètre, vous ferez varier la tension sur l’entrée analogique, ce qui fera varier la durée du delay()
(comprise entre 0 et 1023), faisant ainsi varier la fréquence de clignotement de la LED. Bien entendu, vous auriez pu utiliser une autre entrée analogique (broche 2 ou 3 par exemple) ; il vous aurait suffit de mettre A1 ou A2 dans le programme. Ce montage vous prouve donc qu’il est extrêmement simple d’utiliser une entrée analogique de l’ATtiny grâce à la fonction analogRead()
qui se charge de faire ce qu’il faut pour nous. Comme vous pouvez le remarquer dans le setup, il n’est pas nécessaire de déclarer l’entrée analogique, la fonction analogRead()
faisant toutes les opérations nécessaires au fonctionnement du convertisseur analogique numérique.
PWM et ATtiny
Maintenant que nous avons vu que la fonction analogRead()
fonctionne avec un ATtiny, on peut se demander ce qu’il en est de la fonction analogWrite()
qui permet de créer un signal de type PWM sur les broches du microcontrôleur qui utilise ses timers pour le faire. L’ATmega328 avait 3 timers (deux de 8 bits et un de 16 bits) ce qui permettait d’avoir 6 sorties PWM sur un module UNO. L’ATtiny dispose de deux timers de 8 bits capables également de fabriquer des signaux de type PWM.
La génération d’un tel signal est une opération assez complexe que nous n’allons pas détailler. Ceux qui souhaitent en savoir un peu plus peuvent se reporter à l’article Les Timers (IV) et notamment aux figures 1 et 2 de cet article qui montrent que le signal est récupéré sur des broches OCnA ou OCnB, « n » étant le numéro du timer. La figure 4 montre que certaines broches de l’ATtiny sont appelées OCnX, « n » étant 0 ou 1 (il n’y a que deux timers) et X étant A ou B (les deux canaux pour chaque timer).
La broche 6 permet d’avoir soit le signal OC0B, soit le signal OC1A. Malgré ce multiplexage de fonctions, l’ATtiny semble disposer de 3 broches (3, 5 et 6 ou encore PB4, PB0 et PB1) où il doit être possible de générer de la PWM grâce à la fonction analogWrite()
qui se chargera de réaliser à notre place toutes les opérations nécessaires à la génération de tels signaux.
Voyons cela sur un exemple. Le programme suivant génère trois PWM de rapports cycliques différents (15%, 50% et 85 %) envoyés sur trois LED identiques connectées aux trois sorties PWM de l’ATtiny. Une quatrième LED, identique aux trois autres, est allumée en permanence et permet de comparer son éclat à ceux des autres LED. Vérifiez le programme puis téléversez-le dans un microcontrôleur ATtiny25/45/85.
Programme ATtiny_troisPWM :
// ************************************************************************
// ATtiny_troisPWM.ino
// ************************************************************************
// Envoie un signal PWM de 15% sur broche 3 (PB4), 50% sur broche 5 (PB0)
// et 85% sur broche 6 (PB1).
// La LED sur broche 7 (PB2) est allumee en permanence
const byte led1 = 4; // PB4 ou broche 3
const byte led2 = 0; // PB0 ou broche 5
const byte led3 = 1; // PB1 ou broche 6
const byte led4 = 2; // PB2 ou broche 7
void setup() {
pinMode(led4, OUTPUT);
// pas d autre declaration avec AnalogWrite
digitalWrite(led4, HIGH); // allumage de LED
// generation des trois PWM de rapport cyclique 15, 50 et 85%
analogWrite(led1, 38); // PWM 15%
analogWrite(led2, 128); // PWM 50%
analogWrite(led3, 217); // PWM 85%
}
void loop() {
}
La figure 5 montre le montage à réaliser sur une platine d’essai pour observer les trois PWM et les comparer à une LED allumée en permanence. Il est alimenté en 5 V prélevé sur un module Arduino UNO.
À partir du moment où on sait générer de la PWM, on peut amplifier le signal pour commander un moteur ou des locomotives ; on consultera la série d’articles sur la PWM écrite par Jean-Luc et notamment l’article La PWM : Qu’est-ce que c’est ? (4) qui donne une solution pour le faire. Il devient ainsi facile de fabriquer une alimentation à courant pulsé pour ceux qui opèrent en analogique et veulent avoir des ralentis exceptionnels.
Un clignoteur universel
Comme exemple d’application au modélisme ferroviaire, je vous propose de construire un clignoteur universel qui ne vous coûtera que quelques euros. Vous pourrez ainsi le reproduire en grande quantité pour un prix très modique et il vous permettra de faire clignoter toutes les LED sur votre réseau en pouvant régler la fréquence (période de 0 à 2 secondes, celle-ci pouvant être modifiée avant programmation), le temps d’allumage (de 0 à 100% de la période) ainsi que la luminosité de la LED qui pourra être de la couleur que vous voulez. Ces différents réglages seront prélevés sur trois mini-potentiomètres réglés en fonction de l’effet recherché ; il est parfois préférable d’utiliser un composant électronique pour régler un montage plutôt que de reprogrammer le microcontrôleur en tâtonnant pour obtenir les bonnes valeurs de variables. La figure 6 montre le montage réalisé sur une plaque d’essai qui pourra être recopié sur une plaque à bandes cuivrées où les composants seront soudés. Le potentiomètre le plus à gauche règle le rythme de clignotement, le potentiomètre le plus à droite règle l’intensité lumineuse de la LED, enfin celui du milieu règle la durée d’allumage de la LED qui permet d’aller du flash très court à une LED allumée présentant des moments très brefs d’extinction ; tout est donc réglable lors de l’installation sur le réseau. Le programme est donné juste après cette figure.
Programme ATtiny_Clignoteur_universel :
//*****************************************************************
// ATtiny_Clignoteur_universel.ino
//*****************************************************************
// potentiometre frequence sur broche 7 (A1), potentiometre duree allumage
// sur broche 3 (A2), potentiometre luminosite sur broche 2 (A3)
// periode de clignotement de 0 à 2 sec approximativement
const byte led = 0; // la LED est branchee sur PB0 broche 5 (PWM)
int valeurFreq = 0; // en fait valeur de la periode
int valeurDure = 0; // valeur duree d allumage
int valeurLumi = 0; // valeur luminosite de la LED
unsigned long debutCycle = 0;
void setup() {
pinMode(led, OUTPUT);
}
void loop() {
// lecture des potentiometres
valeurFreq = analogRead(A1); // en millisecondes de 0 à 1023
valeurFreq = valeurFreq * 2; // double la periode possible
valeurDure = analogRead(A2); // en millisecondes de 0 à 1023
valeurDure = valeurDure * 2; // double la duree d allumage possible
if(valeurDure > valeurFreq) {valeurDure = valeurFreq;} // ne peut etre superieure a valeurFreq
valeurLumi = analogRead(A3)/4; // pour intervalle 0-255
// prise de top et allumage LED par PWM
debutCycle = millis();
analogWrite(led, valeurLumi);
while((millis() - debutCycle) < valeurDure) {
// rester comme cela
}
// extinction de la LED
analogWrite(led, 0);
while((millis() - debutCycle) < valeurFreq) {
// rester comme cela
}
// fin de la periode, il faut recommencer
}
Les interruptions sur un ATtiny
La figure 7 permet de voir que certaines broches de l’ATtiny peuvent servir à générer des interruptions.
Comme pour le module UNO, il existe deux sortes d’interruptions qui sont très bien décrites dans l’article Les interruptions (1) : en bleu, une interruption externe sur la broche 7 (PB2) appelée INT0 (le module UNO en possède deux : INT0 et INT1), en vert, les interruptions générées par un changement d’état sur les broches PCINT (Pin Change Interrupt) qui sont au nombre de 6 (une par broche PB0 à PB5).
La fonction attachInterrupt()
va nous permettre d’utiliser facilement l’interruption INT0 sur la broche PB2 de l’ATtiny puisqu’elle se charge de tout configurer à notre place. Le programme suivant est très simple et permet de changer l’état d’une LED par appui sur un poussoir branché sur la broche 7 (PB2) de l’ATtiny, ce qui génère une interruption sur un front descendant. La figure 8 montre le montage à effectuer sur une platine d’essai.
Programme ATtiny_attachInterrupt :
// ************************************************************
// ATtiny_attachInterrupt.ino
// ************************************************************
// Ce programme est inspire de l exemple donne en page reference
// pour attachInterrupt(). INT0 a lieu sur la pin PB2 donc
// interruptPin est initialisee a 2.
const byte ledPin = 0;
const byte interruptPin = 2;
volatile byte state = LOW;
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), blink, FALLING);
}
void loop() {
digitalWrite(ledPin, state);
}
void blink() {
state = !state;
}
La ligne 15 doit être remplacée parattachInterrupt(0, blink, FALLING);
si vous travaillez avec le Board Package ATtiny de Dave A. Mellis qui n’accepte pas digitalPinToInterrupt. Voir la mise à jour de l’article Le microcontrôleur ATtiny45 (2).
Les interruptions PCINT peuvent également être utilisées en configurant comme il se doit les registres du microcontrôleur, ce qui sort du cadre de cet article. Sur ces questions liées aux interruptions, fonctions puissantes, je vous invite une nouvelle fois à la lecture de l’article cité plus haut.
Conclusion
Nous venons de faire un tour de nouvelles possibilités pour nos ATtiny et nous voyons que les fonctions du langage de programmation des cartes Arduino nous simplifient grandement la tâche pour programmer nos microcontrôleurs puisqu’elles se chargent d’effectuer une sorte de cuisine interne que nous n’avons pas à connaître. Les possibilités des microcontrôleurs ATtiny, qu’ils soient de la série 25/45/85 ou bien de la série 24/44/84, sont énormes et sont souvent accessibles grâce aux fonctions de l’IDE qui est vraiment un outil de programmation puissant. En fonction de ce que vous voulez faire, il existe peut-être une bibliothèque adaptée ou qui peut être adaptée aux ATtiny. Et si rien n’existe, avec de la persévérance il reste possible de tout faire soi-même en s’aidant d’internet et des documentations techniques d’Atmel.