This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

ADS1243 reading max scale

Other Parts Discussed in Thread: ADS1243, MSP430F2618

I have an ADS1243 connected to an MSP430F2618.

Vdd = 3.3V, Vref+ 2.5V, Vref- gnd

4 single ended voltages on Ain0 to Ain3, Gnd on Ain4,  Voltages are in the mV range

 

I am getting max value back when I read the ADC, 0x7FFFFF on each channel.

I send the MUX register new channel after DRDY goes low,  then I wait until the next DRDY to read the data.

RANGE =1

SETUP = 0x00

ACR = 0x04

MUX =  0x04, 0x14, 0x24, 0x34 ,  change on each read

Bipolar data format

 

Any help on reading the values correctly would be very helpful.

 

Thanks

Greg

 

 Code Attached:

 

void init_ADC24(void)
{
	uint8_t i,temp;
	uint8_t regValue[10];
	char *ptr;

	ptr = (char *)&Adc24;

	// Config Pins: DRDY, PDWN
	P2SEL &=  ~b11000000;
	P2DIR |=   b10000000;

	// Turn IC On, PDWN
	P2OUT |=   b10000000;
	for(i=0;i<5;i++) _NOP(); // Delay

	// Reset
	P3OUT &= ~P0;            // CS
	while(!(IFG2&UCB0TXIFG));
	UCB0TXBUF = 0xFE;
	while(UCB0STAT&UCBUSY);
	temp = UCB0RXBUF;
	P3OUT |= P0;             // CS
	while(!(P2IN&BIT6));     // DRDY goes high
	while(P2IN&BIT6);        // DRDY

	for(i=0;i<10;i++) _NOP(); // Delay

	// Calibration
	P3OUT &= ~P0;            // CS
	while(!(IFG2&UCB0TXIFG));
	UCB0TXBUF = 0xF0;
	while(UCB0STAT&UCBUSY);
	temp = UCB0RXBUF;
	P3OUT |= P0;             // CS
	while(!(P2IN&BIT6));     // DRDY goes high
	while(P2IN&BIT6);        // DRDY

	for(i=0;i<10;i++) _NOP(); // Delay

	// Write Config Registers
	regValue[0] = 0x50; //  Write
	regValue[1] = 0x08; // Registers count 8 + 1
	regValue[2] = 0x00; // Setup
	regValue[3] = 0x04; // Mux
	regValue[4] = 0x04; // ACR
	regValue[5] = 0x00; // ODAC
	regValue[6] = 0x00; // DIO
	regValue[7] = 0xFF; // DIR
	regValue[8] = 0x00; // IOCON
	P3OUT &= ~P0; // CS
	for(i=0;i<9;i++)
	{
		while(!(IFG2&UCB0TXIFG));
		UCB0TXBUF = regValue[i];
	}
	while(UCB0STAT&UCBUSY);
	temp = UCB0RXBUF;
	P3OUT |= P0; // CS
//while(!(P2IN&BIT6));     // DRDY goes high
	while(P2IN&BIT6);        // DRDY

	for(i=0;i<10;i++) _NOP(); // Delay

	// Read back all registers
	regValue[0] = 0x10;
	regValue[1] = 0x0F;
	P3OUT &= ~P0;            // CS
	while(!(IFG2&UCB0TXIFG));
	UCB0TXBUF = regValue[0];
	while(!(IFG2&UCB0RXIFG));
	temp = UCB0RXBUF;
	while(!(IFG2&UCB0TXIFG));
	UCB0TXBUF = regValue[1];
	while(!(IFG2&UCB0RXIFG));
	temp = UCB0RXBUF;
	for(i=0;i<5;i++) _NOP();

	for(i=0;i<16;i++)
	{
		while(!(IFG2&UCB0TXIFG));
		UCB0TXBUF = 0x00;
		while(!(IFG2&UCB0RXIFG));
		*ptr++ = UCB0RXBUF;
	}
	while(UCB0STAT&UCBUSY);
	P3OUT |= P0;             // CS

	temp++;
}






void read_ADC24(void)
{
	uint8_t i,j,temp;
	uint32_t value=0;
	uint8_t regValue[5];
//	int32_t convValue=0;

	for(j=0;j<4;j++)
	{
		// Wait for DRDRY to go low to minimizes settling error
		while(!(P2IN&BIT6));     // DRDY goes high
		while(P2IN&BIT6);        // DRDY

		// Change Channel
		regValue[0] = b01010000;
		regValue[1] = 0x00;
		switch(j)
		{
		case 0:
			regValue[2] = 0x04; // Mux CH0	pri-volt (V+)
			break;
		case 1:
			regValue[2] = 0x14; // Mux CH1	sec-volt (VSEC)
			break;
		case 2:
			regValue[2] = 0x24; // Mux CH2	sec-sw1  (VSEC_SW1)
			break;
		case 3:
			regValue[2] = 0x34; // Mux CH3	sec-sw2  (VSEC-SW2)
			break;
		}
		P3OUT &= ~P0; // CS
		for(i=0;i<3;i++)
		{
			while(!(IFG2&UCB0TXIFG));
			UCB0TXBUF = regValue[i];
		}
		while(UCB0STAT&UCBUSY);
		temp = UCB0RXBUF;
		P3OUT |= P0; // CS

		// Wait for data conversion
		while(!(P2IN&BIT6));     // DRDY goes high
		while(P2IN&BIT6);        // DRDY


		// Read Data
		value=0;
		regValue[0] = b00000001;
		P3OUT &= ~P0; // CS
		while(!(IFG2&UCB0TXIFG));
		UCB0TXBUF = regValue[0];
		while(UCB0STAT&UCBUSY);
		temp = UCB0RXBUF;
		for(i=0;i<15;i++) _NOP(); // Delay
		for(i=0;i<3;i++)
		{
			while(!(IFG2&UCB0TXIFG));
			UCB0TXBUF = 0x00;
			while(!(IFG2&UCB0RXIFG));
			temp = UCB0RXBUF;
			value <<= 8;
			value += temp;
		}
		while(UCB0STAT&UCBUSY);
		P3OUT |= P0; // CS

		if(value>0x007FFFFF)
			value += 0xFF000000;

		switch(j)
		{
		case 0:
			Adc24.priCnt = value; // Mux CH0	pri-volt (V+)
//			convValue = ((Adc24.priCnt*149)/100*3831)/100000;
//			Data.priVolt = (int16_t)convValue;  // mV
			Data.priVolt = Adc24.priCnt;
			break;
		case 1:
			Adc24.secCnt = value; // Mux CH1	sec-volt (VSEC)
			Data.secVolt = Adc24.secCnt; // mV
			break;
		case 2:
			Adc24.secSw1Cnt = value; // Mux CH2	sec-sw1  (VSEC_SW1)
			Data.secSw1Volt = Adc24.secSw1Cnt; // mV
			break;
		case 3:
			Adc24.secSw2Cnt = value; // Mux CH3	sec-sw2  (VSEC-SW2)
			Data.secSw2Volt = Adc24.secSw2Cnt; // mV
			break;
		}
		_NOP();
	}
	_NOP();
}

 

 
  • Hi Greg,

    Welcome to the forum!  If you are reading full scale it, it can be from communication error or an issue with the reference.  Communication is best verified with an oscilloscope.  Verify too that the reference is properly connected and it is at 2.5V.

    I didn't see anything that stood out to me as an issue with the code.  If you send me your schematic and screen shots of your communication I can look them over for any other possible issue.

    One other thing to consider is your input signals.  They must be referenced in some way to the ADC ground.  If you input a signal from a different power supply, the supply output can be many volts in potential different from one supply with respect to the other.  In other words, one supply can float above the other. If you measure your input relative to a common point you can verify this and usually the common point is the ADC ground. 

    Best regards,

    Bob B

  • Hello,

    Thank you for your comments.

     

    I have attached a pdf of the ADC circuit from my board. 

    I added a output cap to my reference and connected Ain4 to my analog ground.

     

    Here some things to note:

    My reference I check with a scope and meter.. Its was clean, very little ripple.  Voltage read 2.498 V with a Fluke.

    Now on the schamtic I have a power supply on V+  for testing..  Its Set to 5V,  later this will be high voltage up to 80V

    I have AIN1, AIN2, AIN3 channels unpowered. So they should be pulled down to AGND.

    Now the strange part is that all four channel read max value, 0x7FFFFF.  I was expecting an reading on channel 0 and the other channels to read near zero.

     

    Any ideas would be great.

    Thanks

    Greg

    0167.ADS1243.pdf

     

     

     

  • Hi Greg,

    You have AGND and GND.  As VEF- is AGND, and the reference establishes it's voltage to GND, somewhere AGND and GND must connect together.  Is AGND connected to GND?

    Best regards,

    Bob B

  • Yes I do, I have an single point ground connection between them. An zero-ohm resister

     

    Greg

  • Greg,

    Now that we've covered the most common issues, we'll go back to the code.  The WREG command (and it is similar for the RREG) is the command and the starting register in the first byte, followed by the number of bytes being sent (which is the total number of registers written less one) followed by the data for the registers.

    In your initialization routine you have 0x50 (WREG starting at register 0-SETUP) and the number of bytes as 8.  This should be 6 (the first seven register less 1) and not eight.

    In the readADC24 routine, you have 0x50, 0x00, and the mux change.  What you are actually doing is writing to the SETUP register and not the MUX.  This places the input as higher PGA and does not change the mux settings.  It should be 0x51 (WREG and start at register 1-MUX) and 0x00 (1 register).

    Best regards,

    Bob B

  • Bob,

     

    Thank you for your help!!

     Its seem to be finally reading real voltages on all four channels.

     

    My last issue is there an small offset in the values. I measure the inputs of the AIN1 to AIN3, which are at 0V in hardware.

    But the software seems to read high about an 1.3V 

     

    Is this where I use the offset resister to correct this?

     

    Greg

  • Hi Greg,

    Great to hear that you are making progress.  As far as the offset, normally this is pretty small, and the self calibration procedure should take care of the offset.  You can force a change of the offset with registers, but you have to be very careful in doing so.

    I would actually force the input to ground instead of just using the pull-down resistor to see if that makes any difference.  The input is switched capacitor, and there may be charge holding on the external cap.

    Best regards,

    Bob B