|
|
View previous topic :: View next topic |
Author |
Message |
Cogitum
Joined: 22 Mar 2012 Posts: 70 Location: France (Paris)
|
Altimeter MS5607 do not run correctly |
Posted: Thu Jun 13, 2013 6:06 pm |
|
|
HI,
Please I need help
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
|
|
|
Cogitum
Joined: 22 Mar 2012 Posts: 70 Location: France (Paris)
|
|
Posted: Fri Jun 14, 2013 5:39 am |
|
|
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: 19496
|
|
Posted: Fri Jun 14, 2013 8:52 am |
|
|
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)
|
Pull up I2C MS5607 |
Posted: Fri Jun 14, 2013 9:43 am |
|
|
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
|
|
Posted: Fri Jun 14, 2013 10:47 am |
|
|
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)
|
next MS5607 |
Posted: Mon Jun 17, 2013 4:31 pm |
|
|
Now the test program from PCM PROGRAMMER return ADDRESS 0xEE !
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 ?
Thanks for your help |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jun 17, 2013 11:50 pm |
|
|
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)
|
|
Posted: Tue Jun 18, 2013 6:56 am |
|
|
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;
} |
Welcome to the idea to solve this problem
Thanks |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19496
|
|
Posted: Tue Jun 18, 2013 8:31 am |
|
|
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)
|
MS5607 wrong value with this program !? |
Posted: Tue Jun 18, 2013 11:16 am |
|
|
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 ?
? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Tue Jun 18, 2013 5:11 pm |
|
|
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)
|
MS5607 Help |
Posted: Tue Jun 18, 2013 7:39 pm |
|
|
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 !!
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Jun 19, 2013 12:22 am |
|
|
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)
|
Improvment |
Posted: Wed Jun 19, 2013 1:39 am |
|
|
Thanks a lot PCM PROGRAMMER for your pertinent remark !
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 |
|
|
|
|
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
|