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.

How to measure current using MSP430's ADC

Other Parts Discussed in Thread: MSP430G2231

Hi everyone, 

I was just wondering if yall could help me out with how I would program the MSP430G2231 to use its ADC to measure the current that an arbitrary load is drawing from the battery that is supplying power.  

Can you point me to some example code or paste me some snippets?  

I want the microprocessor to be able to make a list of current measurements from the battery every 30 seconds or so...

Thanks, 

Kevin Ting

  • Well, current is measured by the force appearing between two wires. I don't think it is a good idea trying this with an MSP. It is only reliable for determining the current in larger magnitudes. And I don't think it is done at all this way (it is, however, the definition of 1A that uses this setup).

    The way more reliable way is to measure the voltage that appears if the current flows through a (preferrably known) resistor. You can measure this votage (or the voltage difference between beginning and end of the resistor) with an MSPs ADC.
    The drawback of this method is, that you need this resistor, and that it's existence may influence (usually reduce)  the current, and that it consumes energy (converts it to heat) at the rate of W = R*I2 . However, to measure current consumption with a voltage sensor (such as the ADC) you need such a resistor (called shunt).

    Anotehr problem is that you most likely want the voltage over the shunt being as small as possible, once for saving energy, and once for not reducing the voltage over the device that draws the current. But the smaller the voltage, the less reliable is the voltage conversion with the ADC, as it has only limited resolution.

    E.g. when usng a shunt of 1 Ohm, you'll get only 1 mV per mA. The ADC10 only has a resolution of 1.5mV, so everythign below 1.5mA would be 0, and for 1.5 to 3mA you'd get 1.5mA and so on. So you likely need to 'boost' the small voltage using an OpAmp. Depending on where you place the shunt, you'll reaqire an OpAmp that has rail-to-rail inputs and assymetric supply. These cost and, well, consume power. Less power, more costs :)

    For the final code, there are several threads in the forum which deal with the ADC10 and also have code. But I think, the programming of the ADC will be your least problem. The design of the circuit may prove more challenging. And perhaps you'll end up with an external integrated current sensor (probaly sort of a pre-programmed MSP with integrated shunt and amplifying circuitry - isn't that ironic?)

  • Jens-Michael Gross said:
    Depending on where you place the shunt, you'll reaqire an OpAmp that has rail-to-rail inputs and assymetric supply.

    Not exactly. One can have sensing resistor (as you suggested) and two dividers each between the resistor end and GND. Points from dividers can be connected to Intrumentation Amplifier and its output can drive ADC. I advice using instrumentation amplifier rather than operational one. (please check available instumentation amplifiers on TI site: http://focus.ti.com/paramsearch/docs/parametricsearch.tsp?family=analog&familyId=500&uiTemplateId=NODE_STRY_PGE_T ).

    I cannot tell how a circuit should look like, but maube some current mirror could be used for 'copy' measured current and redirecting it to resistor connected to GND. Voltage on the resistor may be measured by ADC in the msp430.

    Regards,
    Piotr Romaniuk, Ph.D.
    ELESOFTROM

     

  • First of all, any time you ask for help making a measurement, specify the range. Are we talking 1000 A to power an electric vehicle or 10 μA in a power-harvesting sensor? And do you need bipolar (battery charging as well as discharging) or unipolar measurement?

    You could also mention the accuracy (both absolute, and repeatability) that you want. It's okay in design to be pretty arm-wavey and say "I'll take what I can afford", but if you actually need 0.1% accuracy, across temperature and traceable to primary standards, that is a lot different than a couple of percent so you can estimate battery life.

    Having said all that, in this case this is a standard problem and there are simple pre-packaged solutions. You install a low-value shunt resistor in the supply (people often prefer to use the +ve supply) and use a specialized amplifier to measure the voltage across it. The amplifiers are specialized, because generally they are supplied from the same battery they're measuring, so they need to able to go above the positive rail.

    There are two designs, one based on a simple difference amplifier, and a specialized "current shunt amplifier" design that holds the bottom ends of a matched pair of resistors at equal voltages and subtracts the sink currents. The latter has faster response and is useful for things like motor control applications. This ADI article explains the pluses and minuses of each.

    See Zetex AN39 and >Linear AN105 for various ideas. Zetex make a variety of current-output current shunt amplifiers. (You stick your own resistor on the bottom to select the output voltage and measurement range you want.)

    For a fun diversion into a more estoteric and challenging current measurement problem, see Jim Williams' efforts to measure the current through a 32 kHz quartz crystal.

    (Damn I wish this forum had a "preview" button; I'm not sure if I closed all those tags.)

  • Piotr Romaniuk said:
    One can have sensing resistor (as you suggested) and two dividers each between the resistor end and GND. Points from dividers can be connected to Intrumentation Amplifier and its output can drive ADC

    Yes, of course this is a possibility, but I don't like it. It introduces additional error (resistor tolerances), noise, and also introduces an additional current path that will influence the measurement. Depending on shunt and divider values, this influence can be from unimportant to significant.

    Piotr Romaniuk said:
    I advice using instrumentation amplifier rather than operational one.

    It's a matter of cost and taste and required amplification.

    Piotr Romaniuk said:
    maube some current mirror could be used for 'copy' measured current and redirecting it to resistor connected to GND

    TH eproblem with most simple current mirrors is that they influence the current. Yes, the curent is the same (if the parts used exactly match, in case of a dual-PNP mirror), ye tthe mirror itself changes the conditions (e.g. the collector/emitter or base/emittor voltages changes dependign on current, reducing the voltage over the measured element and therefore the current). So you will read what is, but not what would be if there were no curren tmirror.

    All this highly depends on the application:

    Cypher Punks said:
    Are we talking 1000 A to power an electric vehicle or 10 μA in a power-harvesting sensor? And do you need bipolar (battery charging as well as discharging) or unipolar measurement?
    You could also mention the accuracy (both absolute, and repeatability) that you want.
    Yep. THis information would be required for a more detailed advice.

    Nice links. :)

  • Jens-Michael Gross said:

    I advice using instrumentation amplifier rather than operational one.

    It's a matter of cost and taste and required amplification.

    [/quote]

    If you use operational amplifier you also need resistors, for feedback loop (setting gain). So problem with resistors still exists: small => extra current, large => the noise. Their tolerance affects amplification anyway. Some instumental amplifiers has these resistors inside a chip, and they are trimmed during production process, so the tolerance is known and asured.

    I am not sure, but maybe there is version of IA that can work with input voltages on the level of positive power supply. Inside there the IA there is usualy a divider, so maybe the circuilt without two dividers would work.

    I agree that there is no general solution, but it depends on range and requirements of measured current.

    Regards,
    Piotr Romaniuk, Ph.D.
    ELESOFTROM

  • Jens-Michael Gross said:
    One can have sensing resistor (as you suggested) and two dividers each between the resistor end and GND. Points from dividers can be connected to Intrumentation Amplifier and its output can drive ADC

    Yes, of course this is a possibility, but I don't like it. It introduces additional error (resistor tolerances), noise ... [/quote]

    According to the noise. The author would like to make a measurement every 30 sec. I think that resistor noise (termal) can be eliminated in this condition, it can be filtred, for example by succesive measurements and calculation an average (also analog methods can help here).

    Regards,
    Piotr Romaniuk, Ph.D.
    ELESOFTROM

     

  • Hi guys thanks for all the replies, 

    For my application, I am trying to measure the amount of current being drawn out of a small Lithium ion battery pack (3.7 V 500mAh), so measurements would be in the order of milliamps.  

    What I'm trying to do with the microprocessor is to read that current and then turn on different pins depending on the current value.

    For example, 

    If the current being drawn is between 30-50mA turn on pin1, if it is between 50-100mA turn on pin2, if it is between 100-200 mA turn on pin3.  

     

    Whats the easiest way to code/implement in hardware something like this?

     

    Thanks, 

    Kevin

  • On a sort of related note, I found this example code and had a few questions about it:

    Can you explain this line to me?:  if (ADC10MEM < 0x88)                      // ADC10MEM = A7 > 0.2V? 

    Why is ADC10MEM less than a hex value but the comment says its seeing if it is greater than a value.

    Also, how does hex x88 correspond to .2 volts? (.2 volts/1.5volts=.13333 volts)

    Finally, could I possibly split it up into multiple if, elseif statements to have a range of voltages and turn different pins to high based on that?

    For example:   

      if (ADC10MEM < 0x88)                  

    turn p1.0 on

    elseif(ADC10MEM < 0x77)

    turn p1.1 on

    etc.

    Thanks, 

    Kevin

     

    //******************************************************************************

    //  MSP430G2x31 Demo - ADC10, Sample A7, 1.5V, TA1 Trig, Ultra-Low Pwr

    //

    //  Description: A7 is sampled 1024/second (32xACLK)with reference to 1.5V. All

    //  activity is interrupt driven with proper usage of MSP430 low-power modes,

    //  ADC10 and Vref demonstrated. Timer_A with both TA1/TA0 used in upmode to

    //  drive ADC10 conversion (continuous mode can also be used). Inside

    //  of TA0_ISR software will enable ADC10 and internal reference and

    //  allow > 30us delay for Vref to stabilize prior to sample start. Sample

    //  start is automatically triggered by TA1 every 32 ACLK cycles. ADC10_ISR

    //  will disable ADC10 and Vref and compare ADC10 conversion code. Internal

    //  oscillator times sample (16x) and conversion (13x). If A7 > 0.2Vcc,

    //  P1.0 is set, else reset. Normal Mode is LPM3.

    //  //* An external watch crystal on XIN XOUT is required for ACLK *//

    //

    //                    +-----(0.9766us)---------\\------------------>+

    //    TA0_ISR        TA1      ADC10_ISR             TA0_ISR        TA1

    //  -----+------------+------------+-----------\\------+------------+----->

    //   Enable ADC    Trigger ADC  Disable ADC

    //   and Vref                   Compare

    //       +-( >30us--->+

    //

    //

    //               MSP430G2x31

    //            -----------------

    //        /|\|              XIN|-

    //         | |                 | 32kHz

    //         --|RST          XOUT|-

    //           |                 |

    //       >---|P1.7/A7     P1.0 |--> LED

    //

    //  D. Dang

    //  Texas Instruments Inc.

    //  October 2010

    //  Built with CCS Version 4.2.0 and IAR Embedded Workbench Version: 5.10

    //******************************************************************************

    #include  "msp430g2231.h"

     

    void main(void)

    {

      WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT

     

      ADC10CTL1 = INCH_7 + SHS_1;               // P1.7, TA1 trigger sample start

      ADC10AE0 = 0x80;                          // P1.7 ADC10 option select

      P1DIR |= 0x01;                            // Set P1.0 to output direction

      TACCTL0 = CCIE;                           // Enable interrupt

      TACCR0 = 32-1;                            // PWM Period

      TACCTL1 = OUTMOD_3;                       // TACCR1 set/reset

      TACCR1 = 2;                               // TACCR1 PWM Duty Cycle

      TACTL = TASSEL_1 + MC_1;                  // ACLK, up mode

      __bis_SR_register(LPM3_bits + GIE);       // Enter LPM3, enable interrupts

    }

     

    // ADC10 interrupt service routine

    #pragma vector=ADC10_VECTOR

    __interrupt void ADC10_ISR(void)

    {

      ADC10CTL0 &= ~ENC;                        // ADC10 disabled

      ADC10CTL0 = 0;                            // ADC10, Vref disabled completely

      if (ADC10MEM < 0x88)                      // ADC10MEM = A7 > 0.2V?

        P1OUT &= ~0x01;                         // Clear P1.0 LED off

      else

        P1OUT |= 0x01;                          // Set P1.0 LED on

    }

     

    // Timer A0 interrupt service routine

    #pragma vector=TIMERA0_VECTOR

    __interrupt void Timer_A(void)

    {

      ADC10CTL0 = SREF_1 + ADC10SHT_2 + REFON + ADC10ON + ADC10IE;

      ADC10CTL0 |= ENC;                         // ADC10 enable set

    }

  • Kevin Ting said:
    Why is ADC10MEM less than a hex value but the comment says its seeing if it is greater than a value.

    Because the action based on this comparison is inverted too. Description says: 'if >, LED on', but after the <0x88, LED is set off.
    I think someone has changed the original code and forget to change the comment. Happens often.

    Kevin Ting said:
    how does hex x88 correspond to .2 volts? (.2 volts/1.5volts=.13333 volts)

    1.5/1023*0x88 = 0.199413489V
    1023 (0x3ff) is the value for VREF, so each 'count' is VREF/1023.

    Kevin Ting said:
    If the current being drawn is between 30-50mA turn on pin1, if it is between 50-100mA turn on pin2, if it is between 100-200 mA turn on pin3.

    So the current you want to detect is in the range of 30..200mA.

    a 1 Ohms resistor in teh current flow (e.g. directly below the battery, but maybe better on the gnd path) would give 30..200mV which you can measure. It will, however, waste 40mW on 200mA and reduce the operating voltage by 0.2V on 200mA. A smaller resistor would cause less voltage rop, but also less resulting output voltage swing.
    While 30mV and 200mV are perfectly detectable with an ADC10, 1/10 of it (by using a 0.1Ohms resistor) drifts into the range of measurement noise. (30mA just giving 3mV and therefore a conversion value of 2), so you definitely need an amplifier (whether OpAmp or IA).

     

  • Piotr Romaniuk said:
    maybe there is version of IA that can work with input voltages on the level of positive power supply

    Most I know require a symmetrical power supply, because usually, they have to amplify differential AC voltages symmetrical to GND. For this reason the internal OpAmps (the IA usually has three built-in, but there are designs with two or one possible, yet rare,a those are jsut OpAmps with resistors and therefore not worth a separate product) are no Rail-to-Rail ones as this is usually not necessary.
    In this application, however, it would.

    I recommend reading this nice document, especially Fig.4 (single OpAmp).

    However, TIs INA333 or one of its brothers seems to do what is required here: single supply and inputs, well, 0.1V to VCC-0.1V. So you cannot use it on a circuit where the PT is tied to GND or VCC directly, but a simple diode (e.g. BAT42) from the PT to GND should result in a stable voltage drop of 0.2V.
    The gain can be programmed with a single resistor.

     

  • I am not familiar with TI (previously Burr Brown if I recall correctly) IAs, I used Analog Device chips. There was very rare limitation to dual supply, an engineer decided what power supply (single or dual) configuration he wanted to use.
    "... they have to amplify differential AC voltages symmetrical to GND."
    I think that IA amplifies difference of two voltages, it is not important to what level are they refered (GND or other). It just 'calculates':
    Vout = Gain x (Vp - Vm) + Vref
    Ground is important for the output, many IA has Vref input that allows setting zero level according to the needs.

    I have one observation: in the current measurement circuit, the sign of the difference is always the same. Maybe it also helps in circuit design.

    The document that you referred is interresting, discuss IA structures. The circuit in fig. 4 is rather teoretical, in practice, this is difficult to set the resitors (again, a lot of resistors :) ).

    "... simple diode ... stable voltage drop of 0.2V..."
    The diode voltage drop depends on the current, if the measurrement need to be precise it may introduce an error. But we do not know what is expected tolerance of measurement.

    KEVIN: Can you specify what error (in mA, or % reffered to expected value) is acceptable in your measurement?

    Regards,
    Piotr Romaniuk, Ph.D.
    ELESOFTROM

    PS
    Sorry for not formatted quotations but it is not working now.
  • Hi Piotr, My acceptable error is around 25-50 mA. Also, can any of yall help me with setting the reference voltage? What are all the possibilities for it to be and how do I set it in my code? Thanks, Kevin
  • Piotr Romaniuk said:
    Sorry for not formatted quotations but it is not working now.

    It was broken during the server maintenance yesterday evening (which swallowed a long response I just finished: when I pressed the 'post' button, I got a 'server maintenance' message and my text was gone.). It's working again since ~4 hours.

    Piotr Romaniuk said:
    I think that IA amplifies difference of two voltages, it is not important to what level are they refered (GND or other).

    Well, it is important. Because mose OpAmps (including those inside an IA) have problems when the inputs go near the rails.
    And since the typical (not the only) application for an IA is to amplify small AC signals (from microphones, voice or musical instruments, hence its name) while suppressing the DC offset and suppressing asymmetrical distortions (crosstalk, that affects both lines into the same direction), a symmetrical power supply is used anyway, so why makinf the OpAmps more complex then necessary to allow a R-R input. Especially if an R-R input introduces nonlinearities near the rail. Even most OpAmps with R-R inputs only support input voltages to the rail (GND) with a very low cutoff frequency. For higher input frequencies, the input voltage can only go as near as 50mV or 100mV to the rail without heavy distortion or latchup.

    believ eme, I've been trhough it when designing a diver circuit for a laser diode when we didn't want to build an additional negative supply for cost reasons. Ever tried to do an analog adding stage without negative supply? All adding circuits found on the net are inverting and therefore require a negative supply. (I finally did it, but it is not trivial, to say the least)

    Piotr Romaniuk said:
    The diode voltage drop depends on the current

    Yes, but on Schottky diodes, it is fairly constant above a certain minimum load of a few µA. e.g. the MBR0520L (which we use because if its extremely low forward voltage on higher currents (0.4V/1A) raises from 0.12 to 0.15V when the current changes from 100µA to 1mA. And another 0.03V from 1mA to 10mA.
    But you're right, it depends on required precision.

    A Bandgap diode, however, produces an even more stable result.

    An alternative is a shunt regulator for base voltage adjustment. The TS431 from ST, for example, provides a minimum, extremenly stable voltage drop of 1.24V (higher if a resistor divider is applied to the sense input) for currents from 60µA to 30mA. It is a shunt regulator, that measn it draws jsut as much current as required break down the voltage over it to 1.24V.

    personally, I use the TS432BC from TSC. Same principle, higher minimum current, but a reference of 2.495V+-0.5%. (2.487..2.513V) An excellent external reference for the MSPs ADC. And the OpAmp adding circuit I mentioned above. It's relatively cheap too.
    It is also an excellent voltage regulator as it exposes a constant load to the power supply, no matter how much the actual current draw of the attached circuit is changing. It does, however, 'waste' the unused energy. But if you don't want supply voltage ripple due to load changes, this is an excellent and easy way. The resulting voltage source has a dynamic resistance of only 0.22Ohms.

  • Hi Jens-Michael,

    Jens-Michael Gross said:
    when I pressed the 'post' button, I got a 'server maintenance' message and my text was gone

    I don't like writing again, so sometimes I get the text into clipboard or external text editor. Too many times I lost long post or e-mail. :)

    Jens-Michael Gross said:
    I think that IA amplifies difference of two voltages, it is not important to what level are they refered (GND or other).

    Well, it is important. Because mose OpAmps (including those inside an IA) have problems when the inputs go near the rails.
    [/quote]

    I agree, the level of the input is important. I meant that from general point of view the IA apmlifies the difference, input signals can have DC offset and it if elliminated.

    Jens-Michael Gross said:

    believ eme, I've been trhough it when designing a diver circuit for a laser diode when we didn't want to build an additional negative supply for cost reasons. Ever tried to do an analog adding stage without negative supply? All adding circuits found on the net are inverting and therefore require a negative supply. (I finally did it, but it is not trivial, to say the least)

    I still think that IAs can work with single supply :) It probably depends on application and the chip. I used IAs in ECG signal recorders (signal range 4mV, details on 10uV), they had single supply and had pseudo ground on the level of half of power supply. I used output reference input for setting this output level.

    From Kevin answer (he probably meant range not error) I conclude that his measurement does not to be high precise. So probably he can start from single OpAmp circuit.

    Regards,
    Piotr Romaniuk, Ph.D.
    ELESOFTROM

     

  • Hi Kevin,

    I think that 25-50mA is a range of your measurement. But if you will measure specific value, what tollerance do you expect (accept)?

    e.g.
    if you will measure 23mA, you may expect 10% error, so the true value would be 21,7 - 25,3mA

    Did I understood correctly?

    Regards,
    Piotr Romaniuk, Ph.D.
    ELESOFTROM

**Attention** This is a public forum