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

PIC16F886 and MLX90614

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



Joined: 08 Oct 2014
Posts: 20

View user's profile Send private message Send e-mail

PIC16F886 and MLX90614
PostPosted: Wed Oct 25, 2017 12:39 pm     Reply with quote

Hi,
I am using MLX90614 Temp. Sensor and PIC16F886. Following is my code
I am facing problem as i am not able to make it wok. I spend few days in the same. I got following code from forum only.

Power supply is of 3.3V to sensor and PIC.
I am using PC3 to SCL and PC4 to SDA.
External XTAL is of 8MHz.

main.c
Code:

#include "main.h"
#include <stdint.h>
//SMBUS Device Address
#define Device_Address 0x50

//RAM Addresses for Temperatures
#define AT_Address 0x06   // Ambient Temperature - The Sensor's internal temperature
#define OT_Address 0x07   // Object Temperature - Whats in the Sensor's FOV

//EEPROM Addresses for Configuration/Writing
#define TO_Max 0x20
#define TO_Min 0x21
#define PWM_Control 0x22
#define TA_Range 0x23
#define Emissivity_Address 0x24
#define Config_Address 0x25
#define SMBUS_Address 0x2E

//Other Stuff for code Readability
#define Write_Bit 0x00
#define Read_Bit 0x01
#define ACK 0x00
#define NACK 0x01

//Function Declarations
int16 MLX_Read_Transaction(int);      // Needs Address to read from
void MLX_Write_Transaction(int,int,int);// Needs Address to write to, lo and hi bytes.
int Create_CRC(int,int,int);         // Needs Address to write to, lo and hi bytes.
int Check_CRC(int,int,int,int);         // Needs Read address,hi, lo and CRC Bytes
int CRC8_CCITT(int, int);            // Starting CRC and Byte to encode/decode

//**********************************************************************************
//                        EXAMPLE FUNCTIONS
//**********************************************************************************
// These are not really part of the driver, just examples of how to call things from
// your program:
//
//   void main()
//   {
//      Read_Object();                     //Gets you Temp of objects in FOV
//      Read_Ambient();                     //Gets you Ambient Temp
//   
//      //LETS EDIT SOME EEPROM VALUES!!!
//      Read_TOMAX();                      //Will read default value - probably 9993
//      MLX_Write_Transaction(TO_Max,0x00,0x00);//Need to erase EEPROM first with 0x0000
//      Read_TOMAX();                      //Will now read 0x0000
//      MLX_Write_Transaction(TO_Max,0xFF,0xFF);//Write desired values
//      Read_TOMAX();                      //Will now read 0xFFFF
//   }
void sendBT(char *str)
{
   while(*str!='\0')
   {
      putchar(*str++);
      delay_ms(10);
   }
}
void Read_Object()
{
   printf("Object Temp:%3.2f\r\n",((MLX_Read_Transaction(OT_Address)*0.02)-273.15));
//     *dat = ((float)raw *0.02 -0.01 ) - 273.15;      // convert Absolute temperature to Degrees Celsius of temperature

   delay_ms(1000);
}

void Read_Ambient()
{
   printf("Ambient Temp:%3.2f\r\n",((MLX_Read_Transaction(AT_Address)*0.02)-273));
   delay_ms(1000);
}

void Read_Config()
{
//   fprintf(lcd_putc,"MLX Configuration:%LX\r\n",MLX_Read_Transaction(Config_Address));
   delay_ms(500);
}

void Read_Emissivity()
{
  // fprintf(lcd_putc,"Emissivity Value:%LX\r\n",MLX_Read_Transaction(Emissivity_Address));
   delay_ms(500);
}
void Read_TOMAX()
{
 //  fprintf(lcd_putc,"TO_MAX:%LX\r\n",MLX_Read_Transaction(TO_Max));
   delay_ms(500);
}

//**********************************************************************************
//                        READ MLX DATA
//**********************************************************************************
// This functions works for both EEPROM and RAM Data from the MLX Sensor.
// A Checksum check is included to confirm Data integrity
int16 MLX_Read_Transaction(uint8_t Read_Address)
{
   int16 MLX_Response;            // Stores the 16 bit responses from the MLX
   int Command=0;               // stores the Address+write/read bit
   int Lo_Byte=0;
   int Hi_Byte=0;
   int CRC=0;

   Command=Device_Address<<1;      // Prepare Command: shift address 1 bit
   Command|=Write_Bit;            // Shifted Address with W/R Bit set or cleared
   i2c_start();               // Send Start Bit
   if (i2c_write(0xB4)==ACK)   // Send "Write" Command to the Device Address
   { 
      i2c_write(Read_Address);   // Write Address to be read
      Command=Device_Address<<1;   // Prepare Command: byte shift address 1 bit
      Command|=Read_Bit;         // Shifted Address with W/R Bit set or cleared
      i2c_start();            // Send Re-Start Bit
      i2c_write(0xB5);           // Send "Read" Command to the Device Address
      Lo_Byte = i2c_read(1);   // Get Low Byte and ACK the read
      Hi_Byte = i2c_read(1);   // Get High Byte and ACK the read
      CRC = i2c_read(0);      // Get CRC and ACK the Read       
   }
   i2c_stop();                  // Hammer Time
   

//   if(Check_CRC(Read_Address,Lo_Byte,Hi_Byte,CRC)==0)
   {
      MLX_Response= make16(Hi_Byte,Lo_Byte);
      return(MLX_Response);
   }
}

//**********************************************************************************
//                        WRITE DATA TO MLX
//**********************************************************************************
// This function writes to the EEPROM of the MLX. It calculates the CRC automatically.
// There is a small delay at the end as "settling time" after the write.
// During testing this delay was required if reading the data Immediatly after the write
void MLX_Write_Transaction(int Write_Address,int Lo_Byte,int Hi_Byte)
{
   int CRC=0;                     // Holds the CRC of data to be sent
   int Command=0;                  //

   CRC=Create_CRC(Write_Address,Lo_Byte,Hi_Byte);

   Command=Device_Address<<1;         // Prepare Command: shift address 1 bit
   Command|=Write_Bit;               // Shifted Address with W/R Bit set or cleared

   i2c_start();                  // Send Start Bit
   if (i2c_write(Command)==ACK)      // Send Device Address
   { 
      i2c_write(Write_Address);      // Write Address to be Written onto
      i2c_write(Lo_Byte);            // Send Low Byte
      i2c_write(Hi_Byte);            // Send Hi Byte   
      i2c_write(CRC);               // Send CRC/PEC   
   }
   i2c_stop();                     // Hammer Time
   delay_ms(10);                  // Allow time after write
}

//**********************************************************************************
//                        CREATE A CRC
//**********************************************************************************
// Calculates the CRC of the DATA to be sent to EEPROM
int Create_CRC(int Write_Address,int Lo_Byte,int Hi_Byte)
{
   int Temp_CRC=0;                        // Holds the intermediate CRC Calculations
   int Command=0;                        //

   Command=Device_Address<<1;               // Prepare Command: shift address 1 bit
   Command|=Write_Bit;                     // Shifted Address with W/R Bit set or cleared

   Temp_CRC=CRC8_CCITT(0x00,Command);         // Device Address
   Temp_CRC=CRC8_CCITT(Temp_CRC,Write_Address);// Memory Address
   Temp_CRC=CRC8_CCITT(Temp_CRC,Lo_Byte);       // LSB Byte
   Temp_CRC=CRC8_CCITT(Temp_CRC,Hi_Byte);       // MSB Byte
   //fprintf(lcd_putc,"New CRC:%X\r\n",Temp_CRC); //DEBUG
   return (Temp_CRC);
}

//**********************************************************************************
//                     CHECK INCOMMING DATA'S CRC
//**********************************************************************************
// Takes the data read from the sensor and checks if the Checksum is Right
int Check_CRC(int Read_Address,int Lo_Byte,int Hi_Byte,int CRC)
{
   int Temp_CRC=0;
   int Command=0;

   Command=Device_Address<<1;               // Prepare Command: shift address 1 bit
   Command|=Write_Bit;                     // Shifted Address with W/R Bit set or cleared
   Temp_CRC=CRC8_CCITT(0x00,Command);         // Device Address
   Temp_CRC=CRC8_CCITT(Temp_CRC,Read_Address); // Memory Address
   Command=Device_Address<<1;               // Prepare Command: shift address 1 bit
   Command|=Read_Bit;                     // Shifted Address with W/R Bit set or cleared
   Temp_CRC=CRC8_CCITT(Temp_CRC,Command);      // Device Address with Read Bit Set
   Temp_CRC=CRC8_CCITT(Temp_CRC,Lo_Byte);       // LSB Byte
   Temp_CRC=CRC8_CCITT(Temp_CRC,Hi_Byte);       // MSB Byte
   Temp_CRC=CRC8_CCITT(Temp_CRC,CRC);          // Received CRC Value
   //fprintf(lcd_putc,"CRC Check:%X\r\n",Temp_CRC); //DEBUG
   return (Temp_CRC);
}

//**********************************************************************************
//                     CRC8-CCITT CALCULATION
//**********************************************************************************
// This function was taken from "AVR Libc Reference Manual" and some names changed.
// Full credit to those involved in its creation.
int CRC8_CCITT(int inCrc, int inData)
{
    int   i;
    int   data;

    data = inCrc ^ inData;

    for ( i = 0; i < 8; i++ )
    {
        if (( data & 0x80 ) != 0 )
        {
            data <<= 1;
            data ^= 0x07;
        }
        else
        {
            data <<= 1;
        }
    }
    return data;
}

   void main()
   {
   while(1)
   {
             output_low(LED);
      Read_Object();                     //Gets you Temp of objects in FOV
      output_high(LED);
      Read_Ambient();                     //Gets you Ambient Temp
   }
      //LETS EDIT SOME EEPROM VALUES!!!
    //  Read_TOMAX();                      //Will read default value - probably 9993
   //   MLX_Write_Transaction(TO_Max,0x00,0x00);//Need to erase EEPROM first with 0x0000
    //  Read_TOMAX();                      //Will now read 0x0000
  //    MLX_Write_Transaction(TO_Max,0xFF,0xFF);//Write desired values
//      Read_TOMAX();                      //Will now read 0xFFFF
   }


Main.h file.
Code:

#include <16F886.h>
#device ADC=16

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O

#use delay(crystal=8MHz)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=PORT1)
#use i2c(Master,slow,sda=PIN_C3,scl=PIN_C4,FORCE_SW)

#define LED PIN_A0
#define DELAY 1000



I think i2c_read is not working properly.
temtronic



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

View user's profile Send private message

PostPosted: Wed Oct 25, 2017 1:36 pm     Reply with quote

1st place to start...
Download and compile the I2C Scanner program that PCM P put in the 'code library'.
Run it and CONFIRM the PIC does see the device.

Be sure to use appropriate I2C bus pullup resistors. Maybe 1k5 ??

Once that confirms the PIC does see the device, then you know the hardware is Ok.

2nd chunk of code.
Create a simple 'write a register then read a register' program. Be sure you can alter the contents of any register of that device that you're supposed to be able to.

once this works

THEN

try your 'real' program.




Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19497

View user's profile Send private message

PostPosted: Wed Oct 25, 2017 1:39 pm     Reply with quote

The default address of this chip is 0x5A, not 0x50.

Always with I2C, the first thing to do is to run the I2C address scanner program from PCM_Programmer (in the code forum). This will tell you if your hardware is working, and what address the device is on.
ep.hobbyiest



Joined: 08 Oct 2014
Posts: 20

View user's profile Send private message Send e-mail

PostPosted: Wed Oct 25, 2017 8:19 pm     Reply with quote

Yes. It was 0x5A only. But i was checking how it working with wrong address.
I was using 0x5A only and not working with that also.

I ran i2c scanner for this device, but got more than 50 address (invalid).
i2c scanner gives correct address for oled, but not working properly with MLX90614.
Ttelmah



Joined: 11 Mar 2010
Posts: 19497

View user's profile Send private message

PostPosted: Thu Oct 26, 2017 1:57 am     Reply with quote

You have got the 'B' device. MLX90614xxx-Bxxxx
It must be a B device to run at 3v (or a D device). Unlike a lot of devices where the higher voltage version will run at lower voltages these don't

If the hardware is working, PCM's scanner will find it. That it is reporting phantom devices, says the pull ups are not doing what they should. What resistors are you using?.
Gabriel



Joined: 03 Aug 2009
Posts: 1067
Location: Panama

View user's profile Send private message

PostPosted: Thu Oct 26, 2017 6:00 am     Reply with quote

As i mentioned on your post on the library..... the serial streams dont match.

G.
_________________
CCS PCM 5.078 & CCS PCH 5.093
ep.hobbyiest



Joined: 08 Oct 2014
Posts: 20

View user's profile Send private message Send e-mail

PostPosted: Thu Oct 26, 2017 9:40 am     Reply with quote

I am using Pull up of 1K8 ohm.
Quote:
As i mentioned on your post on the library..... the serial streams dont match.


are you talking about uart communication? If yes, then Yes it is working properly.

For I2C communication i am using 1 i2c bus only.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Oct 26, 2017 9:41 am     Reply with quote

I wonder if your #use i2c statement is correct, because you have sda
and scl reversed. Normally, you would specify SCL on PIN_C3, and
SDA on PIN_C4. They are reversed in your #use i2c statement below:
Quote:
#use i2c(Master, slow, sda=PIN_C3, scl=PIN_C4, FORCE_SW)

Check your wiring. If it's wired for scl to PIN_C3, and sda to PIN_C4
then you need to fix the statement above to match the wiring.
ep.hobbyiest



Joined: 08 Oct 2014
Posts: 20

View user's profile Send private message Send e-mail

PostPosted: Thu Oct 26, 2017 9:53 am     Reply with quote

Yes my definition is correct only. After connection i checked in code then i was corrected it in code and made it as FORCE_SW.

Result of i2c_scanner:

Code:
Start:
ACK addr: 10
ACK addr: 12
ACK addr: 18
ACK addr: 1A
ACK addr: 1C
ACK addr: 1E
.
.
.
.
ACK addr: DE
ACK addr: E4
ACK addr: E6
ACK addr: E8
ACK addr: EC
ACK addr: EE

Number of i2c chips found: 79


Again i changed the wiring and connected same as hardware i2c.
When i used as FORCE_HW then got stuck after first read.
Code:
#use i2c(Master,fast,sda=PIN_C4,scl=PIN_C3, FORCE_HW)


But after removing of FORCE_HW then it didn't stuck.
Code:
#use i2c(Master,fast,sda=PIN_C4,scl=PIN_C3)


Quote:
You have got the 'B' device. MLX90614xxx-Bxxxx

I tried with giving 5 volt as well. but same result.

is that means problem in i2c hardware?
Gabriel



Joined: 03 Aug 2009
Posts: 1067
Location: Panama

View user's profile Send private message

PostPosted: Fri Oct 27, 2017 6:06 am     Reply with quote

I think you need to post a complete compilable program for others to test, short and simple, that shows the error.

Your serial might be working, but your streams do not match.
My code's print statements use "lcd_putc" as a stream, yours use "PORT1"....also some mis-matches on the use of "printf" vs "fprintf".
Might not be the cause of the problem, but it should be taken care of.
_________________
CCS PCM 5.078 & CCS PCH 5.093
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Oct 27, 2017 11:04 am     Reply with quote

Also post a link to the schematic for your board.

Also post a link to a photo of your test setup, so we can see the connections.
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