A quoi ça sert… un réseau de résistances R-2R ?

reseau resistance r-2r

Avez-vous remarqué que l’Arduino possède des entrées-sorties numériques et des entrées analogiques, mais qu’il n’a pas de sorties analogiques ? Une sortie analogique est pourtant très utile pour certaines applications, comme pour des montages audio et tout ce qui nécessite un contrôle analogique… Et bien nous allons voir qu’avec un réseau de résistances R-2R (resistor ladder en anglais) nous pouvons très simplement réaliser un convertisseur numérique-analogique qui convertit des sorties numériques de l’Arduino en sortie analogique.

Remarque : dans mon tutoriel C’est quoi… un signal PWM ? nous réalisons une pseudo sortie analogique pouvant prendre 256 valeurs. Mais il est important de noter que le signal reste un signal numérique (O V ou 5 V). La modulation des impulsions varie et cela réduit la puissance moyenne délivrée par la sortie numérique. Mais en aucun cas la sortie n’est analogique.

PWM
PWM avec un rapport cyclique de 75%, il ne s’agit pas d’une sortie analogique mais d’une sortie numérique (0 ou 5 V) dont les impulsions sont modulées

Réseau R-2R

Un réseau R-2R est un circuit composé de résistances ayant plusieurs étages identiques. Chaque étage est composé d’une résistance dont la valeur est le double (2R) de la valeur de la résistance qui sépare chaque étage (R). Chaque étage est relié à une sortie numérique de l’Arduino, qui peut prendre les valeurs 0 ou 1 (0 ou 5 V). Le nombre d’étage permet de doubler le nombre possibles de tension de sorties du montage. Le nombre de tensions de sorties différentes est donc 2n ou n est le nombre d’étages.

Dans l’exemple ci-dessous nous avons un réseau de résistances 2-2R composé de 2 étages et qui a donc 2²=4 tensions différentes en sortie.

Voici la table des valeurs de Vsortie en fonction des sorties numériques D0 et D1 de l’Arduino.

Il s’agit donc bien d’un convertisseur numérique-analogique 2 bits !

Plus le réseau de résistances R-2R a d’étages, plus le nombre de tensions de sortie possibles est grand. Un réseau R-2R de n étages est contrôlé par n bits et génère 2n tensions différentes. L’écart entre 2 tensions successives correspond à la résolution du convertisseur numérique -analogique. Cette résolution se calcule grâce à la formule suivante :

ΔV = V0 x 1 / 2n

où V0 est la tension des sorties numériques (5 V sur l’Arduino Uno) et n est le nombre d’étages du réseau R-2R.

On voit que la résolution du convertisseur 2 bits ci-dessus est : ΔV = V0 x 1 / 2n = 5 x 1 / 2² = 1.25 V

Réseau 2-2R de 4 bits

Dans l’exemple ci-dessous vous trouvez un réseau de résistances R-2R composé de 4 étages. Il est possible de générer 2⁴=16 tensions de sorties différentes. On parle d’un réseau de résistance R-2R de 4 bits, qui est un convertisseur numérique-analogique de 4 bits ayant une résolution de 0.3125 V (ΔV = V0 x 1 / 2n = 5 x 1 / 2⁴ = 0.3125 V).

Réseau de résistances R-2R

Voici la table des valeurs de Vsortie en fonction des sorties numériques D0,D1, D2 et D3 de l’Arduino.

Voici la simulation de ce réseau de résistance R-2R de 4 bits réalisé avec falstad. Vous pouvez changer la valeur des sorties numériques de l’Arduino en cliquant sur les H et L (H=High=5V et L=Low=0V) et visualiser directement l’impact sur la tension de sortie du réseau.

J’ai réalisé un exemple de réseau de résistances R-2R 4 bits en utilisant des résistances 4,7 kΩ et 10 kΩ. Le rapport n’est pas 2 entre ces valeurs, cela rend le montage moins linéaire mais j’ai fait avec le matériel disponible. 😉

Protoshield réseau résistances 2-2R
Réseau de résistances R-2R sur un Protoshield Arduino Uno

Dans cet exemple, le programme de l’Arduino Uno incrémente un nombre toutes les 2 secondes et positionne les sortie D0, D2, D4 et D6 avec la valeur du bit 0, 1, 2 et 3 de ce nombre. Nous pouvons donc observer sur un multimètre les valeurs de Vsortie très proches de celles de la table ci-dessus. Les valeurs ne sont pas exactement les même que la table car je n’ai pas utilisé des résistances dont le rapport est exactement 2.

Voici le code de l’Arduino Uno correspondant à ce test :

// Reseau de resistances R-2R 4 bits
// Convertisseur numerique-analogique 4 bits
// https://tutoduino.fr/
// Copyleft 2020


// La fonction r2rAnalogWrite() positionne les sorties 
// numeriques D0, D2, D4 et D6 en fonction de la valeur
// du bit 0, 1, 2 ou 3 de la valeur passee en parametre
void r2rAnalogWrite(uint8_t valeur) {

  digitalWrite(0, (valeur >> 0) & 0x01);
  digitalWrite(2, (valeur >> 1) & 0x01);
  digitalWrite(4, (valeur >> 2) & 0x01);
  digitalWrite(6, (valeur >> 3) & 0x01);

  // variante possible et plus rapide
  // PORTD = ((valeur & 0b1000) << 3) | ((valeur & 0b100) << 2) | ((valeur & 0b10) << 1) | (valeur & 1);
}

void setup() {

  // Les broches numeriques D0, D2, D4 et D6 sont 
  // configurees comme des sorties
  pinMode(0, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(6, OUTPUT);

  // Sors une tension de 0 sur la sortie analogique R2R
  r2rAnalogWrite(0);

}

void loop() {
  uint8_t index;

  // Boucle de 0 à 15 afin de tester toutes les valeurs 
  // des 4 bits du convertisseur numerique-analogique
  for (index=0; index<16 ; index++) {
    r2rAnalogWrite(index);
    delay(2000);
  }
  
  r2rAnalogWrite(0);
  delay(2000);
}

Si on observe à l’oscilloscope la sortie analogique, on voit bien que l’on obtient une rampe dont la tension varie de 0 à 4,68 V. J’ai modifié la temporisation pour l’affichage de la courbe sur l’oscilloscope avec un délai de 2 ms après chaque écriture analogique. On observe bien la résolution de 0,31 V (différence de tension entre 2 pas).

sortie en rampe

Autre exemple, notre sortie analogique peut bien entendu sortir une tension sinusoïdale. Dans cet exemple, le sinus est calculé en faisant appel à la fonction sin à chaque fois. Ce n’est pas une bonne pratique car cela consomme énormément de puissance processeur. La bonne pratique est indiquée en commentaire, il s’agit de pré-calculer les valeurs des sinus dans une table et d’aller lire dans cette table.

Notez que vous pouvez écrire les 8 bits du port D directement (portD = …) plutôt que d’écrire les sortie numériques l’une après l’autre avec la fonction digitalWrite. C’est nettement plus rapide et c’est ce que j’ai utilisé sur ce deuxième exemple.

// Reseau de resistances R-2R 4 bits
// Convertisseur numerique-analogique 4 bits
// https://tutoduino.fr/
// Copyleft 2020

#define tailleTableSinux 64

uint8_t tableSinus[tailleTableSinux] = {8, 8, 9, 10, 10, 11, 12, 12, 13, 13, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 13, 13, 12, 11, 11, 10, 9, 9, 8, 7, 6, 6, 5, 4, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 7};

// La fonction r2rAnalogWrite() positionne les sorties 
// numeriques D0, D2, D4 et D6 en fonction de la valeur
// du bit 0, 1, 2 ou 3 de la valeur passee en parametre
void r2rAnalogWrite(uint8_t valeur) {
  /*
  digitalWrite(0, (valeur >> 0) & 0x01);
  digitalWrite(2, (valeur >> 1) & 0x01);
  digitalWrite(4, (valeur >> 2) & 0x01);
  digitalWrite(6, (valeur >> 3) & 0x01);
  */
  // Alternative plus rapide en ecrivant sur le port D (conprend D0 à D7)
  PORTD = ((valeur & 0b1000) << 3) | ((valeur & 0b100) << 2) | ((valeur & 0b10) << 1) | (valeur & 1);
}

void setup() {

  // Les broches numeriques D0, D2, D4 et D6 sont 
  // configurees comme des sorties
  pinMode(0, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(6, OUTPUT);

}

void loop() {
  uint8_t index;

  // Sors une tension sinusoidale en utilisant la fonction sin
  for (index=0; index<tailleTableSinux ; index++) {
    r2rAnalogWrite(round((sin(index*2.0*3.14/(tailleTableSinux-1))+1)*15/2));
    delay(1);
  }

  /*
  // Sors une tension sinusoidale en utilisant la table precalculee
  // Cette methode doit etre privilegiee car elle est beaucoup plus
  // rapide en temps processeur
  for (index=0; index<tailleTableSinux ; index++) {
    r2rAnalogWrite(tableSinus[index]);
    delay(1);
  }
  /**/
  }

Voici le résultat visualisé sur l’oscilloscope :

sortie sinusoidale

Cet article est disponible sur ma chaîne YouTube, n’hésitez pas à vous y abonner. Merci pour votre attention et à bientôt pour un nouvel article sur mon blog.