Pressure Sensor SCP1000

This Module can be used to plug a Pressure Sensor SCP1000 into your project. Connect your sensors to any digital pin on your board.
Download the source file
Table of contents
(top)
Source - modPressureSCP1000
/**************************************************************************************************
*
* Pressure SCP1000
*
* Version: 1.0.0 - Februar 2009
* Author: Christoph Wartmann / chair for caad - ETH Zürich / wartmann[at].arch.ethz.ch
* Etienne Ribeiro / tutorial assistant caad / eribeiro[at]ethz.ch
*
* Desc: This Module makes it easy to run the SCP1000 Pressure Sensor in your projects.
*
* Protocol: SPI
*
* Voltage: typical 2.7V, max 3.3V
*
* Features implemented:
* - SPI Protocol
* - all supported Operationmodes
*
* Not yet implemented:
* - I2C (supported on Sparkfun Breakout; Software addresses!)
* - self test
* - [Operationmode 4 = Triggered Mode (Not supported on Sparkfun Breakout)]
* - Standby Mode
* - Interrupt
* - Reset
*
* Pins: use any digital pin. example:
* DRDY = 24; (optional)
* CSB = 25;
* DATAIN (MISO) = 26;
* DATAOUT (MOSI) = 27;
* SCK = 28;
*
* Methodes: boolean scp1000_AppendSensor (byte drdy, byte csb, byte datain, byte dataout, byte sckclock, byte Operationmode)
* drdy, csb, datain, dataout, sckclock: digital Pins, drdy is not needed and can be set to -1
* Operationmode: 0 = High speed (15bit, 9Hz), 1 = High resolution (17bit, 1.8Hz), 2 = Ultra low power (15bit, 1Hz)
* return false, if sensor coud not be initialized.
* void scp1000_setOperationMode(int modeid)
* change operation mode
* modeid: 0 = High speed (15bit, 9Hz), 1 = High resolution (17bit, 1.8Hz), 2 = Ultra low power (15bit, 1Hz)
* long scp1000_Read(char which)
* 'p' = get pressure
* 't' = get temperature
* 's'= get status
* 'o' = get operation mode
* 'n' = get operation status
* void scp1000_parseDegrees (int val, int *retSign, int *ret1, int *ret2)
* Parse value to degrees. val = scp1000_Read('t') and scp1000_parseDegrees (val,...)
* *retSign: Return Value (sign) -1 or 1. Access this value by &var
* *ret1: Return Value (upper). Access this value by &var
* *ret2: Return Value (lower). Access this value by &var
* long scp1000_parsePa (long val)
* Parse value to Pascal. val = scp1000_Read('p') and scp1000_parsePa (val)
* void scp1000_parsePa (long val, long *ret1, long *ret2)
* Parse value to Pascal. val = scp1000_Read('p') and scp1000_parsePa (val,...)
* *ret1: Return Value (upper). Access this value by &var
* *ret2: Return Value (lower). Access this value by &var
* boolean scp1000_printStatus (byte state)
* Print current state of sensor. state = scp1000_Read('s') and scp1000_printStatus (state)
* boolean scp1000_printOperation (byte operation)
* Print operation mode. operationmode = scp1000_Read('o') and scp1000_printOperation (operationmode)
*
***************************************************************************************************/
//
// Const
// direct access:
#define Reg_REVID 0x00
#define Reg_DATAWR 0x01
#define Reg_ADDPTR 0x02
#define Reg_OPERATION 0x03
byte const Reg_OPERATION_modes[] = {0x09, 0x0A, 0x0B, 0x0C}; // (0x0C or TRIG pin)
#define Reg_OPSTATUS 0x04
#define Reg_RSTR 0x06
#define Reg_STATUS 0x07
byte const Reg_STATUS_startupbit = 0;
#define Reg_DATARD8 0x1F
byte const Reg_DATARD8_checksumerror = 0x00;
#define Reg_DATARD16 0x20 // 16bit
#define Reg_TEMPOUT 0x21 // 16bit
// indirect access:
#define Reg_CFG 0x00
#define Reg_TWIADD 0x05
#define Reg_USERDATA1 0x29
#define Reg_USERDATA2 0x2A
#define Reg_USERDATA3 0x2B
#define Reg_USERDATA4 0x2C
// more consts
int temp_factor = 20;
int pressure_factor = 4;
//
// Var
int scp1000_DRDY; // 24 1: availability of new measurement
int scp1000_CSB; // 25 selects the chip on multi-chip SPI bus
int scp1000_DATAIN; // 26 MISO (Master In Slave Out)
int scp1000_DATAOUT; // 27 MOSI (Master Out Slave In)
int scp1000_SCKCLOCK; // 28 Clock
// *************************
//
// Functions
//
//
// scp1000_AppendSensor
// -> Operationmode: 0: High speed (15bit, 9Hz), 1: High resolution (17bit, 1.8Hz), 2: Ultra low power (15bit, 1Hz), [3 Low poser but triggerd (15bit to 17bit, 1.8Hz) not supported on Sparkfun Breakout]
boolean scp1000_AppendSensor (byte drdy, byte csb, byte datain, byte dataout, byte sckclock, byte Operationmode) {
// Variables
scp1000_DRDY = drdy;
scp1000_CSB = csb;
scp1000_DATAIN = datain;
scp1000_DATAOUT = dataout;
scp1000_SCKCLOCK = sckclock;
// Pins
pinMode(scp1000_DRDY, INPUT);
pinMode(scp1000_CSB, OUTPUT);
pinMode(scp1000_DATAOUT, OUTPUT);
pinMode(scp1000_DATAIN, INPUT);
pinMode(scp1000_SCKCLOCK, OUTPUT);
digitalWrite(scp1000_CSB, HIGH); //disable device
digitalWrite(scp1000_DATAOUT, LOW);
digitalWrite(scp1000_SCKCLOCK, LOW);
// startup device
boolean success1 = scp1000_startup();
boolean success2 = scp1000_checksumTest();
if (success1 == false || success2==false)
return false;
// Select operation mode
if (Operationmode < 0 || Operationmode > 3) Operationmode = 0;
scp1000_setOperationMode (Operationmode); // Values 0 to 3
// Return
return true;
}
//
// Startup SCP1000
boolean scp1000_startup() {
delay (60); // 60 ms startup delay
for (int i=0;i<6;i++) { // check if startup has finished
int val = scp1000_SPI_read8(Reg_STATUS);
if (int(1<<Reg_STATUS_startupbit & val) == 0) // Startup successfully
return true;
delay (10);
}
return false; // start-up has failed
}
//
// Test Checksum
boolean scp1000_checksumTest() {
int checksum = scp1000_SPI_read8(Reg_DATARD8);
if (Reg_DATARD8_checksumerror == checksum) {// todo
return false;
}
return true;
}
//
// Set operation mode
void scp1000_setOperationMode(int modeid) {
// Stop active Mode (if SCP1000 is already powerd up and running)
scp1000_SPI_write(Reg_OPERATION, 0x00);
delay (50);
// Check if DRDY is LOW (If DRDY is HIGH it is necessary to read the output data before activating new measurement mode)
if (scp1000_DRDY != -1) {
if (digitalRead(scp1000_DRDY) == HIGH)
scp1000_SPI_read16(Reg_DATARD16);
}
// Select an operation mode
byte cmd = Reg_OPERATION_modes[modeid]; // Command to write to register (0C)
scp1000_SPI_write(Reg_OPERATION, cmd);
}
//
// scp1000_Read
// 'p' -> 16bit pressure, 't' -> 16bit temperature, 's' -> status, 'o' -> operation mode, 'n' -> operation status
long scp1000_Read(char which) {
//
long val;
switch(which) {
case 'P':case 'p': // 3bit + 16bit pressure
val = scp1000_SPI_read8(Reg_DATARD8);
val <<= 16;
unsigned int tmpval;
tmpval = scp1000_SPI_read16(Reg_DATARD16);
val += tmpval;
return val;
case 'T':case 't': // 16bit temperature
val = scp1000_SPI_read16(Reg_TEMPOUT);
// if negativ value:
if (int(1<<13 & val) != 0) { // bit 13 == 1
val ^= 16383; // Invert 14 bits (16 bits would be 65535)
val += 1; // plus 1
val *= -1;
}
return val;
break;
case 'S':case 's': // status
return scp1000_SPI_read8(Reg_STATUS);
break;
case 'O':case 'o': // operation mode
return scp1000_SPI_read8(Reg_OPERATION);
break;
case 'N':case 'n': // operation status
return scp1000_SPI_read8(Reg_OPSTATUS);
break;
}
}
//
// scp1000_parseDegrees
// Parse Value to Degres
void scp1000_parseDegrees (int val, int *retSign, int *ret1, int *ret2) {
*retSign = 1;
if (val < 0)
*retSign = -1;
*ret1 = abs(val / temp_factor);
*ret2 = abs(val % temp_factor * 100 / temp_factor);
}
//
// scp1000_parseDegrees
// Parse Value to Pascal
long scp1000_parsePa (long val) {
long ret1;
long ret2;
scp1000_parsePa (val, &ret1, &ret2);
return ret1;
}
void scp1000_parsePa (long val, long *ret1, long *ret2) {
*ret1 = val / pressure_factor;
*ret2 = abs(val % pressure_factor * 100 / pressure_factor);
}
//
// scp1000_printStatus
// Print status in natural language
boolean scp1000_printStatus (byte state) {
Serial.print("Status: ");
Serial.print(state, BIN);
Serial.print(": ");
if (int(1<<6 & state) != 0) // byte 0100 0000
Serial.print (" Acquisition is running."); // externally triggered
if (int(1<<5 & state) != 0) // byte 0010 0000
Serial.print (" New results are available.");
if (int(1<<4 & state) != 0) // byte 0001 0000
Serial.print (" Real time error!"); // interrupt has not been serviced in time, cleared by DATARD16 read operation
if (int(1<<0 & state) != 0) // byte 0000 0001
Serial.print (" Start-up procedure still running");
}
//
// scp1000_printOperation
// Print operation-register value in natural language
boolean scp1000_printOperation (byte operation) {
Serial.print("Operation: 0x");
Serial.print(operation, HEX);
Serial.print(": ");
switch (operation) {
case 0x00:
Serial.print (" NO OPERATION! Select an operation mode!");
break;
case 0x09:
Serial.print (" High speed acquisition mode (continuous measurement).");
break;
case 0x0A:
Serial.print (" High resolution acquisition mode (continuous measurement).");
break;
case 0x0B:
Serial.print (" ultra low power acquisition mode (continuous measurement).");
break;
case 0x0C:
Serial.print (" low power acquisition mode. (external TRIG, NOT SUPPORTED ON SPARKFUN BREAKOUT!)");
break;
default:
Serial.print (" see Datasheet on page 18 Table 11");
break;
}
}
// ***************************
//
// SPI - Functions
//
//
// SPI_write
void scp1000_SPI_write (byte registerByte, byte commandByte) {
digitalWrite(scp1000_CSB, LOW); //turn on device
// 6 bits register address
for (int i=5; i>=0; i--){
// write bit
if (int(1<<i & registerByte) == 0) digitalWrite(scp1000_DATAOUT, LOW); else digitalWrite(scp1000_DATAOUT, HIGH);
// cycle clock
digitalWrite(scp1000_SCKCLOCK, HIGH);
digitalWrite(scp1000_SCKCLOCK, LOW);
}
digitalWrite(scp1000_DATAOUT, HIGH); // Indicate that we are Writing
digitalWrite(scp1000_SCKCLOCK, HIGH);
digitalWrite(scp1000_SCKCLOCK, LOW);
digitalWrite(scp1000_DATAOUT, LOW); // LOW
digitalWrite(scp1000_SCKCLOCK, HIGH);
digitalWrite(scp1000_SCKCLOCK, LOW);
// write 8 bits register content
for (int i=7; i>=0; i--){
// write bit
if (int(1<<i & commandByte) == 0) digitalWrite(scp1000_DATAOUT, LOW); else digitalWrite(scp1000_DATAOUT, HIGH);
// cycle clock
digitalWrite(scp1000_SCKCLOCK, HIGH);
digitalWrite(scp1000_SCKCLOCK, LOW);
}
digitalWrite(scp1000_CSB, HIGH); //turn off device
}
//
// SPI_read8
int scp1000_SPI_read8 (byte registerByte) {
digitalWrite(scp1000_CSB, LOW); //turn on device
// 6 bits register address
for (int i=5; i>=0; i--){
// write bit
if (int(1<<i & registerByte) == 0) digitalWrite(scp1000_DATAOUT, LOW); else digitalWrite(scp1000_DATAOUT, HIGH);
// cycle clock
digitalWrite(scp1000_SCKCLOCK, HIGH);
digitalWrite(scp1000_SCKCLOCK, LOW);
}
digitalWrite(scp1000_DATAOUT, LOW); // Indicate that we are Reading
digitalWrite(scp1000_SCKCLOCK, HIGH);
digitalWrite(scp1000_SCKCLOCK, LOW);
digitalWrite(scp1000_SCKCLOCK, HIGH);
digitalWrite(scp1000_SCKCLOCK, LOW);
// read 8 bits register content
int returnValue = 0;
for (int i=7; i>=0; i--){
// read bit
returnValue += digitalRead (scp1000_DATAIN) << i;
// cycle clock
digitalWrite(scp1000_SCKCLOCK, HIGH);
digitalWrite(scp1000_SCKCLOCK, LOW);
}
digitalWrite(scp1000_CSB, HIGH); //turn off device
return returnValue;
}
//
// SPI_read16
int scp1000_SPI_read16 (byte registerByte) {
digitalWrite(scp1000_CSB, LOW); //turn on device
// 6 bits register address
for (int i=5; i>=0; i--){
// write bit
if (int(1<<i & registerByte) == 0) digitalWrite(scp1000_DATAOUT, LOW); else digitalWrite(scp1000_DATAOUT, HIGH);
// cycle clock
digitalWrite(scp1000_SCKCLOCK, HIGH);
digitalWrite(scp1000_SCKCLOCK, LOW);
}
digitalWrite(scp1000_DATAOUT, LOW); // Indicate that we are Reading
digitalWrite(scp1000_SCKCLOCK, HIGH);
digitalWrite(scp1000_SCKCLOCK, LOW);
digitalWrite(scp1000_SCKCLOCK, HIGH);
digitalWrite(scp1000_SCKCLOCK, LOW);
// read 8 bits register content
int returnValue = 0;
for (int i=15; i>=0; i--){
// read bit
returnValue += digitalRead (scp1000_DATAIN) << i;
// cycle clock
digitalWrite(scp1000_SCKCLOCK, HIGH);
digitalWrite(scp1000_SCKCLOCK, LOW);
}
digitalWrite(scp1000_CSB, HIGH); //turn off device
return returnValue;
}
(top)
Source - Main
/**************************************************************************************************
*
* Pressure SCP1000
*
* Version: 1.0.0 - Februar 2009
* Author: Christoph Wartmann / chair for caad - ETH Zürich / wartmann[at].arch.ethz.ch
* Etienne Ribeiro / tutorial assistant caad / eribeiro[at]ethz.ch
*
* Desc: Shows the use of a SCP1000 Pressure Sensor using SPI.
*
***************************************************************************************************/
//
// Const
byte const DRDY = -1; // 24; // 1: availability of new measurement
byte const CSB = 10; // 25; // selects the chip on multi-chip SPI bus
byte const DATAIN = 11; // 26; // MISO (Master In Slave Out)
byte const DATAOUT = 12; // 27; // MOSI (Master Out Slave In)
byte const SCKCLOCK = 13; // 28; // Clock
int onboardLED = 48; // Wiring-Board: Pin 48, Arduino: Pin 13
//
// Var
boolean startupDone;
//
// Setup
void setup(){
// LED (2 * blink)
pinMode(onboardLED, OUTPUT);
digitalWrite(onboardLED, HIGH);
delay(200);
digitalWrite(onboardLED, LOW);
delay(200);
digitalWrite(onboardLED, HIGH);
// Start Serial
Serial.begin(9600);
// Append Pressure Sensor
// -> Operationmode: 0: High speed (15bit, 9Hz), 1: High resolution (17bit, 1.8Hz), 2: Ultra low power (15bit, 1Hz), [3 Low poser but triggerd (15bit to 17bit, 1.8Hz) not supported on Sparkfun Breakout]
byte operationmode = 1;
startupDone = true;
if (scp1000_AppendSensor (DRDY, CSB, DATAIN, DATAOUT, SCKCLOCK, operationmode) == false) {
Serial.println ("Failed to startup Pressure Sensor");
scp1000_printStatus(scp1000_Read('s'));
startupDone = false;
}
// Operation Mode
scp1000_printOperation(scp1000_Read('o'));
Serial.println ("");
// Operation Status
Serial.print ("Operation Status: 0x");
Serial.print (scp1000_Read('n'), HEX);
Serial.println ("");
}
//
// Loop
void loop() {
if (startupDone) {
// Temperature
int sign;
int temp1;
int temp2;
scp1000_parseDegrees(scp1000_Read('t'), &sign, &temp1, &temp2);
Serial.print ("TEMPERATURE: ");
if (sign == -1)
Serial.print ("-");
Serial.print (temp1, DEC);
Serial.print (".");
Serial.print (temp2, DEC);
Serial.print (" Grad C ");
// Pressure
long pressure = scp1000_parsePa(scp1000_Read('p'));
Serial.print ("PRESSURE: ");
Serial.print (pressure);
Serial.print (" Pa ");
// Hight
long heightCm = scp1000_getHeightCM (pressure);
Serial.print ("Height: ");
Serial.print (heightCm);
Serial.print (" cm");
Serial.println ("");
// Status
scp1000_printStatus(scp1000_Read('s'));
Serial.println ("");
}
// Take a break
delay(100);
}