Code in development (so non functional) of an SPI connection to MS5611

Dependencies:   mbed

Committer:
summers
Date:
Tue Apr 10 11:44:33 2018 +0000
Revision:
8:f8c0d1bb0cd9
Parent:
7:9cbf4da70f36
correct float in temp

Who changed what in which revision?

UserRevisionLine numberNew 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 7:9cbf4da70f36 24 * . This starts the command
summers 5:630aefee388b 25 * . Chip Select (CS) must be pulled high (inactive) after every command
summers 7:9cbf4da70f36 26 * . This can either be immediatly after issuing the command
summers 7:9cbf4da70f36 27 * . or after any delay needed for the command to execute
summers 6:be9a6932c869 28 * . The linear cooeficients are held in the PROM
summers 5:630aefee388b 29 * . This has a CRC4 check sum
summers 5:630aefee388b 30 * . The CRC4 check sum is based on the polymonial 0x13=x^4+x+1
summers 5:630aefee388b 31 * . The CRC4 acts on the first 7 PROM values each 16bit,
summers 5:630aefee388b 32 * . The 8th PROM value, the CRC acts on the 12 MSB of the register
summers 6:be9a6932c869 33 * . In addition it requires bits 9-12 to be zeroed in the check sum
summers 5:630aefee388b 34 */
summers 0:9146d1e52be0 35
summers 1:3295382ddc81 36 Serial pc(SERIAL_TX, SERIAL_RX, 115200); // tx, rx
summers 1:3295382ddc81 37 //DigitalOut led(LED_RED);
summers 1:3295382ddc81 38 //SPI spi(PTC6,PTC7,PTD1,PTC0);
summers 1:3295382ddc81 39 //SPI spi(PTC6,PTC7,PTD1); // my prefered, but mixed
summers 1:3295382ddc81 40 SPI spi(PTC6,PTC7,PTC5); // PTC5 - the LED
summers 1:3295382ddc81 41 //SPI spi(PTD2,PTD3,PTD1);
summers 1:3295382ddc81 42 DigitalOut cs(PTC0);
summers 0:9146d1e52be0 43
summers 0:9146d1e52be0 44 int main()
summers 0:9146d1e52be0 45 {
summers 5:630aefee388b 46 uint16_t PROM[8];
summers 2:b6a0d4ba24a1 47 uint32_t D1,D2;
summers 2:b6a0d4ba24a1 48 double T,P;
summers 1:3295382ddc81 49 cs.write(1); // disable all SPI
summers 6:be9a6932c869 50 pc.printf("Hello World!\n");
summers 1:3295382ddc81 51 MS5611_init(PROM);
summers 1:3295382ddc81 52 for (int i=0; i<8; i++) {
summers 6:be9a6932c869 53 pc.printf("Prom(%i): %i\n",i,PROM[i]);
summers 1:3295382ddc81 54 }
summers 3:a8c38c3fe967 55
summers 3:a8c38c3fe967 56 while (1) {
summers 2:b6a0d4ba24a1 57 // the third paramater gives over samping
summers 2:b6a0d4ba24a1 58 // 0 - 256
summers 2:b6a0d4ba24a1 59 // 1 - 512
summers 2:b6a0d4ba24a1 60 // 2 - 1024
summers 2:b6a0d4ba24a1 61 // 3 - 2048
summers 2:b6a0d4ba24a1 62 // 4 - 4096
summers 2:b6a0d4ba24a1 63 MS5611(&D1,&D2,4);
summers 5:630aefee388b 64 // pc.printf("%i\t%i\t",D1,D2);
summers 2:b6a0d4ba24a1 65
summers 2:b6a0d4ba24a1 66 MS5611_phys(D1,D2,PROM,&T,&P);
summers 2:b6a0d4ba24a1 67
summers 5:630aefee388b 68 // pc.printf("%f\t",T/100.0);
summers 5:630aefee388b 69 // pc.printf("%f\r\n",P/100.0);
summers 8:f8c0d1bb0cd9 70 pc.printf("%i\t%i\t%f\t%f\n",D1,D2,T/100.0,P/100.0);
summers 4:e0dbf2bdb967 71 wait(1.0);
summers 3:a8c38c3fe967 72 }
summers 1:3295382ddc81 73 }
summers 1:3295382ddc81 74
summers 5:630aefee388b 75 void MS5611_init(uint16_t *PROM)
summers 1:3295382ddc81 76 {
summers 3:a8c38c3fe967 77 uint32_t crc=0;
summers 1:3295382ddc81 78 spi.format(8,0); // 8 bit mode 0 - this is default anyway but good to code.
summers 1:3295382ddc81 79 spi.frequency(1000000); // 1MHz is this the minimum?
summers 1:3295382ddc81 80 cs.write(0); // Enable the MS5611 intercae
summers 6:be9a6932c869 81 if (spi.write(0x1e)!=0xfe) { // Reset the device
summers 6:be9a6932c869 82 pc.printf("Error reseting the device\n");
summers 2:b6a0d4ba24a1 83 }
summers 1:3295382ddc81 84 wait_ms(3); // give time for ROM to reload 2.8ms by the spec
summers 2:b6a0d4ba24a1 85 cs.write(1); // close the connection - does it finish the command?
summers 2:b6a0d4ba24a1 86 wait_us(10); // Pause after putting CSB high
summers 1:3295382ddc81 87 for (int i=0; i<8; i++) {
summers 2:b6a0d4ba24a1 88 cs.write(0); // enable the SC to start a command.
summers 6:be9a6932c869 89 if (spi.write(0xa0|(i<<1))!=0xfe) {
summers 6:be9a6932c869 90 pc.printf("Error reading prom(%i)\n",i);
summers 2:b6a0d4ba24a1 91 }
summers 5:630aefee388b 92 PROM[i]=((uint16_t) spi.write(0x00))<<8;
summers 5:630aefee388b 93 PROM[i]|=((uint16_t) spi.write(0x00));
summers 2:b6a0d4ba24a1 94 cs.write(1); // disable CS to finish the command
summers 3:a8c38c3fe967 95 crc|=(i==7)?(PROM[i]&0xff00):PROM[i]; // Note AN520 gives this bit mask
summers 2:b6a0d4ba24a1 96 for (int j=0; j<16; j++) {
summers 2:b6a0d4ba24a1 97 crc=crc<<1;
summers 2:b6a0d4ba24a1 98 if (crc&0x1000000) { // implimt the CRC4 algorithm 0x13 -
summers 3:a8c38c3fe967 99 crc^=0x1300000; // This won't do the last 4 bits of PROM7
summers 2:b6a0d4ba24a1 100 }
summers 2:b6a0d4ba24a1 101 }
summers 2:b6a0d4ba24a1 102 wait_us(10); // Pause probably not stricly needed, but after switching CSB high give a bit of time.
summers 1:3295382ddc81 103 }
summers 2:b6a0d4ba24a1 104 if ((crc>>20)!=(PROM[7]&0xf))
summers 6:be9a6932c869 105 pc.printf("CRC check sum: %x vs recorded %x\n",crc>>20,PROM[7]&0xf);
summers 1:3295382ddc81 106 }
summers 1:3295382ddc81 107
summers 2:b6a0d4ba24a1 108 void MS5611(uint32_t *D1, uint32_t *D2, int os)
summers 1:3295382ddc81 109 {
summers 1:3295382ddc81 110 // cs.write(0);
summers 1:3295382ddc81 111 spi.format(8,0);
summers 1:3295382ddc81 112 spi.frequency(1000000);
summers 2:b6a0d4ba24a1 113 cs.write(0); // Enable the MS5611 intercae
summers 6:be9a6932c869 114 if (spi.write(0x1e)!=0xfe) { // and reset the device
summers 6:be9a6932c869 115 pc.printf("Error reseting the device\n");
summers 2:b6a0d4ba24a1 116 }
summers 2:b6a0d4ba24a1 117 wait_ms(3); // give time for ROM to reload 2.8ms by the spec
summers 2:b6a0d4ba24a1 118 cs.write(1); // close the connection - does it finish the command?
summers 2:b6a0d4ba24a1 119 wait_us(10); // Pause after putting CSB high
summers 2:b6a0d4ba24a1 120 cs.write(0); // Enable the MS5611 intercae
summers 2:b6a0d4ba24a1 121 if (spi.write(0x40|(os<<1))!=0xfe) { // D1 please
summers 6:be9a6932c869 122 pc.printf("Error asking for D1\n");
summers 2:b6a0d4ba24a1 123 }
summers 2:b6a0d4ba24a1 124 cs.write(1); // Disable the MS5611 intercae
summers 6:be9a6932c869 125 wait_us(600<<os); // pause for read, longer when oversampling
summers 2:b6a0d4ba24a1 126 cs.write(0); // Enable the MS5611 intercae
summers 3:a8c38c3fe967 127 if(spi.write(0x00)!=0xfe) { // can I have the result?;
summers 6:be9a6932c869 128 pc.printf("Error reading D1\n");
summers 3:a8c38c3fe967 129 }
summers 4:e0dbf2bdb967 130 *D1=((uint32_t) spi.write(0x00))<<16;
summers 4:e0dbf2bdb967 131 *D1|=((uint32_t) spi.write(0x00))<<8;
summers 4:e0dbf2bdb967 132 *D1|=((uint32_t) spi.write(0x00));
summers 2:b6a0d4ba24a1 133 cs.write(1); // and terminate the command
summers 2:b6a0d4ba24a1 134 wait_us(10); // Pause after putting CSB high
summers 2:b6a0d4ba24a1 135 cs.write(0); // Enable the MS5611 intercae
summers 2:b6a0d4ba24a1 136 if (spi.write(0x50|(os<<1))!=0xfe) { // D2 please
summers 6:be9a6932c869 137 pc.printf("Error asking for D2\n");
summers 2:b6a0d4ba24a1 138 }
summers 2:b6a0d4ba24a1 139 cs.write(1); // Disable the MS5611 intercae
summers 6:be9a6932c869 140 wait_us(600<<os); // pause for read, longer when oversampling
summers 2:b6a0d4ba24a1 141 cs.write(0); // Enable the MS5611 intercae
summers 3:a8c38c3fe967 142 if(spi.write(0x00)!=0xfe) { // can I have the result?;
summers 6:be9a6932c869 143 pc.printf("Error reading D2\n");
summers 3:a8c38c3fe967 144 }
summers 4:e0dbf2bdb967 145 *D2=((uint32_t) spi.write(0x00))<<16;
summers 4:e0dbf2bdb967 146 *D2|=((uint32_t) spi.write(0x00))<<8;
summers 4:e0dbf2bdb967 147 *D2|=((uint32_t) spi.write(0x00));
summers 2:b6a0d4ba24a1 148 cs.write(1); // and terminate the command
summers 2:b6a0d4ba24a1 149 }
summers 2:b6a0d4ba24a1 150
summers 5:630aefee388b 151 void MS5611_phys(uint32_t D1,uint32_t D2,uint16_t *PROM, double *T, double *P)
summers 2:b6a0d4ba24a1 152 {
summers 3:a8c38c3fe967 153 int64_t dt=((int64_t) D2)-(((int64_t) PROM[5])<<8);
summers 2:b6a0d4ba24a1 154 *T=2000.0+((double) dt*PROM[6])/8388608.0;
summers 4:e0dbf2bdb967 155 int64_t off128=(((int64_t) PROM[2])<<23)+(((int64_t) PROM[4])*dt);
summers 4:e0dbf2bdb967 156 int64_t sens256=(((int64_t) PROM[1])<<23)+(((int64_t) PROM[3])*dt);
summers 4:e0dbf2bdb967 157 *P=(((double) D1)*((double) sens256)/4194304.0-((double) off128))/4194304.0;
summers 5:630aefee388b 158 /* this keeps the power expansion - result not diffferent from above
summers 5:630aefee388b 159 Hence the above doesn't have rouding problems.
summers 5:630aefee388b 160 Pp[0]=
summers 5:630aefee388b 161 -((double) PROM[2])*2.0+((double) PROM[4])*((double) PROM[5])/16384.0
summers 5:630aefee388b 162 +((double) D1)*( ((double) PROM[1])*32768.0
summers 5:630aefee388b 163 -((double) PROM[3])*((double) PROM[5]))/68719476736.0
summers 5:630aefee388b 164 -((double) PROM[4])*((double) D2)/4194304.0
summers 5:630aefee388b 165 +((double) D1)*((double) PROM[3])*((double) D2)/17592186044416.0;
summers 5:630aefee388b 166 * this breaks it down by terms
summers 5:630aefee388b 167 Pp[0]=-((double) PROM[2])*2.0+((double) PROM[4])*((double) PROM[5])/16384.0;
summers 5:630aefee388b 168 Pp[1]=+((double) D1)*( ((double) PROM[1])*32768.0
summers 5:630aefee388b 169 -((double) PROM[3])*((double) PROM[5]))/68719476736.0;
summers 5:630aefee388b 170 Pp[2]=-((double) PROM[4])*((double) D2)/4194304.0;
summers 5:630aefee388b 171 Pp[3]=+((double) D1)*((double) PROM[3])*((double) D2)/17592186044416.0;
summers 5:630aefee388b 172 */
summers 5:630aefee388b 173
summers 0:9146d1e52be0 174 }