|
|
View previous topic :: View next topic |
Author |
Message |
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
int64 with PIC18F87J50 |
Posted: Wed Jun 28, 2017 12:52 pm |
|
|
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
|
|
Posted: Wed Jun 28, 2017 1:14 pm |
|
|
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: 19520
|
|
Posted: Thu Jun 29, 2017 12:35 am |
|
|
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
|
|
Posted: Thu Jun 29, 2017 6:27 am |
|
|
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
|
Need help BME280 driver |
Posted: Sun Jul 23, 2017 10:28 pm |
|
|
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
|
|
Posted: Mon Jul 24, 2017 5:01 am |
|
|
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
|
BME280 sensor |
Posted: Tue Jul 25, 2017 2:01 am |
|
|
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: 19520
|
|
Posted: Tue Jul 25, 2017 1:16 pm |
|
|
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
|
BME280 problem with calculate temperature |
Posted: Tue Aug 01, 2017 6:02 am |
|
|
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: 19520
|
|
Posted: Tue Aug 01, 2017 7:01 am |
|
|
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
|
|
Posted: Tue Aug 01, 2017 7:28 am |
|
|
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: 19520
|
|
Posted: Tue Aug 01, 2017 8:04 am |
|
|
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
|
BME280 calculate temperature |
Posted: Tue Aug 01, 2017 10:11 am |
|
|
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: 19520
|
|
Posted: Tue Aug 01, 2017 10:19 am |
|
|
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
|
|
Posted: Wed Aug 02, 2017 12:23 am |
|
|
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 |
|
|
|
|
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
|