This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

nRF52840 - ADS1292

Hi,

I want to read register 0x00 (chip ID) of ads1292. i do following...

=============================================================================================================================

///// init spi /////

spi_config.ss_pin = ARDUINO_7_PIN;
spi_config.miso_pin = ARDUINO_12_PIN;
spi_config.mosi_pin = ARDUINO_11_PIN;
spi_config.sck_pin = ARDUINO_13_PIN;
spi_config.bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST;
spi_config.mode = NRF_DRV_SPI_MODE_0;
spi_config.frequency = NRF_DRV_SPI_FREQ_4M;
spi_config.orc = 0x00;
APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL));
NRF_LOG_INFO("SPI example started.");NRF_LOG_FLUSH();

///// reset the board by pulling low hardware pin /////

nrf_gpio_pin_write(ADS1292_PWDN_PIN, action);

delay(100);

nrf_gpio_pin_write(ADS1292_PWDN_PIN, action);

delay(100);

nrf_gpio_pin_write(ADS1292_PWDN_PIN, action);

delay(100);

/////// stop continues data receive mode ///////

spi_xfer_done=false;memset(m_rx_buf,0,sizeof(m_rx_buf));
spiDataTx[0]=0x11;
APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, spiDataTx, 1, m_rx_buf, sizeof(m_rx_buf)));
while (!spi_xfer_done){__WFE();}
NRF_LOG_FLUSH();

//////// read chip id register (0x00) ///////////

char tempData[3];
tempData[0]=0x20;
tempData[1]=0x00;
tempData[2]=0x00;
spi_xfer_done=false;memset(m_rx_buf,0,sizeof(m_rx_buf));
APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, tempData, 3, m_rx_buf, sizeof(m_rx_buf)));
while (!spi_xfer_done){__WFE();}
NRF_LOG_FLUSH();

=============================================================================================================================

but i always get garbage value. It should come as 0x73 but every time receiving garbage values.

i did exactly same as described in datasheet of ads1292.

Did i anything wrong as far as nRF52 board concern ? Waiting for better solution.

Thanks in advance.

Parents
  • 4MHz and Mode 0 will create difficulties for the ADS1292. Try the following:

    spi_config.frequency = NRF_DRV_SPI_FREQ_500K;  // Ensure less than 4 clk cycles for ADS1292
    spi_config.bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST;
    spi_config.mode      = NRF_DRV_SPI_MODE_1;
    APP_ERROR_CHECK(nrf_drv_spi_init(&mAfeSpiInstance, &spi_config, afe_spi_event_handler, NULL));
    

    Reading the version code is easiest using a single transfer:

    // Scratch pad comms buffers, used for reading all AFE registers - want to preserve these for debugging
    #define AFE_HARDWARE_VERSION 0x53
    
    static uint8_t mTxBuf[] = {ADS_CMND_RREG, NUMBER_OF_ADS_REGISTERS-1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    static uint8_t mRxBuf[sizeof(mTxBuf)];
    static const uint8_t mRxTxBufLength = sizeof(mTxBuf);
    
    /**
     * @brief SPI command to read AFE registers
     * @param event
     */
    static void ReadAfeRegisters(void)
    {
        uint32_t spiAttempCount, mAfeSpiErrorCount = 0;
    
        for (spiAttempCount=0; spiAttempCount < AFE_MAX_ATTEMPTS; spiAttempCount++)
        {
            memset(mRxBuf, '?', mRxTxBufLength);
            mAfePacketTransferComplete = false;
            APP_ERROR_CHECK(nrf_drv_spi_transfer(&mAfeSpiInstance, mTxBuf, mRxTxBufLength, mRxBuf, mRxTxBufLength));
            // Hard delay per byte to transmit
            nrf_delay_us(mRxTxBufLength*AFE_SPI_PER_BYTE_uSECS);
            // Check for ADS1292 Id
            if (mAfePacketTransferComplete && (mRxBuf[2] == AFE_HARDWARE_VERSION))
            {
                // Correct Id for this AFE
                break;
            }
            else
            {
                mAfeSpiErrorCount++;
                // Extra hard delay per byte to transmit
                nrf_delay_us(mRxTxBufLength*AFE_SPI_PER_BYTE_uSECS);
            }
        }
        // Post the results (may be bad)
        ...
    }
    
    /**
     * @brief SPI event handler indicating SPI transfer has completed
     * @param event
     */
    static void afe_spi_event_handler(nrf_drv_spi_evt_t const * p_event, void *p_context)
    {
        mAfePacketTransferComplete = true;
    }
    
    

    Read the data sheet to see why the slow transfer speed is being used in my example; it is related to the number of clock cycles required by the part to handle SPI commands before the next SPI info; faster speeds are ok provided the code manages that restriction - I choose to take the simplest solution :-)

  • Hi,

    Now i am able to read register by selecting spi_config.frequency = NRF_DRV_SPI_FREQ_250K.

    I have another issue that i am unable to write registers.

    i am using below code to write 0x03 register.

    char dataToSend[3];
    dataToSend[0] = 0x03 | WREG;
    ads1292_SPICommand(dataToSend[0]);
    delayMicroSeconds(5);
    dataToSend[1] = 0x00;
    ads1292_SPICommand(dataToSend[1]);
    delayMicroSeconds(5);
    dataToSend[2] = 0x10;
    ads1292_SPICommand(dataToSend[2]);m_length=3;
    //ads1292_SPICommandString(dataToSend,3);

    what i did is...

    first i read 0x03 register and i got 0x10 (default) value then i write 0x03 register using above code and after writing it when i read 0x03 it will return 0x00 value (it should be 0x10).

    Thanks in advanced

Reply
  • Hi,

    Now i am able to read register by selecting spi_config.frequency = NRF_DRV_SPI_FREQ_250K.

    I have another issue that i am unable to write registers.

    i am using below code to write 0x03 register.

    char dataToSend[3];
    dataToSend[0] = 0x03 | WREG;
    ads1292_SPICommand(dataToSend[0]);
    delayMicroSeconds(5);
    dataToSend[1] = 0x00;
    ads1292_SPICommand(dataToSend[1]);
    delayMicroSeconds(5);
    dataToSend[2] = 0x10;
    ads1292_SPICommand(dataToSend[2]);m_length=3;
    //ads1292_SPICommandString(dataToSend,3);

    what i did is...

    first i read 0x03 register and i got 0x10 (default) value then i write 0x03 register using above code and after writing it when i read 0x03 it will return 0x00 value (it should be 0x10).

    Thanks in advanced

Children
  • SPI is a synchronous protocol which uses packets, much improved over byte-orientated asynchronous UART The code you are using looks like Arduino-type code for a device which doesn't properly support SPI, so I would recommend a change of thinking. I don't work for either Nordic or TI, so I can only offer limited support; here is how to use SPI as it was intended, albeit in this case for an ADS1291 which has identical registers and timing to both the ADS1292 and ADS1292R. First define the packet; put in all registers although they don't all have to be actually sent, just adjust the length byte accordingly.

    typedef struct {
      uint8_t ADS1292_CONFIG1;       // 0x0001u ADS1x9x_REG_CONFIG1
      uint8_t ADS1292_CONFIG2;       // 0x0002u ADS1x9x_REG_CONFIG2
      uint8_t ADS1292_LOFF;          // 0x0003u ADS1x9x_REG_LOFF
      uint8_t ADS1292_CH1SET;        // 0x0004u ADS1x9x_REG_CH1SET
      uint8_t ADS1292_CH2SET;        // 0x0005u ADS1x9x_REG_CH2SET
      uint8_t ADS1292_RLD_SENS;      // 0x0006u ADS1x9x_REG_RLD_SENS
      uint8_t ADS1292_LOFF_SENS;     // 0x0007u ADS1x9x_REG_LOFF_SENS
      uint8_t ADS1292_LOFF_STAT;     // 0x0008u ADS1x9x_REG_LOFF_STAT
      uint8_t ADS1292_RESP1;         // 0x0009u ADS1x9x_REG_RESP1
      uint8_t ADS1292_RESP2;         // 0x000Au ADS1x9x_REG_RESP2
      uint8_t ADS1292_GPIO;          // 0x000Bu ADS1x9x_REG_GPIO
    } ADS1292WriteRegisters_t;
    
    typedef struct {
        uint8_t                 Command;
        uint8_t                 AfeRegisterCount;
        ADS1292WriteRegisters_t ADS1292Registers;
    } ADS1292_WritePacket_t;
    
    // AFE Register settings - Default (and typical) values. Note Id is read-only
    static ADS1292WriteRegisters_t mAFE_RegisterRequiredSettings =
      // Lead off detection settings
      //              Lead  Ch 1  Ch 2 RLD   LOff   LOff
      // Conf1 Conf2   Off   Set  Set  Sense Sense  Stat RESP1 RESP2  GPIO    Last column is lead-lead impedance
      // ===== =====  ====  ====  ==== ===== =====  ==== ===== =====  ====    ==================================
        { 0x01, 0xA0, 0x10, 0x10, 0x81, 0x23, 0x00, 0x00, 0x02, 0x07, 0x03}; // Normal scanning
        
    // To avoid enumerated type mix warning define intermediate type
    #define ADS1x9x_CONFIG_REGISTERS     1
    STATIC_ASSERT (ADS1x9x_CONFIG_REGISTERS == ADS1x9x_REG_CONFIG1);
    
    

    Then build the packet to transmit with command and length bytes added; of course you could just define a single structure for this, but in my code there are other reasons not to.

        // Build packet with required settings
        memcpy(&mAfeWriteBuf.ADS1292Registers, &mAFE_RegisterRequiredSettings, sizeof(ADS1292WriteRegisters_t));
        mAfeWriteBuf.Command = ADS_CMND_WREG | ADS1x9x_CONFIG_REGISTERS;
        mAfeWriteBuf.AfeRegisterCount = sizeof(ADS1292WriteRegisters_t)-1;
    
        // Wirte and receive packet
        uint16_t length = sizeof(mAfeWriteBuf);
        APP_ERROR_CHECK(nrf_drv_spi_transfer(&mAfeSpiInstance, (uint8_t *)&mAfeWriteBuf, length, (uint8_t *)&mAfeReadBuf, length));
    

    When all is well, to enable continuous read mode - assuming you want that - issue the following:

        AdsSendCmd(ADS_CMND_START);
        nrf_delay_us(400);
        AdsSendCmd(ADS_CMND_RDATAC);                     // Enable continuous read mode
    

  • Hi,

    I did Exactly what you suggested but still not able to write registers.

  • Did you remember to Stop Continuous Mode as I suggested earlier before you attempt to write? Using 1-byte command ADS_CMND_SDATAC. If the Read Id command is working correctly then that is the usual reason why a write doesn't work; this is described in the data sheet.

Related