|
|
View previous topic :: View next topic |
Author |
Message |
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Sun Aug 13, 2017 8:31 am |
|
|
hm...I was curious about this as I've used Honeywell sensors for the past 2-3 decades....
According to the part number, that's a 3 volt device so I have to ask which PIC are you using? There are both 5 and 3 volt types.
As for the data being 'correct'.. that sensor is a +-20" H20 unit so without doing a lot of math or goggling I don't KNOW if the numbers are correct. 20+H20 would be a bit less than 10 PSI if my grey cells are recalling the conversion correct.
Normally you make a chart of 'key values', say 0,5,10,15,20" and their real expected values in bits/bytes/hex to a) confirm the sensor is working properly and b) that your 'math' computes correctly.
a later post talks about an AD1220 so I'm confused as to what hardware you really are using.
please post what hardware you really are using.
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19540
|
|
Posted: Sun Aug 13, 2017 10:37 am |
|
|
The pressure sensor he is using is a hybrid that Honeywell do. It comprises an EEPROM operated by one CS line, linked to a Texas AD1220 ADC, operated by a second CS line, and then wired internally to the actual pressure sensor. Both units share a single SPI bus.
The Honeywell data sheet is awful, with a lot of the details about operating the ADC much better described in the Texas data sheet for the ADC.
The actual EEPROM contains calibration values for the pressure sensor, and the setup values for the ADC. The thread started with trying to read and use these calibration values. It then moved on to trying to use the temperature value.
Key is that the two units need to be handled separately, but also together. So the calibration values are stored in IEEE floating point format, which then needs to be converted to CCS format. The ADC is meant to be configured by sending it the configuration values specified in the EEPROM. This sets it up to the specific mode that it is meant to be used in for this device. The temperature reading is actually a 14bit ADC signed value. The main ADC readings are 24bit. Each needs to be read and converted separately.
He started trying to use the IEEE conversion on the ADC reading, then ignored being told that this does not want such a conversion....
It is vital to understand the 'dual' nature of the unit..... |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19540
|
|
Posted: Mon Aug 14, 2017 2:06 am |
|
|
Having had a little look at the data sheet this morning, I can see a big reason he is finding this hard....
The two peripherals in the chip, have to use different SPI modes. Ugh.
Now this needs very careful programming. So though I have not done it all (would now need the routine to switch to reading temperature, and the routines to read values from the ADC), I have written a slice of the routines needed (completely untested, these are as I typed them in the morning), to show how the device switching needs to be handled:
Code: |
//Processor setup here
//PIN setup - choose pins to suit your chip
#define CS_EE PIN_A0
#define CS_ADC PIN_A1
#define DRDY PIN_A2
#define EAD_EEPROM 0x3
//EEPROM locations
#define ADC_CONFIG 61
#define OFFSET_MATRIX 130
#define SPAN_MATRIX 210
#define PRESSURE_RANGE 27
#define PRESSURE_MIN 30
#define SHAPE_MATRIX 290
//ADC commands
#define WREG 0x40
#define RDATA 0x10
//Use SPI1 or 2 hardware for SCK, DIN, DOUT
#USE SPI(SPI1, MASTER, MODE=1, baud=4000000, NOINIT, bits=8, stream=ADC)
#USE SPI(SPI1, MASTER, MODE=0, baud=4000000, NOINIT, bits=8, stream=EEPROM)
//Maximum baud supported is 5MHz. PIC won't get to this, unless using a very fast
//master clock but ensures the setup does not attempt to go above 4MHz.
//This sets up two different SPI streams on the same hardware
//Note that all the connections to the chip are shown as requiring 1kR
//pullup resistors. Also that the circuit has a major error, showing the CS_EE
//and Vcc pins reversed. Do not do this....
//Note the second big problem. The EEPROM requires the SPI to be in mode 0 or
//mode 4, while the ADC requires the SPI to be in mode1!.... Ouch.
#include <ieeefloat.c>
void init_spi(void)
{
//just setup things to ensure lines are at the right levels
output_high(CS_EE);
output_high(CS_ADC);
}
void read_block_eeprom(int16 address, char * buffer, int8 nbytes)
{
//Read 'nbytes' from EEPROM at 'address' into 'buffer'
int8 bctr;
int8 instruction;
//first we need to set the SPI to the EEPROM mode
spi_init(EEPROM,TRUE); //setup the EEPROM SPI
//Now the instruction to send has bit 3 set if this is a 9bit address
if (bit_test(address,8))
instruction=EAD_EEPROM | 8; //set the extra ddress bit if required
else
instruction=EAD_EEPROM;
//This also ensures there is a slight delay for the clock to settle
output_low(CS_EE); //select the chip
bctr=spi_xfer(instruction); //use the counter register as dummy here
bctr=spi_xfer(address & 0xFF);
//now have sent the instruction and address
for (bctr=0; bctr<nbytes; bctr++)
{
*(buffer++)=spi_xfer(0); //now clock in the sequential bytes required
}
output_high(CS_EE); //deselect the chip
spi_init(EEPROM,FALSE); //turn off the EEPROM SPI
}
float read_float_eeprom(int16 address)
{
//return a float value from the EEPROM at 'address', uses read_block and converts
unsigned int32 temp;
read_block_eeprom(address, (char *)&temp, 4);
return f_IEEEtoPIC(temp);
}
void write_reg(int8 start, int8 nbytes, char * from)
{
//write nbytes to ADC configuration register 'start', from buffer 'from'
int8 command=WREG;
int8 bctr, dummy;
if (nbytes>4)
return; //not possible to write more than 4 bytes
start &=3; //mask the maximum reg number
spi_init(ADC,TRUE); //setup the ADC SPI
command |= (nbytes-1); //mask in the number of bytes to transfer
command |= start<<2; //and the start address
//again use the maths as a slight delay to ensure bus has settled
output_low(CS_ADC); //select the ADC chip
dummy=spi_xfer(command);//send the command
for (bctr=0; bctr<nbytes; bctr++)
{
spi_xfer(*(from++)); //now clock out the sequential bytes
}
output_high(CS_ADC); //deselect the chip
spi_init(ADC,FALSE); //turn off the ADC SPI
}
void setup_ext_adc(void)
{
//The requirement here is to read the four configuration bytes from the EEPROM
//and then send these to the ADC
char temp_buf[4];
int8 ctr;
for (ctr=0;ctr<4;ctr++)
{
read_block_eeprom(ADC_CONFIG+ctr*2, &temp_buf[ctr], 1);
//for some horrible reason they store the byte values in alternate
//locations - just to make it hard!....
}
//now need to send these to the ADC.
write_reg(0,4,temp_buf); //send the four config bytes
}
void main()
{
init_spi(); //just ensure lines are set to the right levels
setup_ext_adc(); //initialise the ADC from the EEPROM.
//Now you would need the other routines to read the ADC and perform the
//calibration maths etc..
while(TRUE)
{
//main code here
}
}
|
|
|
|
ntrungtruc2003
Joined: 16 Feb 2011 Posts: 42
|
|
Posted: Mon Aug 14, 2017 6:29 am |
|
|
Thanks for your response
After make a excel calculate i recognized the MSB data of press ADC = 0 will be not true in Pcom result.
All parameters for calculate P read from EPROM SPI mode 0
OffsetCoefficient 0 = 316286
OffsetCoefficient 1 = -25,8204
OffsetCoefficient 2 = -0,00277848
OffsetCoefficient 3 = 9,41E-07
SpanCoefficient 0 = -2340250
SpanCoefficient 1 = 149,893
SpanCoefficient 2 = -0,00922975
SpanCoefficient 3 = 6,38153E-07
ShapeCoefficient 0 = 0,500022
ShapeCoefficient 1 = 0,999602
ShapeCoefficient 2 = 0,00683238
ShapeCoefficient 3 = 0,00118424
PressRange = 40
PressMin = -20
After known all parameters, i don't need read EPROM, I just read temperature and press ADC mode 1 together
The temperature ADC is true, but the press ADC is always loss MSB data
I use single mode conversation in ADS1220, not continuous mode, and the time conversation is about 1s, with this delay_ms(1000)
But the MSB data of ADC press = 0.
press[3] =0x00, press[2] = 0x37, press[1] = 0x75
I try with press ADC single mode in ADS1220, because this mode is easy, if not success , i will try with continuous mode.
in main.c
Code: |
//#include <18F248.h>
#include <16F887.h>
#fuses HS,NOPROTECT,NOLVP,NOWDT
#use delay(clock=20000000)
#use rs232(baud=38400, xmit=PIN_C6, rcv=PIN_C7)
//#include <can-18xxx8.c>
//#include <BME280.c>
#include <RSCHONEY.c>
//#include<stdlib.h>
//#include<stdint.h>
//#include <LCDdriver.c>
int16 ms;
#int_timer2
void isr_timer2(void) {
ms++; //keep a running timer that increments every milli-second
}
void main() {
float thermo;
printf("\r\n\r\nCCS CAN EXAMPLE\r\n");
setup_timer_2(T2_DIV_BY_4,79,16); //setup up timer2 to interrupt every 1ms if using 20Mhz clock
delay_ms(200);
// can_set_mode(CAN_OP_LOOPBACK);
enable_interrupts(INT_TIMER2); //enable timer2 interrupt
enable_interrupts(GLOBAL); //enable all interrupts (else timer2 wont happen)
printf("\r\nRunning...");
while(TRUE)
{
/*
// printf("\n\n Thermocouple: %Ld, Ambient: %Ld\n\r",readExtTemp(),readIntTemp());
readMAX();
delay_ms(20);
printf("\r\nSPIVAL40 = %X SPIVAL39 = %X SPIVAL38 = %X SPIVAL37 = %X ", spival[40], spival[39], spival[38], spival[37]);
printf("\r\nSPIVAL36 = %X SPIVAL35 = %X SPIVAL34 = %X SPIVAL33 = %X ", spival[36], spival[35], spival[34], spival[33]);
printf("\r\nSPIVAL32 = %X SPIVAL31 = %X SPIVAL30 = %X SPIVAL29 = %X ", spival[32], spival[31], spival[30], spival[29]);
printf("\r\nSPIVAL28 = %X SPIVAL27 = %X SPIVAL26 = %X SPIVAL25 = %X ", spival[28], spival[27], spival[26], spival[25]);
printf("\r\nSPIVAL24 = %X SPIVAL23 = %X SPIVAL22 = %X SPIVAL21 = %X ", spival[24], spival[23], spival[22], spival[21]);
printf("\r\nSPIVAL20 = %X SPIVAL19 = %X SPIVAL18 = %X SPIVAL17 = %X ", spival[20], spival[19], spival[18], spival[17]);
printf("\r\nSPIVAL16 = %X SPIVAL15 = %X SPIVAL14 = %X SPIVAL13 = %X ", spival[16], spival[15], spival[14], spival[13]);
printf("\r\nSPIVAL12 = %X SPIVAL11 = %X SPIVAL10 = %X SPIVAL9 = %X ", spival[12], spival[11], spival[10], spival[9]);
printf("\r\nSPIVAL8 = %X SPIVAL7 = %X SPIVAL6 = %X SPIVAL5 = %X ", spival[8], spival[7], spival[6], spival[5]);
printf("\r\nSPIVAL4 = %X SPIVAL3 = %X SPIVAL2 = %X SPIVAL1 = %X ", spival[4], spival[3], spival[2], spival[1]);
printf("\r\nSPIVAL0 = %X", spival[0]);
printf("\r\nPressRange = %f", PressMinRangeF());
printf("\r\nPressRange = %e", PressRange());
*/
ReadADCTemperature();
printf("\r\nTemp3 = %X Temp2 = %X Temp1 = %X temp0 = %X ", temp[3], temp[2], temp[1], temp[0]);
printf("\r\nTemperature = %f", Temperature());
ReadADCPress() ;
printf("\r\nPress3 = %X Press2 = %X Press1 = %X Press0 = %X ", press[3], press[2], press[1], press[0]);
delay_ms(500);
}
}
|
in RSC.c
Code: |
#define SPI_MODE_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1 (SPI_L_TO_H)
#define SPI_MODE_2 (SPI_H_TO_L)
#define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_L_TO_H)
#define CS_ADC PIN_B6
#define CS_EE PIN_B7
#define CS_DRY PIN_C0
//#use spi(MASTER, SPI_MODE_1, DO=PIN_B4, CLK=PIN_B5, BITS = 8, LSB_FIRST, SAMPLE_RISE, baud = 100000, stream=MAX31855)
//#use spi(SPI1, MASTER, baud=100000, MODE=0, bits=8, stream=MAX31855)
#use SPI( DI = PIN_B4, DO = PIN_B0, CLK = PIN_B5, baud = 100000, BITS = 8, MODE =0, MSB_FIRST, SAMPLE_RISE, stream=RSC_EE )
#use SPI( DI = PIN_B4, DO = PIN_B0, CLK = PIN_B5, baud = 100000, BITS = 8, MODE =1, MSB_FIRST, SAMPLE_RISE, stream=RSC_ADC )
#include<ieeefloat.c>
static int8 spival[41];
static int8 temp[4];
static int8 press[4];
union conv {
int32 f;
int8 b[4];
};
union conv PressRange, PressMin;
//int16 Count=0;
/*******************************************************************************
//Read SPI data
*******************************************************************************/
void readMAX()
{
output_low(CS_EE);
spi_xfer(RSC_EE,0x0B); //read data at // register 290
spi_xfer(RSC_EE,0x22); // register 0 // 0x00 //0xD2 gerister 210
//delay_us(10);
spival[40]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[39]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[38]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[37]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[36]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[35]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[34]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[33]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[32]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[31]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[30]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[29]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[28]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[27]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[26]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[25]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[24]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[23]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[22]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[21]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[20]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[19]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[18]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[17]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[16]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[15]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[14]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[13]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[12]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[11]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[10]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[9]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[8]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[7]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[6]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[5]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[4]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[3]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[2]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[1]=spi_xfer(RSC_EE,0);
delay_us(10);
spival[0]=spi_xfer(RSC_EE,0);
delay_us(10);
output_high(CS_EE);
}
/*
output_low(CS_DRY);
delay_us(10);
output_high(CS_DRY);
delay_us(10); // ???????????????
output_low(CS_DRY);
delay_us(10);
output_high(CS_DRY);
spi_xfer(RSC_ADC,0x43); // initialize all 4 registers
delay_us(10);
// spi_xfer(RSC_ADC,0x06); // reset adc
//delay_us(10);
*/
void RSCInitADC()
{
output_high(CS_EE);
delay_us(10);
spi_xfer(RSC_ADC,0x44);
}
void ReadADCTemperature()
{
output_high(CS_EE);
output_low(CS_ADC);
spi_xfer(RSC_ADC,0x44); // write on register 1 with 1 byte
spi_xfer(RSC_ADC,0x02); // 06 temperature adc, 04 pressure adc, 0x02 temperature adc singe mode
// spi_xfer(RSC_ADC,0x23); // read 4 registers configurations
//delay_us(10);
spi_xfer(RSC_ADC,0x08); // star converting in continuous mode
delay_ms(1000);
spi_xfer(RSC_ADC,0x10); // read data
// spi_xfer(RSC_ADC,0x04);
temp[3]=spi_xfer(RSC_ADC,0);
temp[2]=spi_xfer(RSC_ADC,0);
temp[1]=spi_xfer(RSC_ADC,0);
temp[0]=spi_xfer(RSC_ADC,0);
//spi_xfer(RSC_ADC,0x02);
//delay_us(10);
output_high(CS_ADC);
delay_us(100);
}
void ReadADCPress()
{
output_high(CS_EE);
output_low(CS_ADC);
spi_xfer(RSC_ADC,0x44); // write on register 1 with 1 byte
delay_us(10);
spi_xfer(RSC_ADC,0x00); // 06 temperature adc, 04 pressure adc, single mode
delay_us(10);
//spi_xfer(RSC_ADC,0x23); // read 4 registers configurations
//delay_us(10);
spi_xfer(RSC_ADC,0x08); // star converting in continuous mode
delay_ms(1000);
spi_xfer(RSC_ADC,0x10); // read data
//delay_us(10);
press[3]=spi_xfer(RSC_ADC,0);
delay_us(10);
press[2]=spi_xfer(RSC_ADC,0);
delay_us(10);
press[1]=spi_xfer(RSC_ADC,0);
delay_us(10);
press[0]=spi_xfer(RSC_ADC,0);
delay_us(10);
output_high(CS_ADC);
}
float Temperature(void)
{
int32 a;
a = make32(0,temp[3], temp[2], temp[1]);
a>>=10;
float b = f_IEEEtoPIC( a);
b = a*0.03125;
return b;
}
float PressMinRangeF(void)
{
PressMin.b[3] = 0x35;//spival[9];//0x42
PressMin.b[2] = 0x00;//spival[8];//0x00
PressMin.b[1] = 0x00;//spival[7];//0x00
PressMin.b[0] = 0x20;//spival[6];//0xA1
return f_IEEEtoPIC(PressMin.f);
}
float PressRange()
{
int32 temp;
temp = make32(0x35,0x00,0x00,0x20);
return f_IEEEtoPIC(temp);
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19540
|
|
Posted: Mon Aug 14, 2017 6:49 am |
|
|
You can't setup two #USE SPI lines, on the same pins without the NOINIT. To use the two setups, you have to use this, and then only initialise when required. Also use the mode numbers as I show. The data sheet tells you the mode numbers, so use them. Much safer. Trying to do it as you are (where it'll switch when called), risks generating an extra clock while the EE/ADC is already selected. The whole point is you setup the mode _before_ the chip is enabled.
Now, while 'hard-coding' the EEPROM data, can potentially work for a one-off, you are committing yourself to having to re-write the program if you change the chip. That's the whole point of the factors being in the EEPROM. Also you should be using the ADC configuration from the EEPROM, as I show, since changing the ADC setup, _will_ invalidate the calibrations. |
|
|
ntrungtruc2003
Joined: 16 Feb 2011 Posts: 42
|
|
Posted: Tue Aug 15, 2017 3:50 am |
|
|
Thanks Ttelmah very much.
After copy all parameters 61, 63, 65, 67 from eprom into register 0, 1,2,3 ADC
the MSB ADC press return a value non-zero, still using single mode in ADS220.
address 61 = 0x0A
address 63 = 0x84
address 65 = 0x40
address 67 = 0x00
I will try with continuous mode following your guide. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Tue Aug 15, 2017 5:32 am |
|
|
re: .....
Key is that the two units need to be handled separately, but also together. So the calibration values are stored in IEEE floating point format, which then needs to be converted to CCS format. The ADC is meant to be configured by sending it the configuration values specified in the EEPROM. This sets it up to the specific mode that it is meant to be used in for this device.
.....
Arrrrgh..... I have a headache just READING this ! What a crazy, insane way to , arrgh... I'm sick. Not aas much as the 'engineer' who designed this chip. It's a nightmare...get one bit wrong during setup....arrgh.
I'm impressed that Mr. T has spent a LOT of time 'decoding' the spec sheets and the bottom line is this is NOT a 'user friendly' device. Have to wonder why anyone would use it over a 'regular' device.
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19540
|
|
Posted: Tue Aug 15, 2017 10:30 am |
|
|
The reason is cost....
Honeywell do some lovely compensated pressure sensors, but these are expensive.
They the do uncompensated sensors. Quite cheap.
This is a lot cheaper than the compensated sensors, but gives you the factors and data to compensate it.
What is insane, is that they don't include an inverter to allow the same SPI mode to be used on both chips, or include the data laid out directly in the format ready to send to the ADC. Mad. |
|
|
ntrungtruc2003
Joined: 16 Feb 2011 Posts: 42
|
|
Posted: Wed Aug 16, 2017 1:18 am |
|
|
Thanks for your response.
Next step is calculate press compensated.
The value adc pressure return press[3] = 0x40, press[2] = 0x88, press[1] =0xF1
in continuous mode following datasheet suggested.
I recognized just 2 byte press[2] and press[1] effected by input pressure
int32 p = make32(0,press[3], press[2], press[1]) ;
Convert to float
pf = f_IEEEtoPIC( p), this value = 5.9266E-39
Code: |
float Pressure(void)
{
float Pint1, Pint2, Pcom_fs, Pcomp;
float OffsetCoefficient_t3 = 9.41E-07 ;
float OffsetCoefficient_t2 = -0.00277848;
float OffsetCoefficient_t1 = -25.8204 ;
float OffsetCoefficient_t0 = 316286 ;
float SpanCoefficient_t3 = 6.38153E-07;
float SpanCoefficient_t2 = -0.00922975;
float SpanCoefficient_t1 = 149.893;
float SpanCoefficient_t0 = -2340250;
float ShapeCoefficient_t3 = 0.00118424;
float ShapeCoefficient_t2 = 0.00683238;
float ShapeCoefficient_t1 = 0.999602;
float ShapeCoefficient_t0 = 0.500022;
float Prange = 40;
float Pmin = -20;
int32 Traw0 = make32(0, temp[3],temp[2], temp[1]);
Traw0>>=10;
float Traw = f_IEEEtoPIC(Traw0);
int32 p = make32(0,press[3],press[2],press[1]);
float Praw = f_IEEEtoPIC( p);
Pint1 = Praw - (OffsetCoefficient_t3*Traw*Traw*Traw + OffsetCoefficient_t2*Traw*Traw + OffsetCoefficient_t1*Traw + OffsetCoefficient_t0 );
Pint2 = Pint1/(SpanCoefficient_t3*Traw*Traw*Traw + SpanCoefficient_t2*Traw*Traw + SpanCoefficient_t1*Traw + SpanCoefficient_t0 );
Pcom_fs = ShapeCoefficient_t3*Pint2*Pint2*Pint2 + ShapeCoefficient_t2*Pint2*Pint2 + ShapeCoefficient_t1*Pint2 + ShapeCoefficient_t0 ;
Pcomp = Pcom_fs*Prange + Pmin;
return Pcomp;
}
|
all parameter Traw, Praw is converted to IEEE754 float. The Pcomp result is 5.402 not changed, may be the ADC pressure result have a problem.
The config ADC is copied from Eprom.
register 0: 0x0A // gain = 32
register 1:0x84 // sps =330
register 2: 0x40 // External reference selected using dedicated REFP0 and REFN0 inputs
register 3:0x00 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19540
|
|
Posted: Wed Aug 16, 2017 3:54 am |
|
|
You are fundamentally missing the point still.....
The ADC does not want/need a conversion to CCS float.
Two chips:
EEPROM Contains several numbers. Some in IEEE floating point format. These are the _only_ values to which the IEEE to CCS conversion should be applied.
The ADC returns just ADC values. _Integers_, both for the temperature and pressure. These do need to be sign extended, but do not want float conversions (they are not float). The integer values are then converted into float values by simply multiplying by a float scale factor, but at no point is a IEEE to CCS conversion needed/wanted for these.
Repeat five times. The only place the IEEE to CCS conversion is wanted is to read the calibration factors from the EEPROM. |
|
|
ntrungtruc2003
Joined: 16 Feb 2011 Posts: 42
|
|
Posted: Thu Aug 17, 2017 5:04 am |
|
|
Thanks for your response
- EPROM parameters are IEEEE
-ADC is signed int32
-When calculate ADC convert to float.
Code: |
float Pressure(void)
{
float Pint1, Pint2, Pcom_fs, Pcomp;
float OffsetCoefficient_t3 = 9.41E-07 ;
float OffsetCoefficient_t2 = -0.00277848;
float OffsetCoefficient_t1 = -25.8204 ;
float OffsetCoefficient_t0 = 316286 ;
float SpanCoefficient_t3 = 6.38153E-07;
float SpanCoefficient_t2 = -0.00922975;
float SpanCoefficient_t1 = 149.893;
float SpanCoefficient_t0 = -2340250;
float ShapeCoefficient_t3 = 0.00118424;
float ShapeCoefficient_t2 = 0.00683238;
float ShapeCoefficient_t1 = 0.999602;
float ShapeCoefficient_t0 = 0.500022;
float Prange = 40;
float Pmin = -20;
signed int32 Traw = make32(0, temp[3],temp[2], temp[1]);
Traw>>=10;
//float Traw = f_IEEEtoPIC(Traw0);
signed int32 Praw = make32(0,press[3],press[2],press[1]);
//float Praw = f_IEEEtoPIC( p);
Pint1 = (float)Praw - (OffsetCoefficient_t3*(float)Traw*(float)Traw*(float)Traw + OffsetCoefficient_t2*(float)Traw*(float)Traw + OffsetCoefficient_t1*(float)Traw + OffsetCoefficient_t0 );
Pint2 = Pint1/(SpanCoefficient_t3*(float)Traw*(float)Traw*(float)Traw + SpanCoefficient_t2*(float)Traw*(float)Traw + SpanCoefficient_t1*(float)Traw + SpanCoefficient_t0 );
Pcom_fs = ShapeCoefficient_t3*Pint2*Pint2*Pint2 + ShapeCoefficient_t2*Pint2*Pint2 + ShapeCoefficient_t1*Pint2 + ShapeCoefficient_t0 ;
Pcomp = Pcom_fs*Prange + Pmin;
return Pcomp;
}
|
The Pcomp result is a bout -71.4406, i have to find a test kit for test ADC. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19540
|
|
Posted: Thu Aug 17, 2017 10:49 am |
|
|
You are putting the number into the _low_ three bytes of the int32. Then rotating right ten times. You have just thrown away the whole low byte, and two bits of the next value....... |
|
|
ntrungtruc2003
Joined: 16 Feb 2011 Posts: 42
|
|
Posted: Fri Aug 18, 2017 5:48 am |
|
|
Thanks Sir
I know my problem is convert ADC Pressure,
I go back to ADC pressure again. Because the temperature is true with temp[3] = MSB, temp[2] = , temp[1] = LSB, this result after convert to float = 31. 5 degree. |
|
|
ntrungtruc2003
Joined: 16 Feb 2011 Posts: 42
|
The problem is solved |
Posted: Sun Sep 17, 2017 9:00 pm |
|
|
Thanks Ttelmah in this forum.
For a long time, I known why the result from ADC returned not true.
The key is TI recommends always sending a START/SYNC command
immediately after the CM bit is set to 1.
Best Regards. |
|
|
|
|
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
|