|
|
View previous topic :: View next topic |
Author |
Message |
ntrungtruc2003
Joined: 16 Feb 2011 Posts: 42
|
Read RSC pressure sensor honeywell |
Posted: Tue Aug 08, 2017 10:27 am |
|
|
Dear Sir
I use PIC16F connect to RSCDRRM020NDSE3 Honeywell SPI.
I can read EPROM register, but I don't know how to correct HEX to float.
The value returned from eprom:
address 31-------------0x42
address 32-------------0x00
address 33-------------0x00
address 34-------------0xA1
I check with https://gregstoll.dyndns.org/~gregstoll/floattohex/
the float 0x42 00 00 A1 = 32.0006
But in my function it returns a value that i don't understand.
The test function 1:
Code: |
union conv {
float f;
int8 b[4];
};
union conv PressRange, PressMin;
float PressMinRangeF(void)
{
PressMin.b[0] = 0x42;//spival[9];
PressMin.b[1] = 0x00;//spival[8];
PressMin.b[2] = 0x00;//spival[7];
PressMin.b[3] = 0xA1;//spival[6];
return PressMin.f;
}
|
printf("\r\nPressRange = %f", PressMinRangeF());
This function returns a value = 0.00
After that I tested with function 2:
Code: |
float PressRange()
{
signed int32 temp;
temp = make32(0x42,0x00,0x00,0xA1);
return (float)temp;
}
|
This printf("\r\nPressRange = %f", PressRange()); , the value is -9395158.96
I have also #include<stdlib.h> and #include<stdint.h> in main.c
But in the case of unsigned int32 the value returned is true = 1107296417
Could you please give me some advice.
Thanks so much.
CCS compiler V5.015 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19512
|
|
Posted: Tue Aug 08, 2017 10:48 am |
|
|
Two separate things:
The first is that you can't change the physical value from an int32, using the cast like this. The cast takes the value represented by the int32.
The int32 value 0x42000001, is 1107296417 .
You can do either using a union, or by co-locating two variables, or by using a make32. Since you show the latter, I'll stick with this.
However then there is the problem of numeric formats.
The PIC does not use IEEE float. It uses a format specifically designed for efficiency in the chip.
Fortunately, CCS supply routines to convert IEEE floats to CCS.
These are in the library "ieeefloat.c".
If you look, the function f_IEEEtoPIC, accepts an int32 (not signed), and returns a CCS compatible float from this. So your function becomes:
Code: |
//obviously #include the library somewhere.
float PressRange()
{
int32 temp; //must not be signed
temp = make32(0x42,0x00,0x00,0xA1);
return f_IEEEtoPIC(temp);
}
|
The int32, is only a carrier for the value, so doesn't want to be signed. |
|
|
ntrungtruc2003
Joined: 16 Feb 2011 Posts: 42
|
|
Posted: Tue Aug 08, 2017 9:20 pm |
|
|
Thanks sir
With Pressure minimum parameter = 0x 42 00 00 A1 this function return 32.00, it is true with IEEE float
Code: |
float PressRange()
{
int32 temp; //must not be signed
temp = make32(0x42,0x00,0x00,0xA1);
return f_IEEEtoPIC(temp);
}
|
But with Pressure Range from RSC Honeywell sensor
Pressure Range = 0x 35 00 00 20,
Code: |
float PressRange()
{
int32 temp; //must not be signed
temp = make32(0x35,0x00,0x00,0x20);
return f_IEEEtoPIC(temp);
}
|
This function printf("\r\nPressRange = %e", PressRange()); return -4.75E-07
,the result is opposite with result from https://gregstoll.dyndns.org/~gregstoll/floattohex/ = +4.75E-07
I need store a true float for next calculate P following sensor. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Aug 08, 2017 10:25 pm |
|
|
ntrungtruc2003 wrote: | CCS compiler V5.015
This function printf("\r\nPressRange = %e", PressRange()); return -4.75E-07
|
I compiled the program shown below with CCS vs. 5.074, and I got
the following result in MPLAB vs. 8.92 simulator:
Quote: | result = 4.768389E-07 |
So I think something is wrong with your vs. 5.015.
Test program:
Code: | #include <18F46K22.h>
#fuses INTRC_IO, NOWDT, BROWNOUT, PUT, NOPBADEN
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS)
#include <ieeefloat.c>
float PressRange()
{
int32 temp; //must not be signed
temp = make32(0x35,0x00,0x00,0x20);
return f_IEEEtoPIC(temp);
}
//======================================
void main()
{
float result;
result = PressRange();
printf("result = %e \r", result);
while(TRUE);
} |
|
|
|
ntrungtruc2003
Joined: 16 Feb 2011 Posts: 42
|
|
Posted: Tue Aug 08, 2017 11:22 pm |
|
|
Thanks Sir
after remove #include<stdlib.h> from main.c , the result is true = 4.7683E-07
#include<stdint.h> |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19512
|
|
Posted: Tue Aug 08, 2017 11:24 pm |
|
|
It may well be a fault with the conversion library on this version (probably how it moves the sign bit). Back before this library existed, code to do the IEEE to PIC conversion was discussed and published here, so it'd perhaps be worth trying using a version of this code.
I did versions ages ago at:
<http://www.ccsinfo.com/forum/viewtopic.php?t=24722&highlight=ieee+ccs>
Ow. Just seen your reply while I was typing. That is very odd!..
However at least you have it working now. |
|
|
ntrungtruc2003
Joined: 16 Feb 2011 Posts: 42
|
|
Posted: Thu Aug 10, 2017 4:53 am |
|
|
Thanks Sir
Next step, I read ADC temperature from RSC sensor, but the value return is 0xFF or 0x00, Following datasheet on 3.1 https://sensing.honeywell.com/honeywell-sensing-trustability-rsc-series-data-sheet-32321348-b-en.pdf
On pin DRDY pulse = 2*Tmod (part 3.1 on datasheet), what is the value of Tmod ?
Step 1: output_low(CS_ADC); //
Step 2: spi_xfer(RSC_ADC,0x44); // initialize all register
Step 3: spi_xfer(RSC_ADC,0x06); // reset ADC
Step4: spi_xfer(RSC_ADC,0x44); // configure register number 1
Step5: spi_xfer(RSC_ADC,0x06); //set bit 1 = temperature of register 1 refer 3.5
Code: |
void ReadADCTemperature()
{
output_high(CS_EE);
output_low(CS_ADC);
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,0x44); //reset default register
delay_us(10);
spi_xfer(RSC_ADC,0x06); // reset adc
delay_us(10);
temp[3]=spi_xfer(RSC_ADC,0);
delay_us(10);
temp[2]=spi_xfer(RSC_ADC,0);
delay_us(10);
temp[1]=spi_xfer(RSC_ADC,0);
delay_us(10);
temp[0]=spi_xfer(RSC_ADC,0);
delay_us(10);
output_high(CS_ADC);
}
|
Thanks you so much, i wish the data from adc feedback |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19512
|
|
Posted: Thu Aug 10, 2017 7:18 am |
|
|
It's worth understanding what this module actually is.
It's a hybrid. Comprises a little circuit, with an ADC, an EEPROM, and some interconnection circuitry together with the piezo pressure transducer.
The ADC is a Texas ADS1220.
This contains the temperature sensor.
If you read this ADC data sheet, it explains DRDY.
"t(MOD) = 1 / f(MOD). Modulator frequency f(MOD) = 256 kHz (normal mode, duty-cycle mode) and 512 kHz (turbo mode), when using the
internal oscillator or an external 4.096-MHz clock."
This actually depends on the configuration bytes which must be copied from the EEPROM.
Now, you don't show us your SPI setup. Hopefully you have 'BITS=8', otherwise spi_xfer will be attempting to send 32bits each time.
Unfortunately the Honeywell sheet is appalling... DRDY, is an _output_ from the unit, which says the conversion has completed. |
|
|
ntrungtruc2003
Joined: 16 Feb 2011 Posts: 42
|
Read RSC pressure sensor honeywell |
Posted: Fri Aug 11, 2017 7:05 am |
|
|
Thank Sir for Texas ADS1220 in this sensor.
The adc temperature read back, but i have a problem with calculate
temp[3] = 0x10
temp[2] = 0xB6
temp[1] = 0xC0
temp[0] = 0xFF
get 14 bit first _0001_0000_1011_01 = 1069*0.03125 = 33.40625 degree, it it true
but in float Temperature(void) printf("\r\nTemperature = %f", Temperature()); the value return is about 4.76E-07
Code: |
void ReadADCTemperature()
{
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,0x06); // 06 temperature adc, 04 pressure adc
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_us(100);
spi_xfer(RSC_ADC,0x10); // read data
delay_us(10);
temp[3]=spi_xfer(RSC_ADC,0);
delay_us(10);
temp[2]=spi_xfer(RSC_ADC,0);
delay_us(10);
temp[1]=spi_xfer(RSC_ADC,0);
delay_us(10);
temp[0]=spi_xfer(RSC_ADC,0);
delay_us(10);
output_high(CS_ADC);
}
float Temperature(void)
{
int32 a;
a = make32(temp[3], temp[2], temp[1],temp[0]);
a>>=10;
//float b = f_IEEEtoPIC( a);
float b = b*0.03125;
return b;
}
|
with the case float b = f_IEEEtoPIC( a); the value printf("\r\nTemperature = %f", Temperature()); is = 4.76E-07 |
|
|
ntrungtruc2003
Joined: 16 Feb 2011 Posts: 42
|
|
Posted: Fri Aug 11, 2017 7:17 am |
|
|
case 1:
Code: |
float Temperature(void)
{
int32 a;
a = make32(temp[3], temp[2], temp[1],temp[0]);
a>>=10;
//float b = f_IEEEtoPIC( a);
float b = a*0.03125;
return b;
}
|
Code: |
cae 2:
float Temperature(void)
{
int32 a;
a = make32(temp[3], temp[2], temp[1],temp[0]);
a>>=10;
float b = f_IEEEtoPIC( a);
b = a*0.03125;
return b;
}
|
the result is about = 4.76E-07 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19512
|
|
Posted: Fri Aug 11, 2017 9:26 am |
|
|
Read the data sheet for the ADC. It tells you the maths that has to be applied to convert this value to a signed int.
The temperature is _not_ coded as a float. It is a simple integer (2's complement for -ve) count from the ADC.
You need to throw away the second pair of bytes completely, put into a signed int16, and then if bit 13 is set (-ve number), perform the ones complement (~), and add one, to give the negative value. You will then have to set bit 15 in a _signed_ int16 result. |
|
|
ntrungtruc2003
Joined: 16 Feb 2011 Posts: 42
|
|
Posted: Sat Aug 12, 2017 2:53 am |
|
|
Thanks Sir
After checked with datasheet, the calculated temperature is true. I just read the positive temperature therefore don't need to process sign bit, the full function to calculate temperature will be done later.
Code: |
float Temperature(void)
{
unsigned int32 a;
a = make32(0,temp[3], temp[2], temp[1]);
a>>=10;
float b = f_IEEEtoPIC( a);
b = a*0.03125;
return b;
}
|
The function for positve temperature.
Next step reading pressure adc.
1. When read only ADC temperature,
The adc temperature value are------------------- temp[3] = 0x10, temp[2] = 0x37, tem[1] = 0xA8, the result is true
2. When read both temperature and presscure
The adc temperature are--------------------------temp[3] =0x00 ,temp[2] = 0x37, temp[1] =0xA8
The adc pressure are ------------------------------press[3] =0x00 ,press[2] = 0x37, press[1] =0xA8
3. When read only ADC pressure
The adc press are---------------------------------- press[3] =0x00 ,press[2] = 0x37, press[1] =0xA8
Code: |
void RSCInitADC()
{
output_high(CS_EE);
delay_us(10);
spi_xfer(RSC_ADC,0x43); // initialize all 4 registers
delay_us(10);
spi_xfer(RSC_ADC,0x06);// reset adc
delay_us(100);
}
void ReadADCTemperature()
{
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,0x06); // 06 temperature adc, 04 pressure adc
delay_us(10);
spi_xfer(RSC_ADC,0x08); // star converting in continuous mode
delay_us(10); // gia tri cu la 100
spi_xfer(RSC_ADC,0x10); // read data
delay_us(10);
temp[3]=spi_xfer(RSC_ADC,0);
delay_us(10);
temp[2]=spi_xfer(RSC_ADC,0);
delay_us(10);
temp[1]=spi_xfer(RSC_ADC,0);
delay_us(10);
output_high(CS_ADC);
}
void ReadADCPressure()
{
output_high(CS_EE);
output_low(CS_ADC);
delay_us(10);
spi_xfer(RSC_ADC,0x44); // write on register 1 with 1 byte
delay_us(10);
spi_xfer(RSC_ADC,0x04); // 06 temperature adc, 04 pressure adc
delay_us(100);
//spi_xfer(RSC_ADC,0x23); // read 4 registers configurations
//delay_us(10);
spi_xfer(RSC_ADC,0x08); // star converting in continuous mode
delay_us(10);
spi_xfer(RSC_ADC,0x10); // read data
delay_us(100);
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)
{
unsigned int32 a;
a = make32(0,temp[3], temp[2], temp[1]);
a>>=10;
float b = f_IEEEtoPIC( a);
b = a*0.03125;
return b;
}
|
In main.c
Code: |
ReadADCTemperature();
delay_ms(10);
//RSCInitADC(); // reset adc
delay_ms(10);
ReadADCPressure() ;
printf("\r\nTemp3 = %X Temp2 = %X Temp1 = %X temp0 = %X ", temp[3], temp[2], temp[1], temp[0]);
printf("\r\nTemperature = %f", Temperature());
printf("\r\nPress3 = %X Press2 = %X Press1 = %X Press0 = %X ", press[3], press[2], press[1], press[0]);
|
The data when read adc pressure loss MSB data, I have also checked register 1 = 0x04 (measure pressure) by using spi_xfer(RSC_ADC,0x23); Could you please give me some advice.
Thank you so much. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19512
|
|
Posted: Sat Aug 12, 2017 7:51 am |
|
|
Don't ignore what the data sheet is telling you.....
The temperature is _not_ stored as a float. It is an integer. You will be getting the wrong value using the IEEE float conversion on it. This is needed for the values stored in the EEPROM as floats. It is not wanted/needed for the value returned as an integer.
It is becoming repetitive to keep telling you to read the data sheet.
I charge £1500 a day to write code. If you want me to code it for you I will. Otherwise you need to stop expecting us to write this for you. |
|
|
ntrungtruc2003
Joined: 16 Feb 2011 Posts: 42
|
|
Posted: Sat Aug 12, 2017 8:39 am |
|
|
Thanks Sir
I will try to solve my problem |
|
|
ntrungtruc2003
Joined: 16 Feb 2011 Posts: 42
|
|
Posted: Sun Aug 13, 2017 8:00 am |
|
|
Hi, after read AD1220 datasheet again, I know the time conversation is tclk * 204850 = 0.8 ms with clk =256khz.
But the adc press return press[3] = 0x00, press[2]= 0x37, press[1] =0xAC press[0] =0xFF.
I don't know with the MSB data of adc pressure = 0x00, is it true or wrong ?
Code: |
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);
}
|
|
|
|
|
|
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
|