| 
	
	|  |  |  
	
		| 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: 19967
 
 
 
			    
 
 | 
			
				|  |  
				|  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: 19967
 
 
 
			    
 
 | 
			
				|  |  
				|  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: 9589
 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
 
 |