Contains necessary classes and functions for ELEC351

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers samplingMaster.cpp Source File

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 }