Author Topic: MSP430 and ADC  (Read 17313 times)

0 Members and 1 Guest are viewing this topic.

Offline Jon86Topic starter

  • Frequent Contributor
  • **
  • Posts: 526
  • Country: gb
MSP430 and ADC
« on: February 23, 2014, 03:33:21 pm »
So I've got an MSP430 hooked up to an LTC2400 SPI ADC, and I'm reading out the data to send via serial.
I managed to find a code example for arduino that I can use with the MSP430 and Energia, but I've got a problem. When the input voltage goes below zero, the output code goes up to 1677216 rather than just clipping at zero, and I'm also not getting the full resolution as the output code is only going up to 8388608 (2^24/2). I'd also like to use the extra four bits of resolution to take it up to 28bits.

I've looked around everywhere, but it's so difficult to find anything on how to use the SPI communication with the MSP430s.
If anyone could give me a bit of guidance with this, it would be greatly appreciated.  :-+
Death, taxes and diode losses.
 

Offline tszaboo

  • Super Contributor
  • ***
  • Posts: 7488
  • Country: nl
  • Current job: ATEX product design
Re: MSP430 and ADC
« Reply #1 on: February 23, 2014, 04:18:24 pm »
Have you read the LTC2400 datasheet? Have you read it again? And page 11-12 again?
 

Offline Jon86Topic starter

  • Frequent Contributor
  • **
  • Posts: 526
  • Country: gb
Re: MSP430 and ADC
« Reply #2 on: February 23, 2014, 04:19:46 pm »
Have you read the LTC2400 datasheet? Have you read it again? And page 11-12 again?

I've read those pages a good 50 times by now, I understand how I need to do what I want, but I don't know how to implement it in code.
Death, taxes and diode losses.
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: MSP430 and ADC
« Reply #3 on: February 23, 2014, 04:50:27 pm »
Quote
the output code goes up to 1677216 rather than just clipping at zero,

You need to read the datasheet a little bit better: pay attention to input range + status bits.
================================
https://dannyelectronics.wordpress.com/
 

Offline Jon86Topic starter

  • Frequent Contributor
  • **
  • Posts: 526
  • Country: gb
Re: MSP430 and ADC
« Reply #4 on: February 23, 2014, 05:16:10 pm »
Quote
the output code goes up to 1677216 rather than just clipping at zero,

You need to read the datasheet a little bit better: pay attention to input range + status bits.

So does the output code go up when Vin goes below zero? And how can I fix this?
Also I still don't understand why I'm only getting half the resolution...
Death, taxes and diode losses.
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: MSP430 and ADC
« Reply #5 on: February 23, 2014, 07:01:41 pm »
It will help you tremendously to go back to the datasheet.

Others may be able to give you an answer now but that doesn't fundamentally solve the problem for you.
================================
https://dannyelectronics.wordpress.com/
 

Offline Jon86Topic starter

  • Frequent Contributor
  • **
  • Posts: 526
  • Country: gb
Re: MSP430 and ADC
« Reply #6 on: February 23, 2014, 09:06:08 pm »
It will help you tremendously to go back to the datasheet.

Others may be able to give you an answer now but that doesn't fundamentally solve the problem for you.

I've been staring at the datasheet for the past 15 minutes, I don't know what I'm missing.
Death, taxes and diode losses.
 

Offline fmaimon

  • Supporter
  • ****
  • Posts: 165
  • Country: br
Re: MSP430 and ADC
« Reply #7 on: February 23, 2014, 09:21:10 pm »
As are you still having problems with what the datasheet says, you may be better reading about binary representation of numbers, signed and unsigned. Try understanding your LTC2400 library and what each bit of your output value does represent.
 

Offline Jon86Topic starter

  • Frequent Contributor
  • **
  • Posts: 526
  • Country: gb
Re: MSP430 and ADC
« Reply #8 on: February 23, 2014, 09:37:58 pm »
As are you still having problems with what the datasheet says, you may be better reading about binary representation of numbers, signed and unsigned. Try understanding your LTC2400 library and what each bit of your output value does represent.

There's 24 bits in the output code from the MSB to the LSB, I can't work out why I'm not getting a range of 2^24?
Could someone not explain this to me? I've tried pretty damn hard to understand the code, but obviously it's been written by someone else with no documentation so it's very difficult to understand since I haven't worked with SPI before.
Death, taxes and diode losses.
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: MSP430 and ADC
« Reply #9 on: February 23, 2014, 10:00:40 pm »
Your issues are far less about the code than the (in)ability to approach a real-life problem. Two examples:

1) fmaimon has laid it out for you bare: get the results, convert them to binary and compare them to the datasheet and ask yourself why you are getting what you are getting. How complicated is that?

2) You asked people to help you with the code. Yet, you don't feel the need to provide people the code. How's anyone going to help you?

All it takes, really, is common sense and hard work (reading the datasheet).


================================
https://dannyelectronics.wordpress.com/
 

Offline Jon86Topic starter

  • Frequent Contributor
  • **
  • Posts: 526
  • Country: gb
Re: MSP430 and ADC
« Reply #10 on: February 23, 2014, 10:29:41 pm »
Look I've read the data sheet, several times.
It clearly states in the datasheet that the output code for Vref should be 111111111111111111111111, which converts to 16777215. I'm asking why I'm not getting the full resolution and why the output is not going all the way up to 16777215 but only half that.

I'm not the sort of person that doesn't read up on things before they ask, I've spend literally several hours trying to find information on this and to work it out but I don't get it.
Telling me to read the datasheet again is just really patronising after how much effort I've put into trying to work this out for myself.

My code's here:

Code: [Select]
/*
  Interface between Arduino DM board and Linear Tech LTC2440 24-bit ADC
  Nov. 12 2010 John Beale

   LTC2440  <---------->  Arduino
   11: /CS <- to digital pin 10  (SS pin)
    7: MOSI <- to digital pin 11 (MOSI pin)
   12: MISO -> to digital pin 12 (MISO pin)
   13: SCLK <- to digital pin 13 (SCK pin)
   10: /EXT - ground
    1: GND - ground
    2: VDD3 - 5V supply

*/

#include <SPI.h>  // include the SPI library

// set I/O pins used in addition to clock, data in, data out
const byte slaveSelectPin = 10;  // digital pin 10 for /CS
const byte resetPin = 9;  // digital pin 9 for /RESET

const int nsamples = 1;  // how many ADC readings to average together

// SPI_CLOCK_DIV16 gives me a 1.0 MHz SPI clock, with 16 MHz crystal on Arduino

void setup() {
 
    Serial.begin(9600);      // set up serial comm to PC at this baud rate
   
    pinMode (slaveSelectPin, OUTPUT);
    pinMode (resetPin, OUTPUT);
    digitalWrite(slaveSelectPin,HIGH);  // chip select is active low
    digitalWrite(resetPin,HIGH);  // reset is active low

    SPI.begin(); // initialize SPI, covering MOSI,MISO,SCK signals
    SPI.setBitOrder(MSBFIRST);  // data is clocked in MSB first
    SPI.setDataMode(SPI_MODE0);  // SCLK idle low (CPOL=0), MOSI read on rising edge (CPHI=0)
    SPI.setClockDivider(SPI_CLOCK_DIV16);  // system clock = 16 MHz, chip max = 1 MHz
}

// =============================================================================
// Main Loop:
// acquire 'nsamples' readings, convert to units of volts, and send out on serial port

void loop() {

int i;
long secs;
float mins;
double volts;
long in;         // incoming serial 32-bit word
long sum = 0;

    for (i=0; i<nsamples; i++) {
      in = SpiRead();
      in &= 0x1FFFFFFF; // force high three bits to zero
      in = in>>5;   // truncate lowest 5 bits
      sum += in;
      delay(198);      // (msec). Total Looptime: +2 msec (overhead for comms)
    }

    // volts =  in * 2.5 / 8.388607;  // 0x7fffff = 8388607
    volts = sum * (2.048/8388607);  // microvolts
    volts = volts / nsamples;
    Serial.println(volts, 6);

} // end main loop


// =================================================================
// SpiRead() -- read out 4 bytes from LTC2440 chip via SPI interface
// =================================================================

long SpiRead(void) {

  long result = 0;
  long b;
 
//  long result2 = 0;// MOSI/SDI pin 7 HIGH => 7 Hz, best resolution

  digitalWrite(slaveSelectPin,LOW);   // take the SS pin low to select the chip
  delayMicroseconds(1);              // probably not needed, only need 25 nsec delay
 
  b = SPI.transfer(0xff);   // B3
  result = b<<8;
  b = SPI.transfer(0xff);   // B2
  result |= b;
  result = result<<8;
  b = SPI.transfer(0xff);   // B1
  result |= b;
  result = result<<8;
  b = SPI.transfer(0xff);   // B0
  result |= b;
 
  // take the SS pin high to de-select the chip:
  digitalWrite(slaveSelectPin,HIGH);
  return(result);
}
Death, taxes and diode losses.
 

Offline Skimask

  • Super Contributor
  • ***
  • Posts: 1433
  • Country: us
Re: MSP430 and ADC
« Reply #11 on: February 23, 2014, 10:35:41 pm »
Reread the 8th post.  Then rereread it.  Then rerereread it.
Then Google any and all words in that post.
Then rererereread it again.
I didn't take it apart.
I turned it on.

The only stupid question is, well, most of them...

Save a fuse...Blow an electrician.
 

Offline Jon86Topic starter

  • Frequent Contributor
  • **
  • Posts: 526
  • Country: gb
Re: MSP430 and ADC
« Reply #12 on: February 23, 2014, 10:40:45 pm »
Reread the 8th post.  Then rereread it.  Then rerereread it.
Then Google any and all words in that post.
Then rererereread it again.

I guess I've got some reading to do ;)
Death, taxes and diode losses.
 

Offline Harvs

  • Super Contributor
  • ***
  • Posts: 1202
  • Country: au
Re: MSP430 and ADC
« Reply #13 on: February 23, 2014, 10:43:54 pm »
You're truncating the lowest 5 bits, when only the lowest 4 bits are "sub LSBs".

Secondly if you want it to do anything reasonable when outside of 0<Vin<VRef then you need to check and handle the EXR bit.  As already stated, the table on page 12 is what you need to be looking at.
 

Offline tszaboo

  • Super Contributor
  • ***
  • Posts: 7488
  • Country: nl
  • Current job: ATEX product design
Re: MSP430 and ADC
« Reply #14 on: February 23, 2014, 10:44:14 pm »
The thing is: People don't like spoon-feeding an adult person with information. Everything what you need is in the datasheet. But I will end your suffering:
The first 4 bit is status bit (Read the friendly datasheet)
You need to bit-wise AND your result with a number (not gonna tell what) and then shift it to get the result.
From the four byte you read every information is there. You get a stupid big number because a status bit changes, get it? RTFD.

And for god sake please learn how to write in hexadecimal. Your pointless 16777215 is a nice, almost round 0xFFFFFF in hex.
 

Offline Jon86Topic starter

  • Frequent Contributor
  • **
  • Posts: 526
  • Country: gb
Re: MSP430 and ADC
« Reply #15 on: February 23, 2014, 10:47:22 pm »
You're truncating the lowest 5 bits, when only the lowest 4 bits are "sub LSBs".

Secondly if you want it to do anything reasonable when outside of 0<Vin<VRef then you need to check and handle the EXR bit.  As already stated, the table on page 12 is what you need to be looking at.

So should I change it to truncate the lowest 4 bits instead? I don't understand what the code's doing, that's my problem here...
I'm just hoping someone can help me fix up my code so I can get the data output that I need, and I can sort the rest out from there.

All I really want is to get the full 28bits out of the ADC, I'm not worried about the extended range but I need to be able to get it to clip at zero rather than jumping up to 4.096, but I can do that in software if I need to.
Death, taxes and diode losses.
 

Offline Jon86Topic starter

  • Frequent Contributor
  • **
  • Posts: 526
  • Country: gb
Re: MSP430 and ADC
« Reply #16 on: February 23, 2014, 10:53:11 pm »
The thing is: People don't like spoon-feeding an adult person with information. Everything what you need is in the datasheet. But I will end your suffering:
The first 4 bit is status bit (Read the friendly datasheet)
You need to bit-wise AND your result with a number (not gonna tell what) and then shift it to get the result.
From the four byte you read every information is there. You get a stupid big number because a status bit changes, get it? RTFD.

And for god sake please learn how to write in hexadecimal. Your pointless 16777215 is a nice, almost round 0xFFFFFF in hex.

Yeah I get the 4 bits are status bits, but what I still don't get is why I'm not actually getting 0xFFFFFF but only half of that. I should be using all 24 bits.

It's not about being spoon fed, it's about the fact that I've spent several bloody hours on trying to work this out for myself and I can't.
Death, taxes and diode losses.
 

Offline miguelvp

  • Super Contributor
  • ***
  • Posts: 5550
  • Country: us
Re: MSP430 and ADC
« Reply #17 on: February 23, 2014, 10:54:38 pm »
I'm a noob too, so I'll give you a hand.

Look at Table 2 on page 12. Bit 29 will flip sign when at 0V (actually can be 1 or 0) But then you need to look at bit 28 to see if you are outside of the range (you want that to be 0) if it changes to 1 then the counter will roll to max value and start decreasing as you decrease the voltage.

Similar thing happens when you go past Vref, the sign won't change (Bit 29 stays on) but bit 28 (extended input range) will turn on, and it will go from max to 0 again.

You could use LTSpice to simulate your circuit to see why you are not reaching Vref for the full 24 bits, or you can measure it to see if your input signal reaches your Vref (Max = Vcc).

As far as using bit 29 and 28 to extend your range, i'm afraid you can only go up to 9/8*Vref (12.5% higher than Vref) or down to -1/8*Vref. So if you have 1 Volt Vref (Vcc) you can only go from -0.125V up to 1.125V. So your range would be not the full extra two bits of precision.

You will get 25% extra range or 1 is to 2^24 as 1.25 is to x, so it's 20971520, so you get
an extra 2,097,152 readings below 0V and also the same amount over Vref.

I did spend 10 mins typing this and reading the datasheet so I might be off in something. But at least I hope it helps you understand what you are seeing.



 

Offline Jon86Topic starter

  • Frequent Contributor
  • **
  • Posts: 526
  • Country: gb
Re: MSP430 and ADC
« Reply #18 on: February 23, 2014, 11:12:45 pm »
Great, that's really helpful :)
I'm now truncating the lowest 4 bits and that seems to have solved my 2^24 problem. I now get 2^24 when Vin is connected to Vref.
All I need now is to get the Sub LSBs out of it.
Death, taxes and diode losses.
 

Offline Jon86Topic starter

  • Frequent Contributor
  • **
  • Posts: 526
  • Country: gb
Re: MSP430 and ADC
« Reply #19 on: February 23, 2014, 11:29:11 pm »
I've been looking at my code and thinking about what's been said here, and I think I've got my head around most of the problem.
I could still do with some help on reading out those additional four bits, if someone doesn't mind :)
Death, taxes and diode losses.
 

Offline miguelvp

  • Super Contributor
  • ***
  • Posts: 5550
  • Country: us
Re: MSP430 and ADC
« Reply #20 on: February 23, 2014, 11:45:39 pm »
Bits 3-0 are sub LSBs below the 24-bit level. Bits 3-0 may be included in averaging or discarded without loss of resolution.

You can do two things,

1) read the sub LSB bits before truncating
 
int subLSB = 0;

     ...

      in = SpiRead();
      in &= 0x1FFFFFFF; // force high three bits to zero

      subLSB = in&0xF;

      in = in>>4;   // truncate lowest 4 bits

In this case subLSB would be like a fix point float [0.]1111b or 2^-1+2^-2+2^-3+2^-4, that you can use for averaging your least significant bit on "in".

 
2) Or use the full 28 bits. ie (add an extra F to your mask, Edit:no don't do this) and don't shift.

One thing is that the most significant bit is the EXT bit, you should check that to see if your value is valid but don't use it for actually computing the value.

Also I didn't read if the sub LSB bits are precise at all, they do mention to be use for averaging but up to you.

By averaging they mean that if the subLSB is equal or greater than say 1000b (8decimal) you can increment your input by one.

Edit: if you go for the full 28bits you have to change your other code.
Edit2: if you use the subLSB your input will act pretty noisy, I would average to actually get the 24bit reading more stable.

And by averaging I would keep an average of subLSB running so when the input is not changing much it helps a stable reading, not just the round up I mentioned before
« Last Edit: February 24, 2014, 12:45:47 am by miguelvp »
 

Offline miguelvp

  • Super Contributor
  • ***
  • Posts: 5550
  • Country: us
Re: MSP430 and ADC
« Reply #21 on: February 24, 2014, 12:12:15 am »
Actually If I was going to write it myself, I wouldn't get rid of the upper 3 bits, only the upper 2.

The code you use clears the sign bit, so you can't tell 0V-1LSB from Vref+1LSB (Edit, nevermind you can tell) but the sign will help you distinguish between those two readings.

int signofIn, extRange, subLSB;
int subLSBAvg =0;

in= SpiRead();
signofIn = (in&0x20000000)?1:-1; // bit 29 is 1 when positive, undetermined right at 0V and 0 when below 0V
extRange = (in&0x10000000)?1:0; // 1 if outside 0-Vref, 0 if within. I would use true/false if you were doing c++
subLSB = in&0xF;
subLSBAvg = (subLSBAvg+subLSB)/2;
in &= 0x0FFFFFFF; // force high 4 bits to zero (clear the EXT since you have extRange)
in = in>>4;   // truncate lowest 4 bits

etc..

then you can use the data if extRange is not true.
you can use the sgnofIn to determine if you went under 0V
use the subLSB to increment your in by one if greater than 0x8 (or 8 ) to round up.
or instead of rounding up with subLSB, use the subLSBAvg to round up get a stable signal.

I wouldn't use the low 4bits for input, they would be very peaky.
« Last Edit: February 24, 2014, 12:21:11 am by miguelvp »
 

Online Andreas

  • Super Contributor
  • ***
  • Posts: 3272
  • Country: de
Re: MSP430 and ADC
« Reply #22 on: February 24, 2014, 09:07:14 pm »
All I need now is to get the Sub LSBs out of it.

Why?

Just some questions:
- do you really know what the parameter 1.5uV noise (effective value) means as peak/peak value?
- how many "noise free" bits will be left over for a single conversion?
- how many values will you have to need to average to get near 24 noise free bits?
- how much noise is generated by your reference voltage IC?

- do you use floating point math on your MSP430?
- If yes: what resolution (mantissa) have your floating point variables?
- what happens if you specify "double" on your compiler. Will he cheat you and pressing the 8 bytes into 4 bytes?

you see: many things to consider above 16 bits resolution.

with best regards

Andreas
 

Offline Jon86Topic starter

  • Frequent Contributor
  • **
  • Posts: 526
  • Country: gb
Re: MSP430 and ADC
« Reply #23 on: February 25, 2014, 09:32:48 am »
Awesome, thanks for the help Andreas and Miguel :)
I see what you mean about the last four bits, I guess it's not worth using them. I was hoping just to add them into the averaging on the PC, and get a bit more resolution out of it. I suppose there's not really much point. Thanks :)
Death, taxes and diode losses.
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: MSP430 and ADC
« Reply #24 on: February 25, 2014, 12:08:11 pm »
Quote
- do you use floating point math on your MSP430?

Spot on. Most of those code pieces are written by Arduino people.
================================
https://dannyelectronics.wordpress.com/
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf