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 support@ccsinfo.com

Read RSC pressure sensor honeywell
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
ntrungtruc2003



Joined: 16 Feb 2011
Posts: 42

View user's profile Send private message

Read RSC pressure sensor honeywell
PostPosted: Tue Aug 08, 2017 10:27 am     Reply with quote

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: 19219

View user's profile Send private message

PostPosted: Tue Aug 08, 2017 10:48 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Aug 08, 2017 9:20 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Aug 08, 2017 10:25 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Aug 08, 2017 11:22 pm     Reply with quote

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: 19219

View user's profile Send private message

PostPosted: Tue Aug 08, 2017 11:24 pm     Reply with quote

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. Smile
ntrungtruc2003



Joined: 16 Feb 2011
Posts: 42

View user's profile Send private message

PostPosted: Thu Aug 10, 2017 4:53 am     Reply with quote

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: 19219

View user's profile Send private message

PostPosted: Thu Aug 10, 2017 7:18 am     Reply with quote

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

View user's profile Send private message

Read RSC pressure sensor honeywell
PostPosted: Fri Aug 11, 2017 7:05 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Aug 11, 2017 7:17 am     Reply with quote

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: 19219

View user's profile Send private message

PostPosted: Fri Aug 11, 2017 9:26 am     Reply with quote

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

View user's profile Send private message

PostPosted: Sat Aug 12, 2017 2:53 am     Reply with quote

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: 19219

View user's profile Send private message

PostPosted: Sat Aug 12, 2017 7:51 am     Reply with quote

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

View user's profile Send private message

PostPosted: Sat Aug 12, 2017 8:39 am     Reply with quote

Thanks Sir

I will try to solve my problem
ntrungtruc2003



Joined: 16 Feb 2011
Posts: 42

View user's profile Send private message

PostPosted: Sun Aug 13, 2017 8:00 am     Reply with quote

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);
}


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  Next
Page 1 of 2

 
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