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.

MSP430F427A issue with SD16

Other Parts Discussed in Thread: MSP430F427A

I'm using a MSP430F427A's SD16 to measure some voltages and current. The voltage channels are working fine. The current channel however, has a strange issue. I've been searching on this forum, but couldn't find a solution. Let me discribe the situation:

We have two firmware versions: 

  • Tester software, for calibration of the analog channels
  • Application software, using the calibration constants.
Both firmware versions have the same init code (clocks, timers, io, etc), the same interrupt handlers/vector table, shared ADC driver, low power mode.
However, the offset on the current channel is different. Also when I do not go to low power mode, I also have a difference in offset between the same firmware versions.
When I calculate the gain factor, this is the same for all.

How can I have a difference in offset between both version and why does the low power mode influence it?

The tester software has less code, so it's longer in low power mode.

Measurements:

0Amps 30Amps
App (low power mode) -31 1202
Tester (low power mode) -39 1194
App (no low power mode) -8 1225
Tester (no low power mode) -11 1222
For all measurements the gain is the same. Delta_Amps / Delta_counts = 30/1233

When I set the current channel to use input channel 7 (offset), ALL four versions as described above have the same offset.

Common init code:

WD_RESET_1S();

/* ACLK = LFXT1CLK = 32768
* SMCLK = 64 * 2 * ACLK = ~4.194 MHz
*/
SCFQCTL = 64-1; /* Set N to divide by 64 */
SCFI0 = FLLD_2; /* DCO range (0.65 - 6.1 MHz) and D to 2) */
FLL_CTL0 = DCOPLUS + OSCCAP1 + OSCCAP0; /* enable D mulitply, cap ~10pF */

/*
The DCO starts at the lowest tap after a PUC or when SCFI0 and SCFI1 are
cleared. Time must be allowed for the DCO to settle on the proper tap for
normal operation. 32 ACLK cycles are required between taps requiring aworst
case of 28 x 32 ACLK cycles for the DCO to settle.
*/
#ifndef __DEBUG__
/* The SUB Rn (1 or more) and JNE (2) are at least 3 cycles
* plus one NOP is at least 4 MCLK cycles.
* 4 * 32 = 64(DCO - N) * 2 (DCO div)
*/
WD_RESET_1S();
{
un16 uOscDelay;
for (uOscDelay = 32L * 28L * 32L; --uOscDelay; )
_NOP();
}
#endif

/* initialise inputs for Buttons */
P2DIR &= ~0x04; /* P2.2 = BUTTON1 */
P1DIR &= ~0x38; /* P3.<3..5> = BUTTON2..BUTTON4 */

/* Initialise Timer A for Buzzer and backlight
* The timers share the input clock frequency but not the mode / reset value
*/
TACTL |= TASSEL1; /* TA: clock = SMCLK, Div = 1 */
TACTL &= ~(TASSEL0 | ID0 | ID1 | MC1);
TACCR0 = TIMER_A_COUNTS;
TIMER_ON;

/* backlight */
TACCR1 = 0;
TACCTL1 = OUTMOD2 | OUTMOD1 | OUTMOD0; /* CCR1 reset-set mode */

/* initialise output for relay, buzzer and backlight */
P1DIR |= 0x07;
P1SEL |= 0x05;
P1OUT &= ~0x02;

/* initialise basic timer for periodical interrupt */
BTCTL |= BTDIV; /* set BTCNT2 to ACLK/256 */
BTCTL &= ~(BTIP0 | BTIP1 | BTIP2); /* =64Hz */
IFG2 &= ~BTIFG; /* reset interrupt flag */
IE2 |= BTIE; /* enable Basic timer interrupt */

ADC init  code:

/* Initialise the ADC */

/* Low power mode off, clock source is MCLK / 4, VMID off, ref on, overflow
* interupt off.
*/
SD16CTL = SD16REFON | SD16DIV1;

/* Continuous conversion, OSR = 265, output 2's complement upper 16 bits only,
* interrupt disabled, grouped with next channel.
*/
SD16CCTL0 = SD16DF | SD16GRP;

/* Continuous conversion, OSR = 265, output 2's complement upper 16 bits only,
* interrupt disabled, grouped with next channel.
*/
SD16CCTL1 = SD16DF | SD16GRP;

/* Continuous conversion, OSR = 256, output 2's complement upper 16 bits only,
* interrupt enabled, not grouped.
*/
SD16CCTL2 = SD16DF | SD16IE;

/* No delay, gain = 8, input channel = 0 (external). */
SD16INCTL0 = SD16GAIN_8 | SD16INCH_0; // current
SD16INCTL1 = SD16GAIN_1 | SD16INCH_1; // voltage
SD16INCTL2 = SD16GAIN_1 | SD16INCH_2; // start voltage

memset(SD16Temp, 0, sizeof(SD16Temp));
memset(adcResult, 0, sizeof(adcResult));
sampleCounter = 0;

/* Start sampling. The channels are grouped, so it is only necessary to
* start the last channel.
*/
SD16CCTL2 |= SD16SC;

If you need more info, please ask.

  • Martin Bosma said:
    When I set the current channel to use input channel 7 (offset), ALL four versions as described above have the same offset.

    Sorry for asking, but are you absolutely sure that you have offset error difference, not noise or transient artefacts? My suggestion is to do 1024 continuous accumulated samples (for each of 4 cases), look for min/max and calculate average - only then suspect offset.

  • The part you quote I'm absolutely sure about it is offset. Input channel 7 is a "short for PGA offset measurement" (page 29-22 of the family reference manual). So if the PGA offset is constant for all cases, this seems ok to me. The offset of the current channel however, in this case input channel 0, is different in all 4 cases, like I described in my first post. It seems that this offset depends on the consumed current of the mcu.

    About the average calculation, in our application we sum 1024 samples and divide by the number of samples.

  • ADC have mux inside so you can't have different ADC offset measurements for different channels. It sounds like board layout problems, ground loop(s). Try rewiring (connect in parallel) ADC current channel to voltage one, check offset results, short current channel, then measure offset.

  • Hello Martin,
    I’ve a little bit experience with the SD converters. They work great, but as Ilmars already said, care must be taken with hardware routing, especially when amplifying (gain) the signal.
    Create a separate Analogue ground which not carrying Digital current.
    Connect the Analogue- terminal separate and direct to the current sensor even if the sensor is already grounded by other ways.
     
    I hope this information helps you.
    - Leo

     

     
  • Martin Bosma said:
    The part you quote I'm absolutely sure about it is offset. Input channel 7 is a "short for PGA offset measurement" (page 29-22 of the family reference manual).

    Well, this feature gives you the internal offset. THis is great if you have 100% ideal external circuitry. But usually you don't. If if you don't, the offset calibration is useless as you have different offsets on each channel.

    For my own projects, I usually do an individual 2-point calibration for each channel and use the calculated offset and gain factors when reading and ADC result, turning it into a voltage. The calibraiton values are modified after being taken once (semi- automated calibration process) so that the final formula only contains multiplicaitons and shifts, no divisions.

    Martin Bosma said:
    About the average calculation, in our application we sum 1024 samples and divide by the number of samples.

    You should use a 10 bit shift instead of a division. Depending on the compiler, this might be way more efficient :)

  • Ok, thanks. I will look into it.

**Attention** This is a public forum