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

Altimeter MS5607 do not run correctly

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Cogitum



Joined: 22 Mar 2012
Posts: 70
Location: France (Paris)

View user's profile Send private message

Altimeter MS5607 do not run correctly
PostPosted: Thu Jun 13, 2013 6:06 pm     Reply with quote

HI,

Please I need help Embarassed
What's wrong ?

My target is to make an altimeter around MS5607 (using AN520).
Hardware seem running well but the result is not there.
With the scope SDA and SCL arent at 3volts and I see the sequence of SCL and SDA.
Using ICD U64 from CCS in DEBUG mode I can read:
P= -0.959126532077789
T= 19.999044418335
D2=D1=0
C= 0x0038,0,005F,0x0018,0x003E,0,000D,0,0037,0,0039,0,00CE
N_CRC = 0,000F
Code:

*****************
///  PIC 18F25K80 at 4MHZ
 

//_____ I N C L U D E S
#include <18F25K80.h>
#include <stdio.h>
#include <math.h>

//_____ D E F I N I T I O N S

 #type SIGNED
 #type INT=16, LONG=32

unsigned long cmd_adc(char cmd);
long cmd_prom(char coef_num);
unsigned char crc4(unsigned int n_prom[]);
int MS5607_Write,start;////

#FUSES WDT                     //No Watch Dog Timer
#FUSES VREGSLEEP_SW            //Ultra low-power regulator is enabled
#FUSES INTRC_HP                //LF-INTOSC in Low-Power mode during Sleep
#FUSES NOXINST                 //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES HSM                      //High speed Osc, medium power 4MHz-16MHz
#FUSES NOBROWNOUT              //No brownout reset

#use delay(clock=4000000)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

//_____ M A C R O S
#define ADDR_W       0xEE // Module address write mode
#define ADDR_R       0xEF // Module address read mode
#define CMD_RESET    0x1E // ADC reset command
#define CMD_ADC_READ 0x00 // ADC read command
#define CMD_ADC_CONV 0x40 // ADC conversion command
#define CMD_ADC_D1   0x00 // ADC D1 conversion
#define CMD_ADC_D2   0x10 // ADC D2 conversion
#define CMD_ADC_256  0x00 // ADC OSR=256
#define CMD_ADC_512  0x02 // ADC OSR=512
#define CMD_ADC_1024 0x04 // ADC OSR=1024
#define CMD_ADC_2048 0x06 // ADC OSR=2048
#define CMD_ADC_4096 0x08 // ADC OSR=4096
#define CMD_PROM_RD  0xA0 // Prom read command 

#define  hi(x)                 (*(&x+1))  // 2ème octets sur un long
#define  lo(x)                 (*(&x))    // 1er octet


//********************************************************
//! @brief send reset sequence
//!
//! @return none
//********************************************************
void MS5607_Reset(void)
{
i2c_start();
i2c_write(addr_W);
i2c_write(CMD_RESET); // send reset sequence
delay_ms(3);          // wait for the reset sequence timing
i2c_stop();
}
//********************************************************
//! @brief preform adc conversion
//!
//! @return 24bit result
//********************************************************
unsigned int32 cmd_adc(char cmd)
{
unsigned int ret=0;
unsigned long temp=0;// int32
i2c_start();
i2c_write(ADDR_W);
i2c_write(CMD_ADC_CONV+cmd); // send conversion command
switch (cmd & 0x0f)          // wait necessary conversion time
{
case 0:CMD_ADC_256 ; delay_us(900); break;
case 1:CMD_ADC_512 ; delay_ms(3);   break;
case 2:CMD_ADC_1024; delay_ms(4);   break;
case 3:CMD_ADC_2048; delay_ms(6);   break;
case 4:CMD_ADC_4096; delay_ms(10);  break;
}

i2c_start();          // set device address and read mode
i2c_write(ADDR_R);    // 0xEF = read
i2c_write(CMD_ADC_READ);
i2c_read(ADDR_R);
ret = i2c_read();     // read MSB and acknowledge
if (ret)
{
i2c_stop();
}
else
{
i2c_start();
i2c_write(ADDR_R);
ret=i2c_read();
temp=65536*ret;
i2c_read(ADDR_R);
ret = i2c_read();     // read byte and acknowledge
i2c_read(ADDR_R);
temp=temp+(256*ret);  // ?
i2c_read(ADDR_R);
ret = i2c_read();     // read LSB and not acknowledge Nact ?? verif
temp=temp+ret;
 
i2c_stop();           // send stop condition
}
return temp;
}
//********************************************************
//! @brief Read calibration coefficients
//!
//! @return coefficient
//********************************************************

long cmd_prom(char coef_num)
{
long data=0;//
i2c_start();
i2c_write(0xEE);
i2c_write(CMD_PROM_RD+coef_num*2);
i2c_start();
i2c_write(0XEF);
hi(data) = i2c_read();
lo(data) = i2c_read();
i2c_stop();
return (data); //
}
 
///********************************************************
///Brief calculate the CRC code
//!
//! @return crc code
//********************************************************
//unsigned int16 n_prom[]={0x3132,0x3334,0x3536,0x3738,0x3940,0x4142,0x4344,0x4546};

unsigned char crc4(unsigned int16 n_prom[])  // int à int16 ?
 
{
int cnt;                          //simple counter
unsigned int n_rem;               //crc reminder
unsigned int crc_read;            //original value of the crc
unsigned char n_bit;
n_rem = 0x00;
crc_read=n_prom[7];               //save read CRC
n_prom[7]=(0xFF00 & (n_prom[7])); //CRC byte is replaced by 0
for (cnt = 0; cnt < 16; cnt++)    //operation is performed on bytes
{                                 //choose LSB or MSB
if (cnt%2==1) n_rem ^= (unsigned short) ((n_prom[cnt>>1]) & 0x00FF);
else n_rem ^= (unsigned short) (n_prom[cnt>>1]>>8);
for (n_bit = 8; n_bit > 0; n_bit--)
{
if (n_rem & (0x8000))
{
n_rem = (n_rem << 1) ^ 0x3000;
}
else
{
n_rem = (n_rem << 1);
}
}
}
n_rem= (0x000F & (n_rem >> 12)); // final 4-bit reminder is CRC code
n_prom[7]=crc_read;              // restore the crc_read to its original place
return (n_rem ^ 0x0);
}
//*****************************************************************************
//! @brief main program
//! ***************************************************************************
//! @return 0
//*****************************************************************************
void main (void)
{
int32 D1;             // ADC value of the pressure conversion
int32 D2;             // ADC value of the temperature conversion
unsigned int16 C[8];  // calibration coefficients
double P;             // compensated pressure value
double T;             // compensated temperature value
double dT;            // difference between actual and measured temperature
double OFF;           // offset at actual temperature
double SENS;          // sensitivity at actual temperature
int i;
unsigned int16 n_crc; // char ?  crc value of the prom

// initialize the I2C hardware module

D1=0;
D2=0;

MS5607_Reset();// reset IC

for (i=0;i<8;i++)
{ C[i]=cmd_prom(i);} // read coefficients
n_crc=crc4(C);       // calculate the CRC

do
{
D2=cmd_adc(CMD_ADC_D2+CMD_ADC_4096); // read D2 Pression
D1=cmd_adc(CMD_ADC_D1+CMD_ADC_4096); // read D1 Temperature

//**************************************************************
// calculate 1st order pressure and temperature (MS5607 1st order algorithm)
//**************************************************************
dT=D2-C[5]*pow(2,8);
OFF=C[2]*pow(2,17)+dT*C[4]/pow(2,6);
SENS=C[1]*pow(2,16)+dT*C[3]/pow(2,7);
T=(2000+(dT*C[6])/pow(2,23))/100;
P=(((D1*SENS)/pow(2,21)-OFF)/pow(2,15))/100;

// P, T, trough RS232 interface...
 printf("Press = %2u/n/r",P);
 printf("Temp = %2u/n/r",T);
/*
#asm
nop;
#endasm
*/

}while(true);
return ;
}


Thanks in advance for your help
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jun 13, 2013 8:23 pm     Reply with quote

Read my comments in this thread about doing a NACK on the last
i2c_read() in each i2c transaction:
http://www.ccsinfo.com/forum/viewtopic.php?t=48067&highlight=nack
There are several places in your program where this problem needs to
be fixed.
Cogitum



Joined: 22 Mar 2012
Posts: 70
Location: France (Paris)

View user's profile Send private message

PostPosted: Fri Jun 14, 2013 5:39 am     Reply with quote

HI PCM programmer,

First : Thanks a lot for your quick answer.

I need to make some change on my program and retest it.

I have one question about one small software from you :

listing is
Code:

//_____ I N C L U D E S
//#include <fichierDef.h>
#include <18F25K80.h>
#FUSES WDT                     //No Watch Dog Timer
//#FUSES WDT128                //Watch Dog Timer uses 1:128 Postscale
#FUSES VREGSLEEP_SW            //Ultra low-power regulator is enabled
#FUSES INTRC_HP                //LF-INTOSC in Low-Power mode during Sleep
#FUSES NOXINST                 //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES HSM                     //High speed Osc, medium power 4MHz-16MHz
//#FUSES NOPLLEN               //4X HW PLL disabled, 4X PLL enabled in software
#FUSES NOBROWNOUT              //No brownout reset
#use delay(clock=4000000)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

// This function writes the slave address to the i2c bus.
// If a slave chip is at that address, it should respond to
// 
int8 get_ack_status(int8 address)
{
int8 status;

i2c_start();
status = i2c_write(address);  // Status = 0 if got an ACK
i2c_stop();

if(status == 0)
   return(TRUE);
else
   return(FALSE);
}

//=================================
void main()
{
int8 i;
int8 status;
int8 count = 0;

printf("\n\rStart:\n\r");

delay_ms(1000);

// Try all slave addresses from 0x10 to 0xEF.
// See if we get a response from any slaves
// that may be on the i2c bus.
for(i=0x10; i < 0xF0; i+=2) //
   {
    status = get_ack_status(i);
    if(status == TRUE)
      { 
       printf("ACK addr: %X\n\r", i);
       count++;
       delay_ms(2000);
      }
   }
if(count == 0)
   printf("\n\rNothing Found");
else
   printf("\n\rNumber of i2c chips found: %u", count);

while(1);
}

I'm trying to retrieve the MS5607 ADDRESS (0xEE) without success.
Count is = 1
Address = 0xF0
I have change the MS 5607 by another one and the result is the same ?
Do you have an idea ?

Thanks a lot for your answer
Ttelmah



Joined: 11 Mar 2010
Posts: 19503

View user's profile Send private message

PostPosted: Fri Jun 14, 2013 8:52 am     Reply with quote

You have got the pull-up resistors on SCL & SDA?.
Perhaps 2K2R each for a 3.3v bus.
Without these the bus won't work.

Best Wishes
Cogitum



Joined: 22 Mar 2012
Posts: 70
Location: France (Paris)

View user's profile Send private message

Pull up I2C MS5607
PostPosted: Fri Jun 14, 2013 9:43 am     Reply with quote

HI Ttelmah
Thanks for your post.
Before the value of 2 R was 4.7K now the value is 2.2K
Unfortunately the result is the same

I do not see where is the problem with the software from PCM Programmer to scan the device address that give 0xF0 and not OxEE
like in the data sheet AN 520 and MS5607-02BA03.

Big mystery !!!?????
ezflyr



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

View user's profile Send private message

PostPosted: Fri Jun 14, 2013 10:47 am     Reply with quote

Hi,

I don't think it's a mystery at all - clearly you have a hardware problem. At this point, you need to tell us which board you are using (show us a link to
the board), or provide a schematic if it's one you made yourself.

John
Cogitum



Joined: 22 Mar 2012
Posts: 70
Location: France (Paris)

View user's profile Send private message

next MS5607
PostPosted: Mon Jun 17, 2013 4:31 pm     Reply with quote

Now the test program from PCM PROGRAMMER return ADDRESS 0xEE ! Very Happy
The problem : configuration of some fuse .....
Main program MS5607
Some value can be read in debug mode unfortunately wrong value.
I'm trying to debug this part of the program :
Original for "atmel" µC (AN520 from MEASUREMENT)
Code:

// *******original*****
/********************************************************
//! @brief preform adc conversion
//!
//! @return 24bit result
//********************************************************
unsigned long cmd_adc(char cmd)
{
unsigned int ret;
unsigned long temp=0;
i2c_send(CMD_ADC_CONV+cmd); // send conversion command
switch (cmd & 0x0f) // wait necessary conversion time
{
case CMD_ADC_256 : _delay_us(900); break;
case CMD_ADC_512 : _delay_ms(3); break;
case CMD_ADC_1024: _delay_ms(4); break;
case CMD_ADC_2048: _delay_ms(6); break;
case CMD_ADC_4096: _delay_ms(10); break;
}
i2c_send(CMD_ADC_READ);
ret = i2c_start(ADDR_R); // set device address and read mode
if ( ret )
{//failed to issue start condition, possibly no device found
i2c_stop();
}
else
{//issuing start condition ok, device accessible
ret = i2c_readAck(); // read MSB and acknowledge
temp=65536*ret;
ret = i2c_readAck(); // read byte and acknowledge
temp=temp+256*ret;
ret = i2c_readNak(); // read LSB and not acknowledge
temp=temp+ret;
i2c_stop(); // send stop condition
}
return temp;
}

Code:

///// PART of the Program in test : **********

//********************************************************
//! @brief preform adc conversion
//! @return 24bit result
//********************************************************
unsigned int32 cmd_adc(char cmd)
{
unsigned int ret=0;
unsigned long temp=0;

i2c_start();
i2c_write(ADDR_W);
i2c_write(CMD_ADC_CONV+cmd); // send conversion command
switch (cmd & 0x0f)          // wait necessary conversion time
{
case CMD_ADC_256 :
 delay_us(900); break;
case CMD_ADC_512 :
 delay_ms(3);   break;
case CMD_ADC_1024:
 delay_ms(4);   break;
case CMD_ADC_2048:
 delay_ms(6);   break;
case CMD_ADC_4096:
 delay_ms(10);  break;
}
i2c_start();
i2c_write(CMD_ADC_READ);
i2c_write(ADDR_R);         // 0xEF = read
i2c_start();               // set device address and read mode
i2c_read(ADDR_R);

                           // read MSB and acknowledge
i2c_start();
i2c_write(ADDR_R);
i2c_write(CMD_ADC_READ);
ret=i2c_read();
temp=65536*ret;
i2c_read(ADDR_R);
ret = i2c_read();      // read byte and acknowledge
temp=temp+256*ret;     //
ret = i2c_read(0);     // read LSB and not acknowledge Nact
temp=temp+ret;
i2c_stop();           // send stop condition

return temp;
}

What's wrong ? Embarassed

Thanks for your help
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Jun 17, 2013 11:50 pm     Reply with quote

Code:

i2c_send(CMD_ADC_READ);
ret = i2c_start(ADDR_R); // set device address and read mode
if ( ret )
{//failed to issue start condition, possibly no device found
i2c_stop();
}
else
{//issuing start condition ok, device accessible
ret = i2c_readAck(); // read MSB and acknowledge
temp=65536*ret;
ret = i2c_readAck(); // read byte and acknowledge
temp=temp+256*ret;
ret = i2c_readNak(); // read LSB and not acknowledge
temp=temp+ret;
i2c_stop(); // send stop condition
}
return temp;
}

How did you take the AN520 code above and translate it into your code ?
You didn't even try to look at the differences between how they do it
and how CCS does it.

They have a routine called i2c_start() which is very different from CCS.
They combine two operations into one function:
Code:

// Send I2C start condition and the address byte.
ret = i2c_start(ADDR_R);


CCS does it as two separate functions, on two lines:
Code:

i2c_start();
ret = i2c_write(address_byte);

Look at their sample code again, and translate it to CCS correctly this time.



AN520:
http://www.meas-spec.com/downloads/C-Code_Example_for_MS56xx,_MS57xx_%28except_analog_sensor%29_and_MS58xx_Series_Pressure_Sensors.pdf
Cogitum



Joined: 22 Mar 2012
Posts: 70
Location: France (Paris)

View user's profile Send private message

PostPosted: Tue Jun 18, 2013 6:56 am     Reply with quote

hello PCM PROGRAMMER

Thanks for your help!

I did some change as recommended but now impossible to compile

(PCWHD Compiler version 4.132)

Error 112 ....line 202 Function used but not defined ... cmd_prom SCR=3478 ?


Code:
#include <18F25K80.h>
#include <stdio.h>
#include <math.h>

//_____ D E F I N I T I O N S

 #type SIGNED
 #type INT=16, LONG=32

unsigned long cmd_adc(char cmd);
long cmd_prom(char coef_num);
unsigned char crc4(unsigned int n_prom[]);


#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES HSM                      //High speed Osc, medium power 4MHz-16MHz
#FUSES NOBROWNOUT               //No brownout reset
#FUSES WDT_NOSLEEP              //Watch Dog Timer, disabled during SLEEP
#FUSES NOPLLEN                  //4X HW PLL disabled, 4X PLL enabled in software             //No brownout reset
#use delay(clock=4000000)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

//_____ M A C R O S
#define ADDR_W       0xEE // Module address write mode
#define ADDR_R       0xEF // Module address read mode
#define CMD_RESET    0x1E // ADC reset command
#define CMD_ADC_READ 0x00 // ADC read command
#define CMD_ADC_CONV 0x40 // ADC conversion command
#define CMD_ADC_D1   0x00 // ADC D1 conversion Pression
#define CMD_ADC_D2   0x10 // ADC D2 conversion TEMPERATURE
#define CMD_ADC_256  0x00 // ADC OSR=256
#define CMD_ADC_512  0x02 // ADC OSR=512
#define CMD_ADC_1024 0x04 // ADC OSR=1024
#define CMD_ADC_2048 0x06 // ADC OSR=2048
#define CMD_ADC_4096 0x08 // ADC OSR=4096
#define CMD_PROM_RD  0xA0 // Prom read command 
#define LED_TEST     PIN_B5

void TESTL(void)
{
 output_high(LED_TEST);
 delay_ms(50);
 output_low(LED_TEST);
 delay_ms(5);
}

//********************************************************
//! @brief send reset sequence
//! @return none
//********************************************************
void MS5607_reset(void)
{
i2c_write(CMD_RESET); // send reset sequence
delay_ms(3);          // 3 wait for the reset sequence timing
}

//********************************************************
//! @brief preform adc conversion
//! @return 24bit result
//********************************************************
unsigned int32 cmd_adc(char cmd)
{
unsigned int ret;
unsigned long temp=0;

i2c_start();
i2c_write(CMD_ADC_CONV+cmd); // send conversion command
switch (cmd & 0x0f)          // wait necessary conversion time
{
case CMD_ADC_256 :  delay_us(900); break;
case CMD_ADC_512 :  delay_ms(3);   break;
case CMD_ADC_1024:  delay_ms(4);   break;
case CMD_ADC_2048:  delay_ms(6);   break;
case CMD_ADC_4096:  delay_ms(10);  break;
}
i2c_write(CMD_ADC_READ);
i2c_start();
ret = i2c_write(ADDR_R); // set device address and read mode
if ( ret )
{//failed to issue start condition, possibly no device found
i2c_stop();
}
else
{//issuing start condition ok, device accessible
i2c_start();
ret = i2c_read(); // read MSB and acknowledge
temp=65536*ret;
i2c_start();
ret = i2c_read(); // read byte and acknowledge
temp=temp+256*ret;
i2c_start();
ret = i2c_read(0); // read LSB and not acknowledge
temp=temp+ret;
i2c_stop(); // send stop condition
}
return temp;
}

//********************************************************
//! @brief Read calibration coefficients
//! @return coefficient
//********************************************************
unsigned int cmd_prom(char coef_num)
{
unsigned int ret;
unsigned int rC=0;
i2c_write(CMD_PROM_RD+coef_num*2); // send PROM READ command
i2c_start();
ret = i2c_write(ADDR_R); // set device address and read mode
if ( ret )
{//failed to issue start condition, possibly no device found
i2c_stop();
}
else
{//issuing start condition ok, device accessible
ret = i2c_read(); // read MSB and acknowledge
rC=256*ret;
ret = i2c_read(0); // read LSB and not acknowledge
rC=rC+ret;
i2c_stop();
}
//#asm
//nop;
//#endasm
return (rC); //
}
 
///********************************************************
///Brief calculate the CRC code
//!
//! @return crc code
//********************************************************
//unsigned int16 n_prom[]={0x3132,0x3334,0x3536,0x3738,0x3940,0x4142,0x4344,0x4546};

unsigned char crc4(unsigned int n_prom[])  //
 
{
int cnt;                          //simple counter
unsigned int n_rem;               //crc reminder
unsigned int crc_read;            //original value of the crc
unsigned char n_bit;
n_rem = 0x00;
crc_read=n_prom[7];               //save read CRC
n_prom[7]=(0xFF00 & (n_prom[7])); //CRC byte is replaced by 0
for (cnt = 0; cnt < 16; cnt++)    //operation is performed on bytes
{                                 //choose LSB or MSB
if (cnt%2==1) n_rem ^= (unsigned short) ((n_prom[cnt>>1]) & 0x00FF);
else n_rem ^= (unsigned short) (n_prom[cnt>>1]>>8);
for (n_bit = 8; n_bit > 0; n_bit--)
{
if (n_rem & (0x8000))
{
n_rem = (n_rem << 1) ^ 0x3000;
}
else
{
n_rem = (n_rem << 1);
}
}
}
n_rem= (0x000F & (n_rem >> 12)); // final 4-bit reminder is CRC code
n_prom[7]=crc_read;              // restore the crc_read to its original place
return (n_rem ^ 0x0);
}

//*****************************************************************************
//! @brief main program
//! ***************************************************************************
//! @return 0
//*****************************************************************************
int  main (void)
{
unsigned long D1;     // ADC value of the pressure conversion
unsigned long D2;     // ADC value of the temperature conversion
unsigned int C[8];    // calibration coefficients
double  P;             // compensated pressure value
double  T;             // compensated temperature value
double  dT;            // difference between actual and measured temperature
double  OFF;           // offset at actual temperature
double  SENS;          // sensitivity at actual temperature
int i;
unsigned char n_crc;  //  crc value of the prom 

// initialize the I2C hardware module
D1=0;
D2=0;

MS5607_Reset();// reset IC

for (i=0;i<8;i++){ C[i]=cmd_prom(i);} // read coefficients
n_crc=crc4(C);                        // calculate the CRC
 
for(;;)
{
TESTL();
D2=cmd_adc(CMD_ADC_D2+CMD_ADC_4096); // read D2 Temperature
D1=cmd_adc(CMD_ADC_D1+CMD_ADC_4096); // read D1 Pression

//**************************************************************
// calculate 1st order pressure and temperature (MS5607 1st order algorithm)
//**************************************************************
dT=D2-C[5]*pow(2,8);
OFF=C[2]*pow(2,17)+dT*C[4]/pow(2,6);
SENS=C[1]*pow(2,16)+dT*C[3]/pow(2,7);
T=(2000+(dT*C[6])/pow(2,23))/100;
P=(((D1*SENS)/pow(2,21)-OFF)/pow(2,15))/100;

// P, T, trough RS232 interface...
 // printf("Test = %2u\n\r",C);
 printf("Press = %u\n\r",P);
 printf("Temp = %u\n\r",T);
 delay_ms(500);

}
return 0;
}


Rolling Eyes

Welcome to the idea to solve this problem
Thanks
Ttelmah



Joined: 11 Mar 2010
Posts: 19503

View user's profile Send private message

PostPosted: Tue Jun 18, 2013 8:31 am     Reply with quote

Your function prototype, must always match the actual function.

You are describing two functions called cmd_prom. One returns an unsigned integer, the other a long....

Best Wishes
Cogitum



Joined: 22 Mar 2012
Posts: 70
Location: France (Paris)

View user's profile Send private message

MS5607 wrong value with this program !?
PostPosted: Tue Jun 18, 2013 11:16 am     Reply with quote

Some value can be displayed on HYPERTERMINAL
TEMP = 136
Press = 140

The code is:
Code:

///  PIC 18F25K80 at 4MHZ
//_____ I N C L U D E S
//#include <fichierDef.h>
#include <18F25K80.h>
#include <stdio.h>
#include <math.h>

//_____ D E F I N I T I O N S
 #type SIGNED
 #type INT=16, LONG=32

unsigned long cmd_adc(char cmd);
unsigned int  cmd_prom(char coef_num);
unsigned char crc4(unsigned int n_prom[]);

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES HSM                      //High speed Osc, medium power 4MHz-16MHz
#FUSES NOBROWNOUT               //No brownout reset
#FUSES WDT_NOSLEEP              //Watch Dog Timer, disabled during SLEEP
#FUSES NOPLLEN                  //4X HW PLL disabled, 4X PLL enabled in software             //No brownout reset
#use delay(clock=4000000)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

//_____ M A C R O S
#define ADDR_W       0xEE // Module address write mode
#define ADDR_R       0xEF // Module address read mode
#define CMD_RESET    0x1E // ADC reset command
#define CMD_ADC_READ 0x00 // ADC read command
#define CMD_ADC_CONV 0x40 // ADC conversion command
#define CMD_ADC_D1   0x00 // ADC D1 conversion Pression
#define CMD_ADC_D2   0x10 // ADC D2 conversion TEMPERATURE
#define CMD_ADC_256  0x00 // ADC OSR=256
#define CMD_ADC_512  0x02 // ADC OSR=512
#define CMD_ADC_1024 0x04 // ADC OSR=1024
#define CMD_ADC_2048 0x06 // ADC OSR=2048
#define CMD_ADC_4096 0x08 // ADC OSR=4096
#define CMD_PROM_RD  0xA0 // Prom read command 
#define LED_TEST     PIN_B5


void TESTL(void)
{
 output_high(LED_TEST);
 delay_ms(50);
 output_low(LED_TEST);
 delay_ms(5);
}

//********************************************************
//! @brief send reset sequence
//! @return none
//********************************************************
void MS5607_reset(void)
{
i2c_start();
i2c_write(ADDR_W);
i2c_write(CMD_RESET); // send reset sequence
delay_ms(3);          // 3 wait for the reset sequence timing
i2c_stop();
}

//********************************************************
//! @brief preform adc conversion
//! @return 24bit result
//********************************************************
unsigned long cmd_adc(char cmd)
{
unsigned int ret;
unsigned long temp=0;

i2c_start();
i2c_write(ADDR_W);
i2c_write(CMD_ADC_CONV+cmd); // send conversion command
switch (cmd & 0x0f)          // wait necessary conversion time
{
case CMD_ADC_256 :  delay_us(900); break;
case CMD_ADC_512 :  delay_ms(3);   break;
case CMD_ADC_1024:  delay_ms(4);   break;
case CMD_ADC_2048:  delay_ms(6);   break;
case CMD_ADC_4096:  delay_ms(10);  break;
}
i2c_start();
i2C_write(ADDR_W);
i2c_write(CMD_ADC_READ);
i2c_start();
ret = i2c_write(ADDR_R); // set device address and read mode
if ( ret )
{//failed to issue start condition, possibly no device found
i2c_stop();
}
else
{//issuing start condition ok, device accessible
i2c_start();
i2c_write(ADDR_R);
ret = i2c_read(); // read MSB and acknowledge
temp=65536*ret;
i2c_start();
i2c_write(ADDR_R);
ret = i2c_read(); // read byte and acknowledge
temp=temp+256*ret;
i2c_start();
i2c_write(ADDR_R);
ret = i2c_read(0); // read LSB and not acknowledge
temp=temp+ret;
i2c_stop(); // send stop condition
}
#asm
nop;
#endasm
return temp;
}

//********************************************************
//! @brief Read calibration coefficients
//! @return coefficient
//********************************************************
unsigned int cmd_prom(char coef_num)
{
unsigned int ret;
unsigned int rC=0;
i2c_start();
i2C_write(addr_w);
i2c_write(CMD_PROM_RD+coef_num*2); // send PROM READ command
i2c_start();
ret = i2c_write(ADDR_R); // set device address and read mode
if ( ret )
{//failed to issue start condition, possibly no device found
i2c_stop();
}
else
{//issuing start condition ok, device accessible
i2c_start();
i2c_write(ADDR_R);
ret = i2c_read();   // read MSB and acknowledge
rC=256*ret;
ret = i2c_read(0);  // read LSB and not acknowledge
rC=rC+ret;
i2c_stop();
}
#asm
nop;
#endasm
return (rC); //
}
 
///*******************************************************
///Brief calculate the CRC code
//! @return crc code
//********************************************************
//unsigned int16 n_prom[]={0x3132,0x3334,0x3536,0x3738,0x3940,0x4142,0x4344,0x4546};

unsigned char crc4(unsigned int n_prom[])  //
 
{
int cnt;                          //simple counter
unsigned int n_rem;               //crc reminder
unsigned int crc_read;            //original value of the crc
unsigned char n_bit;
n_rem = 0x00;
crc_read=n_prom[7];               //save read CRC
n_prom[7]=(0xFF00 & (n_prom[7])); //CRC byte is replaced by 0
for (cnt = 0; cnt < 16; cnt++)    //operation is performed on bytes
{                                 //choose LSB or MSB
if (cnt%2==1) n_rem ^= (unsigned short) ((n_prom[cnt>>1]) & 0x00FF);
else n_rem ^= (unsigned short) (n_prom[cnt>>1]>>8);
for (n_bit = 8; n_bit > 0; n_bit--)
{
if (n_rem & (0x8000))
{
n_rem = (n_rem << 1) ^ 0x3000;
}
else
{
n_rem = (n_rem << 1);
}
}
}
n_rem= (0x000F & (n_rem >> 12)); // final 4-bit reminder is CRC code
n_prom[7]=crc_read;              // restore the crc_read to its original place
return (n_rem ^ 0x0);
}


//*****************************************************************************
//! @brief main program
//! ***************************************************************************
//! @return 0
//*****************************************************************************
int  main (void)
{
unsigned long D1;     // ADC value of the pressure conversion
unsigned long D2;     // ADC value of the temperature conversion
unsigned int C[8];    // calibration coefficients
DOUBLE  P;             // compensated pressure value
DOUBLE  T;             // compensated temperature value
DOUBLE  dT;            // difference between actual and measured temperature
DOUBLE  OFF;           // offset at actual temperature
DOUBLE  SENS;          // sensitivity at actual temperature
int i;
unsigned char n_crc;  //  crc value of the prom 

// initialize the I2C hardware module
D1=0;
D2=0;

MS5607_Reset();// reset IC

for (i=0;i<8;i++){ C[i]=cmd_prom(i);} // read coefficients
n_crc=crc4(C);                        // calculate the CRC
 
for(;;)
{
//TESTL();
D2=cmd_adc(CMD_ADC_D2+CMD_ADC_4096); // read D2 Temperature
D1=cmd_adc(CMD_ADC_D1+CMD_ADC_4096); // read D1 Pression

//**************************************************************
// calculate 1st order pressure and temperature (MS5607 1st order algorithm)
//**************************************************************
dT=D2-C[5]*pow(2,8);
OFF=C[2]*pow(2,17)+dT*C[4]/pow(2,6);
SENS=C[1]*pow(2,16)+dT*C[3]/pow(2,7);
T=(2000+(dT*C[6])/pow(2,23))/100;
P=(((D1*SENS)/pow(2,21)-OFF)/pow(2,15))/100;

// P, T, trough RS232 interface...
 //printf("Test = %2u\n\r",C);
 printf("Press = %u\n\r",P);
 printf("Temp = %u\n\r",T);
 delay_ms(500);
#asm
nop;
#endasm
}
return 0;
}

Display on the debugger:
P= 13047,9140625
T=649,5703125
D1=D2= 16777215
C= (0xFFFF,0xAF07,0xA3AD,0xFFFF,0xFFFF,0x8509,0xFFFF,0xDD8D)
n_crc=0x00

where are my errors Rolling Eyes ?
Idea ?
temtronic



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

View user's profile Send private message

PostPosted: Tue Jun 18, 2013 5:11 pm     Reply with quote

1) without knowing what the real data is supposed to be it's hard to figure out!

however, you should 'play computer', and either manually do all the math step by step or insert 'printf commands' to display interim values to see where your calculations have gone wrong.

sometimes it's a 'casting' error..
sometimes it's not enough brackets(changing the order of things...)...

2) code like this...
/*
#asm
nop;
#endasm
*/
..should be deleted from your program ASAP! It is very confusing to others, even if it's 'commented out'. I have to wonder if some of your other code is 'cut and pasted' from someone elses code and perhaps you've miscut a line or two.

hth
jay
Cogitum



Joined: 22 Mar 2012
Posts: 70
Location: France (Paris)

View user's profile Send private message

MS5607 Help
PostPosted: Tue Jun 18, 2013 7:39 pm     Reply with quote

Hi temtronic

Thanks for your answer.
Just, I hope my i2c line of program are right ..?

All the part of this program seem "work" but the results are wrong !!
Evil or Very Mad
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jun 19, 2013 12:22 am     Reply with quote

Quote:
All the part of this program seem "work" but the results are wrong !!

So check the part that prints out the results. Take some initiative.
Make a test program. Put in some representative values. See if they
print out correctly. If not, look up 'printf' in the CCS manual and see
how to construct a printf statement that will display a floating point number
correctly. Example of test program, using your current code:
Code:
#include <18F25K80.h>
#fuses INTRC_IO,NOWDT
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS)

#type SIGNED
#type INT=16, LONG=32

DOUBLE  P;             
DOUBLE  T;             

//======================================
void main(void)
{

P = 12345.678;
T = 4567.890;

printf("Press = %u\n\r", P);
printf("Temp = %u\n\r",T);

while(1);
}
Cogitum



Joined: 22 Mar 2012
Posts: 70
Location: France (Paris)

View user's profile Send private message

Improvment
PostPosted: Wed Jun 19, 2013 1:39 am     Reply with quote

Smile

Thanks a lot PCM PROGRAMMER for your pertinent remark ! Very Happy


Code:


// P, T, trough RS232 interface...
 printf("D2 = %lu\n\r",D2);
 printf("C = %u\n\r",C);
 printf("Press = %5.3f\n\r",P);
 printf("Temp  = %3.3f\n\r",T);
 delay_ms(500);

Now, i can read on hyperterminal :
D2 = 0
C = 15
Press = 1048.477
Temp = -661.129

I need to trying why no correct value
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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