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