0
Offline
Newbie
Karma: 0
Posts: 15
Arduino rocks
|
 |
« on: June 11, 2008, 03:48:49 pm » |
hello!  i have an arduino skinny (made by sparkfun) that i'm trying to get to talk to an scp1000 pressure sensor via spi. this is the first time i've tried to use the spi interface, and have to admit that i'm floundering a bit. here's the code i'm using: // define spi bus pins #define SLAVESELECT 10 #define SPICLOCK 13 #define DATAOUT 11 //MOSI #define DATAIN 12 //MISO
//Addresses #define REVID 0x00 //ASIC Revision Number #define OPSTATUS 0x04 //Operation Status #define STATUS 0x07 //ASIC Status
char lsb_in_byte; //
void setup() { byte clr; pinMode(DATAOUT, OUTPUT); pinMode(DATAIN, INPUT); pinMode(SPICLOCK,OUTPUT); pinMode(SLAVESELECT,OUTPUT); digitalWrite(SLAVESELECT,HIGH); //disable device SPCR = B01010011; //MPIE=0, SPE=1 (on), DORD=0 (MSB first), MSTR=1 (master), CPOL=0 (clock idle when low), CPHA=0 (samples MOSI on rising edge), SPR1=0 & SPR0=0 (500kHz) // SPI2X=0; //No clock multiplier clr=SPSR; clr=SPDR; delay(10); Serial.begin(9600); // Connect to the serial port 9600 bps Serial.println("SCP1000 Code v0.01"); delay(1000); }
void loop() { lsb_in_byte = read_register(REVID); Serial.print("REVID ["); Serial.print(lsb_in_byte, HEX); Serial.println("]"); lsb_in_byte = read_register(OPSTATUS); Serial.print("OPSTATUS ["); Serial.print(lsb_in_byte, HEX); Serial.println("]"); lsb_in_byte = read_register(STATUS); Serial.print("STATUS ["); Serial.print(lsb_in_byte, HEX); Serial.println("]"); delay(5000); }
char spi_transfer(volatile char data) { SPDR = data; // Start the transmission while (!(SPSR & (1<<SPIF))) // Wait for the end of the transmission { }; return SPDR; // return the received byte }
//Read 8-bit register char read_register(char register_name) { char in_byte; register_name |= 128; //Read command digitalWrite(SLAVESELECT,LOW); //Select SPI Device in_byte = spi_transfer(register_name); //Write byte to device //in_byte is nothing, we need to clock in another 8 bits in_byte = spi_transfer(0x00); //Send nothing, but we should get back the register value digitalWrite(SLAVESELECT,HIGH); return(in_byte); }
//Sends a write command to SCP1000 void write_register(char register_name, char register_value) { char in_byte; register_name &= 127; //Write command digitalWrite(SLAVESELECT,LOW); //Select SPI device in_byte = spi_transfer(register_name); //Send register location in_byte = spi_transfer(register_value); //Send value to record into register digitalWrite(SLAVESELECT,HIGH); }
and here's the output i'm getting: SCP1000 Code v0.01 REVID [0] OPSTATUS [0] STATUS [0] REVID [0] OPSTATUS [0] STATUS [0] REVID [0] OPSTATUS [0] STATUS [0] REVID [0] OPSTATUS [0] STATUS [0] REVID [0] OPSTATUS [0] STATUS [0] no matter which register i read from, i just get zero.  any help would very much be appreciated!  jules.
|
|
|
|
« Last Edit: June 11, 2008, 04:13:45 pm by zzpza »
|
Logged
|
|
|
|
|
Las Vegas, NV
Offline
God Member
Karma: 0
Posts: 503
|
 |
« Reply #1 on: June 11, 2008, 04:04:36 pm » |
I've only skimmed your code, but it looks like you're handling the SPI communication correctly. Do you have access to an oscilloscope? It would be helpful if you could see what your MOSI, MISO, and SCK lines look like. Have you verified that you're using an SPI clock speed that your sensor can handle? Is there anything in the datasheet about a required delay between when you send the register address and when you initiate the junk-byte transmission that will retrieve data from the sensor? I made a post recently to help someone with an SPI problem here: http://forum.pololu.com/viewtopic.php?f=1&t=986My post links to some sample mega644 code for performing SPI communication, but this should be almost identical (if not exactly identical) to what you'd do on the mega168. - Ben
|
|
|
|
|
Logged
|
|
|
|
|
Lacomb, Oregon
Offline
Sr. Member
Karma: 0
Posts: 299
|
 |
« Reply #2 on: June 11, 2008, 09:24:58 pm » |
Here is the document from vti that I used to adapt the code to Propeller spin code.
|
|
|
|
|
Logged
|
Stephen
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 15
Arduino rocks
|
 |
« Reply #3 on: June 12, 2008, 01:15:01 pm » |
Thank you bens and franklin!  It was a timing issue. I added a delay(10); after asserting the slaveselect and the data started to flow. 
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 4
Arduino rocks
|
 |
« Reply #4 on: July 27, 2008, 08:36:11 pm » |
Thank you bens and franklin!  It was a timing issue. I added a delay(10); after asserting the slaveselect and the data started to flow.  Can you post the working code?
|
|
|
|
« Last Edit: July 27, 2008, 08:36:34 pm by zlite »
|
Logged
|
|
|
|
|
N. VA
Offline
Newbie
Karma: 0
Posts: 9
|
 |
« Reply #5 on: August 02, 2008, 11:34:20 am » |
I have completed the code for the SCP and the following should print out temperature in Fahrenheit and pressure in Pascals. The other register are defined if you wanted to return the revision ID or opstatus etc. I think the problem the author had was not timing but never sending a initial command to choose the SCP operation mode. This line is in the setup(). Feel free to ask a question or let me know if you see something inefficient or wrong. // define spi bus pins #define SLAVESELECT 10 #define SPICLOCK 13 #define DATAOUT 11 //MOSI #define DATAIN 12 //MISO #define UBLB(a,b) ( ( (a) << 8) | (b) ) #define UBLB19(a,b) ( ( (a) << 16 ) | (b) )
//Addresses #define REVID 0x00 //ASIC Revision Number #define OPSTATUS 0x04 //Operation Status #define STATUS 0x07 //ASIC Status #define START 0x0A //Constant Readings #define PRESSURE 0x1F //Pressure 3 MSB #define PRESSURE_LSB 0x20 //Pressure 16 LSB #define TEMP 0x21 //16 bit temp
char rev_in_byte; int temp_in; unsigned long pressure_lsb; unsigned long pressure_msb; unsigned long temp_pressure; unsigned long pressure;
void setup() { byte clr; pinMode(DATAOUT, OUTPUT); pinMode(DATAIN, INPUT); pinMode(SPICLOCK,OUTPUT); pinMode(SLAVESELECT,OUTPUT); digitalWrite(SLAVESELECT,HIGH); //disable device SPCR = B01010011; //MPIE=0, SPE=1 (on), DORD=0 (MSB first), MSTR=1 (master), CPOL=0 (clock idle when low), CPHA=0 (samples MOSI on rising edge), SPR1=0 & SPR0=0 (500kHz) clr=SPSR; clr=SPDR; delay(10); Serial.begin(9600); delay(500);
Serial.println("Initialize High Speed Constant Reading Mode"); write_register(0x03,0x09); }
void loop() { rev_in_byte = read_register(REVID); pressure_msb = read_register(PRESSURE); pressure_msb &= B00000111; pressure_lsb = read_register16(PRESSURE_LSB); pressure = UBLB19(pressure_msb, pressure_lsb); pressure /= 4; Serial.print("PRESSURE ["); Serial.print(pressure, DEC); Serial.println("]"); temp_in = read_register16(TEMP); temp_in = temp_in / 20; temp_in = ((1.8) *temp_in) + 32; Serial.print("TEMP F ["); Serial.print(temp_in , DEC); Serial.println("]"); delay(1500); }
char spi_transfer(volatile char data) { SPDR = data; // Start the transmission while (!(SPSR & (1<<SPIF))) // Wait for the end of the transmission { }; return SPDR; // return the received byte }
char read_register(char register_name) { char in_byte; register_name <<= 2; register_name &= B11111100; //Read command digitalWrite(SLAVESELECT,LOW); //Select SPI Device spi_transfer(register_name); //Write byte to device in_byte = spi_transfer(0x00); //Send nothing, but we should get back the register value digitalWrite(SLAVESELECT,HIGH); delay(10); return(in_byte); }
float read_register16(char register_name) { byte in_byte1; byte in_byte2; float in_word; register_name <<= 2; register_name &= B11111100; //Read command
digitalWrite(SLAVESELECT,LOW); //Select SPI Device spi_transfer(register_name); //Write byte to device in_byte1 = spi_transfer(0x00); in_byte2 = spi_transfer(0x00); digitalWrite(SLAVESELECT,HIGH); in_word = UBLB(in_byte1,in_byte2); return(in_word); }
void write_register(char register_name, char register_value) { register_name <<= 2; register_name |= B00000010; //Write command
digitalWrite(SLAVESELECT,LOW); //Select SPI device spi_transfer(register_name); //Send register location spi_transfer(register_value); //Send value to record into register digitalWrite(SLAVESELECT,HIGH); }
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 4
Arduino rocks
|
 |
« Reply #6 on: August 02, 2008, 12:01:19 pm » |
Hurray! It works great. Thanks SO much for posting that! You saved me hours of frustration ;0)
|
|
|
|
|
Logged
|
|
|
|
|
Lacomb, Oregon
Offline
Sr. Member
Karma: 0
Posts: 299
|
 |
« Reply #7 on: August 10, 2008, 03:25:28 pm » |
Conor, sorry to bring up an old thread but I tried your code and it worked but I noticed if I had power to the SCP1000 it would heat up and if I removed power it still worked. How did you have yours hooked up to the Arduino? Thanks.
|
|
|
|
|
Logged
|
Stephen
|
|
|
|
N. VA
Offline
Newbie
Karma: 0
Posts: 9
|
 |
« Reply #8 on: August 18, 2008, 11:18:13 am » |
Franklin,
I have not noticed any over heating by the SCP. It is a 3.3 V device, so if you are using a 5v arduino to power it that might be the problem. I am using the voltage and ground from a Sparkfun wee (lillypad equivalent). Other than that, pins 10-13 for ss, sck, mosi, miso.
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 5
Arduino rocks
|
 |
« Reply #9 on: February 06, 2009, 05:00:07 pm » |
I'm running this code on a Funnel IO from Sparkfun, which is a 3.3v/8MHz Arduino.
I'm getting good serial communications, but all 0's when I run the code. (Every once in a while, I get random numbers).
Any ideas?
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 5
Arduino rocks
|
 |
« Reply #10 on: February 10, 2009, 06:20:52 pm » |
So it's now working (hurray!)
UPDATED: Scratch that, it was actually a bad wiring problem on my part.
UPDATED 2: I'm getting weird readings, like:
MSB = 0x5 LSB = 0xFFFFE6F0
Which means my pressure is 0x5FFFFE6F0, which just seems a bit high for 1000ft above sea level?
My temperature is reasonable (currently 22.8C), and adjusts accordingly, and my Pressure reading has jitter in it of about the right magnitude.
The 0xFFFF in the first half of the LSB is suspicious to me, but I'm running verbatim the code posted above.
|
|
|
|
« Last Edit: February 11, 2009, 09:57:06 am by bpeoples »
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 5
Arduino rocks
|
 |
« Reply #11 on: February 21, 2009, 09:40:59 am » |
Just as an update, I have it working now! Here's the code I needed to do to make it work: pressure_lsb = read_register16(PRESSURE_LSB); pressure_lsb &= 0x0000FFFF;
Does this make any sense at all? My read_register16 function looks thus: float read_register16(char register_name) { byte in_byte1; byte in_byte2; float in_word; register_name <<= 2; register_name &= B11111100; //Read command
digitalWrite(SLAVESELECT,LOW); //Select SPI Device spi_transfer(register_name); //Write byte to device in_byte1 = spi_transfer(0x00); in_byte2 = spi_transfer(0x00); digitalWrite(SLAVESELECT,HIGH); in_word = UBLB(in_byte1,in_byte2); return(in_word); }
Could this be because of the cast from float to unsigned long? I'm using Arduino 0013, did the types change between then and now?
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 4
Arduino rocks
|
 |
« Reply #12 on: March 06, 2009, 03:23:34 pm » |
Hello,
I'm trying to get Temp and Pressure with a SCP1000 using the code above.
I've got PRESSURE [123007] TEMP F [21] PRESSURE [123007] TEMP F [21]
Strange values.
Below is the wiring to Arduino Pro Mini SCK -> pin 13 MISO -> pin 12 MOSI -> pin 11 Now I got a doubt. From the program above : SLAVESELECT 10
What is SLAVESELECT from the SCP1000. I'm using Sparkfun breadk out, and got only CSB / DRDY. How should I connect SLAVESELECT ?
Thanks for your help.
Mersing.
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 1
Arduino rocks
|
 |
« Reply #13 on: March 27, 2009, 09:27:36 am » |
Is it possible to use 2 scp1000 sensors with a single arduino? If so, how do you identify which is which?
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Faraday Member
Karma: 6
Posts: 2504
|
 |
« Reply #14 on: March 27, 2009, 08:49:59 pm » |
MOSI, MISO, and SCK are buses, but the chip select is unique for each device. If the device is a correctly designed SPI device, just wire the second one up identical to the first, except use a different line for chip select.
-j
|
|
|
|
|
Logged
|
|
|
|
|
|