Table des matières:

Arduino et PCF8591 ADC DAC IC : 7 étapes
Arduino et PCF8591 ADC DAC IC : 7 étapes

Vidéo: Arduino et PCF8591 ADC DAC IC : 7 étapes

Vidéo: Arduino et PCF8591 ADC DAC IC : 7 étapes
Vidéo: Electronic Basics #10: Digital to Analog Converter (DAC) 2024, Novembre
Anonim
Arduino et PCF8591 ADC DAC IC
Arduino et PCF8591 ADC DAC IC

Avez-vous déjà voulu plus de broches d'entrée analogiques sur votre projet Arduino, mais sans vouloir débourser pour un Mega ? Ou souhaitez-vous générer des signaux analogiques ? Consultez ensuite le sujet de notre didacticiel – le circuit intégré NXP PCF8591.

Il résout ces deux problèmes car il dispose d'un seul convertisseur DAC (numérique vers analogique) ainsi que de quatre ADC (convertisseurs analogique-numérique) - tous accessibles via le bus I2C. Le PCF8591 est disponible sous forme de DIP, de montage en surface et de module, ce qui le rend facile à expérimenter.

Avant de poursuivre, téléchargez la fiche technique. Le PCF8591 peut fonctionner à la fois sur 5 V et 3,3 V, donc si vous utilisez une carte de développement Arduino Due, Raspberry Pi ou autre 3,3 V, tout va bien. Maintenant, nous allons d'abord expliquer le DAC, puis les ADC.

Étape 1: Utilisation du DAC (convertisseur numérique-analogique)

Utilisation du DAC (convertisseur numérique-analogique)
Utilisation du DAC (convertisseur numérique-analogique)

Le DAC du PCF8591 a une résolution de 8 bits - il peut donc générer un signal théorique compris entre zéro volt et la tension de référence (Vref) en 255 étapes. À des fins de démonstration, nous utiliserons un Vref de 5V, et vous pouvez utiliser un Vref inférieur tel que 3,3V ou tout ce que vous souhaitez que la valeur maximale soit… mais elle doit être inférieure à la tension d'alimentation.

Notez que lorsqu'il y a une charge sur la sortie analogique (une situation réelle), la tension de sortie maximale chute - la fiche technique (que vous avez téléchargée) indique une chute de 10 % pour une charge de 10 kΩ. Maintenant pour notre circuit de démonstration.

A noter l'utilisation de résistances pull-up de 10kΩ sur le bus I2C, et le condensateur de 10μF entre 5V et GND. L'adresse du bus I2C est définie par une combinaison de broches A0 ~ A2, et avec elles toutes à GND, l'adresse est 0x90. La sortie analogique peut être prise à partir de la broche 15 (et il y a un GND analogique séparé sur la broche 13. Connectez également la broche 13 à GND et le circuit GND à Arduino GND.

Pour contrôler le DAC, nous devons envoyer deux octets de données. Le premier est l'octet de contrôle, qui active simplement le DAC et vaut 1000000 (ou 0x40) et l'octet suivant est la valeur entre 0 et 255 (le niveau de sortie). Ceci est démontré dans le croquis suivant:

// Exemple de démo 52.1 PCF8591 DAC

#include "Wire.h" #define PCF8591 (0x90 >> 1) // Configuration de l'annulation de l'adresse du bus I2C() { Wire.begin(); } void loop() { for (int i=0; i<256; i++) { Wire.beginTransmission(PCF8591); // réveille PCF8591 Wire.write(0x40); // octet de contrôle - active le DAC (binaire 1000000) Wire.write(i); // valeur à envoyer au DAC Wire.endTransmission(); // fin de la transmission }

pour (int i=255; i>=0; --i)

{ Wire.beginTransmission(PCF8591); // réveille PCF8591 Wire.write(0x40); // octet de contrôle - active le DAC (binaire 1000000) Wire.write(i); // valeur à envoyer au DAC Wire.endTransmission(); // fin de la transmission } }

Avez-vous remarqué le décalage de bit de l'adresse de bus dans l'instruction #define ? Arduino envoie des adresses 7 bits mais le PCF8591 veut un 8 bits, nous décalons donc l'octet d'un bit.

Étape 2:

Image
Image

Les résultats du croquis sont montrés dans l'image, nous avons connecté le Vref à 5V et la sonde de l'oscilloscope et GND à la sortie analogique et GND respectivement.

Étape 3:

Image
Image

Si vous aimez les courbes, vous pouvez générer des ondes sinusoïdales avec le croquis ci-dessous. Il utilise une table de recherche dans un tableau qui contient les points de données pré-calculés nécessaires:

// Exemple 52.2 PCF8591 DAC démo - onde sinusoïdale

#include "Wire.h" #define PCF8591 (0x90 >> 1) // Adresse bus I2C uint8_t sine_wave[256] = { 0x80, 0x83, 0x86, 0x89, 0x8C, 0x90, 0x93, 0x96, 0x99, 0x9C, 0x9F, 0xA2, 0xA5, 0xA8, 0xAB, 0xAE, 0xB1, 0xB3, 0xB6, 0xB9, 0xBC, 0xBF, 0xC1, 0xC4, 0xC7, 0xC9, 0xCC, 0xCE, 0xD1, 0xD3, 0xD5x, 0xD8, 0xDA 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEB, 0xED, 0xEF, 0xF0, 0xF1, 0xF3, 0xF4, 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD, 0xFC, 0xFB, 0xFA, 0xFA, 0xF9, 0xF8, 0xF6, 0xF5, 0xF4, 0xF3, 0xF, 0xED, 0xEB, 0xEA, 0xE8, 0xE6, 0xE4, 0xE2, 0xE0, 0xDE, 0xDC, 0xDA, 0xD8, 0xD5, 0xD3, 0xD1, 0xCE, 0xCC, 0xC9, 0xC7, 0xC4, 0xB, 1, BC, 0xBF 0xB3, 0xB1, 0xAE, 0xAB, 0xA8, 0xA5, 0xA2, 0x9F, 0x9C, 0x99, 0x96, 0x93, 0x90, 0x8C, 0x89, 0x86, 0x83, 0x80, 0x7D, 0x7A, 0x77, 0x074, 0xA 0x67, 0x64, 0x61, 0x5E, 0x5B, 0x58, 0x55, 0x52, 0x4F, 0x4D, 0x4A, 0x47, 0x44, 0x41, 0x3F, 0x 3C, 0x39, 0x37, 0x34, 0x32, 0x2F, 0x2D, 0x2B, 0x28, 0x26, 0x24, 0x22, 0x20, 0x1E, 0x1C, 0x1A, 0x18, 0x16, 0x15, 0x13, 0x11, 0x10, 0x0F, 0x0B, 0x0A, 0x08, 0x07, 0x06, 0x06, 0x05, 0x04, 0x03, 0x03, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03 0x04, 0x05, 0x06, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0C, 0x0D, 0x0F, 0x10, 0x11, 0x13, 0x15, 0x16, 0x18, 0x1A, 0x1C, 0x1E, 0x20, 0, 0x22, x 0x2B, 0x2D, 0x2F, 0x32, 0x34, 0x37, 0x39, 0x3C, 0x3F, 0x41, 0x44, 0x47, 0x4A, 0x4D, 0x4F, 0x52, 0x55, 0x58, 0x5B, 0x5E, 0x6, 6, 67, 0x 0x70, 0x74, 0x77, 0x7A, 0x7D}; void setup() { Wire.begin(); } void loop() { for (int i=0; i<256; i++) { Wire.beginTransmission(PCF8591); // réveille PCF8591 Wire.write(0x40); // octet de contrôle - active le DAC (binaire 1000000) Wire.write(sine_wave); // valeur à envoyer au DAC Wire.endTransmission(); // fin de la transmission } }

Étape 4:

Image
Image

Pour le vidage d'image DSO suivant, nous avons modifié la Vref à 3,3 V – notez le changement des maxima sur l'onde sinusoïdale.

Vous pouvez maintenant expérimenter avec le DAC pour créer des effets sonores, des signaux ou contrôler d'autres circuits analogiques.

Étape 5: Utilisation des CAN (convertisseurs analogique-numérique)

Si vous avez utilisé la fonction analogRead () sur votre Arduino (au chapitre un), vous connaissez déjà un ADC. Sans PCF8591, nous pouvons lire une tension entre zéro et la Vref et il renverra une valeur comprise entre zéro et 255 qui est directement proportionnelle à zéro et à la Vref.

Par exemple, mesurer 3,3 V devrait renvoyer 168. La résolution (8 bits) de l'ADC est inférieure à celle de l'Arduino embarqué (10 bits), mais le PCF8591 peut faire quelque chose que l'ADC de l'Arduino ne peut pas. Mais nous y viendrons dans un instant. Tout d'abord, pour simplement lire les valeurs de chaque broche ADC, nous envoyons un octet de contrôle pour indiquer au PCF8591 quel ADC nous voulons lire. Pour les CAN de zéro à trois, l'octet de contrôle est respectivement 0x00, 0x01, ox02 et 0x03.

Ensuite, nous demandons deux octets de données à l'ADC et stockons le deuxième octet à utiliser. Pourquoi deux octets ? Le PCF8591 renvoie d'abord la valeur mesurée précédemment, puis l'octet actuel. (Voir Figure 8 dans la fiche technique). Enfin, si vous n'utilisez pas toutes les broches ADC, connectez celles inutilisées à GND. L'exemple d'esquisse suivant récupère simplement les valeurs de chaque broche ADC une par une, puis les affiche sur le moniteur série:

#include "Fil.h"

#define PCF8591 (0x90 >> 1) // Adresse du bus I2C #define ADC0 0x00 // octets de contrôle pour la lecture d'ADC individuels #define ADC1 0x01 #define ADC2 0x02 #define ADC3 0x03 octet valeur0, valeur1, valeur2, valeur3; void setup() { Wire.begin(); Serial.begin(9600); } boucle vide() { Wire.beginTransmission(PCF8591); // réveille PCF8591 Wire.write(ADC0); // octet de contrôle - lire ADC0 Wire.endTransmission(); // fin de la transmission Wire.requestFrom(PCF8591, 2); value0=Wire.read(); value0=Wire.read(); Wire.beginTransmission(PCF8591); // réveille PCF8591 Wire.write(ADC1); // octet de contrôle - lire ADC1 Wire.endTransmission(); // fin de la transmission Wire.requestFrom(PCF8591, 2); value1=Wire.read(); value1=Wire.read(); Wire.beginTransmission(PCF8591); // réveille PCF8591 Wire.write(ADC2); // octet de contrôle - lire ADC2 Wire.endTransmission(); // fin de la transmission Wire.requestFrom(PCF8591, 2); value2=Wire.read(); value2=Wire.read(); Wire.beginTransmission(PCF8591); // réveille PCF8591 Wire.write(ADC3); // octet de contrôle - lire ADC3 Wire.endTransmission(); // fin de la transmission Wire.requestFrom(PCF8591, 2); value3=Wire.read(); value3=Wire.read(); Serial.print(value0); Serial.print(" "); Serial.print(valeur1); Serial.print(" "); Serial.print(valeur2); Serial.print(" "); Serial.print(valeur3); Serial.print(" "); Serial.println(); }

Lors de l'exécution de l'esquisse, les valeurs de chaque ADC dans le moniteur série vous seront présentées. Bien qu'il s'agisse d'une simple démonstration pour vous montrer comment lire individuellement chaque ADC, il s'agit d'une méthode lourde pour obtenir plus d'un octet à la fois à partir d'un ADC particulier.

Étape 6:

Pour ce faire, modifiez l'octet de contrôle pour demander l'auto-incrémentation, ce qui se fait en mettant le bit 2 de l'octet de contrôle à 1. Ainsi, pour commencer à partir de ADC0, nous utilisons un nouvel octet de contrôle binaire 00000100 ou hexadécimal 0x04. Ensuite, demandez cinq octets de données (encore une fois, nous ignorons le premier octet), ce qui obligera le PCF8591 à renvoyer toutes les valeurs dans une chaîne d'octets. Ce processus est illustré dans le schéma suivant:

#include "Fil.h"

#define PCF8591 (0x90 >> 1) // Adresse bus I2C octet valeur0, valeur1, valeur2, valeur3; void setup() { Wire.begin(); Serial.begin(9600); } boucle vide() { Wire.beginTransmission(PCF8591); // réveille PCF8591 Wire.write(0x04); // octet de contrôle - lit ADC0 puis auto-incrémente Wire.endTransmission(); // fin de la transmission Wire.requestFrom(PCF8591, 5); value0=Wire.read(); value0=Wire.read(); value1=Wire.read(); value2=Wire.read(); value3=Wire.read(); Serial.print(value0); Serial.print(" "); Serial.print(valeur1); Serial.print(" "); Serial.print(valeur2); Serial.print(" "); Serial.print(valeur3); Serial.print(" "); Serial.println(); }

Auparavant, nous avons mentionné que le PCF8591 peut faire quelque chose que l'ADC de l'Arduino ne peut pas, et c'est offrir un ADC différentiel. Contrairement à l'Arduino asymétrique (c'est-à-dire qu'il renvoie la différence entre la tension du signal positif et GND, l'ADC différentiel accepte deux signaux (qui ne doivent pas nécessairement être référencés à la terre) et renvoie la différence entre les deux signaux Cela peut être pratique pour mesurer de petits changements de tension pour les cellules de charge, etc.

Étape 7:

Image
Image

La configuration du PCF8591 pour l'ADC différentiel consiste simplement à changer l'octet de contrôle. Si vous passez à la page sept de la fiche technique, alors considérez les différents types de programmation d'entrée analogique. Auparavant, nous utilisions le mode '00' pour quatre entrées, mais vous pouvez sélectionner les autres qui sont clairement illustrées, par exemple l'image.

Donc, pour définir l'octet de contrôle pour deux entrées différentielles, utilisez le binaire 00110000 ou 0x30. Ensuite, il suffit de demander les octets de données et de travailler avec eux. Comme vous pouvez le voir, il existe également une combinaison simple/différentielle et une entrée complexe à trois différentiels. Cependant, nous les laisserons pour le moment.

J'espère que vous avez trouvé cela intéressant, qu'il s'agisse d'ajouter un DAC à vos expériences ou d'en apprendre un peu plus sur les ADC. Veuillez envisager de commander votre PCF8591 auprès de PMD Way.

Cet article vous est présenté par pmdway.com - tout pour les fabricants et les passionnés d'électronique, avec une livraison gratuite dans le monde entier.

Conseillé: