MCP3421 ADC data interpretation

Thread Starter

yef smith

Joined Aug 2, 2020
717
Hello,I want to put 1.5V to the ADC single ended if i use 12bit.

What is supposed to be the digital data for 1.5V analog input?

from adc theory We take ((full scale range)/2^12)*digital_value=analog value
From the data sheet they say 2.048 i dont know if my Full scale range is 0-2.048 or -2.048 till +2.048?
What VDD should i use to this device?
Thanks.
http://ww1.microchip.com/downloads/en/devicedoc/22003e.pdf
 
Last edited:

Thread Starter

yef smith

Joined Aug 2, 2020
717
Hello, If i want to set my mcp3421 at continues mode by setting O/C bit as high.RDY* is 0 when convertion is completed
Then another converstion is started.What happens to the RDY* bit then?
In th manual they say that RDY* is 1 only when we read the data.
So during convertions RDY* stays 0 all the time?

Also , as shown in the datashhet bellow,why writing to RDY in continues mode doesnt affect anithing?
Thanks.
1608637881222.png
 

bogosort

Joined Sep 24, 2011
696
Hello,I want to put 1.5V to the ADC single ended if i use 12bit.

What is supposed to be the digital data for 1.5V analog input?

from adc theory We take ((full scale range)/2^12)*digital_value=analog value
From the data sheet they say 2.048 i dont know if my Full scale range is 0-2.048 or -2.048 till +2.048?
The MCP3421 is a differential input ADC, so with a 2.048 V reference it will convert input voltages between -2.048 and +2.048. In other words, the full-scale range is 4.096 V. Thus, for a 12-bit conversion of 1.5 V (single-ended), you can expect an output code of 1.5 * 2^12 / 4.096 = 1500, which is 0x5DC as 12-bit hex. This is all in the datasheet (see sections 4.5 and 4.9).

What VDD should i use to this device?
This is also in the datasheet: VDD can be anything in the range 2.7 V to 5.5 V.
 

bogosort

Joined Sep 24, 2011
696
Hello, If i want to set my mcp3421 at continues mode by setting O/C bit as high.RDY* is 0 when convertion is completed
Then another converstion is started.What happens to the RDY* bit then?
During conversion the sample data is not ready yet and so the /RDY bit is 1. Once the conversion is complete and the sample value is ready to be read, the /RDY bit changes to 0. You can use this fact to perform a blocking read from the ADC by, for example, looping on the state of the /RDY bit: stay in the loop until its value is 0.

In th manual they say that RDY* is 1 only when we read the data.
So during convertions RDY* stays 0 all the time?
The opposite. We read the data when the /RDY bit is 0; when it is 1, we know that the ADC is busy performing the conversion.

Also , as shown in the datashhet bellow,why writing to RDY in continues mode doesnt affect anithing?
In one-shot mode, writing a 1 to /RDY tells the ADC to begin the conversion process. Once the conversion is complete, the ADC will set /RDY to 0 (just as in the continuous case). In continuous mode, there's no reason to write to /RDY as the ADC is continuously sampling the input, so writing to it does nothing.
 

Thread Starter

yef smith

Joined Aug 2, 2020
717
Hello, We need to connect I2C SDA SCL from expansion header to mcp3421 ADC on a bread board.
based on the efr32fg14 starter kit i haved connected pin20 3v3,pin16 I2C_SDA,pin15 I2C_SCL,pin1 GND

Based on the diagram bellow,We have the expansion header and the Si7021 connected on the same LOCATION
So i think that in order for us to dissable the SI7021 sensor and make the expansion header connected to mcp3421
we need to disable PD15 in the code.

then i have shown bellow a photo from paper ,How the I2C communication should look like the calculation of device address D0 and calculation of config byte 1C.

Then i have made a voltage divider to input single ended my mcp3421 in scope photo 1A where we se the input is 2.4V and pk-pk 194mv.

Then as shown in photos 2A to 2D I have connected the I2C 3.3,gnd,extension header pins to their corresponding MCP.Also i have connected 5.1Kohm resistors to SDA and SCL to 3.3v to make the signal better.
I have used I2C_FLAG_WRITE_READ flag which has the structure shown bellow.
In the code i have set to recieve 4 bits (3 data and 1 config as in the data sheet of mcp3421 bellow).
the full code is shown in the end
unfortunetly i am allowed to upload only 10 photos per comment so i add the I2C scope photos bellow in the next comment
The I2C diagram that was recieved shown in the last photos bellow ,we see a cyclic structure where write at the start the slave sends NACK to my 0xD0 (adress+w)
from mcp3421 Data sheet page 18 device code is 1101 and A2-A0 is 000 plus write bit (0) so the total is 11010000 which is 0xD0
Why its no accepting this data?
Thanks.



EFR32FG14 starter kit:
https://www.silabs.com/documents/public/user-guides/ug318-brd4257b-user-guide.pdf
EFR32FG14 data sheet:
https://www.silabs.com/documents/public/data-sheets/efr32fg14-datasheet.pdf
EFR32FG14 I2C API
I2C - v5.9 - MCU EFR32FG14 API Documentation Silicon Labs
Mcp 3421 datasheet:

https://ww1.microchip.com/downloads/en/DeviceDoc/22003e.pdf


1608753633196.png
1608753665446.png
1608753694486.png
1608753792787.png
1608753872000.png
1608753934105.png
1608753972762.png
1608754025181.png

1608754058434.png

Code:
#include "em_usart.h"
#include "em_ldma.h"

/////////////////
#include "stddef.h"
#include "em_system.h"
#include "em_device.h"
#include "em_chip.h"
#include "em_cmu.h"
#include "em_emu.h"
#include "em_gpio.h"
#include "i2cspm.h"
#include "si7013.h"
#include "sl_sleeptimer.h"
#include "graphics.h"
#include "em_adc.h"
#include "bspconfig.h"





uint8_t com1[1] = {0x1C}; //config command

//page 20 of data sheet
uint8_t i2c_rxBuffer[4]; //[0]-2nd Byte [1]-3rd byte [2]-4th byte [3]-5th config byte
void initUSART1 (void)
{
    CMU_ClockEnable(cmuClock_GPIO, true);
    CMU_ClockEnable(cmuClock_USART1, true);

    // Configure GPIO mode
    GPIO_PinModeSet(gpioPortC, 8, gpioModePushPull, 0); // US1_CLK is push pull
    GPIO_PinModeSet(gpioPortC, 9, gpioModePushPull, 1); // US1_CS is push pull
    GPIO_PinModeSet(gpioPortC, 6, gpioModePushPull, 1); // US1_TX (MOSI) is push pull
    GPIO_PinModeSet(gpioPortC, 7, gpioModeInput, 1);    // US1_RX (MISO) is input
    GPIO_PinModeSet(gpioPortF, 7, gpioModeInput, 1);    // delay gpio

    // Start with default config, then modify as necessary
    USART_InitSync_TypeDef config = USART_INITSYNC_DEFAULT;
    config.master       = true;            // master mode
    config.baudrate     = 1000000;         // CLK freq is 1 MHz
    config.autoCsEnable = true;            // CS pin controlled by hardware, not firmware
    config.clockMode    = usartClockMode0; // clock idle low, sample on rising/first edge
    config.autoCsEnable = true;            // CS pin controlled by  firmware
    config.msbf         = true;            // send MSB first
    config.enable       = usartDisable;    // Make sure to keep USART disabled until it's all set up
    USART_InitSync(USART1, &config);

    // Set USART pin locations
    USART1->ROUTELOC0 = (USART_ROUTELOC0_CLKLOC_LOC11) | // US1_CLK       on location 11 = PC8 per datasheet section 6.4 = EXP Header pin 8
                        (USART_ROUTELOC0_CSLOC_LOC11)  | // US1_CS        on location 11 = PC9 per datasheet section 6.4 = EXP Header pin 10
                        (USART_ROUTELOC0_TXLOC_LOC11)  | // US1_TX (MOSI) on location 11 = PC6 per datasheet section 6.4 = EXP Header pin 4
                        (USART_ROUTELOC0_RXLOC_LOC11);   // US1_RX (MISO) on location 11 = PC7 per datasheet section 6.4 = EXP Header pin 6

    // Enable USART pins
    USART1->ROUTEPEN = USART_ROUTEPEN_CLKPEN | USART_ROUTEPEN_CSPEN | USART_ROUTEPEN_TXPEN | USART_ROUTEPEN_RXPEN;



    // Enable USART1
    USART_Enable(USART1, usartEnable);
    ////////////////////////////////////////////
    //UART INITLIZATION

    USART_InitAsync_TypeDef init = USART_INITASYNC_DEFAULT;



     // Enable oscillator to GPIO and USART0 modules

     CMU_ClockEnable(cmuClock_USART0, true);

     // set pin modes for UART TX and RX pins
     GPIO_PinModeSet(gpioPortA, 1, gpioModeInput, 0);
     GPIO_PinModeSet(gpioPortA, 0, gpioModePushPull, 1);

     // Initialize USART asynchronous mode and route pins
     USART_InitAsync(USART0, &init);
     USART0->ROUTELOC0 = USART_ROUTELOC0_RXLOC_LOC0 | USART_ROUTELOC0_TXLOC_LOC0;
     USART0->ROUTEPEN |= USART_ROUTEPEN_TXPEN | USART_ROUTEPEN_RXPEN;

}//end usart init

int main(void)

{

I2C_TransferSeq_TypeDef i2cTransfer;

I2C_TransferReturn_TypeDef result;



I2CSPM_Init_TypeDef i2cInit = I2CSPM_INIT_DEFAULT;





/* Chip errata */

CHIP_Init();
initUSART1();


// Enabling clock to the I2C, GPIO, LE

CMU_ClockEnable(cmuClock_I2C0, true);

CMU_ClockEnable(cmuClock_GPIO, true);

CMU_ClockEnable(cmuClock_HFLE, true);



// Starting LFXO and waiting until it is stable

CMU_OscillatorEnable(cmuOsc_LFXO, true, true);



I2CSPM_Init(&i2cInit);

// In order to enable the I2C0_SCL function in PC10 you need to use ROUTE 14

// In order to enable the I2C0_SDA function in PC11 you need to use ROUTE 16

//Also note that there's a GPIO pin PD15 that need to be set to high in order to route the signals to the sensor,

// Using PC10 (SCL) and PC11 (SDA)

  GPIO_PinModeSet(gpioPortC, 10, gpioModeWiredAndPullUp, 1);

  GPIO_PinModeSet(gpioPortC, 11, gpioModeWiredAndPullUp, 1);


// GPIO_PinModeSet(gpioPortC, 10, gpioModeWiredAnd, 1);

//  GPIO_PinModeSet(gpioPortC, 11, gpioModeWiredAnd, 1);

  //Si7021 switch off

  GPIO_PinModeSet(gpioPortD, 15, gpioModePushPull, 0);



  // Enable pins at location 15 as specified in datasheet

  I2C0->ROUTEPEN = I2C_ROUTEPEN_SDAPEN | I2C_ROUTEPEN_SCLPEN;

  I2C0->ROUTELOC0 = (I2C0->ROUTELOC0 & (~_I2C_ROUTELOC0_SDALOC_MASK)) | I2C_ROUTELOC0_SDALOC_LOC16;

  I2C0->ROUTELOC0 = (I2C0->ROUTELOC0 & (~_I2C_ROUTELOC0_SCLLOC_MASK)) | I2C_ROUTELOC0_SCLLOC_LOC14;

  i2cTransfer.flags=I2C_FLAG_WRITE_READ;

  i2cTransfer.addr=0xD0;//address with write

  i2cTransfer.buf[0].data=&com1[0];  // Config byte

  i2cTransfer.buf[0].len=1;    //number bytes in config bytes



  i2cTransfer.buf[1].data=i2c_rxBuffer;

  i2cTransfer.buf[1].len=4;    //4 bytes =3 data and 1 config byte

while(1)

{

  result=I2C_TransferInit(I2C0,&i2cTransfer);



  // Sending data

   while (result == i2cTransferInProgress)

   {

    result = I2C_Transfer(I2C0);

   }

   //When sending data ends
   //SPI sending data
   USART_SpiTransfer(USART1,i2c_rxBuffer[0]);
   USART_SpiTransfer(USART1,i2c_rxBuffer[1]);
   USART_SpiTransfer(USART1,i2c_rxBuffer[2]);

   //send UART
   USART_Tx(USART0, '\n');
      USART_Tx(USART0, i2c_rxBuffer[0]);
      USART_Tx(USART0, i2c_rxBuffer[1]);
      USART_Tx(USART0, i2c_rxBuffer[2]);
      USART_Tx(USART0, 'a');
      USART_Tx(USART0, '\n');



}



}
 

bogosort

Joined Sep 24, 2011
696
Then as shown in photos 2A to 2D I have connected the I2C 3.3,gnd,extension header pins to their corresponding MCP.Also i have connected 5.1Kohm resistors to SDA and SCL to 3.3v to make the signal better.
I2C can be picky about the pull-up resistor values. When I used the MCP3421 in a project, I unsuccessfully experimented using several lower resistor values (~5 kΩ) and ended up using 8.2 kΩ. Also, it might help to add a bypass capacitor or two. Here's what I used, which worked well on my PCB at a 400 kHz bus speed:

1608824609084.png

I have used I2C_FLAG_WRITE_READ flag which has the structure shown bellow. . . . The I2C diagram that was recieved shown in the last photos bellow ,we see a cyclic structure where write at the start the slave sends NACK to my 0xD0 (adress+w)
from mcp3421 Data sheet page 18 device code is 1101 and A2-A0 is 000 plus write bit (0) so the total is 11010000 which is 0xD0
Why its no accepting this data?
I'm not familiar with the other hardware you're using, nor with the I2C library you're using, but I'm wondering about the timing in your scope picture. For the start bit, the SDA line seems to come up just as the SCL line goes low. The way I2C works is that the data is placed on SDA and read when SCL goes high, so it may be possible that your start bit is not being read by the ADC. If this is the case, then the ADC will interpret the third bit after the start bit as the actual start bit, and so won't recognize its own address. Consequently, it leaves the ACK line high (NACK).
 

Thread Starter

yef smith

Joined Aug 2, 2020
717
Hello,Start is When SDA goes low while SCL is High .the photo bellow is from a working I2C si7021 (0x80 adress) sensor device.
I cant see the difference between the two except that the clock is less squared in the working photo.
My device is on breadboard not on PCB.What is the difference between the photos.


I dont have those components so i used 10u and 10Kohms
and i attached its photo bellow.
Its just that we see Start ->8 clock->nack

I verified in the manual 0xD0 is the adress of the device.
and we do sample in the scope photos 11010000
What could cause that problem?
Thanks.


1608830258809.png
1608831983098.png
 

Attachments

bogosort

Joined Sep 24, 2011
696
Hello,Start is When SDA goes low while SCL is High .the photo bellow is from a working I2C si7021 (0x80 adress) sensor device.
I cant see the difference between the two except that the clock is less squared in the working photo.
My device is on breadboard not on PCB.What is the difference between the photos.
I read a bit more on the I2C protocol and I think your timing is fine, as the START condition is initiated solely by a high-to-low transition on SDA while SCL is high, which your timing satisfies.

Looking at my own code, I noticed that I used a different format for the ADC address:
C:
#define ADC_ADDRESS 0x68    // default address is 0110 1000
The MCP3421 address is a 7-bit number, but you write it as an 8-bit value (0xD0 = 1101 0000). It's possible that your I2C library, in forming the I2C packet, may be removing the MSB of your address. Can you try using address 0x68?
 

Thread Starter

yef smith

Joined Aug 2, 2020
717
Hello ,I tried to send 0x68 in the first session i still get a NACK as shown bellow.
How can find the adress of the device by communicating with it.
Athother thing if we get a NACK could it mean that the device is not working at all?
Thanks.

1608839382553.png
 

bogosort

Joined Sep 24, 2011
696
Athother thing if we get a NACK could it mean that the device is not working at all?
Yes, the NACK state is the default state (line high), so even with no device connected you would receive a NACK.

However, before I would suspect a broken device I would experiment with different values of pull-up resistors. A graph in this document shows that as the bus capacitance increases, the resistor value must be lowered. Breadboards have much larger capacitances than PCBs, so if you're using 10k resistors they may be too large for the protocol. Also, be sure you are running at lowest possible I2C speed while you debug, as the higher speeds have more strict timing requirements.

https://www.ti.com/lit/an/slva689/slva689.pdf?ts=1608840973250
 
Top