problema de frecuencia de muestreo de ADC MCP3421

1

Estoy escribiendo un controlador para mcp3421 IC de ADC y tengo un problema cuando mido en la precisión de 12 bits. Eso es 240 muestras por segundo.

En la hoja de datos, los valores mínimo y máximo son 176 SPS y 328 SPS. Así que espero poder ver una nueva medición cada:

-min: \ $ 1sec / 176 \ $ - > \ $ 5,69msec \ $

o

-max: \ $ 1sec / 328 \ $ - > \ $ 3,05msec \ $

En realidad, sondea el mcp3421 cada 7 ms para estar seguro de que obtiene una nueva medición, pero el indicador RDY (0 = nueva medición) se establece cada 50 ms.

¿Eso es normal? ¿Por qué sucede esto?

Aquí está el árbol (cada 7 ms)

yaquíestáelbosque(cada50ms)

 * \brief Reads all mcp3421 registers.
 * 
 * \bug Needs a timeout mechanism or it might hang in a loop if device hardware fails.
 * 
 * It reads mcp3421 and expects either 4 or 3 bytes.
 * If it is in 18-bit all bytes are used.
 * If it is not 18-bit the lower byte is not used.
 * 
 * \param[in,out]   me          The mcp3421 handle.
 * \param[out]      upper       The first byte.
 * \param[out]      middle      The second byte.
 * \param[out]      lower       The third byte(18bit) or configuration byte(12,14,16bit).
 * \param[out]      config_reg  Register is the 3rd byte(12,14,16bit) in row or the 4rth(18bit).
 * 
 * \retval          0           Success.
 * \retval          1           Failed.
 */
static int mcp3421_read_all( mcp3421_t* me, uint8_t* upper, uint8_t* middle, uint8_t* lower, uint8_t* config_reg )
{
    //TODO: Add timeout_ms
    int err = 0;
    do 
    {
        /* Read mcp3421 register */
        uint8_t data[4] = { 0x00, 0x00, 0x00, 0x90 };
        if( i2c_master_receive( &(me->bus), me->address, data, 4U, MCP3421_TIMEOUT ) )
        {
            /* Exit with error */
            errorHandler();
            return 1;
        }

        /* Get data */
        *upper = data[0];
        *middle = data[1];
        *lower = data[2];
        *config_reg = data[3];

        /* Wait until the next read */
        if( mcp3421_delayUntilNextRead( *config_reg ) )
        {
            /* Exit with error */
            errorHandler();
            return 1;
        }

        /* Check if registers are updated */
        if( ( (*config_reg) & RDY_Mask ) == 0 )
        {
            /* Exit with success */
            return 0;
        }
        err++;
    }
    while( err<200 );

    /* Exit with failure */
    errorHandler();
    return 1;
}
    
pregunta Tedi

1 respuesta

0

Cuando se solicita repetidamente el byte de configuración después de los bytes de datos (2 en el caso de 12/14 / 16bit y 3 en el caso de 18bit), el registro de configuración está cambiando. Por lo tanto, si su código cuenta en el último valor de configuración adquirido, puede perder un indicador RDY u obtener uno incorrecto.

Mi código hizo eso y es un error.

La solución alternativa es pedir la cantidad correcta de bytes o el siguiente código.

/**
 * \brief Reads all mcp3421 registers.
 * 
 * \bug Needs a timeout mechanism or it might hang in a loop if device hardware fails.
 * 
 * It reads mcp3421 and expects either 4 or 3 bytes.
 * If it is in 18-bit all bytes are used.
 * If it is not 18-bit the lower byte is not used.
 * 
 * In 12/14/16-bit the middle byte is set to zero.
 * 
 * \param[in,out]   me          The mcp3421 handle.
 * \param[out]      upper       The first byte.
 * \param[out]      middle      The second byte.
 * \param[out]      lower       The third byte(18bit) or configuration byte(12,14,16bit).
 * \param[out]      config_reg  Register is the 3rd byte(12,14,16bit) in row or the 4rth(18bit).
 * 
 * \retval          0           Success.
 * \retval          1           Failed.
 */
static int mcp3421_read_all( mcp3421_t* me, uint8_t* upper, uint8_t* middle, uint8_t* lower, uint8_t* config_reg )
{
    //TODO: Add timeout_ms
    uint32_t err = 0;
    do 
    {
        /* Read mcp3421 register */
        uint8_t data[4] = { 0x00, 0x00, 0x00, 0x90 };
        if( i2c_master_receive( &(me->bus), me->address, data, 4U, MCP3421_TIMEOUT ) )
        {
            /* Exit with error */
            errorHandler();
            return 1;
        }

        /* Get data */
        *config_reg = data[3];//This is config for all data rates.
        if( mcp3421_unmarshal_sample_rate( *config_reg ) == mcp3421_sample_rate_18bit )
        {
            /* 18 bit */
            *upper = data[0];
            *middle = data[1];
            *lower = data[2];
            *config_reg = data[3];
        }
        else
        {
            /* 12/14/16 bit */
            *upper = data[0];
            //*middle = 0;
            *lower = data[1];
            *config_reg = data[2];
        }

        /* Check if registers are updated */
        if( ( (*config_reg) & RDY_Mask ) == 0 )
        {
            /* Exit with success */
            return 0;
        }
        err++;
    }
    while( err<1000 );

    /* Exit with failure */
    errorHandler();
    return 1;
}
    
respondido por el Tedi

Lea otras preguntas en las etiquetas