// // 4. Februar 2009 // // Pressure SCP1000 // by Etienne Ribeiro // // Protocol: SPI // voltage: typ 2.7V, max 3.3V // // this Module makes it easy to run SCP1000 Pressure Sensor in your Projects. // 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 // - negativ Temperature // - Interrupt // - Reset // // Pins: you can use any digital pin // [DRDY = 24; (optional)] // CSB = 25; // DATAIN (MISO) = 26; // DATAOUT (MOSI) = 27; // SCK = 28; // // 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) { // switch(which) { case 'P':case 'p': // 3bit + 16bit pressure long val; 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 return scp1000_SPI_read16(Reg_TEMPOUT); 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 *ret1, int *ret2) { *ret1 = 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_getHightCM // Based on barometric formula long scp1000_getHightCM (long pa) { double fpratio; double fcm; fpratio = double(pa)/101325.0f; fcm = 4433076.9*(1.0 - pow(double(fpratio),0.190275)); return fcm > 0.0f ? long(fcm+0.5f) : long(fcm-0.5f); } /* long scp1000_getHightCM_v2 (long pa) { long pi = 1; long pr = pa; long altitude_cm = 4433000 - c_m * pow(pr, c_exp); return altitude_cm ; } */ // // 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; }