Sensor de temperatura Microchip 9808 - Resultado de cálculo incorrecto

Estoy usando un sensor de temperatura Microchip MCP9808 I2C ( https://learn.adafruit.com/adafruit-mcp9808-precision-i2c-temperature-sensor-guide/overview ).

Tengo problemas para calcular la temperatura usando los valores que estoy leyendo del sensor.

La temperatura es de 13 bits de ancho. De acuerdo con la hoja de datos, necesito enviar dos comandos de lectura, la primera lectura devolverá el byte superior y la segunda lectura devolverá el byte inferior. 3 de los bits restantes se utilizan para indicar alarmas de temperatura y 1 bit se utiliza para indicar el signo de la lectura (positivo o negativo).

Puedo leer los dos bytes usando el código de muestra de la hoja de datos como punto de partida. Sin embargo, los valores que obtengo son incorrectos. Tampoco puedo obtener temperaturas negativas, así que creo que mi código tiene algún problema.

Estoy usando un adaptador USB->I2C y he escrito una implementación en C# del código de muestra de la hoja de datos para calcular la temperatura.

ingrese la descripción de la imagen aquí

Y luego mi código (que aparte de algunas conversiones adicionales necesarias debido a la forma en que C# maneja los tipos de datos) creo que es idéntico.

    public static double CalculateAmbientTemperature(byte upperByte, byte lowerByte)
    {
        const byte ALERT_MASK_VALUE = 0x1F;
        const byte CLEAR_SIGN_MASK = 0x0F;

        double temperature = 0.00;

        upperByte = (byte)(upperByte & ALERT_MASK_VALUE);

        // Ambient temperature less than 0 degrees
        if((upperByte & (byte)(upperByte & 0x10)) == 0x10)
        {
            upperByte = (byte)(upperByte & CLEAR_SIGN_MASK);
            temperature = 256.0 - ((double)upperByte * 16.0 + (double)lowerByte / 16.0);
        }
        else
        {
            temperature = ((double)upperByte * 16.0 + (double)lowerByte / 16.0);
        }

        return temperature;
    }

Entonces, para probar el código, he estado enviando los bytes: START_BIT 0x3E (the address) 0x05 (the address of the temperature register)esto le dice al sensor que apunte el indicador de registro al registro de temperatura, de modo que cuando envíe los dos comandos de lectura, lea desde ese registro.

Y cuando leo los datos, obtengo 0xC1 0x24. Cuando paso estos valores a la función, obtengo 17.0625 grados C. Teniendo en cuenta que estoy sosteniendo un cubo de hielo en el sensor. (Actualmente no tengo una forma más precisa). Básicamente, mi cálculo es defectuoso, pero no sé por dónde empezar para solucionarlo.

Cualquier ayuda sería apreciada.

(EDITAR: para verificar que puedo leer el chip correctamente, leo el registro de ID del fabricante y obtengo el 0x54 esperado)

Tu CLEAR_SIGN_MASKapariencia es incorrecta. Debería ser0x1F
Oh vamos. Siempre hay una mejor manera. Triture un poco de hielo, haga una suspensión de hielo y agua en un recipiente, coloque el sensor en una bolsa de plástico, sumérjalo en la mezcla de hielo y agua y déle tiempo para que alcance el equilibrio. Estarás muy cerca de cero.
@EugeneSh. ¿Cómo es eso? La hoja de datos dice 0x0F?
@user9993 Lo siento, me perdí un poco. Ignorar :)
Calculo manualmente esos valores como 18,25 grados. Pero luego, obtuve el orden de precedencia correcto en mi cálculo. Consejo: no trabaje en doble hasta justo al final. Guárdelo como números enteros.
@Majenko ¿Puede explicar cómo puedo usar el orden de precedencia correcto con mi código?
Primero construya un entero de 16 bits a partir de sus dos bytes. Luego, enmascare los bits que no desea, luego, y solo entonces, debe dividirlos entre 16. Entonces, está trabajando con 0xC124, luego 0x0124, luego 0x012.4
¿Estás seguro de que estás leyendo los datos correctos? Intente leer los registros que contienen valores conocidos y asegúrese de obtenerlos correctamente.
17.0625 sería el resultado de 0xC1 0x11 no 0xC1 0x24. Dado que el byte en C# no está firmado, parece correcto, pero las conversiones podrían ser un problema en C/C++ si el byte estaba firmado.
¿Dónde compraste ese chip? ¿Algún distribuidor, o simplemente de china? Compré algunas piezas de MCP9808 de Mouser y otras de Aliexpress. Los de Mouser leen la temperatura exactamente como en el ejemplo de la hoja de datos. Pero cada uno de los de Ali está dando una temperatura muy aleatoria. Así que consideré que esos chips de porcelana estaban defectuosos. Ahora veo que probablemente podría ser causado por un algoritmo diferente.
Tengo el mío en los tableros de Adafruit, todavía no los he comprado como IC solo todavía. Esos de China suenan como 100% falsos, no tienen nada que ver con algoritmos. ¿Estás al 100% puedes reproducir los problemas cada vez? Personalmente, nunca compraría circuitos integrados ni ningún otro tipo de componente de Aliexpress, nunca. Los IC/componentes falsos son un problema muy conocido que se remonta a décadas. adafruit.com/product/1782
Sí, mis chips originales miden la temperatura con bastante buena consistencia (digamos 26C). Pero esos chips de Ali son basura. Uno da alrededor de 10C, otro alrededor de 20C, otro alrededor de 28C, etc. Están muy lejos. Parece que el precio era demasiado bueno para ser verdad. Ahora veo la respuesta de @freshness, se trata de un cálculo incorrecto.

Respuestas (1)

Me he encontrado con este problema recientemente. El error se origina en la hoja de datos del fabricante. Cuando se establece el indicador 'negativo', el cálculo adecuado es:

temp -= 256;  // correct!

en lugar de

temp = 256 - temp;  // incorrect! But this is the example in the datasheet!

Aquí hay un par de ejemplos de código de control para el MCP9808 en Github:

lexruee/mcp9808

adafruit/Adafruit_MCP9808_Library

Gracias por las ediciones. Además: he enviado un informe de error de documentación a Microchip. Veremos cómo responden.
¿Alguna vez respondieron? @Frescura
No, no lo hicieron. Recibí una solicitud de encuesta aproximadamente un año después y la califiqué bastante baja, pero no hubo reconocimiento ni cambios en la documentación.
¡Que molesto! @Frescura
He usado el cálculo de la hoja de datos y da valores correctos. Tu ecuación modificada da resultados falsos.
Tal vez no fui lo suficientemente claro: la hoja de datos es correcta, pero el código de implementación de muestra en la hoja de datos es incorrecto. Por lo tanto, no copie y pegue simplemente el código C de la hoja de datos.