Contains necessary classes and functions for ELEC351
samplingMaster/samplingMaster.cpp@2:e2b885367ba8, 2017-12-27 (annotated)
- Committer:
- Luka_Danilovic
- Date:
- Wed Dec 27 15:28:20 2017 +0000
- Revision:
- 2:e2b885367ba8
dateAndTime: FINISHED; samplingMaster: FINISHED; recordsMaster: IN PROGRESS
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Luka_Danilovic | 2:e2b885367ba8 | 1 | #include "mbed.h" |
Luka_Danilovic | 2:e2b885367ba8 | 2 | #include "samplingMaster.hpp" |
Luka_Danilovic | 2:e2b885367ba8 | 3 | |
Luka_Danilovic | 2:e2b885367ba8 | 4 | /* Spec said that we are not allowed to use any third party code unless it is |
Luka_Danilovic | 2:e2b885367ba8 | 5 | from ARM or STmicroelectronics, so I wrote my own driver for sampling BMP280 & |
Luka_Danilovic | 2:e2b885367ba8 | 6 | ADC in succesion. Ths code for MPB280 was inspired by the BMP280 Datasheet: |
Luka_Danilovic | 2:e2b885367ba8 | 7 | [https://cdn-shop.adafruit.com/datasheets/BST-BMP280-DS001-11.pdf] |
Luka_Danilovic | 2:e2b885367ba8 | 8 | and BMP280 mbed library by "charlie": |
Luka_Danilovic | 2:e2b885367ba8 | 9 | [https://os.mbed.com/users/CHARLY/code/BMP280/] */ |
Luka_Danilovic | 2:e2b885367ba8 | 10 | |
Luka_Danilovic | 2:e2b885367ba8 | 11 | C_sensorData::C_sensorData() |
Luka_Danilovic | 2:e2b885367ba8 | 12 | { |
Luka_Danilovic | 2:e2b885367ba8 | 13 | |
Luka_Danilovic | 2:e2b885367ba8 | 14 | //********************************LDR ADC*********************************// |
Luka_Danilovic | 2:e2b885367ba8 | 15 | AnalogIn ldrADC(PA_0); // Establish Analog In for ADC |
Luka_Danilovic | 2:e2b885367ba8 | 16 | |
Luka_Danilovic | 2:e2b885367ba8 | 17 | //******************************BMP280 I2C********************************// |
Luka_Danilovic | 2:e2b885367ba8 | 18 | I2C sensorLink(D14, D15); // Establish I2C comms |
Luka_Danilovic | 2:e2b885367ba8 | 19 | |
Luka_Danilovic | 2:e2b885367ba8 | 20 | inst[0] = CONTROL_REGISTER; // Register address |
Luka_Danilovic | 2:e2b885367ba8 | 21 | inst[1] = 0b01101101; // Temp x4, Pressure x4, Forced mode |
Luka_Danilovic | 2:e2b885367ba8 | 22 | sensorLink.write(I2C_adr, inst, 2); |
Luka_Danilovic | 2:e2b885367ba8 | 23 | |
Luka_Danilovic | 2:e2b885367ba8 | 24 | inst[0] = Tsb_IIR_REGISTER; // Register address |
Luka_Danilovic | 2:e2b885367ba8 | 25 | inst[1] = 0x00; // No standby, No IIR filter |
Luka_Danilovic | 2:e2b885367ba8 | 26 | sensorLink.write(I2C_adr, inst, 2); |
Luka_Danilovic | 2:e2b885367ba8 | 27 | |
Luka_Danilovic | 2:e2b885367ba8 | 28 | inst[0] = DIG_Tn_REGISTERS; // Read trimming parameters instruction |
Luka_Danilovic | 2:e2b885367ba8 | 29 | sensorLink.write(I2C_adr, inst, 1); |
Luka_Danilovic | 2:e2b885367ba8 | 30 | sensorLink.read(I2C_adr, inst, 6); |
Luka_Danilovic | 2:e2b885367ba8 | 31 | |
Luka_Danilovic | 2:e2b885367ba8 | 32 | /* For instructions how to decode trimming parameters please refer to the |
Luka_Danilovic | 2:e2b885367ba8 | 33 | BMP280 datasheet, page 21, chapter 3.11.2, table 17: "Compensation parameter |
Luka_Danilovic | 2:e2b885367ba8 | 34 | storage, naming and data type" */ |
Luka_Danilovic | 2:e2b885367ba8 | 35 | T1Trim = (inst[1]<<8)|inst[0]; |
Luka_Danilovic | 2:e2b885367ba8 | 36 | T2Trim = (inst[3]<<8)|inst[2]; |
Luka_Danilovic | 2:e2b885367ba8 | 37 | T3Trim = (inst[5]<<8)|inst[4]; |
Luka_Danilovic | 2:e2b885367ba8 | 38 | |
Luka_Danilovic | 2:e2b885367ba8 | 39 | inst[0] = DIG_Pn_REGISTERS; // Read trimming parameters instruction |
Luka_Danilovic | 2:e2b885367ba8 | 40 | sensorLink.write(I2C_adr, inst, 1); |
Luka_Danilovic | 2:e2b885367ba8 | 41 | sensorLink.read(I2C_adr, inst, 18); |
Luka_Danilovic | 2:e2b885367ba8 | 42 | |
Luka_Danilovic | 2:e2b885367ba8 | 43 | /* For instructions how to decode trimming parameters please refer to the |
Luka_Danilovic | 2:e2b885367ba8 | 44 | BMP280 datasheet, page 21, chapter 3.11.2, table 17: "Compensation parameter |
Luka_Danilovic | 2:e2b885367ba8 | 45 | storage, naming and data type" */ |
Luka_Danilovic | 2:e2b885367ba8 | 46 | P1Trim = (inst[ 1]<<8)|inst[ 0]; |
Luka_Danilovic | 2:e2b885367ba8 | 47 | P2Trim = (inst[ 3]<<8)|inst[ 2]; |
Luka_Danilovic | 2:e2b885367ba8 | 48 | P3Trim = (inst[ 5]<<8)|inst[ 4]; |
Luka_Danilovic | 2:e2b885367ba8 | 49 | P4Trim = (inst[ 7]<<8)|inst[ 6]; |
Luka_Danilovic | 2:e2b885367ba8 | 50 | P5Trim = (inst[ 9]<<8)|inst[ 8]; |
Luka_Danilovic | 2:e2b885367ba8 | 51 | P6Trim = (inst[11]<<8)|inst[10]; |
Luka_Danilovic | 2:e2b885367ba8 | 52 | P7Trim = (inst[13]<<8)|inst[12]; |
Luka_Danilovic | 2:e2b885367ba8 | 53 | P8Trim = (inst[15]<<8)|inst[14]; |
Luka_Danilovic | 2:e2b885367ba8 | 54 | P9Trim = (inst[17]<<8)|inst[16]; |
Luka_Danilovic | 2:e2b885367ba8 | 55 | } |
Luka_Danilovic | 2:e2b885367ba8 | 56 | |
Luka_Danilovic | 2:e2b885367ba8 | 57 | TDS_sensorData C_sensorData::read() |
Luka_Danilovic | 2:e2b885367ba8 | 58 | { |
Luka_Danilovic | 2:e2b885367ba8 | 59 | //*********************************SETUP**********************************// |
Luka_Danilovic | 2:e2b885367ba8 | 60 | TDS_sensorData sensorData; // Type def struct to hold the data |
Luka_Danilovic | 2:e2b885367ba8 | 61 | AnalogIn ldrADC(PA_0); // Establish Analog In for ADC |
Luka_Danilovic | 2:e2b885367ba8 | 62 | I2C sensorLink(D14, D15); // Establish I2C comms |
Luka_Danilovic | 2:e2b885367ba8 | 63 | |
Luka_Danilovic | 2:e2b885367ba8 | 64 | /* N.B in forced mode you must write to CONTROL_REGISTER to wake the IMU up. |
Luka_Danilovic | 2:e2b885367ba8 | 65 | It automaticly sleeps when measurments are aquired but leaves the registers |
Luka_Danilovic | 2:e2b885367ba8 | 66 | readable for the I2C link */ |
Luka_Danilovic | 2:e2b885367ba8 | 67 | inst[0] = CONTROL_REGISTER; // Register address |
Luka_Danilovic | 2:e2b885367ba8 | 68 | inst[1] = 0b01101101; // Temp x4, Pressure x4, Forced mode |
Luka_Danilovic | 2:e2b885367ba8 | 69 | sensorLink.write(I2C_adr, inst, 2); |
Luka_Danilovic | 2:e2b885367ba8 | 70 | |
Luka_Danilovic | 2:e2b885367ba8 | 71 | //******************************TEMPERATURE*******************************// |
Luka_Danilovic | 2:e2b885367ba8 | 72 | inst[0] = TEMP_ADDRESS_VAL; // Start of temperature register |
Luka_Danilovic | 2:e2b885367ba8 | 73 | sensorLink.write(I2C_adr, inst, 1); |
Luka_Danilovic | 2:e2b885367ba8 | 74 | sensorLink.read(I2C_adr, &inst[1], 3); |
Luka_Danilovic | 2:e2b885367ba8 | 75 | |
Luka_Danilovic | 2:e2b885367ba8 | 76 | tempT = (inst[1]<<12)|(inst[2]<<4)|(inst[3]>>4); |
Luka_Danilovic | 2:e2b885367ba8 | 77 | // ^ ^ ^ |
Luka_Danilovic | 2:e2b885367ba8 | 78 | // MSB REGISTER LSB REGISTER X_LSB REGISTER |
Luka_Danilovic | 2:e2b885367ba8 | 79 | |
Luka_Danilovic | 2:e2b885367ba8 | 80 | /* For instructions how to compensate values please refer to the |
Luka_Danilovic | 2:e2b885367ba8 | 81 | BMP280 datasheet, page 21 & 22, chapter 3.11.3, pseudo code */ |
Luka_Danilovic | 2:e2b885367ba8 | 82 | tempA = ((((tempT>>3)-(T1Trim<<1)))*T2Trim)>>11; |
Luka_Danilovic | 2:e2b885367ba8 | 83 | tempB = (((((tempT>>4)-T1Trim)*((tempT>>4)-T1Trim))>>12)*T3Trim)>>14; |
Luka_Danilovic | 2:e2b885367ba8 | 84 | tempT = tempA+tempB; |
Luka_Danilovic | 2:e2b885367ba8 | 85 | sensorData.temp = ((float)((tempT * 5 + 128) >> 8))/100; |
Luka_Danilovic | 2:e2b885367ba8 | 86 | |
Luka_Danilovic | 2:e2b885367ba8 | 87 | //********************************PRESURE********************************// |
Luka_Danilovic | 2:e2b885367ba8 | 88 | inst[0] = PRES_ADDRESS_VAL; // Start of presure register |
Luka_Danilovic | 2:e2b885367ba8 | 89 | sensorLink.write(I2C_adr, inst, 1); |
Luka_Danilovic | 2:e2b885367ba8 | 90 | sensorLink.read(I2C_adr, &inst[1], 3); |
Luka_Danilovic | 2:e2b885367ba8 | 91 | |
Luka_Danilovic | 2:e2b885367ba8 | 92 | tempP = (inst[1]<<12)|(inst[2]<<4)|(inst[3]>>4); |
Luka_Danilovic | 2:e2b885367ba8 | 93 | // ^ ^ ^ |
Luka_Danilovic | 2:e2b885367ba8 | 94 | // MSB REGISTER LSB REGISTER X_LSB REGISTER |
Luka_Danilovic | 2:e2b885367ba8 | 95 | |
Luka_Danilovic | 2:e2b885367ba8 | 96 | /* For instructions how to compensate values please refer to the |
Luka_Danilovic | 2:e2b885367ba8 | 97 | BMP280 datasheet, page 21 & 22, chapter 3.11.3, pseudo code. |
Luka_Danilovic | 2:e2b885367ba8 | 98 | |
Luka_Danilovic | 2:e2b885367ba8 | 99 | Please note that the compensation in the datasheet is done with 64 bit |
Luka_Danilovic | 2:e2b885367ba8 | 100 | signed values. However, "charlie's" BMP280 driver which does the |
Luka_Danilovic | 2:e2b885367ba8 | 101 | compensation using 32 bit signed values has inspired me to write my |
Luka_Danilovic | 2:e2b885367ba8 | 102 | compensation algorithm as follows. This makes the algorithm more efficient |
Luka_Danilovic | 2:e2b885367ba8 | 103 | without sacrifising relevant acuracy |
Luka_Danilovic | 2:e2b885367ba8 | 104 | |
Luka_Danilovic | 2:e2b885367ba8 | 105 | N.B the pressure calculated by the following algorithm is in hPa which is |
Luka_Danilovic | 2:e2b885367ba8 | 106 | a newer unit with equivalence of: 1hPA = 1mbar*/ |
Luka_Danilovic | 2:e2b885367ba8 | 107 | |
Luka_Danilovic | 2:e2b885367ba8 | 108 | tempA = (tempT>>1)-64000; |
Luka_Danilovic | 2:e2b885367ba8 | 109 | tempB = (((tempA>>2)*(tempA>>2))>>11)*P6Trim; |
Luka_Danilovic | 2:e2b885367ba8 | 110 | tempB = tempB+((tempA*P5Trim)<<1); |
Luka_Danilovic | 2:e2b885367ba8 | 111 | tempB = (tempB>>2)+(P4Trim<<16); |
Luka_Danilovic | 2:e2b885367ba8 | 112 | tempA = (((P3Trim*(((tempA>>2)*(tempA>>2))>>13))>>3)+((P2Trim*tempA)>>1))>>18; |
Luka_Danilovic | 2:e2b885367ba8 | 113 | tempA = ((32768+tempA)*P1Trim)>>15; |
Luka_Danilovic | 2:e2b885367ba8 | 114 | |
Luka_Danilovic | 2:e2b885367ba8 | 115 | if(tempA == 0) { |
Luka_Danilovic | 2:e2b885367ba8 | 116 | sensorData.pres = 0; |
Luka_Danilovic | 2:e2b885367ba8 | 117 | } |
Luka_Danilovic | 2:e2b885367ba8 | 118 | tempP = (((1048576-tempP)-(tempB>>12)))*3125; // Compensate for 64 bit loss |
Luka_Danilovic | 2:e2b885367ba8 | 119 | if(tempP < PREAS_UPER_LIMIT) { |
Luka_Danilovic | 2:e2b885367ba8 | 120 | tempP = (tempP<<1)/tempA; |
Luka_Danilovic | 2:e2b885367ba8 | 121 | } else { |
Luka_Danilovic | 2:e2b885367ba8 | 122 | tempP = (tempP/tempA)*2; |
Luka_Danilovic | 2:e2b885367ba8 | 123 | } |
Luka_Danilovic | 2:e2b885367ba8 | 124 | |
Luka_Danilovic | 2:e2b885367ba8 | 125 | tempA = ((int32_t)P9Trim*((int32_t)(((tempP>>3)*(tempP>>3))>>13)))>>12; |
Luka_Danilovic | 2:e2b885367ba8 | 126 | tempB = (((int32_t)(tempP>>2))*(int32_t)P8Trim)>>13; |
Luka_Danilovic | 2:e2b885367ba8 | 127 | sensorData.pres = ((float)((tempP+((tempA + tempB+P7Trim)>>4))))/100; |
Luka_Danilovic | 2:e2b885367ba8 | 128 | |
Luka_Danilovic | 2:e2b885367ba8 | 129 | |
Luka_Danilovic | 2:e2b885367ba8 | 130 | //******************************LIGHT LEVEL*******************************// |
Luka_Danilovic | 2:e2b885367ba8 | 131 | sensorData.ligt = ldrADC.read(); // Read ldr value |
Luka_Danilovic | 2:e2b885367ba8 | 132 | |
Luka_Danilovic | 2:e2b885367ba8 | 133 | //RETURN SENSOR DATA// |
Luka_Danilovic | 2:e2b885367ba8 | 134 | return sensorData; |
Luka_Danilovic | 2:e2b885367ba8 | 135 | } |