Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
main.cpp@5:630aefee388b, 2018-03-30 (annotated)
- Committer:
- summers
- Date:
- Fri Mar 30 11:14:51 2018 +0000
- Revision:
- 5:630aefee388b
- Parent:
- 4:e0dbf2bdb967
- Child:
- 6:be9a6932c869
Driver Version which works with all linear terms enabled
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
summers | 0:9146d1e52be0 | 1 | #include "mbed.h" |
summers | 1:3295382ddc81 | 2 | #include "main.h" |
summers | 5:630aefee388b | 3 | /* This code is to drive the Measurement Specialties MS5611-01BA03 |
summers | 5:630aefee388b | 4 | * pressure sensor. The sensor measures pressure via piezo electric |
summers | 5:630aefee388b | 5 | * sensor, that is measured by a 24bit delta-sigma ADC. Temperure is |
summers | 5:630aefee388b | 6 | * also measured via the same ADC. |
summers | 5:630aefee388b | 7 | * |
summers | 5:630aefee388b | 8 | * Pressure is then calculated via a first order equation in this code |
summers | 5:630aefee388b | 9 | * where both the pressure offset and linear term are also both linear |
summers | 5:630aefee388b | 10 | * dependent on temperature. |
summers | 5:630aefee388b | 11 | * |
summers | 5:630aefee388b | 12 | * Higher order terms are avaiable, but are not included in this code |
summers | 5:630aefee388b | 13 | * at present. |
summers | 5:630aefee388b | 14 | * |
summers | 5:630aefee388b | 15 | * The sensor can be accessed by either SPI or I2C, this code uses SPI. |
summers | 5:630aefee388b | 16 | * |
summers | 5:630aefee388b | 17 | * The algorithms are based on the MS5611-01BA03 data sheet, and also |
summers | 5:630aefee388b | 18 | * AN520 |
summers | 5:630aefee388b | 19 | * |
summers | 5:630aefee388b | 20 | * Some details are not clear in the documents, these are: |
summers | 5:630aefee388b | 21 | * . The commands are 7bit, the 8th bit is a stop bit and must be zero |
summers | 5:630aefee388b | 22 | * . The sensor will reply to the command with 0xfe, e.g. has it own stop bit |
summers | 5:630aefee388b | 23 | * . If 0xfe is not receieved error condition has happened |
summers | 5:630aefee388b | 24 | * . This starts the command, but does not complete it |
summers | 5:630aefee388b | 25 | * . Chip Select (CS) must be pulled high (inactive) after every command |
summers | 5:630aefee388b | 26 | * . The linear cooeficients are help in the PROM |
summers | 5:630aefee388b | 27 | * . This has a CRC4 check sum |
summers | 5:630aefee388b | 28 | * . The CRC4 check sum is based on the polymonial 0x13=x^4+x+1 |
summers | 5:630aefee388b | 29 | * . The CRC4 acts on the first 7 PROM values each 16bit, |
summers | 5:630aefee388b | 30 | * . The 8th PROM value, the CRC acts on the 12 MSB of the register |
summers | 5:630aefee388b | 31 | * . In addition in requires bits 9-12 to be zeroed in the check sum |
summers | 5:630aefee388b | 32 | */ |
summers | 0:9146d1e52be0 | 33 | |
summers | 1:3295382ddc81 | 34 | Serial pc(SERIAL_TX, SERIAL_RX, 115200); // tx, rx |
summers | 1:3295382ddc81 | 35 | //DigitalOut led(LED_RED); |
summers | 1:3295382ddc81 | 36 | //SPI spi(PTC6,PTC7,PTD1,PTC0); |
summers | 1:3295382ddc81 | 37 | //SPI spi(PTC6,PTC7,PTD1); // my prefered, but mixed |
summers | 1:3295382ddc81 | 38 | SPI spi(PTC6,PTC7,PTC5); // PTC5 - the LED |
summers | 1:3295382ddc81 | 39 | //SPI spi(PTD2,PTD3,PTD1); |
summers | 1:3295382ddc81 | 40 | DigitalOut cs(PTC0); |
summers | 0:9146d1e52be0 | 41 | |
summers | 0:9146d1e52be0 | 42 | int main() |
summers | 0:9146d1e52be0 | 43 | { |
summers | 5:630aefee388b | 44 | uint16_t PROM[8]; |
summers | 2:b6a0d4ba24a1 | 45 | uint32_t D1,D2; |
summers | 2:b6a0d4ba24a1 | 46 | double T,P; |
summers | 1:3295382ddc81 | 47 | cs.write(1); // disable all SPI |
summers | 2:b6a0d4ba24a1 | 48 | pc.printf("Hello World!\r\n"); |
summers | 1:3295382ddc81 | 49 | MS5611_init(PROM); |
summers | 1:3295382ddc81 | 50 | for (int i=0; i<8; i++) { |
summers | 2:b6a0d4ba24a1 | 51 | pc.printf("Prom(%i): %i\r\n",i,PROM[i]); |
summers | 1:3295382ddc81 | 52 | } |
summers | 3:a8c38c3fe967 | 53 | |
summers | 3:a8c38c3fe967 | 54 | while (1) { |
summers | 2:b6a0d4ba24a1 | 55 | // the third paramater gives over samping |
summers | 2:b6a0d4ba24a1 | 56 | // 0 - 256 |
summers | 2:b6a0d4ba24a1 | 57 | // 1 - 512 |
summers | 2:b6a0d4ba24a1 | 58 | // 2 - 1024 |
summers | 2:b6a0d4ba24a1 | 59 | // 3 - 2048 |
summers | 2:b6a0d4ba24a1 | 60 | // 4 - 4096 |
summers | 2:b6a0d4ba24a1 | 61 | MS5611(&D1,&D2,4); |
summers | 5:630aefee388b | 62 | // pc.printf("%i\t%i\t",D1,D2); |
summers | 2:b6a0d4ba24a1 | 63 | |
summers | 2:b6a0d4ba24a1 | 64 | MS5611_phys(D1,D2,PROM,&T,&P); |
summers | 2:b6a0d4ba24a1 | 65 | |
summers | 5:630aefee388b | 66 | // pc.printf("%f\t",T/100.0); |
summers | 5:630aefee388b | 67 | // pc.printf("%f\r\n",P/100.0); |
summers | 5:630aefee388b | 68 | pc.printf("%i\t%i\t%f\t%f\r\n",D1,D2,T/100,P/100.0); |
summers | 4:e0dbf2bdb967 | 69 | wait(1.0); |
summers | 3:a8c38c3fe967 | 70 | } |
summers | 1:3295382ddc81 | 71 | } |
summers | 1:3295382ddc81 | 72 | |
summers | 5:630aefee388b | 73 | void MS5611_init(uint16_t *PROM) |
summers | 1:3295382ddc81 | 74 | { |
summers | 3:a8c38c3fe967 | 75 | uint32_t crc=0; |
summers | 1:3295382ddc81 | 76 | spi.format(8,0); // 8 bit mode 0 - this is default anyway but good to code. |
summers | 1:3295382ddc81 | 77 | spi.frequency(1000000); // 1MHz is this the minimum? |
summers | 1:3295382ddc81 | 78 | cs.write(0); // Enable the MS5611 intercae |
summers | 2:b6a0d4ba24a1 | 79 | if (spi.write(0x1E)!=0xfe) { |
summers | 2:b6a0d4ba24a1 | 80 | pc.printf("Error reseting the device\r\n"); |
summers | 2:b6a0d4ba24a1 | 81 | } |
summers | 1:3295382ddc81 | 82 | wait_ms(3); // give time for ROM to reload 2.8ms by the spec |
summers | 2:b6a0d4ba24a1 | 83 | cs.write(1); // close the connection - does it finish the command? |
summers | 2:b6a0d4ba24a1 | 84 | wait_us(10); // Pause after putting CSB high |
summers | 1:3295382ddc81 | 85 | for (int i=0; i<8; i++) { |
summers | 2:b6a0d4ba24a1 | 86 | cs.write(0); // enable the SC to start a command. |
summers | 2:b6a0d4ba24a1 | 87 | if (spi.write(0xA0|(i<<1))!=0xfe) { |
summers | 2:b6a0d4ba24a1 | 88 | pc.printf("Error reading prom(%i)\r\n",i); |
summers | 2:b6a0d4ba24a1 | 89 | } |
summers | 5:630aefee388b | 90 | PROM[i]=((uint16_t) spi.write(0x00))<<8; |
summers | 5:630aefee388b | 91 | PROM[i]|=((uint16_t) spi.write(0x00)); |
summers | 2:b6a0d4ba24a1 | 92 | cs.write(1); // disable CS to finish the command |
summers | 3:a8c38c3fe967 | 93 | crc|=(i==7)?(PROM[i]&0xff00):PROM[i]; // Note AN520 gives this bit mask |
summers | 2:b6a0d4ba24a1 | 94 | for (int j=0; j<16; j++) { |
summers | 2:b6a0d4ba24a1 | 95 | crc=crc<<1; |
summers | 2:b6a0d4ba24a1 | 96 | if (crc&0x1000000) { // implimt the CRC4 algorithm 0x13 - |
summers | 3:a8c38c3fe967 | 97 | crc^=0x1300000; // This won't do the last 4 bits of PROM7 |
summers | 2:b6a0d4ba24a1 | 98 | } |
summers | 2:b6a0d4ba24a1 | 99 | } |
summers | 2:b6a0d4ba24a1 | 100 | wait_us(10); // Pause probably not stricly needed, but after switching CSB high give a bit of time. |
summers | 1:3295382ddc81 | 101 | } |
summers | 2:b6a0d4ba24a1 | 102 | if ((crc>>20)!=(PROM[7]&0xf)) |
summers | 2:b6a0d4ba24a1 | 103 | pc.printf("CRC check sum: %x vs recorded %x\r\n",crc>>20,PROM[7]&0xf); |
summers | 1:3295382ddc81 | 104 | } |
summers | 1:3295382ddc81 | 105 | |
summers | 2:b6a0d4ba24a1 | 106 | void MS5611(uint32_t *D1, uint32_t *D2, int os) |
summers | 1:3295382ddc81 | 107 | { |
summers | 1:3295382ddc81 | 108 | // cs.write(0); |
summers | 1:3295382ddc81 | 109 | spi.format(8,0); |
summers | 1:3295382ddc81 | 110 | spi.frequency(1000000); |
summers | 2:b6a0d4ba24a1 | 111 | cs.write(0); // Enable the MS5611 intercae |
summers | 2:b6a0d4ba24a1 | 112 | if (spi.write(0x1E)!=0xfe) { // and reset the device |
summers | 2:b6a0d4ba24a1 | 113 | pc.printf("Error reseting the device\r\n"); |
summers | 2:b6a0d4ba24a1 | 114 | } |
summers | 2:b6a0d4ba24a1 | 115 | wait_ms(3); // give time for ROM to reload 2.8ms by the spec |
summers | 2:b6a0d4ba24a1 | 116 | cs.write(1); // close the connection - does it finish the command? |
summers | 2:b6a0d4ba24a1 | 117 | wait_us(10); // Pause after putting CSB high |
summers | 2:b6a0d4ba24a1 | 118 | cs.write(0); // Enable the MS5611 intercae |
summers | 2:b6a0d4ba24a1 | 119 | if (spi.write(0x40|(os<<1))!=0xfe) { // D1 please |
summers | 2:b6a0d4ba24a1 | 120 | pc.printf("Error asking for D1\r\n"); |
summers | 2:b6a0d4ba24a1 | 121 | } |
summers | 2:b6a0d4ba24a1 | 122 | cs.write(1); // Disable the MS5611 intercae |
summers | 2:b6a0d4ba24a1 | 123 | wait_us(600*(1<<os)); // pause for read, longer when oversampling |
summers | 2:b6a0d4ba24a1 | 124 | cs.write(0); // Enable the MS5611 intercae |
summers | 3:a8c38c3fe967 | 125 | if(spi.write(0x00)!=0xfe) { // can I have the result?; |
summers | 3:a8c38c3fe967 | 126 | pc.printf("Error reading D1\r\n"); |
summers | 3:a8c38c3fe967 | 127 | } |
summers | 4:e0dbf2bdb967 | 128 | *D1=((uint32_t) spi.write(0x00))<<16; |
summers | 4:e0dbf2bdb967 | 129 | *D1|=((uint32_t) spi.write(0x00))<<8; |
summers | 4:e0dbf2bdb967 | 130 | *D1|=((uint32_t) spi.write(0x00)); |
summers | 2:b6a0d4ba24a1 | 131 | cs.write(1); // and terminate the command |
summers | 2:b6a0d4ba24a1 | 132 | wait_us(10); // Pause after putting CSB high |
summers | 2:b6a0d4ba24a1 | 133 | cs.write(0); // Enable the MS5611 intercae |
summers | 2:b6a0d4ba24a1 | 134 | if (spi.write(0x50|(os<<1))!=0xfe) { // D2 please |
summers | 2:b6a0d4ba24a1 | 135 | pc.printf("Error asking for D2\r\n"); |
summers | 2:b6a0d4ba24a1 | 136 | } |
summers | 2:b6a0d4ba24a1 | 137 | cs.write(1); // Disable the MS5611 intercae |
summers | 2:b6a0d4ba24a1 | 138 | wait_us(600*(1<<os)); // pause for read, longer when oversampling |
summers | 2:b6a0d4ba24a1 | 139 | cs.write(0); // Enable the MS5611 intercae |
summers | 3:a8c38c3fe967 | 140 | if(spi.write(0x00)!=0xfe) { // can I have the result?; |
summers | 3:a8c38c3fe967 | 141 | pc.printf("Error reading D2\r\n"); |
summers | 3:a8c38c3fe967 | 142 | } |
summers | 4:e0dbf2bdb967 | 143 | *D2=((uint32_t) spi.write(0x00))<<16; |
summers | 4:e0dbf2bdb967 | 144 | *D2|=((uint32_t) spi.write(0x00))<<8; |
summers | 4:e0dbf2bdb967 | 145 | *D2|=((uint32_t) spi.write(0x00)); |
summers | 2:b6a0d4ba24a1 | 146 | cs.write(1); // and terminate the command |
summers | 2:b6a0d4ba24a1 | 147 | } |
summers | 2:b6a0d4ba24a1 | 148 | |
summers | 5:630aefee388b | 149 | void MS5611_phys(uint32_t D1,uint32_t D2,uint16_t *PROM, double *T, double *P) |
summers | 2:b6a0d4ba24a1 | 150 | { |
summers | 3:a8c38c3fe967 | 151 | int64_t dt=((int64_t) D2)-(((int64_t) PROM[5])<<8); |
summers | 2:b6a0d4ba24a1 | 152 | *T=2000.0+((double) dt*PROM[6])/8388608.0; |
summers | 4:e0dbf2bdb967 | 153 | int64_t off128=(((int64_t) PROM[2])<<23)+(((int64_t) PROM[4])*dt); |
summers | 4:e0dbf2bdb967 | 154 | int64_t sens256=(((int64_t) PROM[1])<<23)+(((int64_t) PROM[3])*dt); |
summers | 4:e0dbf2bdb967 | 155 | *P=(((double) D1)*((double) sens256)/4194304.0-((double) off128))/4194304.0; |
summers | 5:630aefee388b | 156 | /* this keeps the power expansion - result not diffferent from above |
summers | 5:630aefee388b | 157 | Hence the above doesn't have rouding problems. |
summers | 5:630aefee388b | 158 | Pp[0]= |
summers | 5:630aefee388b | 159 | -((double) PROM[2])*2.0+((double) PROM[4])*((double) PROM[5])/16384.0 |
summers | 5:630aefee388b | 160 | +((double) D1)*( ((double) PROM[1])*32768.0 |
summers | 5:630aefee388b | 161 | -((double) PROM[3])*((double) PROM[5]))/68719476736.0 |
summers | 5:630aefee388b | 162 | -((double) PROM[4])*((double) D2)/4194304.0 |
summers | 5:630aefee388b | 163 | +((double) D1)*((double) PROM[3])*((double) D2)/17592186044416.0; |
summers | 5:630aefee388b | 164 | * this breaks it down by terms |
summers | 5:630aefee388b | 165 | Pp[0]=-((double) PROM[2])*2.0+((double) PROM[4])*((double) PROM[5])/16384.0; |
summers | 5:630aefee388b | 166 | Pp[1]=+((double) D1)*( ((double) PROM[1])*32768.0 |
summers | 5:630aefee388b | 167 | -((double) PROM[3])*((double) PROM[5]))/68719476736.0; |
summers | 5:630aefee388b | 168 | Pp[2]=-((double) PROM[4])*((double) D2)/4194304.0; |
summers | 5:630aefee388b | 169 | Pp[3]=+((double) D1)*((double) PROM[3])*((double) D2)/17592186044416.0; |
summers | 5:630aefee388b | 170 | */ |
summers | 5:630aefee388b | 171 | |
summers | 0:9146d1e52be0 | 172 | } |