Problème de lecture ADC via SPI sur Raspberry Pi avec une sonde TDS Keyestudio

Bonjour à tous,

Pour un projet aquarium (Raspberry/home assistant)
Je rencontre des difficultés pour lire correctement les valeurs d’une sonde TDS Keyestudio V1.0 connectée à un Raspberry Pi via un convertisseur ADC Texas Instruments ADS8688.
La tension varie bien en fonction de la conductivité de l’eau, mais les valeurs lues par le Raspberry Pi ne correspondent pas à celles obtenues avec un multimètre.

Matériel utilisé :

Raspberry Pi X** (précisez le modèle, ex. Pi 4, Pi Zero, etc.)
Convertisseur ADC** : Texas Instruments ADS8688
Mode SPI** : Mode 1 (CPOL=0, CPHA=1)
Fréquence SPI** : 500 kHz
Sonde TDS** : Keyestudio V1.0
Alimentation de la sonde** : 5V
Sortie analogique attendue** : 0V à 2.3V selon la conductivité

Problèmes rencontrés :

La tension lue varie avec la salinité, mais les valeurs ne sont pas cohérentes avec celles obtenues avec un multimètre.
Les valeurs SPI brutes sont bien reçues et varient**, mais la conversion ne semble pas correcte.
Les tensions affichées par le script sont bien plus basses que celles mesurées en réel.

Tests effectués:

Changement du mode SPI

Mode 0: Aucune lecture correcte
Mode 1: Variations observées, mais écart significatif avec la réalité

Lecture brute SPI et traitement des données

Exclusion des 2 bits inutiles du registre ADC
Test de conversion sur 14 bits et 16 bits
Aucun mode ne donne une tension réaliste

*Facteur de conversion utilisé :

tension = (raw_value / 16384) * 5.0  # ADC sur 14 bits

Le facteur est-il correct ?** Dois-je appliquer un gain ADC ?

Consultation de la documentation de l’ADS8688

Lecture ADC sur 16 bits → Donne les mêmes valeurs
Vérification du facteur de conversion
Recherche d’un facteur de gain éventuel

Datasheet ADC ADS8688
Documentation sonde TDS
Documentation sonde TDS 2

Questions:

Mon facteur de conversion est-il correct ou dois-je ajuster le gain de l’ADC ?
Dois-je modifier le mode SPI ou la fréquence pour améliorer la lecture ?
Pourquoi l’ADC ne restitue pas une tension correcte malgré la variation des données SPI brutes ?
Faut-il appliquer un filtrage logiciel sur les valeurs SPI pour éviter des erreurs ?

Merci d’avance pour votre aide je suis bloqué depuis une bonne semaine :confused:

import pigpio
import time

# Initialisation du SPI (Mode 3, 500 kHz)
pi = pigpio.pi()
spi = pi.spi_open(0, 500000, 3)  # SPI0, 500 kHz, Mode 3 (CPOL=1, CPHA=1)

if spi >= 0:
    print("\nSPI ouvert avec succes\n")

    # Lecture du registre Device ID
    cmd_device_id = [0b10101100, 0x00, 0x00]  # Commande pour lire le Device ID
    count, response = pi.spi_xfer(spi, cmd_device_id)
    print("Reponse du registre Device ID:", response)

    # Configuration du CH1 en mode unipolaire 5V
    cmd_config_ch1 = [0b10101100, 0x02, 0b00000110]  # Config CH1 
    pi.spi_xfer(spi, cmd_config_ch1)
    time.sleep(0.5)  # Pause stabilisation

    # Verification apres configuration
    cmd_read_config_ch1 = [0b10101100, 0x02, 0x00]  # Lire config CH1
    count, response_config = pi.spi_xfer(spi, cmd_read_config_ch1)
    print("Configuration CH1 apres ecriture:", response_config)

    while True:  # Boucle infinie avec lecture toutes les 10s
        print("\n*** Nouvelle lecture SPI ***")

        # Lecture de la valeur brute ADC sur CH1
        cmd_read_ch1 = [0b10101100, 0x00, 0x00]  # Lecture valeur CH1
        count, response = pi.spi_xfer(spi, cmd_read_ch1)

        # Affichage des donnees SPI brutes
        print("Donnees brutes SPI (HEX)  :", [hex(x) for x in response])
        print("Donnees brutes SPI (BIN)  :", [bin(x) for x in response])
        print("Longueur du tableau recu  :", len(response))
        print("Tableau SPI complet       :", response)

        # Decomposition des octets recus
        if len(response) >= 3:
            print("Octet 0 :", bin(response[0]))
            print("Octet 1 :", bin(response[1]))
            print("Octet 2 :", bin(response[2]))

            # Extraction en 14 bits (on ignore les 2 bits inutiles)
            raw_value_14b = ((response[1] & 0x3F) << 8) | response[2]
            print("Valeur ADC brute (14 bits) :", raw_value_14b)

            # Extraction en 16 bits (verif si necessaire)
            raw_value_16b = (response[1] << 8) | response[2]
            print("Valeur ADC brute (16 bits) :", raw_value_16b)

            # Conversion en tension (Plage 0-5V)
            resolution = 16384  # Pour 14 bits
            # resolution = 65536  # Pour 16 bits
            tension_14b = (raw_value_14b / resolution) * 5.0
            tension_16b = (raw_value_16b / 65536) * 5.0  
            print("Tension mesuree (14 bits) :", round(tension_14b, 4), "V")
            print("Tension mesuree (16 bits) :", round(tension_16b, 4), "V")

            # Compensation de temperature 
            temperature = 25.0  # Temperature par defaut 
            compensation_coeff = 1.0 + 0.02 * (temperature - 25.0)
            tension_compensee = tension_14b * compensation_coeff
            print("Tension compensee (T=25C) :", round(tension_compensee, 4), "V")

            # Conversion en TDS (ppm) - Formule standard pour sonde TDS
            tds_value = (133.42 * tension_compensee**3
                        - 255.86 * tension_compensee**2
                        + 857.39 * tension_compensee)
            print("Valeur TDS estimee       :", round(tds_value, 2), "ppm")

        else:
            print("Erreur : Donnees SPI incorrectes")

        time.sleep(10)  # Pause de 10 secondes entre chaque lecture

else:
    print("Erreur d'ouverture du SPI !")