Go Down

Topic: SPI with ADC slow and extra bit somehow (Read 1 time) previous topic - next topic

Hello, I have some questions about my SPI connection with an ADC (http://www.ti.com/product/ads7886)
Here's the code:
Code: [Select]
#include <SPI.h>
int time = 0;
long tot = 0;

void setup() {
  SPI.setBitOrder(MSBFIRST);
  SPI.setClockDivider(SPI_CLOCK_DIV2);
  SPI.setDataMode(SPI_MODE3);
  const int SS = 10;
  SPI.begin();

}

void loop() {
  digitalWrite(SS,LOW); 
  byte MSB = SPI.transfer(0);
  byte LSB = SPI.transfer(0);
  unsigned int value = MSB*256 + LSB;
  digitalWrite(SS,HIGH);
  tot += 1;
  time = millis();
  if (time >= 1000) {
    Serial.begin(9600);
    Serial.println(tmp);
    Serial.println(time);
    Serial.println(tot);
    while(1){} 
  }
}


So with clock divider = 2, which should mean 8 Mhz, i should be getting 8M/16[bits] = 500,000 integer data per second.
I'm consistently getting 45081 :(
Another strange thing is that I'm getting results over 4095, which is 12 bits. For some reason it goes all the way up to 13 bits, though it's a 12 bit ADC. This happens with both of my adc's, so i think it isnt that I fried this part while soldering :) any ideas?

PaulS

Quote
Here's the code

That won't compile. Where is tmp defined?

Quote
Another strange thing is that I'm getting results over 4095, which is 12 bits. For some reason it goes all the way up to 13 bits, though it's a 12 bit ADC.

How do you know? You aren't printing MSB, LSB, or value anywhere.

Nick Gammon

The processor runs at 16 MHz (I am presuming as you didn't say) and instructions are an average of 2 clock cycles. So there is no way, in a single instruction, that you are going to do everything you have in "loop". It's even 8 lines of C++ code (assuming the branch isn't taken) plus entering and exiting loop itself.

Quote
Code: [Select]
  unsigned int value = MSB*256 + LSB;


You are better off shifting the byte left, hopefully the compiler will do that for you:

Code: [Select]
  unsigned int value = (MSB << 8) | LSB;

Quote
Code: [Select]

    Serial.println(tmp);
    Serial.println(time);


Your code doesn't compile. There is no "tmp" there.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Oh right sorry about the tmp. I cut some commented code out to make it easier to read and cut that out too by accident.
the commented code is also where i had it go slower and transmit everything over serial. I got some interesting stuff like 8100.

So about the SPI clock: does it continuously flicker (during rest of loop) or only when I call SPI.transfer()?

Also I ran some other tests, and I'm wondering if the arduino is limiting itself? Because i put in an extra if statement that was true sometimes, within which i put a sin, cos, tan, calculation on 'time' and I still got that same number of results: 45081.

Nick Gammon

Flicker? Sin? Sounds bad.

No the clock only does stuff during the transfer. The very essence of the clock is that it tells the "other end" there is data there. If it was active at other times, the other end would be getting garbage.

Perhaps post your code that produces this number 45081.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Bleagh im not very good at explaining   :smiley-roll-sweat:

the code i posted originally is the code that produces the 45081 (which is the number of loops it has done in 1000 milliseconds).
The code I used to transmit the actual values is only slightly different:

Code: [Select]
#include <SPI.h>
int time = 0;
//long tot = 0;
//unsigned long tmp = 0;

void setup() {
  SPI.setBitOrder(MSBFIRST);
  SPI.setClockDivider(SPI_CLOCK_DIV4);
  SPI.setDataMode(SPI_MODE3);
  const int SS = 10;
  SPI.begin();
  Serial.begin(115000);

}

void loop() {
  digitalWrite(SS,LOW); 
  byte MSB = SPI.transfer(0);
  byte LSB = SPI.transfer(0);
//  unsigned int value = MSB*256 + LSB;
  unsigned int value = (MSB << 8) | LSB; //updated
  digitalWrite(SS,HIGH);
  sendByte(MSB);         //binary MSB
  sendByte(LSB);         //binary LSB
  Serial.println(value);  // value
  Serial.println(" ");     //separator
/*  tot += 1;
  time = millis();
  if ((time-tmp) >= 1000) {
    Serial.begin(115000);
    Serial.println(tmp);
    Serial.println(time);
    Serial.println(tot);
    while(1){} 
  }
*/
}
//made this so it won't chop of the leading 0's when sending binary over SPI
void sendByte(byte num){
  unsigned int i = 128; //binary: 10000000
  for (int x = 0; x < 8; x++) {
    if ((i&num) != 0) {
      Serial.print(1);
    }
    else {
      Serial.print(0);
    }
    i >>= 1;
  }
  Serial.print("\n");
}


here I'm not worried about the speed or number of transfers, just getting some of the data

Nick Gammon

Bear with me a bit here. I'm not trying to be difficult. I'm trying to help you.

Quote
the code i posted originally is the code that produces the 45081 (which is the number of loops it has done in 1000 milliseconds).


No, it doesn't. It won't compile. There is no "tmp" defined. So if you would be kind enough to post code, that compiles, that demonstrates your point, we can take it from there.

Your more recent post doesn't compile for me either, at least under version 0022 of the IDE:

Code: [Select]
void setup() {
  SPI.setBitOrder(MSBFIRST);
  SPI.setClockDivider(SPI_CLOCK_DIV4);
  SPI.setDataMode(SPI_MODE3);
  const int SS = 10;
  SPI.begin();
  Serial.begin(115000);

}


Note that SS goes out of scope at this point, so I get this:

Code: [Select]
sketch_jan02b.cpp: In function 'void loop()':
sketch_jan02b:16: error: 'SS' was not declared in this scope


So if you specify which version of the IDE you are using, that would help too. I don't personally use 1.0 unless I have to chase down a problem, because of major incompatibilities with previous versions.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

#7
Jan 02, 2012, 07:42 am Last Edit: Jan 02, 2012, 07:44 am by flyingsilverfin Reason: 1
Pulled up a version of what i was using before, which compiles for me and gets the result of 45081
Code: [Select]
#include <SPI.h>
int time = 0;
long tot = 0;
long tmp = 0;

void setup() {
 SPI.setBitOrder(MSBFIRST);
 SPI.setClockDivider(SPI_CLOCK_DIV4);
 SPI.setDataMode(SPI_MODE3);
 const int SS = 10;
 SPI.begin();
 tmp = millis();
}

void loop() {
 digitalWrite(SS,LOW);  
 byte MSB = SPI.transfer(0);
 byte LSB = SPI.transfer(0);
 unsigned int value = (MSB << 8) | LSB; //just added this
 digitalWrite(SS,HIGH);
 tot += 1;
 time = millis();
 if ((time-tmp) >= 1000) {
   Serial.begin(115000);
   Serial.println(tmp);
   Serial.println(time);
   Serial.println(tot);
   while(1){}  
 }
}


turns out I'm using version 1.0. Not that it the backward incompatibilities would bother me much because i just started using arduino (and microprocs in general)

Nick Gammon

OK, well using version 1.0 of the IDE, and uploading your sketch, yes I can definitely confirm you get:

Code: [Select]
0
1000
45081


So what? This is without any hardware connected. You are basically timing how quickly you can do SPI transfers, and they will take the same time every time you test. Even with nothing connected.

As I explained above, you can't expect 500,000 transfers per second, because the processor has to "do stuff" apart from doing the SPI. Like, storing things in memory, checking the time, etc.

So the bigger issue, which you said above, is why you seem to be getting "bad" data.

Can you give examples of this data?
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

I've attatched a txt doc with some data (obtained from the code I posted earlier)
Used a 1k pot and then turned it up toward the end of the data

3 serial transfers: MSB, LSB, then the total value

I'll be gone for the next few days (vacation's over... back to school :(), might be able to drop in once or twice in some airport, so no rush

PaulS

Quote
I've attatched a txt doc with some data (obtained from the code I posted earlier)

Attached it to what? Not your post.

Agh internet in developing countries can be a pain. I got booted out of the network right when i clicked post once.
Trying again

btw i fed the 1K pot the 5v from the arduino, forgot to mention that

Go Up