Problems SPI pressure sensor SCP1000

02 Apr 2010

http://www.sparkfun.com/commerce/product_info.php?products_id=8161

Has anyone bought this pressure sensor? I have problems with the SPI communication.
Forgive me for my lack of Knowledge. (both English and electronics)

I have found a code which is known to have worked in the arduino:
My idea is to translate this code to mbed

Arduino code:

//--------------1-------------------------
// define spi bus pins
#define SLAVESELECT 10  //nuestro pin 8
#define SPICLOCK 13      // nuestro pin 7
#define DATAOUT 11	//MOSI nuestro pin 5
#define DATAIN 12	 //MISO nuestro pin 6
#define UBLB(a,b)  ( ( (a) << 8) | (b) )
#define UBLB19(a,b) ( ( (a) << 16 ) | (b) )


//---------------2----------------------

//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


//---------------3-----------------------

char rev_in_byte;	    
int temp_in;
unsigned long pressure_lsb;
unsigned long pressure_msb;
unsigned long temp_pressure;
unsigned long pressure;


//---------------4-----------------------
void setup()
{
  byte clr; //  arduino command
  pinMode(DATAOUT, OUTPUT); //nuestro pin 5
  pinMode(DATAIN, INPUT);  // nuestro pin 6
  pinMode(SPICLOCK,OUTPUT); // nuestro pin 7
  pinMode(SLAVESELECT,OUTPUT); // nuestro pin 8
  digitalWrite(SLAVESELECT,HIGH); //disable device hacemos lo mismo con cs = 1;
  
  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;//para limpiar el buffer
  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);
  
}

//-----------------------5------------------------

char spi_transfer(volatile char data)
{
  SPDR = data;			  // Start the transmission
  while (!(SPSR & (1<<<= 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);
  
}

//---------------------7---------------------------
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);
}

//-----------------------8----------------------------
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);
} 

And this is my try to translate de code:

//---------------1-------------------------

#include "mbed.h"

SPI spi(p5, p6, p7); // mosi, miso, sclk
DigitalOut cs(p8);

Serial pc(USBTX, USBRX); // tx, rx

#define UBLB(a,b)  ( ( (a) << 8) | (b) )
#define UBLB19(a,b) ( ( (a) << 16 ) | (b) )

//-----------------2------------------------
//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

//---------------3-----------------------

char rev_in_byte;	    
int temp_in;
unsigned long pressure_lsb;
unsigned long pressure_msb;
unsigned long temp_pressure;
unsigned long pressure;

//-----------------4------------------------

int main() {
	cs=1;
	pc.baud(921600);
	spi.frequency(500000); // the fastest of the sensor
	spi.format(8, 0); // duda son dos palabras de 8 bits? 
	wait(0.5);
	pc.printf("Initialize High Speed Constant Reading Mode");
	write_register(0x03,0x09);

 while (1) {
	rev_in_byte = read_register(REVID);
  
  	pressure_msb = read_register(PRESSURE);
  //	pressure_msb &= B00000111; -----arduino read command
  	pressure_lsb = read_register16(PRESSURE_LSB);
  	pressure = UBLB19(pressure_msb, pressure_lsb);
 	pressure /= 4;
  
  	pc.printf("PRESSURE [");
  	pc.printf(pressure, DEC);
  	pc.printf("]");
  
  	temp_in = read_register16(TEMP);
  	temp_in = temp_in / 20;
  	temp_in = ((1.8) *temp_in) + 32;
  	pc.printf("TEMP F [");
  	pc.printf(temp_in , DEC);
  	pc.printf("]");

  	wait(1500);
}	   
}

//------------------------5---------------------
char spi_transfer(volatile char data)
{
  spi.write(data);
}

//------------------------6----------------------

char read_register(char register_name)
{
    char in_byte;
    register_name <<= 2;
 //   register_name &= B11111100;  -----arduino read command
    cs=0; //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
    cs=1;
    wait(10);
    return in_byte;
  
}

//------------------------7------------------------

float read_register16(char register_name)
{
    byte in_byte1;
    byte in_byte2;
    float in_word;
    
    register_name <<= 2;
 //   register_name &= B11111100;  -----arduino read command

    cs=0; //Select SPI Device
    spi_transfer(register_name); //Write byte to device
    in_byte1 = spi_transfer(0x00);    
    in_byte2 = spi_transfer(0x00);
    cs=1;
    in_word = UBLB(in_byte1,in_byte2);
    return in_word;
}

//-----------------------8----------------------------

void write_register(char register_name, char register_value)
{
    register_name <<= 2;
//    register_name |= B00000010; -----arduino write command
    cs=0; //Select SPI device
    spi_transfer(register_name); //Send register location
    spi_transfer(register_value); //Send value to record into register
    cs=1;
} 
I have no idea of what "register_name |= B00000010;" does and how can I
do the same thing with mbed.

However, I now I am a bit ambitious for my knowledge. So I tryed a simplier
program.


I want to call for the temperature, recieve the hex number (16 bits) and print
it in the computer screen.

I give some pictures of the user guide that I think they have the most relevat
information.

 

 

My program:

 

#include "mbed.h"

SPI spi(p5, p6, p7); // mosi, miso, sclk
DigitalOut cs(p8);
Serial pc(USBTX, USBRX); // tx, rx


//Addresses
#define TEMP 0x21       //16 bit temp



int main() {
    // Setup the spi for 8 bit data, high steady state clock,
    // second edge capture, with a 500kHz clock rate
    cs=1;
    spi.format(8,0);
    spi.frequency(500000);
    wait(1);

    // Select the device by seting chip select low
    cs = 0;

    // Send 0x21
    spi.write(TEMP);

    // Send a dummy byte to receive the contents of the 0x21 register (16 bits)
    int in_byte1 = spi.write(0x00);
    int in_byte2 = spi.write(0x00);
    cs=1;
    pc.printf("ox%X",in_byte1);//------------------------------
    pc.printf("ox%X",in_byte2);//---------------------------
}
and this is what I get:

ox7F  (in_byte1)
oxFF  (in_byte2)


0111-1111-1111-1111 

If I do as the example in the guide:

xx11-1111-1111-1111

s=1 (bit pattern of a negative temperature data)

TEMPOUT inverted data =  00-0000-0000

So I don't receive any temperature!!!

Please!! I need help!! 

02 Apr 2010

I have been looking at this post, and thanks to the analyzer I am understanding how SPI works. The key is to order the bits as you need.

http://mbed.org/forum/mbed/topic/467/?page=1#comment-2620

Looking at the code that solves the problem I have some basic questions

int sca3000_read(int address) {
    int nrw = 0;      // we're doing a read
    SCA_CSB_PIN = 0;
    int command = (address << 2) | (nrw << 1); 
    spi.write(command);             // write out the address (1st 8 bits)
    int result = spi.write(0xFF);   // read the result (2nd 8 bits)
    SCA_CSB_PIN = 1;
    return result;
}

You need to write this secuence:

I A5 I A4 I A3 I A2 I A1 I A0 I RB/WR I          I  then you recieve from the sensor...

the instruccion is 0x05 (8 bits), so you have to eliminate the first two ceros

0000-0101

so with "(address << 2)" you get "00010100"

we are doing a read so we need a "0" in the RB/WR bit, it is called "int nrw=0;"

then with the "command = (address<<2) I (nrw<<1);"

00010100 OR 00000000 = 00010100     why you need to do that? it makes any difference?

Now you have what you need and you send it:

spi.write(command);

And recieve:

int result=spi.write(0xFF);

while you do this  the MOSI line  is sending 1111-1111. In the example form the handbook:

int whoami = spi.write(0x00);

I suppose it denpends on what the sensor demands.. am I mistaken?

In "result" you store the 8 bit.

 

the next part of the code:

 

int main() {
    pc.baud(921600);
    spi.format(8, 0);
    SCA_RESET_PIN = 0;
    SCA_CSB_PIN = 1;
    wait(0.01);
    SCA_RESET_PIN = 1;
    wait(2);

    // SCA3000 Register Format:
    //  X_MSB @ 0x05   X_LSB @ 0x04
    // [ s | d(11:5) ] [ d(4:0) | x(3) ]
    while (1) {
        int msb = sca3000_read(0x05);
        int lsb = sca3000_read(0x04);
        int16_t result = (msb << 8) | (lsb & 0xF8); // construct result and ignore bottom 3 bits
        pc.printf("X: %d\r\n", result);
        wait(0.005);
    }
}

msb = d17 d16 d15 d14 d13 d12 d11 d10

lsb = d27 d26 d25 d24 d23 d22 d21 d20

0xF8= 1111-1000

lsb & 0xF8 = d27 d26 d25 d24 d23  0  0  0

int16_t result = (msb << 8) | (lsb & 0xF8); // construct result and ignore bottom 3 bits

= d17 d16 d15 d14 d13 d12 d11 d10 d27 d26 d25 d24 d23  0  0  0
02 Apr 2010

 

To get my 16 bit temperature code the instruction is: 0x21 = 0010-0001

#include "mbed.h"

SPI spi(p5, p6, p7); // mosi, miso, sclk
DigitalOut cs(p8);
Serial pc(USBTX, USBRX); // tx, rx

//Addresses
#define TEMP 0x21       //16 bit temp


int main() {
    spi.format(8, 0);
    spi.frequency(250000);
    cs = 1;
    wait(2);
    pc.printf("TEMP: %X\r\n",TEMP);
    int nrw = 0;
    int address = TEMP;      // we're doing a read
    int command = (address << 2) | (nrw << 1);
    pc.printf("command: %X\r\n",command);
    cs = 0; 
    spi.write(command);             
    int byte1 = spi.write(0xFF);
    int byte2 = spi.write(0xFF);   
    cs = 1;
    int result = (byte1 << 8) | (byte2);
    pc.printf("byte 1: %X\r\n",byte1);
    pc.printf("byte 2: %X\r\n",byte2);
    pc.printf("result: %X\r\n",result);     
}

and this is what i get: TEMP: 21 command: 84 byte 1: 0 byte 2: 0 result: 0
I don't know what I 'm doing wrong!!

command 84 = 1000-0100 , i am sending just the same as the example!

03 Apr 2010 . Edited: 03 Apr 2010

good!! I'm having response. This is a simple program that put an opperating mode and ask the sensor what opperating mode has.

 

//---------------1-------------------------

#include "mbed.h"

SPI spi(p5, p6, p7); // mosi, miso, sclk
DigitalOut cs(p8);

Serial pc(USBTX, USBRX); // tx, rx

#define UBLB(a,b)  ( ( (a) << 8) | (b) )
#define UBLB19(a,b) ( ( (a) << 16 ) | (b) )

//-----------------2------------------------
//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

//---------------3-----------------------

char rev_in_byte;	    
int temp_in;
unsigned long pressure_lsb;
unsigned long pressure_msb;
unsigned long temp_pressure;
unsigned long pressure;

void read_register(char register_name)
{
    register_name <<=2;
    register_name &= 0xFC;
    pc.printf("registro que pedimos que lea: register_name: 0x%X\r\n", register_name);
    cs=0; //Select SPI device
    spi.write(register_name); //Send register location
    int register_value=spi.write(0x00);
    cs=1;
    pc.printf("valor del registro que hemos pedido: register_value: 0x%X\r\n", register_value);
}


void write_register(char register_name, char register_value)
{
    register_name <<= 2;
    register_name |= 0x02; 
    pc.printf("nombre del registro que queremos cambiar: register_name: 0x%X\r\n", register_name);
    pc.printf("valor que le queremos asociar: register_value: 0x%X\r\n", register_value);
    cs=0; //Select SPI device
    spi.write(register_name); //Send register location
    spi.write(register_value); //Send value to record into register
    cs=1;
} 



//-----------------4------------------------

int main() {
// configuracion---------------------------------
    cs=1;
	spi.frequency(500000); // the fastest of the sensor
	spi.format(8, 0);  
	wait(0.5);
//------------------------------------------------

pc.printf("Initialize High Speed Constant Reading Mode\r\n");
write_register(0x03,0x09);
wait(0.5);
read_register(0x03);

}
03 Apr 2010

I got the pressure (Pa) and the temperature (ºC)

 

//---------------1-------------------------

#include "mbed.h"

SPI spi(p5, p6, p7); // mosi, miso, sclk
DigitalOut cs(p8);

Serial pc(USBTX, USBRX); // tx, rx


//-----------------2------------------------
//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

//---------------3-----------------------
    
float temp_in;
unsigned long pressure_lsb;
unsigned long pressure_msb;
unsigned long temp_pressure;
unsigned long pressure;

char read_register(char register_name)
{
    register_name <<=2;
    register_name &= 0xFC;
    cs=0; //Select SPI device
    spi.write(register_name); //Send register location
    char register_value=spi.write(0x00);
    cs=1;
    return register_value;  
}


void write_register(char register_name, char register_value)
{
    register_name <<= 2;
    register_name |= 0x02; //le estamos diciendo que escriba
    cs=0; //Select SPI device
    spi.write(register_name); //Send register location
    spi.write(register_value); //Send value to record into register
    cs=1;
} 

float read_register16(char register_name)
{   
    register_name <<= 2;
    register_name &= 0xFC; //Read command
    cs=0; //Select SPI Device
    spi.write(register_name); //Write byte to device
    int in_byte1 = spi.write(0x00);    
    int in_byte2 = spi.write(0x00);
    cs=1;
    float in_word= (in_byte1<<=8) | (in_byte2);   
    return(in_word);
}


//-----------------4------------------------

int main() {
// configuracion---------------------------------
    cs=1;
	spi.frequency(500000); // the fastest of the sensor
	spi.format(8, 0); // duda son dos palabras de 8 bits? 
	wait(0.5);
//------------------------------------------------
pc.printf("RESET\r\n");
write_register(0x06,0x01);
wait(0.5);

pc.printf("Initialize High Resolution Constant Reading Mode\r\n");
write_register(0x03,0x0A);
wait(0.5);

while (1) {  
  pressure_msb = read_register(PRESSURE);
  pressure_msb &= 0x07;
  pressure_lsb = read_register16(PRESSURE_LSB);
  pressure = ((pressure_msb<<16)| pressure_lsb);
  pressure /= 4;
  temp_in = read_register16(TEMP);
  temp_in = temp_in / 20;
  pc.printf("TEMPERATURA: %.2f,PRESION:  %.2u\r",temp_in ,pressure);
  wait(1);
  
}

}