ADC values ​​are changing each time you assemble or disassemble or tighten the screws of a mechanical assembly

Hello,

I'm developing a torque meter using nrf82832 I fixed complete wheatsotne bridge in my metal part that need measure deformation, but each time that I assemble or disassemple or thighten the screws, the value of adc is changing..

Below, the saadc configuration that I'm using:

void saadc_init(void) {
    //  SAADC config & calibrate
    nrfx_saadc_config_t saadc_config = NRFX_SAADC_DEFAULT_CONFIG;
    APP_ERROR_CHECK(nrfx_saadc_init(&saadc_config, saadc_event_handler));
    while (nrfx_saadc_is_busy())
        sd_app_evt_wait();

    // Channels config
    //Bateria
    nrf_saadc_channel_config_t battery_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);//NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_VDD);
    APP_ERROR_CHECK(nrf_drv_saadc_channel_init( 0, &battery_config));

    //Celulas de carga
    nrf_saadc_channel_config_t cell_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_DIFFERENTIAL(NRF_SAADC_INPUT_AIN4, NRF_SAADC_INPUT_AIN7);
    cell_config.reference = NRF_SAADC_INPUT_AIN5;
    cell_config.gain = NRF_SAADC_GAIN1_4;
    APP_ERROR_CHECK(nrf_drv_saadc_channel_init( 1, &cell_config));
    
    // double buffering
    APP_ERROR_CHECK(nrfx_saadc_buffer_convert(buffer[0], INPUTS));
    APP_ERROR_CHECK(nrfx_saadc_buffer_convert(buffer[1], INPUTS));
}

The values ​​read from the adc each time I modify the mechanical part

Just electronic boad
<info> app:  -1924.00 <CR><LF>
<info> app:  -1936.00 <CR><LF>
<info> app:  -1930.00 <CR><LF>
<info> app:  -1914.00 <CR><LF>
<info> app:  -1926.00 <CR><LF>
<info> app:  -1920.00 <CR><LF>
<info> app:  -1918.00 <CR><LF>
<info> app:  -1928.00 <CR><LF>
<info> app:  -1886.00 <CR><LF>
<info> app:  -1930.00 <CR><LF>
<info> app:  -1924.00 <CR><LF>
<info> app:  -1930.00 <CR><LF>
<info> app:  -1920.00 <CR><LF>
<info> app:  -1936.00 <CR><LF>
<info> app:  -1920.00 <CR><LF>
<info> app:  -1932.00 <CR><LF>
<info> app:  -1932.00 <CR><LF>
<info> app:  -1924.00 <CR><LF>
<info> app:  -1928.00 <CR><LF>
<info> app:  -1912.00 <CR><LF>
<info> app:  -1930.00 <CR><LF>


Just first metal borad part with the screws
<info> app:  -1850.00 <CR><LF>
<info> app:  -1842.00 <CR><LF>
<info> app:  -1844.00 <CR><LF>
<info> app:  -1828.00 <CR><LF>
<info> app:  -1852.00 <CR><LF>
<info> app:  -1838.00 <CR><LF>
<info> app:  -1846.00 <CR><LF>
<info> app:  -1846.00 <CR><LF>
<info> app:  -1838.00 <CR><LF>
<info> app:  -1850.00 <CR><LF>
<info> app:  -1840.00 <CR><LF>
<info> app:  -1848.00 <CR><LF>
<info> app:  -1838.00 <CR><LF>
<info> app:  -1840.00 <CR><LF>
<info> app:  -1852.00 <CR><LF>
<info> app:  -1842.00 <CR><LF>
<info> app:  -1842.00 <CR><LF>
<info> app:  -1844.00 <CR><LF>
<info> app:  -1834.00 <CR><LF>
<info> app:  -1850.00 <CR><LF>

Just first metal borad part with the screws again
<info> app:  -520.00 <CR><LF>
<info> app:  -492.00 <CR><LF>
<info> app:  -514.00 <CR><LF>
<info> app:  -528.00 <CR><LF>
<info> app:  -504.00 <CR><LF>
<info> app:  -512.00 <CR><LF>
<info> app:  -522.00 <CR><LF>
<info> app:  -514.00 <CR><LF>
<info> app:  -512.00 <CR><LF>
<info> app:  -510.00 <CR><LF>
<info> app:  -510.00 <CR><LF>
<info> app:  -500.00 <CR><LF>
<info> app:  -510.00 <CR><LF>
<info> app:  -500.00 <CR><LF>
<info> app:  -504.00 <CR><LF>
<info> app:  -514.00 <CR><LF>
<info> app:  -512.00 <CR><LF>
<info> app:  -512.00 <CR><LF>
<info> app:  -514.00 <CR><LF>
<info> app:  -504.00 <CR><LF>

Completely mechanical board
<info> app:  -496.00 <CR><LF>
<info> app:  -500.00 <CR><LF>
<info> app:  -500.00 <CR><LF>
<info> app:  -500.00 <CR><LF>
<info> app:  -512.00 <CR><LF>
<info> app:  -514.00 <CR><LF>
<info> app:  -514.00 <CR><LF>
<info> app:  -498.00 <CR><LF>
<info> app:  -488.00 <CR><LF>
<info> app:  -500.00 <CR><LF>
<info> app:  -506.00 <CR><LF>
<info> app:  -486.00 <CR><LF>
<info> app:  -532.00 <CR><LF>
<info> app:  -488.00 <CR><LF>
<info> app:  -496.00 <CR><LF>
<info> app:  -494.00 <CR><LF>
<info> app:  -484.00 <CR><LF>
<info> app:  -510.00 <CR><LF>
<info> app:  -494.00 <CR><LF>
<info> app:  -456.00 <CR><LF>

Dissasselmby all parts and assembly mechanical board again
<info> app:  -436.00 <CR><LF>
<info> app:  -442.00 <CR><LF>
<info> app:  -450.00 <CR><LF>
<info> app:  -434.00 <CR><LF>
<info> app:  -460.00 <CR><LF>
<info> app:  -440.00 <CR><LF>
<info> app:  -444.00 <CR><LF>
<info> app:  -440.00 <CR><LF>
<info> app:  -466.00 <CR><LF>
<info> app:  -458.00 <CR><LF>
<info> app:  -440.00 <CR><LF>
<info> app:  -448.00 <CR><LF>
<info> app:  -450.00 <CR><LF>
<info> app:  -444.00 <CR><LF>
<info> app:  -440.00 <CR><LF>
<info> app:  -440.00 <CR><LF>
<info> app:  -454.00 <CR><LF>
<info> app:  -448.00 <CR><LF>
<info> app:  -444.00 <CR><LF>
<info> app:  -446.00 <CR><LF>

Others values of my electronic circuit:

Brigde: 3V supply using Vref3v (ISL21080CIH330Z-TK)

Using INA333 with gain 1000 and reference with 1.5V supply with Vref1.5V (ISL21080CIH315Z-TK)

The wheatsone bridge using 350ohm strain gauges

Anyone help me if I need change any SAADC configuration?

Regards

Laerte

Parents
  • Perhaps check that NRF_SAADC_INPUT_AIN5 is derived from +3V bridge excitation and not INA333 1.5V reference or ensure INA333 1.5V reference tracks +3V bridge excitation otherwise bridge measurement is differential but not not ratiometric and therefore varies with bridge excitation. Also bridge arm resistance (and hence load on the +3V bridge excitation) varies as the assembly is flexed with changes in screw tightness if the base is not rigid.

Reply
  • Perhaps check that NRF_SAADC_INPUT_AIN5 is derived from +3V bridge excitation and not INA333 1.5V reference or ensure INA333 1.5V reference tracks +3V bridge excitation otherwise bridge measurement is differential but not not ratiometric and therefore varies with bridge excitation. Also bridge arm resistance (and hence load on the +3V bridge excitation) varies as the assembly is flexed with changes in screw tightness if the base is not rigid.

Children
  • The base is very rigid and very tight. The strain gauges that I'm using already have temperature compensation. Below. the schematic of my project where the bridge circuit is conected.

  • Let's assume the 3V supply changes (for whatever reason); this will change the differential output of the bridge. Using the 3V supply as the reference for the SAADC on NRF_SAADC_INPUT_AIN5 which does not change by the same percentage as the bridge supply introduces an unwanted change in bridge output because the bridge supply is not the 3V supply but (350/550)*3=1.9V. Using a similar derived value for the SAADC reference would then track the changing bridge excitation voltage. Worth a try; or just get rid of the two 100R resistors R1 and R2 and see if that helps

    Edit: If power is removed or restored then the SAADC needs recalibrating, sorry I should have thought of suggesting that

  • I removed r1 and r2 resistors, but the adc values continue changing after any mechanic modifications.

    Edit: If power is removed or restored then the SAADC needs recalibrating, sorry I should have thought of suggesting that

    I agree, but I'm not using it in my code calibrations functions that found in nrfx_saadc.c. I need use it?

    below my code that read adc values.

    #define AMOSTRAS_DIVISAO       50

    void saadc_event_handler(nrfx_saadc_evt_t const *p_event) {
        
        ret_code_t err_code;
        int16_t sample_ADC;

        if (p_event->type == NRFX_SAADC_EVT_DONE){
            nrf_saadc_value_t *adc_result = p_event->data.done.p_buffer;
            uint16_t mv = adc_to_mv(adc_result[0]);
            battery_level = battery_level_in_percent(mv);

            APP_ERROR_CHECK(nrfx_saadc_buffer_convert(adc_result, INPUTS));

            RESbatt = adc_result[0]; //tensao da bateria
            sample_ADC = adc_result[1];
            
            if(m_scale.calibrating == true)
            {
                vetor_adc[index_vetor++] = sample_ADC;//REScell;
                if (index_vetor>=AMOSTRAS_DIVISAO)
                {
                    index_vetor = 0;
                    m_scale.calibrating = false;
                }
                adc_cell_sum=0;
                for (int i=0; i<AMOSTRAS_DIVISAO; i++)
                {
                    adc_cell_sum += vetor_adc[i];
                }
        
                adc_leitura = (adc_cell_sum/AMOSTRAS_DIVISAO); //calculo do offset
                m_scale.offset = adc_leitura;
            }  
            REScell = sample_ADC;    
            err_code = ble_bas_battery_level_update(&m_bas, battery_level, BLE_CONN_HANDLE_ALL);
        
            if ((err_code != NRF_SUCCESS)&&(err_code != NRF_ERROR_INVALID_STATE)&&(err_code != NRF_ERROR_RESOURCES)&&(err_code != NRF_ERROR_BUSY)&&(err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING))
            {
                APP_ERROR_HANDLER(err_code);
            }
        }
    }

    the saadc_event_handler function iscalled every 5ms.

  • Yes, doing the SAADC internal calibration (once or periodically) would help. Couple of tickets which might help, hard to find the best as there are so many:

    continuous-adc-sampling-issue

    trying-to-understand-saadc-changes

    Edit: AIN4, AIN5 and AIN7 require small caps to GND close to nRF52 pins, maybe 10nF or 100nF as a minimum; also try 12-bit resolution if using 10-bit

  • Hi,

    Yes, doing the SAADC internal calibration (once or periodically) would help. Couple of tickets which might help, hard to find the best as there are so many:

    I tried to do it using the example code of the "continuous-adc-sampling-issue", where I inserted the calibration function in my saadc_init, but now, I have problems with my saadc_event_handler function.

    below, my modified function:

    void saadc_init(void) {
        //  SAADC config & calibrate
        nrfx_saadc_config_t saadc_config = NRFX_SAADC_DEFAULT_CONFIG;
        APP_ERROR_CHECK(nrfx_saadc_init(&saadc_config, saadc_event_handler));
        while (nrfx_saadc_is_busy())
            sd_app_evt_wait();

        // Channels config
        //Bateria
        nrf_saadc_channel_config_t battery_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);//NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_VDD);
        APP_ERROR_CHECK(nrf_drv_saadc_channel_init( 0, &battery_config));

        //Celulas de carga
        nrf_saadc_channel_config_t cell_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_DIFFERENTIAL(NRF_SAADC_INPUT_AIN4, NRF_SAADC_INPUT_AIN7);
        cell_config.reference = NRF_SAADC_INPUT_AIN5;
        cell_config.gain = NRF_SAADC_GAIN1_4;
        APP_ERROR_CHECK(nrf_drv_saadc_channel_init( 1, &cell_config));
        
        // double buffering
        APP_ERROR_CHECK(nrfx_saadc_buffer_convert(buffer[0], INPUTS));
        APP_ERROR_CHECK(nrfx_saadc_buffer_convert(buffer[1], INPUTS));

    // Calibrate the SAADC by finding its offset
        NRF_SAADC->TASKS_CALIBRATEOFFSET = 1;
        while (NRF_SAADC->EVENTS_CALIBRATEDONE == 0);
        NRF_SAADC->EVENTS_CALIBRATEDONE = 0;
        while (NRF_SAADC->STATUS == (SAADC_STATUS_STATUS_Busy << SAADC_STATUS_STATUS_Pos));
    }

    This form is correct?

    The returned error of the saadc_timeout_handler is:

    <error> app: ERROR 8 [NRF_ERROR_INVALID_STATE]

    static void saadc_timeout_handler(void *p_context) { // ADC for battery status
        UNUSED_PARAMETER(p_context);
        APP_ERROR_CHECK(nrfx_saadc_sample());
    }

    Regards

Related