Sunteți pe pagina 1din 7

23/3/2018 SCP1000 pressure sensor notes - Helpful

SCP1000 pressure sensor notes


From Helpful
This article/section is a stub — probably a pile of half-sorted notes, is not well-checked
so may have incorrect bits. (Feel free to ignore, fix, or tell me)

Some specs

30kPa - 120kPa pressure range (≈ 0.3 atm to ~1.2 atm)


~1.5Pa resolution (according to datasheet; may vary a little depending on use. I got
jitter of a few dozen Pascal in all modes (but this may be my wiring - my first
breadboarded tests jittered a lot more and I never quite figured out why)
also exposes the temperature that it uses for correction (in 0.05°C steps)
wants 3.3V (supply and communication)
Two variants: one that speaks I2C (at max 400kHz) and one that speaks SPI (at max
500kHz). VTI (http://www.vti.fi/en/) uses D01 to mark the SPI one, and D11 to
mark the I2C one
power consumption quoted as:
0.2 µA in powerdown mode (while you hold its PD pin high)
~1µA in standby (e.g. while waiting to be triggered, and in non-sampling
mode)
~3.5µA for periodic measurements (~1/sec)
~25µA for continuous high-res or high-speed measurements
25µA down to nearly 1µA for triggered, depending on speed of triggering

Notes on operation

On timing:

Startup (after first powered, after powerdown, and after reset) takes up to 150ms:
60ms is basically a given wait time
...after which you can either wait for STATUS's STARTUP bit, or just wait
90ms

In SPI, wait for ≥100ns after you assert slave select (more than that may be prudent)

The modes of operation (write into OPERATION):

https://helpful.knobs-dials.com/index.php/SCP1000_pressure_sensor_notes 1/7
23/3/2018 SCP1000 pressure sensor notes - Helpful

(0x0A) continuous measurements, high resolution mode (17 bits, refreshing at


~1.8Hz, consuming ~25µA)
(0x09) continuous measurements, high speed (15 bits, refreshing at ~9Hz,
consuming ~25µA)
(0x0B) periodic measurements (15 bits, refreshing at ~1Hz, consuming ~3.5µA)
(0x03) triggered (lower power, stands by at ~1µA and active time depends on
trigger speed, e.g. ~25µA for ~2/sec and ~3µA for ~1/sec)
(0x00) non-sampling mode (~1µA; also useful as low(-ish) power state, also
necessary between mode switches)

I'm guessing the speed versus resolution is just how much it supersamples. Note that the
pressure value is always retrieved as a 19-bit int (always in the same scale), that the
15/17 bits seems to be an indication of whether the lowest-significance bits should be
considered noise.

While the SCP1000 is an SPI slave, DRDY (both a pin and an internal register bit) is
raised when the module has a new sample ready. You could use it to signal (or interrupt)
the SPI master to service the SPC1000. Since the DRDY state is in a register, you don't
need to use DRDY wire to trigger the master, but it does mean you'll service it faster and
don't need to poll the sensor a lot.

Fast-enough servicing matters because in the continuous sampling modes, the chip
expects you to consume the sample fairly quickly after it raises DRDY. After you read
DATARD16, DRDY will go low again. If you do not read the value in time (that time
depends mostly on refresh speed of the mode), STATUS[RTERR] (bit 4) will become 1,
and you have to read DATARD16 to clear this -- and that read may give nonsense data).

When you cannot guarantee that you'll read out the value fast enough (e.g. on
microcontrollers that can be unpredictably busy), look at triggered mode: it only requires
that you read the data before the next time you trigger(verify). To use triggering, set the
triggered mode, and then either pulse on the TRIG pin (pulse length at least 200ns) or
write 0x0C in the OPERATION register (0x03). The sensor needs some time doing the
actual sample before it raises DRDY (apparently at least 140ms in the 15-bit mode and at
least 500ms in the 17-bit mode). To select the resolution you set 0x05 in CFG for 17 bits
(the default), or 0x0D for 15 bits, before triggering.

The more interesting registers:

https://helpful.knobs-dials.com/index.php/SCP1000_pressure_sensor_notes 2/7
23/3/2018 SCP1000 pressure sensor notes - Helpful

(0x03) OPERATION
- set the mode here.
When switching
between modes you
should write 0x00 first
to disable sampling,
then set the mode you
want. Check for
readiness in the status
register - or just wait
for ~50ms(verify))
(0x1F in SPI, 0x7F in
TWI) DATARD8 - the SPC1000's registers (from the datasheet)
3 most significant bits
[2:0] of the 19-bit pressure value
(0x20 in SPI, 0x80 in TWI) DATARD16 - the 16 least significant bits of the 19-bit
pressure data. Note that reading this specific register has other effects
(0x21 in SPI, 0x81 in TWI) TEMPOUT - 14 bits of temperature data in [13:0]
(0x07) STATUS - ASIC status
Bit 0 (STARTUP): 0 if startup has finished, 1 if it's still working
Bit 4 (RTERR): data not read fast enough after DRDY; clear by reading
DATARD16
Bit 5 (DRDY): mirrors DRDY pin
(0x00) CFG, lets you set 17 bits (0x05) or 15 bits (0x0D) and only seems relevant
to triggered mode

There are more, some registers do double service when doing indirect data reads/writes,
and you can read/write the EEPROM, but if you need any of that you can can shoo and
read the PDF.

The pressure data is an integer in the range 120000 (for 30kPa) and 480000 (for 120kPa),
so divide by 4. If the raw figure is outside that range you should treat it as invalid. I've
seen values around four billion.

The temperature data is a signed (two's complement) int, and you divide by 20 for
degrees Celsius (so has ~.05 degrees resolution).

If you take the PD pin high, the sensor will stay powered down (consuming ~0.2 μA),
and the output pins will tristate. If you take PD low to start it up, wait a bit for startup.

https://helpful.knobs-dials.com/index.php/SCP1000_pressure_sensor_notes 3/7
23/3/2018 SCP1000 pressure sensor notes - Helpful

See also:

http://www.parallax.com/Portals/0/Downloads/docs/prod/sens/SCP1000-
FamilySpec.pdf

On an Arduino

These are primarily notes


It won't be complete in any sense.
It exists to contain fragments of useful information.

Most arduinos are 5V and the SCP1000 wants all its pins to be 3.3V (including the SPI
ones), so unless you have one of the few Arduinos that works on 3.3V you'll want to
drop the voltage from 5V to ~3.3V. (It'll work on 5V, but it's probably not very good for
the sensor in the long run).

The easiest way, which cheats a little, is probably to add some inline resistors the lines
(except MISO, as that's powered from the SCP1000), mostly to make the job easier for
the SCP's internal clamping diodes - they can only handle so much current, and you're
limiting how much they'll see.

For this and some other solutions, see [1]


(http://www.sparkfun.com/commerce/tutorial_info.php?tutorials_id=65).

You may also want to pull up slave select, though this may not be strictly
necessary(verify).

Example code, using an interrupt setup (which means you free your loop() from having
to poll (but make sure there's no noise on the interrupt line)):

/*
* Reads VTI's SCP1000-D01 (SPI) 30-120kPa pressure sensor
*
* Based on some code on the arduino.cc forums by a certain Conor,
* generalized somewhat and adapted to follow the datasheet more,
* although I'm not sure whether this needs more delays,
* as e.g. in the VTI code sample.
*
* This version uses the sensor's DRDY pin to interrupt the Arduino
* (via arduino digital pin 2), which means we don't have to poll
* from the arduino side, and we service the sensor more immediately
* after it's done.
*
* Without that interrupt you would probably poll for the STATUS's DRDY bit:
* if (scp_read_register8(SCP1000_REG_STATUS, SPI_SLAVESELECT)&B00100000)
* service_scp1000();
* I suggest only doing this with triggered mode, to avoid the whole RTERR issue.
*

https://helpful.knobs-dials.com/index.php/SCP1000_pressure_sensor_notes 4/7
23/3/2018 SCP1000 pressure sensor notes - Helpful
* You can simplify this code a little (it was stripped from a two-SCP1000 test)
*/

// MOSI, MISO and SCLK are fixed if you use the AVR's hardware SPI
// but you still need to declare them as input/output pins in setup()
#define SPI_SLAVESELECT 10
#define SPI_MOSI 11
#define SPI_MISO 12
#define SPI_CLOCK 13

//The SCP1000 register addresses that we use


#define SCP1000_REG_RSTR 0x06 //reset
#define SCP1000_REG_OPERATION 0x03 //Mode of operation
#define SCP1000_REG_STATUS 0x07 //ASIC Status
#define SCP1000_REG_DATARD8 0x1F //most significant 3 bits of 19-bit pressure
#define SCP1000_REG_DATARD16 0x20 //least significant 16 bits of 19-bit pressure
#define SCP1000_REG_TEMPOUT 0x21 //14 bit temperature
#define SCP1000_REG_OPSTATUS 0x04 //Operation Status

#define SCP1000_OPERATION_HIGHRES 0x0A // 17 bits, refreshing at ~1.8Hz, consuming ~25uA


#define SCP1000_OPERATION_HIGHSPEED 0x09 // 15 bits, refreshing at ~9Hz, consuming ~25uA
#define SCP1000_OPERATION_LOWPOWER 0x0B // 15 bits, refreshing at ~1Hz, consuming ~3.5uA
#define SCP1000_OPERATION_TRIGGERED 0x0C // 15 bits (~140ms) or 17bits (~500ms) depending on CFG register,
// stands by at ~1μA and uses 1-25uA depending on trigger speed

//Volatile because they are updated from the interrupt function


volatile boolean new_sample;
volatile byte temp_status;
volatile int temperature_raw;
volatile signed int signed_temperature;
volatile unsigned long pressure_raw;

unsigned long last_triggered;

void setup() {
Serial.begin(9600); // For monitoring

// SPI init
byte clr; //dummy variable
pinMode(SPI_MOSI, OUTPUT);
pinMode(SPI_MISO, INPUT );
pinMode(SPI_CLOCK, OUTPUT);
pinMode(SPI_SLAVESELECT, OUTPUT);
digitalWrite(SPI_SLAVESELECT, HIGH); // HIGH: do not select
digitalWrite(SPI_CLOCK, HIGH);
SPCR = B01010011; // MPIE=0 (no interrupt enable)
// SPE=1 (enable SPI)
// DORD=0 (MSB first)
// MSTR=1 (AVR is master)
// CPOL=0 (clock idle when low)
// CPHA=0 (samples on rising edge)
// SPR1=1 & SPR0=1 (250kHz)
clr=SPSR; // clear status register (by just reading it)
clr=SPDR; // clear data register (by just reading it)

//SCP1000 Init: Reset, wait for startup (takes ~60ms because we explicitly wait that long), set sampling mode
scp_write_register(SCP1000_REG_RSTR, 0x01, SPI_SLAVESELECT);
delay(60);
while (scp_read_register8(SCP1000_REG_STATUS, SPI_SLAVESELECT)&B00000001) delay(10);
//presumably the 50ms wait after setting 0x00 mode doesn't apply when we have just reset
//scp_write_register(SCP1000_REG_OPERATION, SCP1000_OPERATION_HIGHRES, SPI_SLAVESELECT);
//scp_write_register(SCP1000_REG_OPERATION, SCP1000_OPERATION_HIGHSPEED, SPI_SLAVESELECT);
//This examples uses (SPI-based) triggering, so the previous two lines (continuous modes) are commented out

//Use a rising edge on Arduino pin 2 (connected to the SCP1000's DRDY pin)
// to service the sensor via an interrupt.
pinMode(2,INPUT);
attachInterrupt(0, service_scp1000, RISING); // interrupt 0: arduino digital pin 2

new_sample=false;
}

void loop() {

//when you want an occasional, triggered sample:


// (if you set a continuous mode in setup, you don't want this part)

https://helpful.knobs-dials.com/index.php/SCP1000_pressure_sensor_notes 5/7
23/3/2018 SCP1000 pressure sensor notes - Helpful
if (abs(millis()-last_triggered)>5000) { // For example every five seconds
scp_write_register(SCP1000_REG_OPERATION, SCP1000_OPERATION_TRIGGERED, SPI_SLAVESELECT);
last_triggered=millis();
} else {
// Twiddle our thumbs visibly.
delay(10);
Serial.write('.');
}

// When the interrupt function marks that a new sample is available, print it.
if (new_sample) {
new_sample=false;
Serial.print("\nTemperature: ");
Serial.print(signed_temperature/20.);
Serial.print(" degrees Celsius (raw: ");
Serial.print(temperature_raw);
Serial.print(")\nPressure: ");
Serial.print(pressure_raw/400.);
Serial.print(" millibar (raw: ");
Serial.print(pressure_raw);
Serial.print(")\n\n");
}
}

void service_scp1000() { // Reads the sensor, sets mostly-raw values in global volatile variables
// Theoretically we won't miss a DRDY when it interrupts the uC, but it can't hurt to check
temp_status = scp_read_register8(SCP1000_REG_STATUS, SPI_SLAVESELECT);
if (temp_status&B00010000) {
//if either RTERR was set, clear it by reading data and skip real output
scp_read_register16(SCP1000_REG_DATARD16, SPI_SLAVESELECT);
////check that that worked:
//tstat2 = scp_read_register8(SCP1000_REG_STATUS, SPI_SLAVESELECT1);
//if (tstat2&B00010000) Serial.print("RTERR cleared ");
//else Serial.print("RTERR still there - huh? ");
//Serial.print("\n");
// We give up on this sample and wait for the next.

} else { // No error, go ahead and read.


temperature_raw = scp_read_register16(SCP1000_REG_TEMPOUT, SPI_SLAVESELECT);
// This should deal with negative temperatures -- and some of this is probably redundant
if (temperature_raw&0x2000) signed_temperature=temperature_raw|0xC000;
else signed_temperature=temperature_raw&0x1FFF; //mask probably unnecessary

pressure_raw = ((unsigned long)scp_read_register8(SCP1000_REG_DATARD8, SPI_SLAVESELECT))<<16;


pressure_raw = pressure_raw|scp_read_register16(SCP1000_REG_DATARD16, SPI_SLAVESELECT);
//Note that if this raw figure is outside the range 120000-480000,
// you should consider it invalid (and it may be wildly so)

new_sample=true;
}

/********************** SPI helper functions ***************/


char spi_transfer(volatile char data=0x00) { //0x00 is dummy data in case you want to receive
SPDR = data; // triggers send
while (!(SPSR & (1<<SPIF))) {}; // wait for transmission end
return SPDR; // return the received byte
}

/* Asks for pin because this was written to test two SPC1000s on the same bus
*
* The SCP wants its addresses shifted <<2
* with the new bit 0 always 0,
* and bit 1 controls read(0)/write(1)
*/
char scp_read_register8(char register_address, byte select_pin) {
char in_byte;
register_address = register_address<<2;
digitalWrite(select_pin,LOW); //Select SPI Device
spi_transfer(register_address); //Write byte to device
in_byte = spi_transfer();
digitalWrite(select_pin,HIGH);
return in_byte;
}

https://helpful.knobs-dials.com/index.php/SCP1000_pressure_sensor_notes 6/7
23/3/2018 SCP1000 pressure sensor notes - Helpful

unsigned int scp_read_register16(char register_address, byte select_pin) {


byte in_byte1,in_byte2;
unsigned int in_word;
register_address = register_address<<2;
digitalWrite(select_pin,LOW); //Select SPI Device
spi_transfer(register_address);
in_byte1 = spi_transfer();
in_byte2 = spi_transfer();
digitalWrite(select_pin,HIGH);
in_word = (in_byte1<<8)|in_byte2;
return in_word;
}

void scp_write_register(char register_address, char register_value, byte select_pin) {


register_address = (register_address<<2)|B00000010;
digitalWrite(select_pin,LOW); //Select SPI device
spi_transfer(register_address); //Send register location
spi_transfer(register_value); //Send value to record into register
digitalWrite(select_pin,HIGH);
}

Note that for continuous sampling and two sensors, waiting for one DRDY and then the
other will mean your reads will be out of sync and you'll eventually not service a DRDY
fast enough. You can choose to miss one sample and rely on checking RTERR and
clearing with a read, but there are various cleverer setups.

Retrieved from "https://helpful.knobs-dials.com/index.php?


title=SCP1000_pressure_sensor_notes&oldid=42617"
Category: Electronics

This page was last modified on 19 August 2013, at 13:46.


Content is available under GNU Free Documentation License 1.2 unless otherwise
noted.

https://helpful.knobs-dials.com/index.php/SCP1000_pressure_sensor_notes 7/7

S-ar putea să vă placă și