|
|
View previous topic :: View next topic |
Author |
Message |
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
MLX90614 Driver |
Posted: Mon Sep 19, 2016 9:27 pm |
|
|
Hi All,
In the spirit of expanding this library I am sharing my MLX90614 driver.
I needed the sensor recently and noticed there is no driver on this library.
The driver below does pretty much everything needed for this chip.
Including writing to the EEPROM for configuration.
Be careful when changing stuff or factory calibration will be lost.
The CRC functions work for both checking the incoming data and obviously for writing to the chip.
I will not post a sample program as I don't think its necessary for this as its pretty simple. I've included some examples on the driver itself.
Code: |
//**********************************************************************************
// MLX90614 Driver
//**********************************************************************************
// By: Gabriel E. Barrios F.
// Date: 19/09/2016
// Panama, Panama
////////////////////////////////////////////////////////////////////////////////////
// This is a driver for the MLX90614ESF-BAA Single Zone IR Thermometer.
// Read and Write functions are provided and all the pertinent CRC stuff is included.
// This driver can read EEPROM and RAM on the MLX, and can also Write to EEPROM.
// This driver is for a Single Sensor on the I2C BUS
////////////////////////////////////////////////////////////////////////////////////
//SMBUS Device Address
#define Device_Address 0x5A
//RAM Addresses for Temperatures
#define AT_Address 0x06 // Ambien 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 Read_Object()
{
fprintf(lcd_putc,"Object Temp:%3.2f\r\n",((MLX_Read_Transaction(OT_Address)*0.02)-273));
delay_ms(500);
}
void Read_Ambient()
{
fprintf(lcd_putc,"Ambient Temp:%3.2f\r\n",((MLX_Read_Transaction(AT_Address)*0.02)-273));
delay_ms(500);
}
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(int 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(Command)==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(Command); // Send "Read" Command to the Device Address
Lo_Byte = i2c_read(ACK); // Get Low Byte and ACK the read
Hi_Byte = i2c_read(ACK); // Get High Byte and ACK the read
CRC = i2c_read(ACK); // 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;
}
|
Hope this helps some of you.
G. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
mohammad3d
Joined: 28 Mar 2009 Posts: 17
|
|
Posted: Fri Jun 30, 2017 4:55 am |
|
|
Dear Gabriel,
Thanks for your driver sharing...
This is great.
Can you send a complete program on specified PIC like 16F or 18F series, that uses your driver for sending object temperature on serial port?
Very thanks again for your great work.
Regards. |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Fri Jun 30, 2017 10:52 am |
|
|
Examples of what you ask are already provided on the driver.
Literally, include the driver in your file and do this:
Code: |
//**********************************************************************************
// 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
// }
|
_________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
ep.hobbyiest
Joined: 08 Oct 2014 Posts: 20
|
|
Posted: Wed Oct 25, 2017 12:23 pm |
|
|
Hi,
I am using your code. But data is not being read correctly.
I could see some variation in temperature. But not correct.
Code: | Object Temp:-272.01
Ambient Temp:-270.98
Object Temp:-272.79
Ambient Temp:-270.02 |
What could be the problem ?
I am using PIC16F886 and connected SDA to PC3 and SCL to PC4.
Pull-up are provided.
My circuits work on 3.3 Volt.
Following is my 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
|
|
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Thu Oct 26, 2017 5:53 am |
|
|
Hi,
The most obvious problem I see is that your serial STREAM declaration does not match the stream on the code's print statements.
Other possible reasons:
Check your pullups.
Check your I2C declaration.
G. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
patan_mustafa
Joined: 10 Dec 2006 Posts: 2
|
|
Posted: Sat Dec 23, 2017 2:08 am |
|
|
If you add following lines before read sensor, code works well.
Code: |
output_low(PIN_C4);
output_low(PIN_C3);
delay_ms(500);
|
|
|
|
|
|
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
|