Contains necessary classes and functions for ELEC351
Embed:
(wiki syntax)
Show/hide line numbers
samplingMaster.cpp
00001 #include "mbed.h" 00002 #include "samplingMaster.hpp" 00003 00004 /* Spec said that we are not allowed to use any third party code unless it is 00005 from ARM or STmicroelectronics, so I wrote my own driver for sampling BMP280 & 00006 ADC in succesion. Ths code for MPB280 was inspired by the BMP280 Datasheet: 00007 [https://cdn-shop.adafruit.com/datasheets/BST-BMP280-DS001-11.pdf] 00008 and BMP280 mbed library by "charlie": 00009 [https://os.mbed.com/users/CHARLY/code/BMP280/] */ 00010 00011 C_sensorData::C_sensorData() 00012 { 00013 00014 //********************************LDR ADC*********************************// 00015 AnalogIn ldrADC(PA_0); // Establish Analog In for ADC 00016 00017 //******************************BMP280 I2C********************************// 00018 I2C sensorLink(D14, D15); // Establish I2C comms 00019 00020 inst[0] = CONTROL_REGISTER; // Register address 00021 inst[1] = 0b01101101; // Temp x4, Pressure x4, Forced mode 00022 sensorLink.write(I2C_adr, inst, 2); 00023 00024 inst[0] = Tsb_IIR_REGISTER; // Register address 00025 inst[1] = 0x00; // No standby, No IIR filter 00026 sensorLink.write(I2C_adr, inst, 2); 00027 00028 inst[0] = DIG_Tn_REGISTERS; // Read trimming parameters instruction 00029 sensorLink.write(I2C_adr, inst, 1); 00030 sensorLink.read(I2C_adr, inst, 6); 00031 00032 /* For instructions how to decode trimming parameters please refer to the 00033 BMP280 datasheet, page 21, chapter 3.11.2, table 17: "Compensation parameter 00034 storage, naming and data type" */ 00035 T1Trim = (inst[1]<<8)|inst[0]; 00036 T2Trim = (inst[3]<<8)|inst[2]; 00037 T3Trim = (inst[5]<<8)|inst[4]; 00038 00039 inst[0] = DIG_Pn_REGISTERS; // Read trimming parameters instruction 00040 sensorLink.write(I2C_adr, inst, 1); 00041 sensorLink.read(I2C_adr, inst, 18); 00042 00043 /* For instructions how to decode trimming parameters please refer to the 00044 BMP280 datasheet, page 21, chapter 3.11.2, table 17: "Compensation parameter 00045 storage, naming and data type" */ 00046 P1Trim = (inst[ 1]<<8)|inst[ 0]; 00047 P2Trim = (inst[ 3]<<8)|inst[ 2]; 00048 P3Trim = (inst[ 5]<<8)|inst[ 4]; 00049 P4Trim = (inst[ 7]<<8)|inst[ 6]; 00050 P5Trim = (inst[ 9]<<8)|inst[ 8]; 00051 P6Trim = (inst[11]<<8)|inst[10]; 00052 P7Trim = (inst[13]<<8)|inst[12]; 00053 P8Trim = (inst[15]<<8)|inst[14]; 00054 P9Trim = (inst[17]<<8)|inst[16]; 00055 } 00056 00057 TDS_sensorData C_sensorData::read() 00058 { 00059 //*********************************SETUP**********************************// 00060 TDS_sensorData sensorData; // Type def struct to hold the data 00061 AnalogIn ldrADC(PA_0); // Establish Analog In for ADC 00062 I2C sensorLink(D14, D15); // Establish I2C comms 00063 00064 /* N.B in forced mode you must write to CONTROL_REGISTER to wake the IMU up. 00065 It automaticly sleeps when measurments are aquired but leaves the registers 00066 readable for the I2C link */ 00067 inst[0] = CONTROL_REGISTER; // Register address 00068 inst[1] = 0b01101101; // Temp x4, Pressure x4, Forced mode 00069 sensorLink.write(I2C_adr, inst, 2); 00070 00071 //******************************TEMPERATURE*******************************// 00072 inst[0] = TEMP_ADDRESS_VAL; // Start of temperature register 00073 sensorLink.write(I2C_adr, inst, 1); 00074 sensorLink.read(I2C_adr, &inst[1], 3); 00075 00076 tempT = (inst[1]<<12)|(inst[2]<<4)|(inst[3]>>4); 00077 // ^ ^ ^ 00078 // MSB REGISTER LSB REGISTER X_LSB REGISTER 00079 00080 /* For instructions how to compensate values please refer to the 00081 BMP280 datasheet, page 21 & 22, chapter 3.11.3, pseudo code */ 00082 tempA = ((((tempT>>3)-(T1Trim<<1)))*T2Trim)>>11; 00083 tempB = (((((tempT>>4)-T1Trim)*((tempT>>4)-T1Trim))>>12)*T3Trim)>>14; 00084 tempT = tempA+tempB; 00085 sensorData.temp = ((float)((tempT * 5 + 128) >> 8))/100; 00086 00087 //********************************PRESURE********************************// 00088 inst[0] = PRES_ADDRESS_VAL; // Start of presure register 00089 sensorLink.write(I2C_adr, inst, 1); 00090 sensorLink.read(I2C_adr, &inst[1], 3); 00091 00092 tempP = (inst[1]<<12)|(inst[2]<<4)|(inst[3]>>4); 00093 // ^ ^ ^ 00094 // MSB REGISTER LSB REGISTER X_LSB REGISTER 00095 00096 /* For instructions how to compensate values please refer to the 00097 BMP280 datasheet, page 21 & 22, chapter 3.11.3, pseudo code. 00098 00099 Please note that the compensation in the datasheet is done with 64 bit 00100 signed values. However, "charlie's" BMP280 driver which does the 00101 compensation using 32 bit signed values has inspired me to write my 00102 compensation algorithm as follows. This makes the algorithm more efficient 00103 without sacrifising relevant acuracy 00104 00105 N.B the pressure calculated by the following algorithm is in hPa which is 00106 a newer unit with equivalence of: 1hPA = 1mbar*/ 00107 00108 tempA = (tempT>>1)-64000; 00109 tempB = (((tempA>>2)*(tempA>>2))>>11)*P6Trim; 00110 tempB = tempB+((tempA*P5Trim)<<1); 00111 tempB = (tempB>>2)+(P4Trim<<16); 00112 tempA = (((P3Trim*(((tempA>>2)*(tempA>>2))>>13))>>3)+((P2Trim*tempA)>>1))>>18; 00113 tempA = ((32768+tempA)*P1Trim)>>15; 00114 00115 if(tempA == 0) { 00116 sensorData.pres = 0; 00117 } 00118 tempP = (((1048576-tempP)-(tempB>>12)))*3125; // Compensate for 64 bit loss 00119 if(tempP < PREAS_UPER_LIMIT) { 00120 tempP = (tempP<<1)/tempA; 00121 } else { 00122 tempP = (tempP/tempA)*2; 00123 } 00124 00125 tempA = ((int32_t)P9Trim*((int32_t)(((tempP>>3)*(tempP>>3))>>13)))>>12; 00126 tempB = (((int32_t)(tempP>>2))*(int32_t)P8Trim)>>13; 00127 sensorData.pres = ((float)((tempP+((tempA + tempB+P7Trim)>>4))))/100; 00128 00129 00130 //******************************LIGHT LEVEL*******************************// 00131 sensorData.ligt = ldrADC.read(); // Read ldr value 00132 00133 //RETURN SENSOR DATA// 00134 return sensorData; 00135 }
Generated on Tue Jul 12 2022 18:37:11 by
1.7.2