2022年12月23日 星期五

壓力感測器實作 – GMP102數位式氣壓感測器

壓力感測器實作 – GMP102數位式氣壓感測器

 

電路圖

 

HUB-5168

 


Ameba A1_Lite

 


程式列表

GMP102.h

 

#ifndef __GMP102_H__

#define __GMP102_H__

 

#define GMP102_7BIT_I2C_ADDR    0x6C  //SA0=GND

//#define GMP102_7BIT_I2C_ADDR    0x6D  //SA0=VIO

#define GMP102_TEMPERATURE_SENSITIVITY 256.00  //1 Celsius = 256 code

#define GMP102_T_CODE_TO_CELSIUS(tCode) (((float)(tCode)) / GMP102_TEMPERATURE_SENSITIVITY)

 

//Registers Address

#define GMP102_REG_RESET    0x00

#define GMP102_REG_PID      0x01

#define GMP102_REG_STATUS   0x02

  #define STATUS_DRDY         0x01

#define GMP102_REG_PRESSH   0x06

#define GMP102_REG_PRESSM   0x07

#define GMP102_REG_PRESSL   0x08

#define GMP102_REG_TEMPH    0x09

#define GMP102_REG_TEMPL    0x0A

#define GMP102_REG_CMD      0x30

  #define T_Forced_mode       0x08

  #define P_Forced_mode       0x09

#define GMP102_REG_CONFIG1  0xA5

  #define CONFIG1_RAW         0x02

#define GMP102_REG_CONFIG2  0xA6

#define GMP102_REG_CONFIG3  0xA7

#define GMP102_REG_CALIB00  0xAA

//Total calibration register count: AAh~BBh total 18

#define GMP102_CALIBRATION_REGISTER_COUNT 18

//Total calibration parameter count: total 9

#define GMP102_CALIBRATION_PARAMETER_COUNT (GMP102_CALIBRATION_REGISTER_COUNT/2)

//Soft reset

#define GMP102_SW_RST_SET_VALUE    0x24

 

/* PID */

#define GMP102_PID__REG GMP102_REG_PID

/* Soft Rest bit */

#define GMP102_RST__REG    GMP102_REG_RESET

#define GMP102_RST__MSK    0x24

#define GMP102_RST__POS    0

/* DRDY bit */

#define GMP102_DRDY__REG   GMP102_REG_STATUS

#define GMP102_DRDY__MSK   0x01

#define GMP102_DRDY__POS   0

/* P OSR bits */

#define GMP102_P_OSR__REG  GMP102_REG_CONFIG2

#define GMP102_P_OSR__MSK  0x07

#define GMP102_P_OSR__POS  0

/* T OSR bits */

#define GMP102_T_OSR__REG  GMP102_REG_CONFIG3

#define GMP102_T_OSR__MSK  0x07

#define GMP102_T_OSR__POS  0

 

#define GMP102_GET_BITSLICE(regvar, bitname)  \

  ((regvar & bitname##__MSK) >> bitname##__POS)

 

#define GMP102_SET_BITSLICE(regvar, bitname, val)      \

  ((regvar & ~bitname##__MSK) | ((val<<bitname##__POS)&bitname##__MSK))

 

typedef enum {

  GMP102_P_OSR_256   = 0x04,

  GMP102_P_OSR_512   = 0x05,

  GMP102_P_OSR_1024  = 0x00,

  GMP102_P_OSR_2048  = 0x01,

  GMP102_P_OSR_4096  = 0x02,

  GMP102_P_OSR_8192  = 0x03,

  GMP102_P_OSR_16384 = 0x06,

  GMP102_P_OSR_32768 = 0x07,

} GMP102_P_OSR_Type;

 

typedef enum {

  GMP102_T_OSR_256   = 0x04,

  GMP102_T_OSR_512   = 0x05,

  GMP102_T_OSR_1024  = 0x00,

  GMP102_T_OSR_2048  = 0x01,

  GMP102_T_OSR_4096  = 0x02,

  GMP102_T_OSR_8192  = 0x03,

  GMP102_T_OSR_16384 = 0x06,

  GMP102_T_OSR_32768 = 0x07,

} GMP102_T_OSR_Type;

 

#endif // __GMP102_H__

 

GMP102_Ameba.ino

/*

 * Program Description:

 * --------------------

 *

* Ameba BW16                  GMP102

 * ---------                 -------------

 *     3.3V |            VDD | Pin8      |

 *      VSS |            VSS | Pin7      |

 *          | SCL -----> SCL | Pin4      |

 *          | SDA -----> SDA | Pin3      |

 *          |

* ----------

 * ----------

 * GMP102 Application note for Calibrated Pressure Calculation

 * https://github.com/GlobalMEMS/Application-Notes

 */

 

 

/*----------------------------------------------------------------------------

 * Includes

 *----------------------------------------------------------------------------*/

#include <GTimer.h>

#include "BLEDevice.h"

#include <Wire.h>

#include "GMP102.h"

 

/*----------------------------------------------------------------------------

 * DEFINITIONS

 *----------------------------------------------------------------------------*/

#define BLE_DEVICE_NAME    "Ameba_BLE"

#define UART_SERVICE_UUID      "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"

#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"

#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"

 

#define STRING_BUF_SIZE 100

 

// HUB 5168

#define GreenLED 3 //PA30

#define BlueLED 9 //PA15

//#define  DebugPrg

 

/*----------------------------------------------------------------------------*/

/* STRUCTURES                                                                 */

/*----------------------------------------------------------------------------*/

typedef union _SystemStatus

{

  char  _byte;

  struct

  {

    unsigned b_10msDone:1;

    unsigned b_100msDone:1;

    unsigned b_1secDone:1;

    unsigned RESV:5;

  };

} SystemStatus;

 

/*----------------------------------------------------------------------------*/

/* Global CONSTANTS                                                           */

/*----------------------------------------------------------------------------*/

BLEService UartService(UART_SERVICE_UUID);

BLECharacteristic Rx(CHARACTERISTIC_UUID_RX);

BLECharacteristic Tx(CHARACTERISTIC_UUID_TX);

BLEAdvertData advdata;

BLEAdvertData scndata;

 

bool notify = false;

bool updated = false;

String rxString = "";

int counter = 0;

bool TimerDone = false;

 

unsigned long  now;

SystemStatus  SystemStatusbits;

 

unsigned char Data_Buffer[128]={0};

unsigned char buffer;

int PADCData,ADC0;

int TADCData;

 

float pressure,height,temperature,DisplayData;

unsigned char CalData[18];

float CalData2[9];

static const float GMP102_CALIB_SCALE_FACTOR[] = {

                   1.0E+00,

                   1.0E-05,

                   1.0E-10,

                   1.0E-05,

                   1.0E-10,

                   1.0E-15,

                   1.0E-12,

                   1.0E-17,

                   1.0E-21 };

 

static float fp_base_sea_level_Pa = 101325.f;

 

/*----------------------------------------------------------------------------*/

/* Start Function                                                             */

/*----------------------------------------------------------------------------*/

void setup(void)

{

  pinMode(BlueLED, OUTPUT);

  Wire.begin();

  Serial.begin(115200);                 // optional serial monitor

  Serial.println(F("\r\nGobalMEMS GMP102 test"));

 

  advdata.addFlags(GAP_ADTYPE_FLAGS_LIMITED | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED);

  advdata.addCompleteName(BLE_DEVICE_NAME);

  scndata.addCompleteServices(BLEUUID(UART_SERVICE_UUID));

 

  Rx.setWriteNRProperty(true);  // Enable write without response (write command)

  Rx.setWritePermissions(GATT_PERM_WRITE);

  Rx.setWriteCallback(writeCB);

  Rx.setBufferLen(STRING_BUF_SIZE);

  Tx.setReadProperty(true);

  Tx.setReadPermissions(GATT_PERM_READ);

  Tx.setNotifyProperty(true);

  Tx.setCCCDCallback(notifCB);

  Tx.setBufferLen(STRING_BUF_SIZE);

 

  UartService.addCharacteristic(Rx);

  UartService.addCharacteristic(Tx);

 

  BLE.init();

  BLE.configAdvert()->setAdvData(advdata);

  BLE.configAdvert()->setScanRspData(scndata);

  BLE.configServer(1);

  BLE.addService(UartService);

 

  BLE.beginPeripheral();

 

  SensorInital();

 

  // timerid 0, period 10s, invoke Timerhandler

  GTimer.begin(0, (10 * 1000 * 1000), Timerhandler);

  now = millis();  // system timer0

  SystemStatusbits._byte = 0;

}

 

void loop(void)

{

  char String1[200];

 

  digitalWrite(BlueLED, LOW);

  PDataRead();

  digitalWrite(BlueLED, HIGH);

  TDataRead();

  temperature=TADCData/GMP102_TEMPERATURE_SENSITIVITY;

  pressure=GMP102_PRESSURE_CAL(TADCData,PADCData);

  height=GMP102_Altitude_CAL(pressure);

 

  sprintf(String1,"Temperature:%d 'C, Pressure:%d hPa, Approx Altitude:%d m",

                  (int)temperature,(int)pressure/100,(int)height);

  Serial.println(String1);

 

  if(TimerDone == true)

  {

    if(updated){

      Serial.println(rxString); // raw output

      updated = false; // clear flag for another update

    }

 

    String msg = ("Temperature: " + String((int) temperature) + "°C\t" + "Pressure: " + String((int) pressure/100) + "hPa\n");

 

    Tx.writeString(msg);

    if (BLE.connected(0) && notify) {

      Tx.notify(0);

    }   

  }

 

  SYS_TIMER();      // work on timer0

  if(SystemStatusbits.b_1secDone==1)

  {

    SystemStatusbits.b_1secDone=0;

  }

}

 

/*----------------------------------------------------------------------------*/

/* Write I2C Device Register Data                                             */

/*----------------------------------------------------------------------------*/

void I2C_WriteData(unsigned char DeviceAddr, unsigned char *DataBuffer, unsigned char StartAddress, unsigned char ByteCount)

{

  // Send the received data to slave

  Wire.beginTransmission(DeviceAddr);  //Device_ID_Addr

  Wire.write(StartAddress);

 

  for(;ByteCount>0;ByteCount--)

  {

    Wire.write(*DataBuffer++);

  }

  Wire.endTransmission();

}

 

/*----------------------------------------------------------------------------*/

/* Read I2C Device Register Data                                              */

/*----------------------------------------------------------------------------*/

void I2C_ReadData(unsigned char DeviceAddr, unsigned char *DataBuffer, unsigned char StartAddress, unsigned char ByteCount)

{

  unsigned char au8DestinationData;

 

  // send the received data to slave

  Wire.beginTransmission(DeviceAddr);  //Device_ID_Addr

  Wire.write(StartAddress);

  Wire.endTransmission();

 

  Wire.requestFrom(DeviceAddr, ByteCount);    // request 1 bytes from slave device

  //Read Register Data From I2C Device

  for(;ByteCount>0;ByteCount--)

  {

    while (Wire.available())  // slave may send less than requested

    {

      au8DestinationData = Wire.read(); // receive a byte as character

      *DataBuffer++ = (unsigned char) au8DestinationData;

    #if defined(DebugPrg)

      Serial.print(F("Addr-"));

      Serial.print(StartAddress++,HEX);

      Serial.print(F(":"));

      Serial.println(au8DestinationData,HEX);

    #endif

    }

  }

}

 

/*----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*/

void PDataRead(void)

{

  char Raw=0;

  char DRDY=0;

 

  do

  {

    Data_Buffer[0]=CONFIG1_RAW;

    I2C_WriteData(GMP102_7BIT_I2C_ADDR,Data_Buffer,GMP102_REG_CONFIG1,1);

    delay(1000);

    I2C_ReadData(GMP102_7BIT_I2C_ADDR,Data_Buffer,GMP102_REG_CONFIG1,1);

    Raw=Data_Buffer[0];

    delay(1000);

  }while(Raw!=CONFIG1_RAW);

 

  Data_Buffer[0]=P_Forced_mode;  //P-Forced mode, Make a single shot pressure conversion

  I2C_WriteData(GMP102_7BIT_I2C_ADDR,Data_Buffer,GMP102_REG_CMD,1);

  delay(1000);

 

  while(DRDY!=STATUS_DRDY)

  {

    I2C_ReadData(GMP102_7BIT_I2C_ADDR,Data_Buffer,GMP102_REG_STATUS,1);

    DRDY=Data_Buffer[0];

    delay(1000);

  }

  //I2C_ReadData(GMP102_7BIT_I2C_ADDR,Data_Buffer,GMP102_REG_PRESSH,5);

  I2C_ReadData(GMP102_7BIT_I2C_ADDR,Data_Buffer,GMP102_REG_PRESSH,3);

  PADCData=(Data_Buffer[0]<<16)+(Data_Buffer[1]<<8)+Data_Buffer[2];

#if defined(DebugPrg)

  Serial.println(PADCData,HEX);

#endif

 

  if((PADCData<0)||(PADCData>0x800000))

  {

    PADCData=~PADCData;

    PADCData=PADCData&0xFFFFFF;

    PADCData=PADCData+1;

  }

}

 

void TDataRead(void)

{

  char Raw=0;

  char DRDY=0;

 

  do

  {

    Data_Buffer[0]=0x00;

    I2C_WriteData(GMP102_7BIT_I2C_ADDR,Data_Buffer,GMP102_REG_CONFIG1,1);

    delay(1000);

    I2C_ReadData(GMP102_7BIT_I2C_ADDR,Data_Buffer,GMP102_REG_CONFIG1,1);

    Raw=Data_Buffer[0];

    delay(1000);

  }while(Raw!=0x00);

 

  Data_Buffer[0]=T_Forced_mode;  //T-Forced mode, Make a single shot pressure conversion

  I2C_WriteData(GMP102_7BIT_I2C_ADDR,Data_Buffer,GMP102_REG_CMD,1);

  delay(1000);

 

  I2C_ReadData(GMP102_7BIT_I2C_ADDR,Data_Buffer,GMP102_REG_STATUS,1);

  DRDY=Data_Buffer[0];

  delay(1000);

 

  while(DRDY!=STATUS_DRDY)

  {

    I2C_ReadData(GMP102_7BIT_I2C_ADDR,Data_Buffer,GMP102_REG_STATUS,1);

    DRDY=Data_Buffer[0];

    delay(1000);

  }

 

  I2C_ReadData(GMP102_7BIT_I2C_ADDR,Data_Buffer,GMP102_REG_TEMPH,2);

  TADCData=((Data_Buffer[0]<<8)+Data_Buffer[1]);

#if defined(DebugPrg)

  Serial.println(TADCData,HEX);

#endif

}

 

int GMP102_PRESSURE_CAL(int temp_data,int press_data)

{

  // 100 Pa = 1 millibar (Pa = newton per square meter)

  int data = CalData2[0]+

         CalData2[1]*temp_data+

         CalData2[2]*temp_data*temp_data+

         CalData2[3]*press_data+

         CalData2[4]*temp_data*press_data+

         CalData2[5]*temp_data*temp_data*press_data+

         CalData2[6]*press_data*press_data+

         CalData2[7]*temp_data*press_data*press_data+

         CalData2[8]*temp_data*temp_data*press_data*press_data;

  return data;

}

 

int GMP102_Altitude_CAL(float press_data)

{

  // Pressure altitude conversion

  // See https://en.wikipedia.org/wiki/Pressure_altitude

  float data = 44307.694f *(1.0f -pow(press_data/fp_base_sea_level_Pa,0.190284f));

  return data;

}

 

void SensorInital(void)

{

  char Raw=0;

  char DRDY=0;

  unsigned char i,WriteData[4]={0,0,0,0};

  int tmp;

 

  /* GMP102 soft reset */

  Data_Buffer[0]=GMP102_SW_RST_SET_VALUE;

  I2C_WriteData(GMP102_7BIT_I2C_ADDR,Data_Buffer,GMP102_REG_RESET,1);

  delay(100);  /* Wait 100ms for reset complete */

 

  I2C_ReadData(GMP102_7BIT_I2C_ADDR,Data_Buffer,GMP102_REG_PID,1);

#if defined(DebugPrg)

  Serial.print(GMP102_REG_PID,HEX);

  Serial.print(F(":"));

  Serial.println(Data_Buffer[0]);

#endif

 

  /* GMP102 get the pressure calibration parameters */

  I2C_ReadData(GMP102_7BIT_I2C_ADDR,CalData,GMP102_REG_CALIB00,18);

  delay(1000);

 

  for(i=0;i<9;i++)

  {

    tmp=(CalData[i*2]<<8)+CalData[i*2+1];

    CalData2[i]=((tmp<<16)>>18)*(pow(10,CalData[i*2+1]&0x03))*GMP102_CALIB_SCALE_FACTOR[i];

  }

 

  I2C_WriteData(GMP102_7BIT_I2C_ADDR,WriteData,GMP102_REG_CALIB00,4);

}

 

void writeCB (BLECharacteristic* chr, uint8_t connID) {

  printf("Characteristic %s write by connection %d :\n", chr->getUUID().str(), connID);

  if (updated == false && chr->getDataLen() > 0) {

    rxString = chr->readString();

    updated = true;

  }

}

 

void notifCB (BLECharacteristic* chr, uint8_t connID, uint16_t cccd) {

  if (cccd & GATT_CLIENT_CHAR_CONFIG_NOTIFY) {

    printf("Notifications enabled on Characteristic %s for connection %d \n", chr->getUUID().str(), connID);

    notify = true;

  } else {

    printf("Notifications disabled on Characteristic %s for connection %d \n", chr->getUUID().str(), connID);

    notify = false;

  }

}

 

void Timerhandler(uint32_t data) {

  counter++;

  Serial.print("counter: ");

  Serial.println(counter);

  TimerDone = true;

}

 

/*----------------------------------------------------------------------------*/

void SYS_TIMER() {

  static byte  tm_10ms = 0;

  static byte  tm_100ms = 0;

  static byte  tm_1sec = 0;

 

  while (millis() - now >= 10) {

    now += 10;

    tm_10ms++;

    tm_100ms++;

    tm_1sec++;

  }

  if (tm_1sec >= 100) {

    tm_1sec -= 100;

    SystemStatusbits.b_1secDone=1;

    //PROCESS_1sec();

  }

  if (tm_100ms >= 10) {

    tm_100ms -= 10;

    SystemStatusbits.b_100msDone=1;

    //PROCESS_100ms();

  }

  if (tm_10ms != 0) {

    tm_10ms -= 1;

    SystemStatusbits.b_10msDone=1;

    //PROCESS_10ms();

  }

}

 

//void PROCESS_1sec(){

//}

 

//void PROCESS_100ms(){

//}

 

//void PROCESS_10ms(){

//}

 

/*----------------------------------------------------------------------------*/

/* End Of File                                                                */

/*----------------------------------------------------------------------------*/

 

執行結果



沒有留言:

張貼留言