Convertisseur A/D 16bits[résolu]

Bonjour,

Je viens demander secours à propos d’un problème avec un Convertisseur A/D 16 bits ADS 1115 qui ne fonctionne pas comme je l’attendais.

Voici au tout début de mon programme arduino l’initialisation d’un objet ads

#include <Adafruit_ADS1015.h> //ADC 16 bits
// ****** Pour ADC 16 bits *****
 Adafruit_ADS1115 ads;

Je pensais, par ce procédé avoir initialisé une instance ads de Adafruit_ADS1115

La suite du programme utilise cette instance pour mesurer une tension en mode 16 bits et ensuite afficher le résultat.
Tout parait fonctionner correctement, mais en surveillant les résultats pour des tensions faibles (quelques dizaines de mV), je me suis aperçu que sur le résultat de la conversion sur 16 bits, les 4 bits de poids faible étaient systématiquement écrasés (forcés à 0)
Comme si j’avais un convertisseur 12 bits (ADS 1015)
J’ai un peu regardé le contenu de la bibliothèque Adafruit :

– Dans ADS1015.h j’ai repéré ce qui est pour moi accessible

 public:
  Adafruit_ADS1015(uint8_t i2cAddress = ADS1015_ADDRESS);
  void begin(void);
  uint16_t  readADC_SingleEnded(uint8_t channel);
  int16_t   readADC_Differential_0_1(void);
  int16_t   readADC_Differential_2_3(void);
  void      startComparator_SingleEnded(uint8_t channel, int16_t threshold);
  int16_t   getLastConversionResults();
  void      setGain(adsGain_t gain);
  adsGain_t getGain(void);

// Derive from ADS1105 & override construction to set properties
class Adafruit_ADS1115 : public Adafruit_ADS1015
{
 public:
  Adafruit_ADS1115(uint8_t i2cAddress = ADS1015_ADDRESS);

 private:
};

Dans mon programme arduino je lis le résultat de la convertion de la façon suivante :

 lcd.print("afficher CAD");
  while (!TOUCHE(BpSuite))
  {lcd.setCursor(0,1);
   lcd.print(ads.readADC_SingleEnded(0));
   lcd.print("   ");
   lcd.setCursor(11,1);
   lcd.print(ads.getLastConversionResults());
   lcd.print("   ");
   delay(250);
  }

Donc , logiquement, cela devrait fonctionner en 16 bits et pas en 12 bits

J’ai ensuite un peu plus regardé dans le fichier Adafruit_ADS1015.ccp :

/**************************************************************************/
/*!
    @brief  Instantiates a new ADS1015 class w/appropriate properties
*/
/**************************************************************************/
Adafruit_ADS1015::Adafruit_ADS1015(uint8_t i2cAddress) 
{
   m_i2cAddress = i2cAddress;
   m_conversionDelay = ADS1015_CONVERSIONDELAY;
   m_bitShift = 4;
   m_gain = GAIN_TWOTHIRDS; /* +/- 6.144V range (limited to VDD +0.3V max!) */
}

/**************************************************************************/
/*!
    @brief  Instantiates a new ADS1115 class w/appropriate properties
*/
/**************************************************************************/
Adafruit_ADS1115::Adafruit_ADS1115(uint8_t i2cAddress)
{
   m_i2cAddress = i2cAddress;
   m_conversionDelay = ADS1115_CONVERSIONDELAY;
   m_bitShift = 0;
   m_gain = GAIN_TWOTHIRDS; /* +/- 6.144V range (limited to VDD +0.3V max!) */
}

Mon programme devrait appeler “Adafruit_ADS1115::Adafruit_ADS1115(uint8_t i2cAddress)”
Dans lequel m_bitShift = 0; c’est à dire que les 4 bits de poids faible ne devraient pas êtres masqués …
Ce qui n’est pas ce que j’ai constaté quand j’ai vérifié en faisant mesurer une petite tension d’une dizaine de mV par le convertisseur.
(En faisant croitre la tension à partir de 0, je devrais obtenir 0, 1, 2, 3 etc et non 0…16…32 …48

Bon, pour tout dire, je galère pas mal.

Merci par avance

Serge .D

Bonjour,
es-tu conscient que si tu travaille par exemple en 3.3v, 1 bit représente 0.05 mV ?

Bonjour et merci de répondre.

Je ne pense pas que le problème vienne de cela car j'ai pris beaucoup de précautions pour la partie électrique :
-- Une alim de labo associée avec deux diviseurs de tension successifs ainsi que des diodes de protection pour limiter la plage de tension injectée. (Limitation de -0,2 à +2V et condensateur de filtrage d'éventuels parasites)
-- Un voltmètre numérique mesurant la tension injectée, calibres 0,2V ou 2V)
J'ai aussi vérifié par voie logicielle en affichant successivement la valeur convertie ainsi que la dernière valeur convertie :

lcd.print("afficher CAD");
  while (!TOUCHE(BpSuite))
  {lcd.setCursor(0,1);
   lcd.print(ads.readADC_SingleEnded(0));
   lcd.print("   ");
   lcd.setCursor(11,1);
   lcd.print(ads.getLastConversionResults());
   lcd.print("   ");
   delay(250);
  }

Le gain de l'amplificateur du circuit convertisseur était la valeur par défaut (2/3)
Et je n'ai rien vu dans la bibliothéque adafruit, mais je suis plus à l'aise en electronique que sur le logiciel ...

Serge .D

pour vérifier si ton programme passe, ou pas par telle ou telle étape, il faut déboguer
par exemple modifier temporairement la bibliothèque en faisant un serialprintlf(m_bitShift); pour voir

Merci bien :

Mon soupçon serait éventuellement la procédure :

Adafruit_ADS1015::Adafruit_ADS1015(uint8_t i2cAddress)

Qui serait peut-être appelée alors que c'est :

// Derive from ADS1105 & override construction to set properties[color=#222222][/color]
class Adafruit_ADS1115 : public Adafruit_ADS1015

Qui surcharge la précédente devant être appelée pour du 16 bits
Ma proposition serait, dans "Adafruit_ADS1015::Adafruit_ADS1015(uint8_t i2cAddress)"
Remplacer :
m_bitShift = 4;
Par
m_bitShift = 0;

Bon, je n'ai jamais fait cela.
Comment placer le : serialprintlf(m_bitShift);

Merci par avance.

Serge .D

une bibliothèque, c'est un morceau de ton code qui est déjà écrit, et qui va s'exécuter comme les autres parties de ton code
le fichier c++ qui correspond à Adafruit_ADS1015.h est celui où tu vas insérer les serialprintlf(m_bitShift);
puis tu sauvegarde ce fichier

quand tout est rentré dans l'ordre, tu peux rétablir ce fichier

normalement, il y n'y a pas lieu de trafiquer dans les bibliothèques ; il y a certainement un appel qui se passe mal, mais mon niveau lamentable en c++ ne me permet pas de le voir au 1er coup d'oeil, comme certains ici en sont bien capables

Merci beaucoup,

Je vais tenter cela pour "pister" le cheminement dans la bibliothèques Adafruit à l'occasion d'une demande de conversion.
Ce sera pour le début de 2021
En attendant, bonne année, on fera "au mieux"

Serge .D

Bon, nous sommes encore en 2020..... mais j'ai quand-même jeté un coup d'œil approfondi :

Adafruit_ADS1015::Adafruit_ADS1015(uint8_t i2cAddress) 
{
   m_i2cAddress = i2cAddress;
   m_conversionDelay = ADS1015_CONVERSIONDELAY;
   m_bitShift = 4;  //ici_1
   m_gain = GAIN_TWOTHIRDS; /* +/- 6.144V range (limited to VDD +0.3V max!) */
}

Au repère "//ici_1 j'ai inséré un serial.println(m_bitShif);

Pour voir si ce n'était pas Adafruit_ADS1015 qui était initialisé à la place de Adafruit_ADS1115 (version 16 bits)
Et bien, c'est bien le constructeur 16 bits qui est initialisé. et m_bitShift est bien initialisé à 0.

Ensuite j'ai regardé la fonction qui sort le résultat de la conversion :

uint16_t Adafruit_ADS1015::readADC_SingleEnded(uint8_t channel) {
  if (channel > 3)
  {
    return 0;
  }
  
  // Start with default values
  uint16_t config = ADS1015_REG_CONFIG_CQUE_NONE    | // Disable the comparator (default val)
                    ADS1015_REG_CONFIG_CLAT_NONLAT  | // Non-latching (default val)
                    ADS1015_REG_CONFIG_CPOL_ACTVLOW | // Alert/Rdy active low   (default val)
                    ADS1015_REG_CONFIG_CMODE_TRAD   | // Traditional comparator (default val)
                    ADS1015_REG_CONFIG_DR_1600SPS   | // 1600 samples per second (default)
                    ADS1015_REG_CONFIG_MODE_SINGLE;   // Single-shot mode (default)

  // Set PGA/voltage range
  config |= m_gain;

  // Set single-ended input channel
  switch (channel)
  {
    case (0):
      config |= ADS1015_REG_CONFIG_MUX_SINGLE_0;
      break;
    case (1):
      config |= ADS1015_REG_CONFIG_MUX_SINGLE_1;
      break;
    case (2):
      config |= ADS1015_REG_CONFIG_MUX_SINGLE_2;
      break;
    case (3):
      config |= ADS1015_REG_CONFIG_MUX_SINGLE_3;
      break;
  }

  // Set 'start single-conversion' bit
  config |= ADS1015_REG_CONFIG_OS_SINGLE;

  // Write config register to the ADC
  writeRegister(m_i2cAddress, ADS1015_REG_POINTER_CONFIG, config);

  // Wait for the conversion to complete
  delay(m_conversionDelay);

  // Read the conversion results
  // Shift 12-bit results right 4 bits for the ADS1015
  return readRegister(m_i2cAddress, ADS1015_REG_POINTER_CONVERT) >> m_bitShift;  
}

J'ai inséré un serial.println(m_bitShif); juste avant le retour de la fonction et sa valeur est toujours 0.

Juste avant le retour de la fonction, il y a un :

  delay(m_conversionDelay);

J'ai mis un délai supplémentaire pour voir (en fait je triple la valeur) :

Résultat : aucun changement. Grrrr !
Suite au prochain n° ....

Serge .D

Mon soupçon quitte le logiciel et regarde le matériel …
Je déclare mon convertisseur en 12 bits dans le programme Arduino et je regarde le retour dans les mêmes conditions de tension d’entrée (0,2, 4, 6, 8 mV …)
J’obtiens rigoureusement les mêmes résultats en déclaration 12 bits que 16 bits sauf un décalage de 4bits forcés à 0 dans le deuxième cas.
Ce qui me parait logique si mon petit module marqué ADS1115 en sérigraphie sur le C Imprimé est en réalité un ADS1015 12 bits.
Sur le circuit intégré lui même, pas de marquage lisible.
Comme c’est un petit circuit lowcost Grrr !

Merci encore à trimarco232 qui m’a encouragé.

Serge .D

Bonsoir et bonne année.

Pour faire la synthèse :

  • J'ai vérifié pas a pas le fonctionnement de la bibliothéque Adafruit et je n'ai rien trouvé
  • J'ai déclaré mon convertisseur donné pour AD1115 16bits en AD1015 12 bits et il semblerait bien que mon manque de résolution ne serait pas du à un pB logiciel mais matériel. Mon circuit supposé 16 bits se comporte comme un 12 bits.
    Pour être archi- sûr j'ai changé de bibliothéque et j'obtiens à nouveau le même fonctionnement.
    Donc, pour moi, c'est le circuit qui n'est pas le bon.

Petite question : quelqu'un aurait-il rencontré le même problème ?

Serge .D

aligote:
J’ai inséré un serial.println(m_bitShif); juste avant le retour de la fonction et sa valeur est toujours 0.
(…)
Serge .D

Bonjour,
attention aux conclusions hâtives : la valeur 0 est peut-être due au fait que la variable n’a pas été correctement lue dans le contexte … essaye avec une valeur différente de 0 pour t’en assurer

trimarco232:
Bonjour,
attention aux conclusions hâtives : la valeur 0 est peut-être due au fait que la variable n'a pas été correctement lue dans le contexte ... essaye avec une valeur différente de 0 pour t'en assurer

OK, je vais tenter d'affecter autrement :

  • Je laisse m_bitShift affecté à 4 dans le constructeur 12 bits
  • Je change son affectation à 0 par une affectation à 1 dans le constructeur du 16 bits qui normalement surcharge celui du 12 Bits
    Ensuite je piste la valeur de m_bitShift et je regarde le registre 16 bits qui contient le résultat de la dernière conversion.
    Bon je tenterai cela demain.
    Serge .D

Les librairies Adafruit sont généralement de bonne qualité et bien testées il serait étonnant que ce ne soit pas le cas pour celle-ci.
Le soupçon d'aligote s'explique bien par comportement décrit, le convertisseur 12 bits délivrant une valeur justifiée à gauche.
Le fait qu'un composant Texas ne soit pas bien marqué est assez surprenant.
Lorsqu'on voit que l'ADS1115 coûte le double du 1015 on se dit qu'il est tout à fait possible qu'un petit malin ait voulu se faire de l'argent facilement.

@aligote, quitte à bricoler dans la librairie, pour commencer il suffirait de remplacer m_bitShift par 0 dans la ligne

return readRegister(m_i2cAddress, ADS1015_REG_POINTER_CONVERT) >> m_bitShift;

La sérigraphie d'un ADS1115 est difficile à lire, il faut un microscope électronique.
Je lis 7A, puis logo Texas, puis en dessous BOGI.

fdufnews:
@aligote, quitte à bricoler dans la librairie, pour commencer il suffirait de remplacer m_bitShift par 0 dans la ligne

return readRegister(m_i2cAddress, ADS1015_REG_POINTER_CONVERT) >> m_bitShift;

Je remet ici la fonction que j'appelle dans mon programme arduino :

uint16_t Adafruit_ADS1015::readADC_SingleEnded(uint8_t channel) {
  if (channel > 3)
  {
    return 0;
  }
  
  // Start with default values
  uint16_t config = ADS1015_REG_CONFIG_CQUE_NONE    | // Disable the comparator (default val)
                    ADS1015_REG_CONFIG_CLAT_NONLAT  | // Non-latching (default val)
                    ADS1015_REG_CONFIG_CPOL_ACTVLOW | // Alert/Rdy active low   (default val)
                    ADS1015_REG_CONFIG_CMODE_TRAD   | // Traditional comparator (default val)
                    ADS1015_REG_CONFIG_DR_1600SPS   | // 1600 samples per second (default)
                    ADS1015_REG_CONFIG_MODE_SINGLE;   // Single-shot mode (default)

  // Set PGA/voltage range
  config |= m_gain;

  // Set single-ended input channel
  switch (channel)
  {
    case (0):
      config |= ADS1015_REG_CONFIG_MUX_SINGLE_0;
      break;
    case (1):
      config |= ADS1015_REG_CONFIG_MUX_SINGLE_1;
      break;
    case (2):
      config |= ADS1015_REG_CONFIG_MUX_SINGLE_2;
      break;
    case (3):
      config |= ADS1015_REG_CONFIG_MUX_SINGLE_3;
      break;
  }

  // Set 'start single-conversion' bit
  config |= ADS1015_REG_CONFIG_OS_SINGLE;

  // Write config register to the ADC
  writeRegister(m_i2cAddress, ADS1015_REG_POINTER_CONFIG, config);

  // Wait for the conversion to complete
  delay(m_conversionDelay);

  // Read the conversion results
  // Shift 12-bit results right 4 bits for the ADS1015
  return readRegister(m_i2cAddress, ADS1015_REG_POINTER_CONVERT) >> m_bitShift;

J'ai déjà fait quelques tests :

  • Juste avant le retour de la fonction j'ai déjà inséré un :
 serial.println(m_bitShif);
  • j'ai aussi forcé m_bitShift à 0 ou 4 avant le retour.
    Cela dit, je suis assez d'accord même si je ne suis pas du tout spécialiste du soft, l'examen du code fait penser à quelque chose de très propre et bien documenté.
    D'où mon sentiment que l'origine de mon problème serait plutôt Hardware.
    Merci à tous pour vos suggestions
    Serge .D

Rebonjour à tous,

Voila, en fouinant dans les évaluations de vendeurs de modules ADS1115 asiatiques, je suis tombé sur cela :

1,0 sur 5 étoiles contrefacon !!!
Commenté en France le 9 novembre 2020
Nombre d’unités: 5Achat vérifié
ce produit n’est pas un module avec un ADS1115 !!! mais un module marqué ADS1115 avec un chip ADS1015 12 bit seulement.

1,0 sur 5 étoiles Beware, incorrect IC.
Commenté au Royaume-Uni le 15 novembre 2020
Nombre d’unités: 3Achat vérifié
Echoing a previous review, These are 12-bit not 16-bit ADCs. They are NOT ADS1115. They seem to be compatible and will function, but with 12 bit resolution.
Most frustrating.

Serge .D

Finalement, il faudrait que je trouve un fournisseur sûr et pas hors de prix.

Des idées ?

Merci par avance.

Serger .D

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.