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

Problem with SPI data transfer with 2 channels (ADC peripheral)

Hi, 

I was able to use SPI communication to read data from ADS1220 (one channel of a 3-channel ADC) and transmit it via NUS ble service to my NRF Toolbox app and RTT logger on my PC (each data transfer is 3 bytes).  Currently this is using 1 input pin of the ADC. 


I would now like to switch between the 2 inputs of the ADC in turn and continuously receive data from both channels in real time. I wrote the following program which alternately initializes the ADC for a specific channel config and then calls data from it.  

      spi_init();

      init_ain1(); 
      nrf_delay_ms(100);

      // Start execution.
      NRF_LOG_INFO("Debug logging for UART over RTT started.");
      advertising_start();

      // Enter main loop.
      for (;;)
      {
          idle_state_handle();      
          init_ain1();       //writes to ADC registers for channel change 
          data_call_for_ch1();
          nrf_delay_ms(1000); 
          init_ain2(); 
          data_call_ch2(); 
          NRF_LOG_FLUSH(); 

          
         
      }
      
      
      
      
      
      
      
      ///// This is my data call/transfer SPI function. Same for ch2
      
      void data_call_for_ch1(void)
  {
      uint32_t err_code=0;
      uint16_t  ble_buff_len = m_rx_bufferSize;

    
   
      memset(m_tx_buf, 0, (m_rx_bufferSize+3) );
      m_tx_buf[0] = 0x08;    // HEX command for transfer
     
      memset(m_rx_buf, 0, m_rx_bufferSize);
      spi_xfer_done = false;

      nrf_gpio_pin_clear(SPI_CS_PIN);
      APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, m_tx_buf, 1, m_rx_buf, m_rx_bufferSize));

      while (!spi_xfer_done)
      {
          __WFE();
      }

      NRF_LOG_FLUSH();


   

      if (m_conn_handle != BLE_CONN_HANDLE_INVALID)
      {

          err_code = ble_nus_data_send(&m_nus, m_rx_buf, &ble_buff_len, m_conn_handle);
          if ((err_code != NRF_ERROR_INVALID_STATE) &&
              (err_code != NRF_ERROR_RESOURCES) &&
              (err_code != NRF_ERROR_NOT_FOUND))
          {
              APP_ERROR_CHECK(err_code);
          }
      }

}


 void init_ain1 (void)   // Same config settings for Ch2

  {

    // Registers Config for pH AIN1
    memset(m_tx_buf, 0, (m_rx_bufferSize+3) );
    // Reg hex settings 
    m_tx_buf[0] = 0x40;
    m_tx_buf[1] = 0x82;
    m_tx_buf[2] = 0x10;
    m_tx_buf[3] = 0x06; 
    m_tx_buf[4] = 0x20; 
        
    memset(m_rx_buf, 0, m_rx_bufferSize);
    spi_xfer_done = false;

    nrf_delay_ms(100); 

    nrf_gpio_pin_clear(SPI_CS_PIN);
    APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, m_tx_buf, 5, m_rx_buf, m_rx_bufferSize));

      while (!spi_xfer_done)
      {
          __WFE();
      }
      


  }

      
      



According to the ADC ADS1220 datasheet, the ADS1220 register 0 has to be re-written for it to change input channel... 
However, whenever I try to re-configure the registers before a data transfer call, I start receiving all "FFFFFF..." data. In my earlier experience with this ADC, it gives out "FFFFFF" when you try to call data faster than it is available. However, no matter how much delay I add, the problem persists and I cannot switch between channels in my program. I am not if the "FFFF"
data represents the same problem or something else... 

SPI frequency = 4 MHz 
SPI Mode 1 
40 Samples/sec on Turbo Mode (512kHz Modulator clock)


Embedded Studio, nRF52382, TI- ADS1220, ble_nus, SDK 15.2

Parents
  • I think the write command above is incorrect; the first byte requires write command 0x40 (as you have) but also the starting register and number of registers-1. 0x40 only writes 1 register to starting register address 0.

    8.5.3.6 WREG (0100 rrnn)
    The WREG command writes the number of bytes specified by nn (number of bytes to be written – 1) to the device configuration register, starting at register address rr. The command is completed after nn + 1 bytes are clocked in after the WREG command byte. For example, the command to write two bytes (nn = 01) starting at configuration register 0 (rr = 00) is 0100 0001. The configuration registers are updated on the last SCLK falling edge.

    I haven't checked your intended register values, but to write to 4 registers from Register 0 change the first byte to 0x43:

        // Reg hex settings 
        m_tx_buf[0] = 0x40 | 0x00 | (4-1); // Write to register 0 for 4 registers
        m_tx_buf[1] = 0x82;
        m_tx_buf[2] = 0x10;
        m_tx_buf[3] = 0x06; 
        m_tx_buf[4] = 0x20; 

  •   Yes you are correct. I did fix this. Thank you for your response. 

    However the problem does not seem to be with the way I am configuring/writing to ADC for initialization. When I configure ADC regs outside the main for () loop, the ADC data is fine and everything works great. 

    When I paste the exact configuration/initializing code in the main for() loop to re-config my ADC continuously , that's when I stop getting proper data from the ADC. 

    What would you suggest I do in that case? 


  • Could it be a timing issue?

    Have you looked at the signals with a scope or analyser, and compared the "working" and "non-working" cases?

    And, as already suggested, have you checked with the manufacturer (TI?) whether this is the best way to be using their device? It sounds a little odd to be completely re-initialising just to use a different channel ...

  • I will look more into that. Thank you. 

    Has anyone ever tried initializing and using two SPI instances in one program to get data from two initialized SPIs in the same program? (both instances have separate spi_evt_handlers etc )  


  • So I put my ADC (ads1220 from TI) into Continuous Conversion Mode from single shot mode (I was using this mode before), and that enabled me to configure (write to ADC ) in real time. 

    So yes, it's a timing issue. Just in case anyone else ever needs it. Thank you everyone. 

Reply Children
No Data
Related