Library for the use of the atmospheric pressure sensor SCP1000

Committer:
s_inoue_mbed
Date:
Thu Sep 18 13:09:39 2014 +0000
Revision:
1:1b2027cbe629
Parent:
0:a224293d7af4
Bug fix: below-zero temperature is sufficiently treated.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
s_inoue_mbed 0:a224293d7af4 1 /* Copyright (c) 2014 Shigenori Inoue, MIT License
s_inoue_mbed 0:a224293d7af4 2 *
s_inoue_mbed 1:1b2027cbe629 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
s_inoue_mbed 1:1b2027cbe629 4 * and associated documentation files (the "Software"), to deal in the Software without restriction,
s_inoue_mbed 1:1b2027cbe629 5 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
s_inoue_mbed 1:1b2027cbe629 6 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
s_inoue_mbed 0:a224293d7af4 7 * furnished to do so, subject to the following conditions:
s_inoue_mbed 0:a224293d7af4 8 *
s_inoue_mbed 1:1b2027cbe629 9 * The above copyright notice and this permission notice shall be included in all copies or
s_inoue_mbed 0:a224293d7af4 10 * substantial portions of the Software.
s_inoue_mbed 0:a224293d7af4 11 *
s_inoue_mbed 1:1b2027cbe629 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
s_inoue_mbed 1:1b2027cbe629 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
s_inoue_mbed 1:1b2027cbe629 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
s_inoue_mbed 1:1b2027cbe629 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
s_inoue_mbed 0:a224293d7af4 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
s_inoue_mbed 0:a224293d7af4 17 */
s_inoue_mbed 0:a224293d7af4 18
s_inoue_mbed 0:a224293d7af4 19 #include "SCP1000.h"
s_inoue_mbed 0:a224293d7af4 20
s_inoue_mbed 0:a224293d7af4 21 /* Constructor */
s_inoue_mbed 0:a224293d7af4 22 SCP1000::SCP1000(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName trig, PinName drdy) :
s_inoue_mbed 0:a224293d7af4 23 _s(mosi, miso, sclk), _cs(cs), _trig(trig), _drdy(drdy)
s_inoue_mbed 0:a224293d7af4 24 {
s_inoue_mbed 0:a224293d7af4 25 init();
s_inoue_mbed 0:a224293d7af4 26 }
s_inoue_mbed 0:a224293d7af4 27
s_inoue_mbed 0:a224293d7af4 28 /* Destructor */
s_inoue_mbed 0:a224293d7af4 29 SCP1000::~SCP1000() {}
s_inoue_mbed 0:a224293d7af4 30
s_inoue_mbed 0:a224293d7af4 31 /* Write an 8-bit data to an address in the SCP1000 via SPI */
s_inoue_mbed 0:a224293d7af4 32 void SCP1000::write(int addr, int data)
s_inoue_mbed 0:a224293d7af4 33 {
s_inoue_mbed 0:a224293d7af4 34 uint8_t f_addr;
s_inoue_mbed 0:a224293d7af4 35 uint8_t f_data;
s_inoue_mbed 0:a224293d7af4 36
s_inoue_mbed 0:a224293d7af4 37 /* Creating the address frame, adding the WRITE bit */
s_inoue_mbed 0:a224293d7af4 38 f_addr = ( static_cast<uint8_t>(addr << 2) | 0x02);
s_inoue_mbed 0:a224293d7af4 39
s_inoue_mbed 0:a224293d7af4 40 /* Creating the data frame */
s_inoue_mbed 0:a224293d7af4 41 f_data = static_cast<uint8_t>(data);
s_inoue_mbed 0:a224293d7af4 42
s_inoue_mbed 0:a224293d7af4 43 _cs = 0;
s_inoue_mbed 0:a224293d7af4 44 _s.write(f_addr);
s_inoue_mbed 0:a224293d7af4 45 _s.write(f_data);
s_inoue_mbed 0:a224293d7af4 46 _cs = 1;
s_inoue_mbed 0:a224293d7af4 47 }
s_inoue_mbed 0:a224293d7af4 48
s_inoue_mbed 0:a224293d7af4 49 /* Read an 8-bit data from an address in the SCP1000 via SPI */
s_inoue_mbed 0:a224293d7af4 50 int SCP1000::read8(int addr)
s_inoue_mbed 0:a224293d7af4 51 {
s_inoue_mbed 0:a224293d7af4 52 uint8_t f_addr;
s_inoue_mbed 0:a224293d7af4 53 uint8_t f_data;
s_inoue_mbed 0:a224293d7af4 54
s_inoue_mbed 0:a224293d7af4 55 /* Creating the address frame, adding the WRITE bit */
s_inoue_mbed 0:a224293d7af4 56 f_addr = static_cast<uint8_t>(addr << 2);
s_inoue_mbed 0:a224293d7af4 57
s_inoue_mbed 0:a224293d7af4 58 _cs = 0;
s_inoue_mbed 0:a224293d7af4 59 _s.write(f_addr);
s_inoue_mbed 0:a224293d7af4 60 f_data = _s.write(0x00);
s_inoue_mbed 0:a224293d7af4 61 _cs = 1;
s_inoue_mbed 0:a224293d7af4 62
s_inoue_mbed 0:a224293d7af4 63 return static_cast<int>(f_data);
s_inoue_mbed 0:a224293d7af4 64 }
s_inoue_mbed 0:a224293d7af4 65
s_inoue_mbed 0:a224293d7af4 66 /* Read a 16-bit data from an address in the SCP1000 via SPI */
s_inoue_mbed 0:a224293d7af4 67 int SCP1000::read16(int addr)
s_inoue_mbed 0:a224293d7af4 68 {
s_inoue_mbed 0:a224293d7af4 69 uint8_t f_addr;
s_inoue_mbed 0:a224293d7af4 70 uint8_t f_data_h;
s_inoue_mbed 0:a224293d7af4 71 uint8_t f_data_l;
s_inoue_mbed 0:a224293d7af4 72
s_inoue_mbed 0:a224293d7af4 73 /* Creating the address frame, adding the WRITE bit */
s_inoue_mbed 0:a224293d7af4 74 f_addr = static_cast<uint8_t>(addr << 2);
s_inoue_mbed 0:a224293d7af4 75
s_inoue_mbed 0:a224293d7af4 76 _cs = 0;
s_inoue_mbed 0:a224293d7af4 77 _s.write(f_addr);
s_inoue_mbed 0:a224293d7af4 78 f_data_h = _s.write(0x00);
s_inoue_mbed 0:a224293d7af4 79 f_data_l = _s.write(0x00);
s_inoue_mbed 0:a224293d7af4 80 _cs = 1;
s_inoue_mbed 0:a224293d7af4 81
s_inoue_mbed 0:a224293d7af4 82 return (static_cast<int>(f_data_h) << 8) + static_cast<int>(f_data_l);
s_inoue_mbed 0:a224293d7af4 83 }
s_inoue_mbed 0:a224293d7af4 84
s_inoue_mbed 0:a224293d7af4 85 /* Initialize the SCP1000 */
s_inoue_mbed 0:a224293d7af4 86 int SCP1000::init(void)
s_inoue_mbed 0:a224293d7af4 87 {
s_inoue_mbed 0:a224293d7af4 88 int d_read;
s_inoue_mbed 0:a224293d7af4 89 int cnt = 0;
s_inoue_mbed 0:a224293d7af4 90 _cs = 1;
s_inoue_mbed 0:a224293d7af4 91 _trig = 0;
s_inoue_mbed 0:a224293d7af4 92
s_inoue_mbed 0:a224293d7af4 93 /* SPI setting */
s_inoue_mbed 0:a224293d7af4 94 _s.format(8, 0);
s_inoue_mbed 0:a224293d7af4 95 _s.frequency(1000000);
s_inoue_mbed 0:a224293d7af4 96
s_inoue_mbed 0:a224293d7af4 97 /* Software reset of SCP1000 */
s_inoue_mbed 0:a224293d7af4 98 write(RSTR, 0x01);
s_inoue_mbed 0:a224293d7af4 99
s_inoue_mbed 0:a224293d7af4 100 /* Waiting for 60 ms as in the datasheet */
s_inoue_mbed 0:a224293d7af4 101 wait_ms(60);
s_inoue_mbed 0:a224293d7af4 102
s_inoue_mbed 0:a224293d7af4 103 /* Reading STATUS registor until its LSB = 0 */
s_inoue_mbed 0:a224293d7af4 104 do {
s_inoue_mbed 0:a224293d7af4 105 d_read = read8(STATUS);
s_inoue_mbed 0:a224293d7af4 106 if ((d_read & 0x01) == 0) {
s_inoue_mbed 0:a224293d7af4 107 break;
s_inoue_mbed 0:a224293d7af4 108 } else {
s_inoue_mbed 0:a224293d7af4 109 cnt++;
s_inoue_mbed 0:a224293d7af4 110 wait_ms(10);
s_inoue_mbed 0:a224293d7af4 111 }
s_inoue_mbed 0:a224293d7af4 112
s_inoue_mbed 0:a224293d7af4 113 if (cnt > 100) {
s_inoue_mbed 0:a224293d7af4 114 return ERR;
s_inoue_mbed 0:a224293d7af4 115 }
s_inoue_mbed 0:a224293d7af4 116 } while (true);
s_inoue_mbed 0:a224293d7af4 117
s_inoue_mbed 0:a224293d7af4 118 /* Reading DATARD8 registor to check its LSB = 1 */
s_inoue_mbed 0:a224293d7af4 119 d_read = read8(DATARD8);
s_inoue_mbed 0:a224293d7af4 120 if ((d_read & 0x01) == 0) {
s_inoue_mbed 0:a224293d7af4 121 return ERR;
s_inoue_mbed 0:a224293d7af4 122 } else {
s_inoue_mbed 0:a224293d7af4 123 return OK;
s_inoue_mbed 0:a224293d7af4 124 }
s_inoue_mbed 0:a224293d7af4 125 }
s_inoue_mbed 0:a224293d7af4 126
s_inoue_mbed 0:a224293d7af4 127 /* Set the measurement mode of the SCP1000 */
s_inoue_mbed 0:a224293d7af4 128 void SCP1000::setMode(int mode)
s_inoue_mbed 0:a224293d7af4 129 {
s_inoue_mbed 0:a224293d7af4 130 write(OPERATIONS, 0x00);
s_inoue_mbed 0:a224293d7af4 131 wait_ms(50);
s_inoue_mbed 0:a224293d7af4 132 switch(mode) {
s_inoue_mbed 0:a224293d7af4 133 case HIGH_RESOLUTION:
s_inoue_mbed 0:a224293d7af4 134 write(OPERATIONS, 0x0A);
s_inoue_mbed 0:a224293d7af4 135 break;
s_inoue_mbed 0:a224293d7af4 136 case HIGH_SPEED:
s_inoue_mbed 0:a224293d7af4 137 write(OPERATIONS, 0x09);
s_inoue_mbed 0:a224293d7af4 138 break;
s_inoue_mbed 0:a224293d7af4 139 case ULTRA_LOW_POWER:
s_inoue_mbed 0:a224293d7af4 140 write(OPERATIONS, 0x0B);
s_inoue_mbed 0:a224293d7af4 141 break;
s_inoue_mbed 0:a224293d7af4 142 case LOW_POWER_17BIT:
s_inoue_mbed 0:a224293d7af4 143 write(ADDPTR, 0x00);
s_inoue_mbed 0:a224293d7af4 144 write(DATAWR, 0x05);
s_inoue_mbed 0:a224293d7af4 145 write(OPERATIONS, 0x02);
s_inoue_mbed 0:a224293d7af4 146 write(OPERATIONS, 0x0C);
s_inoue_mbed 0:a224293d7af4 147 break;
s_inoue_mbed 0:a224293d7af4 148 case LOW_POWER_15BIT:
s_inoue_mbed 0:a224293d7af4 149 write(ADDPTR, 0x00);
s_inoue_mbed 0:a224293d7af4 150 write(DATAWR, 0x0D);
s_inoue_mbed 0:a224293d7af4 151 write(OPERATIONS, 0x02);
s_inoue_mbed 0:a224293d7af4 152 write(OPERATIONS, 0x0C);
s_inoue_mbed 0:a224293d7af4 153 break;
s_inoue_mbed 0:a224293d7af4 154 default: /* High resolution mode by default */
s_inoue_mbed 0:a224293d7af4 155 write(OPERATIONS, 0x0A);
s_inoue_mbed 0:a224293d7af4 156 break;
s_inoue_mbed 0:a224293d7af4 157 }
s_inoue_mbed 0:a224293d7af4 158 }
s_inoue_mbed 0:a224293d7af4 159
s_inoue_mbed 0:a224293d7af4 160 /* Trigger the measurement by TRIG wire in Low Power Mode */
s_inoue_mbed 0:a224293d7af4 161 void SCP1000::triggerHard(void)
s_inoue_mbed 0:a224293d7af4 162 {
s_inoue_mbed 0:a224293d7af4 163 _trig = 1;
s_inoue_mbed 0:a224293d7af4 164 wait_us(1);
s_inoue_mbed 0:a224293d7af4 165 _trig = 0;
s_inoue_mbed 0:a224293d7af4 166 }
s_inoue_mbed 0:a224293d7af4 167
s_inoue_mbed 0:a224293d7af4 168 /* Trigger the measurement by register writing in Low Power Mode */
s_inoue_mbed 0:a224293d7af4 169 void SCP1000::triggerSoft(void)
s_inoue_mbed 0:a224293d7af4 170 {
s_inoue_mbed 0:a224293d7af4 171 write(OPERATIONS, 0x0C);
s_inoue_mbed 0:a224293d7af4 172 }
s_inoue_mbed 0:a224293d7af4 173
s_inoue_mbed 0:a224293d7af4 174 /* Check the data readiness */
s_inoue_mbed 0:a224293d7af4 175 bool SCP1000::IsReady(void)
s_inoue_mbed 0:a224293d7af4 176 {
s_inoue_mbed 0:a224293d7af4 177 if (_drdy == 1) {
s_inoue_mbed 0:a224293d7af4 178 return true;
s_inoue_mbed 0:a224293d7af4 179 } else {
s_inoue_mbed 0:a224293d7af4 180 return false;
s_inoue_mbed 0:a224293d7af4 181 }
s_inoue_mbed 0:a224293d7af4 182 }
s_inoue_mbed 0:a224293d7af4 183
s_inoue_mbed 0:a224293d7af4 184 /* Read temperature measurement result in degrees Celcius */
s_inoue_mbed 0:a224293d7af4 185 float SCP1000::readTemperature(void)
s_inoue_mbed 0:a224293d7af4 186 {
s_inoue_mbed 0:a224293d7af4 187 int temp_raw;
s_inoue_mbed 0:a224293d7af4 188 temp_raw = read16(TEMPOUT);
s_inoue_mbed 1:1b2027cbe629 189
s_inoue_mbed 1:1b2027cbe629 190 /* Check the below-zero temperature */
s_inoue_mbed 1:1b2027cbe629 191 if ((temp_raw | 0x2000) == 1) {
s_inoue_mbed 1:1b2027cbe629 192 temp_raw ^= 0x2000;
s_inoue_mbed 1:1b2027cbe629 193 temp_raw = -temp_raw;
s_inoue_mbed 1:1b2027cbe629 194 }
s_inoue_mbed 1:1b2027cbe629 195
s_inoue_mbed 1:1b2027cbe629 196 /* Return the temperature as float */
s_inoue_mbed 0:a224293d7af4 197 return static_cast<float>(temp_raw) * 0.05;
s_inoue_mbed 0:a224293d7af4 198 }
s_inoue_mbed 0:a224293d7af4 199
s_inoue_mbed 0:a224293d7af4 200 /* Read atmospheric pressure measurement result in hectopascal */
s_inoue_mbed 0:a224293d7af4 201 float SCP1000::readPressure(void)
s_inoue_mbed 0:a224293d7af4 202 {
s_inoue_mbed 0:a224293d7af4 203 int press_raw_h;
s_inoue_mbed 0:a224293d7af4 204 int press_raw_l;
s_inoue_mbed 0:a224293d7af4 205 press_raw_h = read8(DATARD8);
s_inoue_mbed 0:a224293d7af4 206 press_raw_l = read16(DATARD16);
s_inoue_mbed 1:1b2027cbe629 207
s_inoue_mbed 1:1b2027cbe629 208 /* Return the atmospheric pressure as float */
s_inoue_mbed 0:a224293d7af4 209 return static_cast<float>((press_raw_h << 16) + press_raw_l) * 0.0025;
s_inoue_mbed 0:a224293d7af4 210 }