Monday, September 12, 2011

Integration of BOSCH BMP085 using JENNIC 2-wire serial interface (I2Ccompatible) on JN-5148

The article describes use of Jennic hardware API library (AppHardwareApi_JN514x.h) for reading and writing data from the BOSCH BMP085 temperature and pressure sensor.

Hardware Description:
- The Jennic JN-5148 provides 2-wire synchronous serial interface, following I2C protocol, containing two lines of SCL (Serial Clock Line) connected to DIO14 and bi-directional SDA (Serial Data Line) connected to DIO15. The detailed description of Jennic Serial Interface and associated functions can be found at http://www.jennic.com/files/support_files/JN-UG-3066-Integrated-Peripherals-API.pdf.

- The BOSCH BMP085 consists of SCL (Serial Clock Line) connected to pin 6 and bi-directional SDA (Serial Data Line) connected to pin 7. The comprehensive description of BMP085 can be found at http://www.bosch-sensortec.com/content/language1/downloads/BST-BMP085-DS000-05.pdf.

Protocol Implementation Algorithm:
Major focus of this article is on how to communicate with BMP085 in order to read/write operations, and mathematical calculations for temperature and pressure can be found in the datasheet of BMP085.
Implementation is based on configuring Jennic as Master without interrupts enable and BMP085 as Slave device. The operational frequency 100 kHz is derived from Jennic system clock of 16 MHz by using pre-defined formula,

Operational Frequency = 16/[(Prescaler + 1) * 5]

Steps:
  • Jennic as Master Device and BMP085 as Slave Device configuration
  • Read calibration data from E2PROM of BMP085 for temperature and pressure
  • Reading and calculation of temperature
  • Reading and calculation of pressure
  • Resolution of output data is; Pressure – 0.01 hPa, and Temperature – 0.1 ˚C
Associated Jennic Functions:
  • void vAHI_SiMasterConfigure (bool_t bPulseSuppressionEnable, bool_t bInterruptEnable, uint8 u8PreScaler);
  • void vAHI_SiMasterWriteSlaveAddr (uint8 u8SlaveAddress, bool_t bReadStatus);
  • bool_t bAHI_SiMasterSetCmdReg (bool_t bSetSTA, bool_t bSetSTO, bool_t bSetRD, bool_t bSetWR, bool_t bSetAckCtrl, bool_t bSetIACK);
  • bool_t bAHI_SiMasterPollTransferInProgress (void);
  • void vAHI_SiMasterWriteData8 (uint8 u8Out);
  • uint8 u8AHI_SiMasterReadData8 (void);
Reading/Writing data from BMP085:
From the datasheet the BMP module address LSB distinguishes between read (1) and write (0) operations, corresponding to address 0xEF (read) and 0xEE (write). Where 0x77 is the BMP085 device address which will be Slave address.

// Sensor Address - Write Operation
uint8 BMP085_W = 0xEE;
// Sensor Address - Read Operation
uint8 BMP085_R  = 0xEF;

PRIVATE void vI2CRead (uint8 u8ReadAddress, uint8* u8DataOut, uint8 u8Length)
{
          uint8 i = 0;
          uint8 u8ReadLength;
          bool_t bFlag = FALSE;
          u8ReadLength = u8Length;
          vAHI_SiMasterWriteSlaveAddr (BMP085_W>>1, FALSE); // FALSE - Write Operation
          bFlag = bAHI_SiMasterSetCmdReg (E_AHI_SI_START_BIT,
                                                                      E_AHI_SI_NO_STOP_BIT,
                                                                      E_AHI_SI_NO_SLAVE_READ,
                                                                      E_AHI_SI_SLAVE_WRITE,
                                                                      E_AHI_SI_SEND_ACK,
                                                                      E_AHI_SI_NO_IRQ_ACK);
          while(bAHI_SiMasterPollTransferInProgress());    // Wait While Busy
          vAHI_SiMasterWriteData8(u8ReadAddress);          // Address to Start Read From
          bFlag = bAHI_SiMasterSetCmdReg(E_AHI_SI_NO_START_BIT,
                                                                      E_AHI_SI_NO_STOP_BIT,
                                                                      E_AHI_SI_NO_SLAVE_READ,
                                                                      E_AHI_SI_SLAVE_WRITE,
                                                                      E_AHI_SI_SEND_ACK,
                                                                      E_AHI_SI_NO_IRQ_ACK);
          while(bAHI_SiMasterPollTransferInProgress());    // Wait While Busy
          vAHI_SiMasterWriteSlaveAddr(BMP085_R>>1,TRUE); // TRUE - Read Operation
          vAHI_SiMasterSetCmdReg(E_AHI_SI_START_BIT,
                                                  E_AHI_SI_NO_STOP_BIT,
                                                  E_AHI_SI_NO_SLAVE_READ,
                                                  E_AHI_SI_SLAVE_WRITE,
                                                  E_AHI_SI_SEND_ACK,
                                                  E_AHI_SI_NO_IRQ_ACK);
          while(bAHI_SiMasterPollTransferInProgress()); // wait while busy
          // now we can start reading data back from the eeprom
          while(u8ReadLength > 0)
          {
                    if(u8ReadLength < 2)    // is it the last byte
                    {
                              vAHI_SiMasterSetCmdReg(E_AHI_SI_NO_START_BIT,
                                                                      E_AHI_SI_STOP_BIT,
                                                                      E_AHI_SI_SLAVE_READ,
                                                                      E_AHI_SI_NO_SLAVE_WRITE,
                                                                      E_AHI_SI_SEND_NACK,
                                                                      E_AHI_SI_NO_IRQ_ACK);
                    }
                    else
                    {
                              vAHI_SiMasterSetCmdReg(E_AHI_SI_NO_START_BIT,
                                                                      E_AHI_SI_NO_STOP_BIT,
                                                                      E_AHI_SI_SLAVE_READ,
                                                                      E_AHI_SI_NO_SLAVE_WRITE,
                                                                      E_AHI_SI_SEND_ACK,
                                                                      E_AHI_SI_NO_IRQ_ACK);
                    }
                    while(bAHI_SiMasterPollTransferInProgress()); // wait while busy
                    u8DataOut[i] = u8AHI_SiMasterReadData8();
                    i=i+1;
                    u8ReadLength--;
          }
}

PRIVATE void vI2CWrite (uint8* u8DataIn, uint8 u8Length)
{
          uint8 i = 0;
          uint8 u8WriteLength;
          u8WriteLength = u8Length;
          // set slave address
          vAHI_SiMasterWriteSlaveAddr(BMP085_W >> 1,FALSE);
          bAHI_SiMasterSetCmdReg(E_AHI_SI_START_BIT,
                                                  E_AHI_SI_NO_STOP_BIT,
                                                  E_AHI_SI_NO_SLAVE_READ,
                                                  E_AHI_SI_SLAVE_WRITE,
                                                  E_AHI_SI_SEND_ACK,
                                                  E_AHI_SI_NO_IRQ_ACK);
          while(bAHI_SiMasterPollTransferInProgress()); // wait while busy
          // now we can start writing data to the device
          while(u8WriteLength > 0)
          {
                    // data to write
                    vAHI_SiMasterWriteData8(u8DataIn[i++]);
                    if(u8WriteLength < 2)    // is it the last byte
                    {
                              bAHI_SiMasterSetCmdReg(E_AHI_SI_NO_START_BIT,
                                                                      E_AHI_SI_STOP_BIT,
                                                                      E_AHI_SI_NO_SLAVE_READ,
                                                                      E_AHI_SI_SLAVE_WRITE,
                                                                      E_AHI_SI_SEND_NACK,
                                                                      E_AHI_SI_NO_IRQ_ACK);
                    }
                    else
                    {
                              bAHI_SiMasterSetCmdReg(E_AHI_SI_NO_START_BIT,
                                                                      E_AHI_SI_NO_STOP_BIT,
                                                                      E_AHI_SI_NO_SLAVE_READ,
                                                                      E_AHI_SI_SLAVE_WRITE,
                                                                      E_AHI_SI_SEND_ACK,
                                                                      E_AHI_SI_NO_IRQ_ACK);
                    }
                    u8WriteLength--;
                    while(bAHI_SiMasterPollTransferInProgress()); // wait while busy
          }
}

I spent few days in understanding I2C protocol in general to start integration of pressure sensor with Jennic board, so I thought it would be beneficial to write in blog for others who found difficulty as well.

If anyone still interested in complete code, you can ask. I can send it you :)

Integration of SQLite3 and Netbeans C/C++ IDE

Few days back, I wanted to use SQLite database for one of my project. I spend couple of hours to find a way to integrate with Netbeans. Mayb...