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!
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:
My 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.
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);
}
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.
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.
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.
I have tried your code with a "Seeduino", and it works very fine.
But I need a smaller board for my project .
I 'm trying despairingly this code on a "Stickduino" or a "Pro mini" (5V with a regulator, but I have tried also with the supply of the Pro mini 3V)
Impossible to obtain correct values (it's always '0')
I have verified all the solders, all the wires....Nothing !!
Hi,
I just thought I'd add something to this old thread. It seems some people have been having trouble getting the code to work. I too had my fair share of problems and have posted them below in an effort to help others in the future who may have similar problems. I'm not sure if the problems of the previous 2 poster are related to mine, but perhaps they have found a solution at this stage.
Anyway, I bought the SCP1000 breakout board from sparkfun and tried to interface it to an arduino duemilnova. The first problem was the 5V I/O pins on the arduino and the 3.3V pins on the SCP1000. To overcome this I got the logic level converters also from sparkfun and wired them up. Still the code did not work. The details provided by sparkfun for the logic level converters are a little misleading if not read carefully, on the low voltage side you will get half of the voltage on the high side, and not the actual low voltage. The problem I had was that I was driving 2.5V to the SCP1000 I/O pins and had the SCP1000 powered of a 3.3V supply. There is mention in the datasheet for the SCP1000 that Vcc cannot differ from the I/O voltages by more than a certain amount. (I don't have to hand the exact values). So the solution was to power the SCP1000 of 2.5V. This actually produces less error comapared to a higher voltage according to the datasheet also, which is a bonus. I have been getting what seem to be acuarate readings of pressure and temperature ever since.
Anyway hopfully this post will save somebody some time in getting their sensor to work.
I'm new to Arduino, this Forum and how to use them, but you have to start somewhere.
I bought the Arduino Duemilanove and SCP1000 (pressure sensor from Sparkfun.) I've been reading this thread, but what I need is also a schematic how to connect the SCP1000 to the Arduino
Can anyone help me with a schematic and code for the Duemilanove.