CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

int64 with PIC18F87J50
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Gabriel



Joined: 03 Aug 2009
Posts: 1067
Location: Panama

View user's profile Send private message

int64 with PIC18F87J50
PostPosted: Wed Jun 28, 2017 12:52 pm     Reply with quote

Hi all,

I tried declaring an int64 and seems the compiler does not recognize it.
how can i get around this?

can i not do 64bit math with 18F?

thanks.

G.
_________________
CCS PCM 5.078 & CCS PCH 5.093
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Wed Jun 28, 2017 1:14 pm     Reply with quote

Hi Gabriel,

The CCS manual for the PCB, PCM, and PCH compilers shows 'int32' as the largest value under the Data Definitions - Type Specifiers topic.

Just out of curiosity, why do you *need* an int64 variable?
_________________
John

If it's worth doing, it's worth doing in real hardware!
Ttelmah



Joined: 11 Mar 2010
Posts: 19518

View user's profile Send private message

PostPosted: Thu Jun 29, 2017 12:35 am     Reply with quote

CCS in the PIC12/16/18 chips is close to implementing ANSI C90. However int64 was only added to ANSI C around C99. Now generally it is only needed for things like large number shifts, which CCS can already do with it's multi-byte shift function. Outside this there is very little that ever needs an int64, and the sheer size of the library makes it impractical on most of the smaller PIC's. On the larger PIC24/30/33 chips, support for int64 has been added.
There are a number of published libraries to add int64 to compilers that are only C89/90 compliant, and one of these could be compiled in CCS. However except for very basic functions (+/- etc.), be prepared for just how bulky the functions will be.
Gabriel



Joined: 03 Aug 2009
Posts: 1067
Location: Panama

View user's profile Send private message

PostPosted: Thu Jun 29, 2017 6:27 am     Reply with quote

I was developing a driver for the BME280 chip and the conversion formulas as per the datasheet called for int64 math.....

I later found the datasheet included a 32 bit equivalent formula as well, so this post is Null now.

This is by far the most complicated sensor I've ever used... not hard just "un-natural".
_________________
CCS PCM 5.078 & CCS PCH 5.093
ntrungtruc2003



Joined: 16 Feb 2011
Posts: 42

View user's profile Send private message

Need help BME280 driver
PostPosted: Sun Jul 23, 2017 10:28 pm     Reply with quote

Dear Sir,

Could you please share BME280 driver for PIC18F
Thanks you very so much if you can help
temtronic



Joined: 01 Jul 2010
Posts: 9229
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Jul 24, 2017 5:01 am     Reply with quote

You should have a look at what 'others' have done. I was curuous to see what the sensor does and found a link to Sparkfun. While they use the Arduino, it isn't that hard to cross-convert into CCS C.
It might be a good starting point to build from.

Jay
ntrungtruc2003



Joined: 16 Feb 2011
Posts: 42

View user's profile Send private message

BME280 sensor
PostPosted: Tue Jul 25, 2017 2:01 am     Reply with quote

Code:
//************************************************
//  BME280 Barometric Pressure Sensor
//
//  - Datasheet:  https://cdn-shop.adafruit.com/datasheets/BST-BME280_DS001-10.pdf
//
//  - Written in CCS PCH C using floating point math
//  - Several integer math versions of this driver exist but the speed improvement is
//    not warranted in typical weather station type applications
// 
//  - Based on a paper posted to thebackshed.com by 
//    https://learn.adafruit.com/adafruit-bme280-humidity-barometric-pressure-temperature-sensor-breakout/wiring-and-test 
//
//
//    Revision - integer algotihm
//     
//    07/24/2017
//
//  Nguyen Trung Truc
// 
//************************************************
// place a #use i2c statement in the main program and comment this out if not applicable
#define BME280_SDA  PIN_C4
#define BME280_SCL  PIN_C3
#use i2c(master, sda=BME280_SDA, scl=BME280_SCL)

#include <math.h>
#define BME280_ADDRESS 0x77          // I2C address of BME280 VDD
//calibration values of BME280
       
       static unsigned int16 dig_T1;
       static int16  dig_T2;
       static int16  dig_T3;
       static unsigned int16  dig_P1;
       static int16  dig_P2;
       static int16  dig_P3;
       static int16  dig_P4;
       static int16  dig_P5;
       static int16  dig_P6;
       static int16  dig_P7;
       static int16  dig_P8;
       static int16  dig_P9;

       static unsigned int8  dig_H1;
       static int16  dig_H2;
       static unsigned int8  dig_H3;
       static int16  dig_H4;
       static int16  dig_H5;
       static int8   dig_H6;
       static int32 t_fine;

int8 BME280ReadByte(int8 address);
int16 BME280ReadInt(int8 address) ;
int32 BME280Read24(int8 data);
void BME280WriteByte(int8 address, int8 data) ;
int1 BME280ReadingCalibration(void);
void BME280Calibration();
void BME280SetSampling();

int1 BME280Begin(unsigned int8  addr)
{
   
    // check if sensor, i.e. the chip ID is correct
    if(BME280ReadByte(0xD0) != 0x60)
        return false;
    // reset the device using soft-reset
    // this makes sure the IIR is off, etc.
    BME280WriteByte(0xE0, 0xB6);

    // wait for chip to wake up.
    delay_us(300);

    // if chip is still reading calibration, delay
    while ( BME280ReadingCalibration())
          delay_us(100);

    BME280Calibration(); // read trimming parameters, see DS 4.2.2

    BME280SetSampling(); // use defaults

    return true;
}

void BME280SetSampling()
{
 
     BME280WriteByte(0xF2,0x03);
     BME280WriteByte(0xF5,0x6C);
     BME280WriteByte(0xF4,0x6E);
    // you must make sure to also set REGISTER_CONTROL after setting the
    // CONTROLHUMID register, otherwise the values won't be applied (see DS 5.4.3)
    // write8(BME280_REGISTER_CONTROLHUMID, _humReg.get());
    // write8(BME280_REGISTER_CONFIG, _configReg.get());
    // write8(BME280_REGISTER_CONTROL, _measReg.get());
}

//----------------------------------------------
int8 BME280ReadByte(int8 address)
//----------------------------------------------
{
int8 data;

   i2c_start();
   i2c_write(BME280_ADDRESS);
   i2c_write(address);
   i2c_start();
   i2c_write(BME280_ADDRESS | 0x01 );
   data=i2c_read(0);
   i2c_stop();
   return(data);
}



//----------------------------------------------
int16 BME280ReadInt(int8 address)
//----------------------------------------------
{
int8 msb, lsb;
int16 temp;

   i2c_start();
   i2c_write(BME280_ADDRESS);
   i2c_write(address);
   i2c_start();
   i2c_write(BME280_ADDRESS | 0x01 );
   msb = i2c_read();
   lsb = i2c_read(0);
   i2c_stop();
   temp = make16(msb, lsb);
   return ( temp );
}


//----------------------------------------------
void BME280WriteByte(int8 address, int8 data)
//----------------------------------------------
{
   i2c_start();
   i2c_write(BME280_ADDRESS);
   i2c_write(address);
   i2c_write(data);
   i2c_stop();
}

void BME280Calibration()
//----------------------------------------------
{   
  dig_T1 = BME280ReadInt(0x88);
  dig_T2 = BME280ReadInt(0x8A);
  dig_T3 = BME280ReadInt(0x8C);
  dig_P1 = BME280ReadInt(0x8E);
  dig_P2 = BME280ReadInt(0x90);
  dig_P3 = BME280ReadInt(0x92);
  dig_P4 = BME280ReadInt(0x94);
  dig_P5 = BME280ReadInt(0x96);
  dig_P6 = BME280ReadInt(0x98);
  dig_P7 = BME280ReadInt(0x9A);
  dig_P8 = BME280ReadInt(0x9C);
  dig_P9 = BME280ReadInt(0x9E);
  dig_H1 = BME280ReadInt(0xA1);
  dig_H2 = BME280ReadInt(0xE1);
  dig_H3 = BME280ReadInt(0xE3);
  dig_H4 = BME280ReadInt(0xE4)<<4;
  dig_H5 = BME280ReadInt(0xE5)>>4;
  dig_H6 = BME280ReadInt(0xE7);
}

//----------------------------------------------
// Read the uncompensated temperature value
//----------------------------------------------

int32 BME280Read24(int8 data)
{
 unsigned int32 value;
 int8 msb, lsb, xlsb;
 
      i2c_start();
      i2c_write(BME280_ADDRESS);
      i2c_write(data);
     
      i2c_start();
      i2c_write(BME280_ADDRESS | 0x01);
     
      // Read register 0xF6 (MSB), 0xF7 (LSB), and 0xF8 (XLSB)
     
      msb = i2c_read();
      lsb = i2c_read();
      xlsb = i2c_read(0); // NACK on last read
      i2c_stop(); //*/
     
      value = make32(0,msb,lsb,xlsb);

    return value;
}

int1 BME280ReadingCalibration(void)
{
 // unsigned int8 const rStatus = BME280ReadByte(0xF3);
  int8 rStatus = BME280ReadByte(0xF3);
  return (rStatus & (1 << 0)) != 0;
}

float BME280ReadTemperature(void)
{
    int32 var1, var2;

    int32 adc_T = BME280Read24(0xFA); //FA THE TEMPERATURE REGISTER
    if (adc_T == 0x800000) // value in case temp measurement was disabled
        return 0;
    adc_T >>= 4;

    var1 = ((((adc_T>>3) - ((int32)dig_T1 <<1))) *
            ((int32)dig_T2)) >> 11;
             
    var2 = (((((adc_T>>4) - ((int32)dig_T1)) *
              ((adc_T>>4) - ((int32)dig_T1))) >> 12) *
            ((int32)dig_T3)) >> 14;

    t_fine = var1 + var2;

    float T = (t_fine * 5 + 128) >> 8;
    return T/100;
}


float BME280ReadPressure(void) {
    int32 var1, var2, p;

   // readTemperature(); // must be done first to get t_fine

    int32 adc_P = BME280Read24(0XF7);
    if (adc_P == 0x800000) // value in case pressure measurement was disabled
        return 0;
    adc_P >>= 4;

    var1 = ((int32)t_fine) - 128000;
    var2 = var1 * var1 * (int32)dig_P6;
    var2 = var2 + ((var1*(int32)dig_P5)<<17);
    var2 = var2 + (((int32)dig_P4)<<35);
    var1 = ((var1 * var1 * (int32)dig_P3)>>8) +
           ((var1 * (int32)dig_P2)<<12);
    var1 = (((((int32)1)<<47)+var1))*((int32)dig_P1)>>33;

    if (var1 == 0) {
        return 0; // avoid exception caused by division by zero
    }
    p = 1048576 - adc_P;
    p = (((p<<31) - var2)*3125) / var1;
    var1 = (((int32)dig_P9) * (p>>13) * (p>>13)) >> 25;
    var2 = (((int32)dig_P8) * p) >> 19;

    p = ((p + var1 + var2) >> 8) + (((int32)dig_P7)<<4);
    return (float)p/256;
}

float BME280ReadHumidity(void) {
    //readTemperature(); // must be done first to get t_fine

    int32 adc_H = BME280ReadInt(0xFD);// BME280_REGISTER_HUMIDDATA
    if (adc_H == 0x8000) // value in case humidity measurement was disabled
        return 0;
       
    int32  v_x1_u32r;

    v_x1_u32r = (t_fine - ((int32)76800));

    v_x1_u32r = (((((adc_H << 14) - (((int32)dig_H4) << 20) -
                    (((int32)dig_H5) * v_x1_u32r)) + ((int32)16384)) >> 15) *
                 (((((((v_x1_u32r * ((int32)dig_H6)) >> 10) *
                      (((v_x1_u32r * ((int32)dig_H3)) >> 11) + ((int32)32768))) >> 10) +
                    ((int32)2097152)) * ((int32)dig_H2) + 8192) >> 14));

    v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) *
                               ((int32)dig_H1)) >> 4));

    v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r;
    v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r;
    float h = (v_x1_u32r>>12);
    return  h / 1024.0;
}

// Read the uncompensated pressure value
//----------------------------------------------


This code converted from aduino, in float BME280ReadPressure(void), all of variable using int64, but ccs can not support int64 therefore i used int32 for this function.

I'm not sure that int32 is correct for this function, anybody have experiments with BME280 I2C ?
Ttelmah



Joined: 11 Mar 2010
Posts: 19518

View user's profile Send private message

PostPosted: Tue Jul 25, 2017 1:16 pm     Reply with quote

Look at section 8.2 in the datasheet.
This gives a listing for the code required, using int32 arithmetic. It is this that the poster above used.
ntrungtruc2003



Joined: 16 Feb 2011
Posts: 42

View user's profile Send private message

BME280 problem with calculate temperature
PostPosted: Tue Aug 01, 2017 6:02 am     Reply with quote

Dear Sir

1.) I use PIC16F887 I2c FORCE_SW connect to BME280
sda = PIN_D0
scl = PIN_D1

2.) I had successfully read and write the BME280's register,
The problem is the temperature after calculated is not true ( it equal about 357.8 degree), I have aslo used "burst read" but the result is the same.

The trimming parameter readout for calculate temperature is in the following
dig_T1 = 64366
dig_T2 = 14952
dig_T3 = 12800
adc_T is bout ( 557243 - 56xxxx)
3.) setup indoor navigation mode


Could you please help me an advice. Thanks you so much

BME280.C

Code:

//************************************************
//  BME280 Barometric Pressure Sensor
//
//  - Datasheet:  https://cdn-shop.adafruit.com/datasheets/BST-BME280_DS001-10.pdf
//
//  - Written in CCS PCH C using floating point math
//  - Several integer math versions of this driver exist but the speed improvement is
//    not warranted in typical weather station type applications
// 
//  - Based on a paper posted to thebackshed.com by 
//    https://learn.adafruit.com/adafruit-bme280-humidity-barometric-pressure-temperature-sensor-breakout/wiring-and-test 
//
//
//    Revision - integer algotihm
//     
//    07/24/2017
//
//  Nguyen Trung Truc
//  08/17/12
//************************************************
// place a #use i2c statement in the main program and comment this out if not applicable
//#define BME280_SDA  PIN_C4
//#define BME280_SCL  PIN_C3
#use i2c(master, sda=PIN_D0, scl=PIN_D1, FORCE_SW)
#define BME280_ADDRESS 0xEE          // I2C address of BME280 VDD
#include <math.h>
//calibration values of BME280
       
       static unsigned int16 dig_T1;
       static signed int16  dig_T2;
       static signed int16  dig_T3;
       static unsigned int16  dig_P1;
       static signed int16  dig_P2;
       static signed int16  dig_P3;
       static signed int16  dig_P4;
       static signed int16  dig_P5;
       static signed int16  dig_P6;
       static signed int16  dig_P7;
       static signed int16  dig_P8;
       static signed int16  dig_P9;
       static unsigned int8  dig_H1;
       static signed int16  dig_H2;
       static unsigned int8  dig_H3;
       static signed int16  dig_H4;
       static signed int16  dig_H5;
       static signed int8   dig_H6;
       static int32 t_fine, var1, var2, adc_P, adc_T;
       static int16 adc_H;
int8 BME280ReadByte(int8 address);
int16 BME280ReadInt(int8 address) ;
int32 BME280Read24(int8 data);
void BME280WriteByte(int8 address, int8 data) ;
int1 BME280ReadingCalibration(void);
void BME280Calibration();
void BME280SetSampling();

void init_BME280()
{
   output_float(PIN_D0);
   output_float(PIN_D1);
}
int1 BME280Begin()
{
   
    // check if sensor, i.e. the chip ID is correct
    if(BME280ReadByte(0xD0) != 0x60)
        return 0;
    // reset the device using soft-reset
    // this makes sure the IIR is off, etc.
    BME280WriteByte(0xE0, 0xB6);

    // wait for chip to wake up.
    delay_ms(300);

    // if chip is still reading calibration, delay
    while ( BME280ReadingCalibration())
          delay_ms(100);

    BME280Calibration(); // read trimming parameters, see DS 4.2.2

    BME280SetSampling(); // use defaults

    return 1;
}
void BME280SetSampling()
{
 
     BME280WriteByte(0xF2,0x03); // oversampling x 4, ctr_hum
     BME280WriteByte(0xF5,0x68); //011 (250ms tstandby) 0100 (filter coefficient =4) 0 (i2c)
     BME280WriteByte(0xF4,0x6E);// 011 011 10 temperature oversampling x 4, pressure oversampling x 4, force mode
    // you must make sure to also set REGISTER_CONTROL after setting the
    // CONTROLHUMID register, otherwise the values won't be applied (see DS 5.4.3)
    // write8(BME280_REGISTER_CONTROLHUMID, _humReg.get());
    // write8(BME280_REGISTER_CONFIG, _configReg.get());
    // write8(BME280_REGISTER_CONTROL, _measReg.get());
}

int8 BME280ReadID()
//----------------------------------------------
{
int8 data;

   i2c_start();
   i2c_write(0xEE); // 0X77 11101110X IS IC ADDRESS, 0X76 IS 1110 110
   i2c_write(0xD0);
   i2c_start();
   i2c_write(0xEF );
   data=i2c_read(0);
   i2c_stop();
   delay_us(20);
   return(data);
}
//----------------------------------------------
int8 BME280ReadByte(int8 address)
//----------------------------------------------
{
int8 data;

   i2c_start();
   i2c_write(BME280_ADDRESS);
   i2c_write(address);
   i2c_start();
   i2c_write(BME280_ADDRESS | 0x01 );
   data=i2c_read(0);
   i2c_stop();
   return(data);
}



//----------------------------------------------
int16 BME280ReadInt(int8 address)
//----------------------------------------------
{
int8 msb, lsb;
int16 temp;

   i2c_start();
   i2c_write(BME280_ADDRESS);
   i2c_write(address);
   i2c_start();
   i2c_write(BME280_ADDRESS | 0x01 );
   msb = i2c_read();
   lsb = i2c_read(0);
   i2c_stop();
   temp = make16(msb, lsb);
   return ( temp );
}


//----------------------------------------------
void BME280WriteByte(int8 address, int8 data)
//----------------------------------------------
{
   i2c_start();
   i2c_write(BME280_ADDRESS);
   i2c_write(address);
   i2c_write(data);
   i2c_stop();
}

void BME280Calibration()
//----------------------------------------------
{   
  dig_T1 = BME280ReadInt(0x88);
  dig_T2 = BME280ReadInt(0x8A);
  dig_T3 = BME280ReadInt(0x8C);
  dig_P1 = BME280ReadInt(0x8E);
  dig_P2 = BME280ReadInt(0x90);
  dig_P3 = BME280ReadInt(0x92);
  dig_P4 = BME280ReadInt(0x94);
  dig_P5 = BME280ReadInt(0x96);
  dig_P6 = BME280ReadInt(0x98);
  dig_P7 = BME280ReadInt(0x9A);
  dig_P8 = BME280ReadInt(0x9C);
  dig_P9 = BME280ReadInt(0x9E);
  dig_H1 = BME280ReadByte(0xA1);
  dig_H2 = BME280ReadInt(0xE1);
  dig_H3 = BME280ReadByte(0xE3);
  dig_H4 = (BME280ReadByte(0xE4)<<4|(BME280ReadByte(0xE5) & 0xF));
  dig_H5 = (BME280ReadByte(0xE6)<<4|(BME280ReadByte(0xE5) >>4));
  dig_H6 = BME280ReadByte(0xE7);
}

//----------------------------------------------


// Read the uncompensated temperature value
//----------------------------------------------
void BurstRead()
{
      int8 data[8]; 
      i2c_start();
      i2c_write(BME280_ADDRESS);
      i2c_write(0xF7);
     
      i2c_start();
      i2c_write(BME280_ADDRESS | 0x01);
      data[0] = i2c_read();
      data[1] = i2c_read();
      data[2] = i2c_read();
      data[3] = i2c_read();
      data[4] = i2c_read();
      data[5] = i2c_read();
      data[6] = i2c_read();
      data[7] = i2c_read(0);
     
      i2c_stop();
      adc_P = make32(0,data[0],data[1],data[2]);
     // adc_T = make32(0,data[3],data[4]);
      adc_T  = make32(0,data[3],data[4],data[5]);
      adc_H = make16(data[6],data[7]);
     
      // Read register 0xF6 (MSB), 0xF7 (LSB), and 0xF8 (XLSB)
}

int32 BME280Read24(int8 data)
{
 unsigned int32 value;
 int8 msb, lsb, xlsb;
 
      i2c_start();
      i2c_write(BME280_ADDRESS);
      i2c_write(data);
     
      i2c_start();
      i2c_write(BME280_ADDRESS | 0x01);
     
      // Read register 0xF6 (MSB), 0xF7 (LSB), and 0xF8 (XLSB)
     
      msb = i2c_read();
      lsb = i2c_read();
      xlsb = i2c_read(0); // NACK on last read
      i2c_stop(); //*/
     
      value = make32(0,msb,lsb,xlsb);

    return value;
}

int1 BME280ReadingCalibration(void)
{
 // unsigned int8 const rStatus = BME280ReadByte(0xF3);
  int8 rStatus = BME280ReadByte(0xF3);
  return (rStatus & (1 << 0)) != 0; // return 1 if bus is busy reading 1<<0  is 1 shifted left 0 times
}

void BME280TakeForcedMeasurement()
{   
   
     BME280WriteByte(0xF4,0x6E); //011 011 01 pressure oversampling x 4, temperature oversampling x 4, forced mode
     while (BME280ReadByte(0xF4) & 0x08)  // wait until measurement has been completed, otherwise we would read the values from the last measurement
      delay_us(10);
    }
   
 

float BME280ReadTemperature(void)
{

 
    int32 var1, var2;

    adc_T = BME280Read24(0xFA); //FA THE TEMPERATURE REGISTER
    if (adc_T == 0x800000) // value in case temp measurement was disabled
        return 0;
    adc_T >>= 4;

    var1 = ((((adc_T>>3) - ((int32)dig_T1 <<1)))*((int32)dig_T2)) >> 11;
             
     var2 = (((((adc_T>>4) - ((int32)dig_T1)) * ((adc_T>>4) - ((int32)dig_T1))) >> 12) *((int32)dig_T3)) >> 14;
   
    t_fine = var1 + var2;

    float T = (t_fine * 5 + 128) >> 8;
    return T/100;
   
}
float BME280ReadPressure(void) {
    int32 var1, var2, p;

   // readTemperature(); // must be done first to get t_fine

    int32 adc_P = BME280Read24(0XF7);
    if (adc_P == 0x800000) // value in case pressure measurement was disabled
        return 0;
    adc_P >>= 4;

    var1 = ((int32)t_fine) - 128000;
    var2 = var1 * var1 * (int32)dig_P6;
    var2 = var2 + ((var1*(int32)dig_P5)<<17);
    var2 = var2 + (((int32)dig_P4)<<35);
    var1 = ((var1 * var1 * (int32)dig_P3)>>8) +
           ((var1 * (int32)dig_P2)<<12);
    var1 = (((((int32)1)<<47)+var1))*((int32)dig_P1)>>33;

    if (var1 == 0) {
        return 0; // avoid exception caused by division by zero
    }
    p = 1048576 - adc_P;
    p = (((p<<31) - var2)*3125) / var1;
    var1 = (((int32)dig_P9) * (p>>13) * (p>>13)) >> 25;
    var2 = (((int32)dig_P8) * p) >> 19;

    p = ((p + var1 + var2) >> 8) + (((int32)dig_P7)<<4);
    return (float)p/256;
}

float BME280ReadHumidity(void) {
    //readTemperature(); // must be done first to get t_fine

    //int32 adc_H = BME280ReadInt(0xFD);// BME280_REGISTER_HUMIDDATA
    if (adc_H == 0x8000) // value in case humidity measurement was disabled
        return 0;
    int32  v_x1_u32r;

    v_x1_u32r = (t_fine - ((int32)76800));

    v_x1_u32r = (((((adc_H << 14) - (((int32)dig_H4) << 20) -
                    (((int32)dig_H5) * v_x1_u32r)) + ((int32)16384)) >> 15) *
                 (((((((v_x1_u32r * ((int32)dig_H6)) >> 10) *
                      (((v_x1_u32r * ((int32)dig_H3)) >> 11) + ((int32)32768))) >> 10) +
                    ((int32)2097152)) * ((int32)dig_H2) + 8192) >> 14));

    v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7)*((int32)dig_H1)) >> 4));
    v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r;
    v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r;
    float h = (v_x1_u32r>>12);
    return  h / 1024.0;
}

// Read the uncompensated pressure value
//----------------------------------------------





and the main.c

Code:

//#include <16f877A.h>
#include <16F887.h>
#fuses HS, NOLVP, NOWDT, NOPROTECT
#use   delay (clock=8000000) //Use built-in function: delay_ms() & delay_us()
#use rs232(baud=38400, xmit=PIN_C6, rcv=PIN_C7)
#include "LCD_TM.c" //use module function
#include "BME280.c"
void main(void)
{
int8 a;
float temp;
 init_BME280();
      BME280Begin();
      delay_ms(20);
     
      printf("\r\ndig_T1: =%LU dig_T2=%Ld dig_T3=%Ld", dig_T1, dig_T2, dig_T3);
      printf("\r\nP1=%Ld P2=%Ld  P3=%Ld P4=%Ld P5=%Ld P6=%Ld P7=%Ld P8=%Ld P9=%Ld",dig_P1, dig_P2, dig_P3, dig_P4, dig_P5, dig_P6, dig_P7, dig_P8, dig_P9 );
     
while(true)
   {
     
   
     
      temp = BME280ReadTemperature();
      delay_ms(50);
   
      lcd_init();
      lcd_gotoxy(1,1);
      printf(lcd_putc, "%Lu",adc_T);   
     
      lcd_gotoxy(10,1);
      printf(lcd_putc, "%3.1f",temp);
     
      lcd_gotoxy(1,2);
   
     
     
      a = BME280ReadByte(0xF3);
      BME280WriteByte(0xF5,0x68); //011 (250ms tstandby) 0100 (filter coefficient =4) 0 (i2c)
      BME280WriteByte(0xF4,0x6E);
      lcd_gotoxy(14,2);
      printf(lcd_putc, "%u",a); 
     
      delay_ms(500);
   
    }
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19518

View user's profile Send private message

PostPosted: Tue Aug 01, 2017 7:01 am     Reply with quote

Look again at the data sheet code.

Note that BME280_S32_t, is a signed int32, and BME280_U32_t, is an unsigned int32. Note that 99% of the maths uses the _signed_ type.

You are omitting this critical distinction.

The simplest way to use the code, is to cut and paste it directly. If you typedef the two types, the actual conversion maths can be used 'as is'.
temtronic



Joined: 01 Jul 2010
Posts: 9229
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Aug 01, 2017 7:28 am     Reply with quote

a comment.

Whenever doing 'complicated math', it's best to display intermediate calculations and do the math yourself to confirm EACH step of the calculations is correct.
Use KNOWN test values, for temperature say, 0, 50, 100*C. Do ALL the math and get a set of known values. Perhaps use a spreadsheet to CONFIRM the numbers are correct.
Reminds me of GIGO. Garbage In ,Garbage Out. A faulty sensor ,giving bad data then a "+x" insead of "-x" in the math is a sure way to ruin a few hours(or days) of your life.
If you have bipolar ( negative AND positive) values, check BOTH ! Just because it works for one does not mean it'll work for the other. Also do the LIMITS ! Full scale vaules at both ends....

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19518

View user's profile Send private message

PostPosted: Tue Aug 01, 2017 8:04 am     Reply with quote

There is also a big caveat.

CCS does a logical shift right, even on signed values. If you are right shifting a signed number, you need to sign extend this yourself.

Have a look at:
<http://www.ccsinfo.com/forum/viewtopic.php?t=54417&highlight=signed+shift>

I've posted better versions in other similar threads at times, but this is reliable and simple.

K&R specifically say the result of a right shift on a signed value is 'undefined'. Unfortunately the posted code relies on this....
ntrungtruc2003



Joined: 16 Feb 2011
Posts: 42

View user's profile Send private message

BME280 calculate temperature
PostPosted: Tue Aug 01, 2017 10:11 am     Reply with quote

Thanks for your response

Following BME280 from Bosch BME280 API
https://github.com/BoschSensortec/BME280_driver, have another int32 function for calculte temperarute.

But the problem hasn't been solved yet.
I have also tested by excel file.
dig_T1: 64366
dig_T2: 14952
dig_T3: 12800
adc_T is an interger 20 bits: 556463

and the excel's result is negative number about (-5xxx), therefore i think the
new function is ok, but the adc_T is not good.

The adc_T input will be 12xxxxx to have the result of temperature is true.
This is the first time i test with this sensor, therefore i don't know what is true value for adc_T.

Hope you can helps.

Code:

int32 Compensate_Temperature(void)
{
    adc_T = BME280Read24(0xFA); //FA THE TEMPERATURE REGISTER
    if (adc_T == 0x800000) // value in case temp measurement was disabled
        return 0;
    //adc_T >>= 4;
   int32 var1;
   int32 var2;
   int32 temperature;
   int32 temperature_min = -4000;
   int32 temperature_max = 8500;

   var1 = (int32)((adc_T / 8) - ((int32)dig_T1 * 2));
   var1 = (var1 * ((int32)dig_T2)) / 2048;
   var2 = (int32)((adc_T / 16) - ((int32)dig_T1));
   var2 = (((var2 * var2) / 4096) * ((int32)dig_T3)) / 16384;
   t_fine = var1 + var2;
   temperature = (t_fine * 5 + 128) / 256;

   if (temperature < temperature_min)
      temperature = temperature_min;
   else if (temperature > temperature_max)
      temperature = temperature_max;

   return temperature;
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19518

View user's profile Send private message

PostPosted: Tue Aug 01, 2017 10:19 am     Reply with quote

Change _all_ the int32 declarations to signed.

The default 'int32' on most processors is signed _unless you specify otherwise_. On CCS it isn't.

So (for instance):

int32 temperature_min = -4000;

will actually load temperature_min with 0xFFFFF060.

If you printed it as a signed would give -4000.

However if you then perform maths on it, the results will be the results of the unsigned arithmetic, not signed.

In particular the > and < tests will be wrong....

Just to confirm (went and checked - you have included the comma in the link get rid of this...), in the code, int32_t, is a signed int32, and uint32_t is an unsigned int32. If you include the standard types library (stdint.h), that already contains these definitions, and the original code will compile without changes....
ntrungtruc2003



Joined: 16 Feb 2011
Posts: 42

View user's profile Send private message

PostPosted: Wed Aug 02, 2017 12:23 am     Reply with quote

Thanks sir

The problem has been solved after checked datasheet again.

The true trimming parameter readout is
dig_T1: 28411
dig_T2:26682
dig_T3:50
adc_T: 89xxxxx

The true parameters are refererred from adruino board.

Code:

         dig_T1 = BME280Read16_LE(0x88);
         dig_T2 = BME280ReadS16_LE(0x8A);
         dig_T3 = BME280ReadS16_LE(0x8C);


I have also added 2 new fuction for receive signed int16, unsigned int16 from i2c.

Code:

//----------------------------------------------
int16 BME280Read16(int8 address)
//----------------------------------------------
{
int8 msb, lsb;
unsigned int16 temp;

   i2c_start();
   i2c_write(BME280_ADDRESS);
   i2c_write(address);
   i2c_start();
   i2c_write(BME280_ADDRESS | 0x01 );
   msb = i2c_read();
   lsb = i2c_read(0);
   i2c_stop();
   temp = (msb<<8)|lsb;  //make16(msb, lsb);
   return ( temp );
}

/**************************************************************************/
/*!
    @brief  Reads a signed 16 bit value over I2C or SPI
*/
/**************************************************************************/
int16 BME280ReadS16(int8 address)
{
    return ((signed int16)BME280Read16(address));
}

unsigned int16 BME280Read16_LE(int8 address)
{
    unsigned int16 temp = BME280Read16(address);
    return (temp >> 8) | (temp << 8);
}
int16 BME280ReadS16_LE(int8 address)
{
    return (int16)BME280Read16_LE(address);
}



Next step will be test with pressure and humidity, thanks for your response
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2, 3  Next
Page 1 of 3

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group