Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Diff: MLX90620.cpp
- Revision:
- 0:8c2ddd9801ca
- Child:
- 1:fd536ebc7eaf
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/MLX90620.cpp Tue Jun 14 19:17:47 2016 +0000
@@ -0,0 +1,275 @@
+//NOTE: "Step Measurement Mode" was removed from new MLX90620 data sheet, page 22 dated Sept 19 2012
+// which is used in this implementation
+
+#include "mbed.h"
+#include "MLX90620.h"
+
+//these bufferes must reside in main.cpp
+//extern char* MLXEEbuf; //256 uint8_ts, holds contents of EEPROM
+//extern char* MLXRamBuf; //128 uint8_ts, 0x0 - 0x3f 'uint16_t', holds contents of RAM array
+//extern char* MLXRamCmmd; // 8 uint8_ts, MLX90620 i2c command i/o buffer
+/*
+uint16_t Config = 0; //MLX90620 configuration register
+uint16_t OscTrim = 0; //MLX90620 oscillator trim register
+uint16_t PtatD = 0; //MLX90620 PTAT data register
+int16_t VCP = 0; //VCP / TGC
+int16_t Vth25X = 0;
+float TaXX = 0.0;
+
+//For To
+int8_t AcpX = 0;
+int8_t BcpX = 0;
+float Kt1fX = 0.0;
+float Kt2fX = 0.0;
+int8_t TGCX = 0;
+uint8_t BiScaleX = 0;
+uint16_t theta0X = 0;
+uint8_t theta0ScaleX = 0;
+uint8_t deltaThetaScaleX = 0;
+uint16_t elipsonX = 0;
+int8_t AiPixelX = 0; //eeprom address range 0x00 - 0x3f
+int8_t BiPixelX = 0; //eeprom address range 0x40 - 0x7f
+uint8_t dThetaPixelX = 0; //eeprom address range 0x80 - 0xbf
+int16_t VirPixelX = 0;
+double TempPxlX = 0;
+*/
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+// Constructor
+
+MLX90620::MLX90620(PinName sda, PinName scl, const char* name) : _i2c(sda, scl){
+ _i2c.frequency(400000); //set up i2c speed
+ _i2c.stop(); //initialize with a stop
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+//copy contents of EEPROM inside the MLX90620 into a local buffer. Data is used for lookup tables and parameters
+
+#define MLX_EEP_EASY_LOAD 1
+
+int MLX90620::LoadEEPROM(mlx_struct& Pntr) {
+
+ //clear out buffer first
+ for(int i = 0; i < 256; i++) { //option to clear out EEPROM buffer first
+ Pntr.MLXEEbuf[i] = 0;
+ }
+
+ //load the entire EEPROM
+ Pntr.MLXEEbuf[0] = 0; //start at address 0 of EEPROM
+ if(!_i2c.write(MLX_EEPADDR, Pntr.MLXEEbuf, 1, true)) { //send command, 0 returned is ok
+
+#ifdef MLX_EEP_EASY_LOAD
+ _i2c.read((MLX_EEPADDR + 1), Pntr.MLXEEbuf, 256); //**** this command does not work with the KL25Z anv v63 of mbed.lbr !!!! //load contents of EEPROM
+#else
+ _i2c.start();
+ _i2c.write(MLX_EEPADDR + 1);
+ for(int i = 0; i < 256; i++) {
+ Pntr.MLXEEbuf[i] = _i2c.read(1);
+ }
+ _i2c.stop();
+#endif
+
+ } else {
+ _i2c.stop(); //don't read EEP if write is broken
+ return(1); //return with error
+ }
+ return(0); //return with ok
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+//copy oscillator offset from MLXEEbuf to MLX90620 (MS byte = 0)
+
+int MLX90620::SetOscTrimReg(mlx_struct& Pntr) {
+ Pntr.MLXRamCmmd[0] = 4; //command
+ Pntr.MLXRamCmmd[1] = Pntr.MLXEEbuf[MLX_EETRIM] - 0xaa; //LS byte check
+ Pntr.MLXRamCmmd[2] = Pntr.MLXEEbuf[MLX_EETRIM]; //oscillator trim value
+ Pntr.MLXRamCmmd[3] = 0x100 - 0xaa; //MS byte check
+ Pntr.MLXRamCmmd[4] = 0; //MS byte = 0
+ int r = _i2c.write(MLX_RAMADDR, Pntr.MLXRamCmmd, 5, false); //send command
+ return(r); //return ok or error
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+//get oscillator offset register from MLX90620
+
+uint16_t MLX90620::GetOscTrimReg(mlx_struct& Pntr) {
+ Pntr.MLXRamCmmd[0] = 2; //command
+ Pntr.MLXRamCmmd[1] = MLX_TRIM; //address of register
+ Pntr.MLXRamCmmd[2] = 0; //address step
+ Pntr.MLXRamCmmd[3] = 1; //# of reads
+ _i2c.write(MLX_RAMADDR, Pntr.MLXRamCmmd, 4, true); //send command
+ _i2c.read(MLX_RAMADDR, Pntr.MLXRamCmmd, 2); //get 16 bit register
+ Pntr.OscTrim = (Pntr.MLXRamCmmd[1] << 8) + Pntr.MLXRamCmmd[0]; //store register
+ return(Pntr.OscTrim); //return value
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+//initialize the configuration register
+//******* NOTE: Step measurement mode was removed from new data sheet dated Sept 19 2012
+
+int MLX90620::SetConfigReg(mlx_struct& Pntr) {
+ Pntr.MLXRamCmmd[0] = 3; //command
+ //old mode
+ //MLXRamCmmd[1] = 0x14c - 0x55; //LS byte check
+ //MLXRamCmmd[2] = 0x4c; //LS config value, step meas mode, 4Hz array *******
+ Pntr.MLXRamCmmd[1] = 0x10c - 0x55; //LS byte check
+ Pntr.MLXRamCmmd[2] = 0x0c; //LS config value, normal mode, 4Hz array *******
+ Pntr.MLXRamCmmd[3] = 0x5c - 0x55; //MS byte check
+ Pntr.MLXRamCmmd[4] = 0x5c; //MS config value, 8Hz Ta, 400k i2c
+ int r = _i2c.write(MLX_RAMADDR, Pntr.MLXRamCmmd, 5, false);
+ return(r);
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+//get configuration register from MLX90620
+
+uint16_t MLX90620::GetConfigReg(mlx_struct& Pntr) {
+ Pntr.MLXRamCmmd[0] = 2; //command
+ Pntr.MLXRamCmmd[1] = MLX_CONFIG; //address of register
+ Pntr.MLXRamCmmd[2] = 0; //address step
+ Pntr.MLXRamCmmd[3] = 1; //# of reads
+ _i2c.write(MLX_RAMADDR, Pntr.MLXRamCmmd, 4, true);
+ _i2c.read(MLX_RAMADDR, Pntr.MLXRamCmmd, 2);
+ Pntr.Config = (Pntr.MLXRamCmmd[1] << 8) + Pntr.MLXRamCmmd[0];
+ return(Pntr.Config);
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+//get PTAT register from MLX90620
+
+uint16_t MLX90620::GetPTATReg(mlx_struct& Pntr) {
+ Pntr.MLXRamCmmd[0] = 2; //command
+ Pntr.MLXRamCmmd[1] = MLX_PTATSENS; //address of register
+ Pntr.MLXRamCmmd[2] = 0; //address step
+ Pntr.MLXRamCmmd[3] = 1; //# of reads
+ _i2c.write(MLX_RAMADDR, Pntr.MLXRamCmmd, 4, true);
+ _i2c.read(MLX_RAMADDR, Pntr.MLXRamCmmd, 2);
+ Pntr.PtatD = (Pntr.MLXRamCmmd[1] << 8) + Pntr.MLXRamCmmd[0];
+ return(Pntr.PtatD);
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+//get VCP / TGC register from MLX90620
+
+int16_t MLX90620::GetTGCReg(mlx_struct& Pntr) {
+ Pntr.MLXRamCmmd[0] = 2; //command
+ Pntr.MLXRamCmmd[1] = MLX_TGCSENS; //address of register
+ Pntr.MLXRamCmmd[2] = 0; //address step
+ Pntr.MLXRamCmmd[3] = 1; //# of reads
+ _i2c.write(MLX_RAMADDR, Pntr.MLXRamCmmd, 4, true);
+ _i2c.read(MLX_RAMADDR, Pntr.MLXRamCmmd, 2);
+ VCP = (Pntr.MLXRamCmmd[1] << 8) + Pntr.MLXRamCmmd[0];
+ return(VCP);
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+//get RAM dump from MLX90620
+bool firstDump = false;
+
+void MLX90620::LoadMLXRam(mlx_struct& Pntr) {
+ Pntr.MLXRamCmmd[0] = 2; //command
+ Pntr.MLXRamCmmd[1] = 0; //start address
+ Pntr.MLXRamCmmd[2] = 1; //address step
+ Pntr.MLXRamCmmd[3] = 0x40; //# of reads
+ _i2c.write(MLX_RAMADDR, Pntr.MLXRamCmmd, 4, true);
+ _i2c.read(MLX_RAMADDR, Pntr.MLXRamBuf, 0x80);
+ Pntr.PtatD = MLX90620::GetPTATReg(Pntr);
+ VCP = MLX90620::GetTGCReg(Pntr);
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+//start measurement MLX90620
+
+int MLX90620::StartMeasurement(mlx_struct& Pntr) {
+ Pntr.MLXRamCmmd[0] = 1; //command
+ Pntr.MLXRamCmmd[1] = 8; //address of config register
+ int r = _i2c.write(MLX_RAMADDR, Pntr.MLXRamCmmd, 2, false);
+ return(r);
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+// Initial Calculations for Ta and To
+
+float MLX90620::GetDieTemp(mlx_struct& Pntr) {
+ Pntr.PtatD = MLX90620::GetPTATReg(Pntr);
+ float TaX = (-Kt1fX + sqrt(pow(Kt1fX, 2.0f) - 4.0f * Kt2fX * ((float)(Vth25X - Pntr.PtatD))))/(2.0f * Kt2fX) + 25.0f;
+ return(TaX);
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+// Initial Calculations for Ta and To
+
+void MLX90620::CalcTa_To(mlx_struct& Pntr) {
+ //Calculate Ta first
+ Vth25X = (Pntr.MLXEEbuf[MLX_TAINDEX + 1] << 8) + Pntr.MLXEEbuf[MLX_TAINDEX + 0];
+ int16_t Kt1 = (Pntr.MLXEEbuf[MLX_TAINDEX + 3] << 8) + Pntr.MLXEEbuf[MLX_TAINDEX + 2];
+ int16_t Kt2 = (Pntr.MLXEEbuf[MLX_TAINDEX + 5] << 8) + Pntr.MLXEEbuf[MLX_TAINDEX + 4];
+ Kt1fX = Kt1 / 1024.0;
+ Kt2fX = Kt2 / 1048576.0;
+ TaXX = MLX90620::GetDieTemp(Pntr);
+
+ //Calculate To
+ AcpX = Pntr.MLXEEbuf[MLX_TOINDEX + 0];
+ BcpX = Pntr.MLXEEbuf[MLX_TOINDEX + 1];
+// uint16_t thetaCPX = (EEbuf[MLX_TOINDEX + 3] << 8) + MLXEEbuf[MLX_TOINDEX + 2];
+ TGCX = Pntr.MLXEEbuf[MLX_TOINDEX + 4];
+ BiScaleX = Pntr.MLXEEbuf[MLX_TOINDEX + 5];
+ theta0X = (Pntr.MLXEEbuf[MLX_TOINDEX + 13] << 8) + Pntr.MLXEEbuf[MLX_TOINDEX + 12];
+ theta0ScaleX = Pntr.MLXEEbuf[MLX_TOINDEX + 14];
+ deltaThetaScaleX = Pntr.MLXEEbuf[MLX_TOINDEX + 15];
+ elipsonX = (Pntr.MLXEEbuf[MLX_TOINDEX + 17] << 8) + Pntr.MLXEEbuf[MLX_TOINDEX + 16];
+/*
+ printf("Vth(25) = %6d 0x%x\nTa1 = %6d 0x%x\nTa2 = %6d 0x%x\n", Vth25X, Vth25X, Kt1, Kt1, Kt2, Kt2);
+ printf("Kt1fX = %f\nKt2fX = %f\nTaXX = %f\n\n", Kt1fX, Kt2fX, TaXX);
+ printf("Acp = %6d 0x%x\nBcp = %6d 0x%x\nThCP = %6d 0x%x\n", AcpX, AcpX, BcpX, BcpX, thetaCPX, thetaCPX);
+ printf("TGC = %6d 0x%x\nBiS = %6d 0x%x\nTh0 = %6d 0x%x\n", TGCX, TGCX, BiScaleX, BiScaleX, theta0X, theta0X);
+ printf("T0s = %6d 0x%x\nDts = %6d 0x%x\nelip = %6d 0x%x\n\n", theta0ScaleX, theta0ScaleX, deltaThetaScaleX, deltaThetaScaleX, elipsonX, elipsonX);
+*/
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+// Pixel Temperature Calculation
+
+double MLX90620::CalcPixel(mlx_struct& Pntr, int Pixel) {
+ AiPixelX = Pntr.MLXEEbuf[Pixel]; //eeprom address range 0x00 - 0x3f
+ BiPixelX = Pntr.MLXEEbuf[Pixel + 0x40]; //eeprom address range 0x40 - 0x7f
+ dThetaPixelX = Pntr.MLXEEbuf[Pixel + 0x80]; //eeprom address range 0x08 - 0xbf
+ VirPixelX = (Pntr.MLXRamBuf[Pixel * 2 + 1] << 8) + Pntr.MLXRamBuf[Pixel * 2]; //ram address range 0x000 - 0x08f, 16b
+ float Vcp_off_comp = VCP - (AcpX + BcpX / powf(2.0f,BiScaleX) * (TaXX - 25.0f));
+ float VirPixel_off_comp = VirPixelX - (AiPixelX + BiPixelX / powf(2.0f,BiScaleX) * (TaXX - 25.0f));
+ float VirPixel_off_comp2 = (float(AiPixelX) + float(BiPixelX) / float(1 << BiScaleX) * (TaXX - 25.0f));
+ VirPixel_off_comp2 = VirPixelX - VirPixel_off_comp2;
+ float VirPixel_tgc_comp = VirPixel_off_comp - TGCX / 32.0 * Vcp_off_comp;
+ float elipsonf = elipsonX / 32768.0;
+ float VirPixel_comp = VirPixel_tgc_comp / elipsonf;
+ double theta28 = theta0X / powf(2.0, theta0ScaleX) + dThetaPixelX / powf(2.0, deltaThetaScaleX);
+ double TempPxl = powf((VirPixel_comp / theta28 + powf((TaXX + 273.15f), 4.0f)), (1.0f / 4.0f)) - 273.15f;
+/*
+ printf("\r\n\r\npixel = %d\r\n", Pixel);
+ printf("Acp = %d\r\nBcp = %d\r\nBiS = %d\r\n", AcpX, BcpX, BiScaleX);
+ printf("Vcp = %d\r\neps = %d\r\nTGC = %d\r\n", VCP, elipsonX, TGCX);
+ printf("Vcp_off_comp = %f\r\n", Vcp_off_comp);
+ printf("VirPixel_off_comp = %f\r\n", VirPixel_off_comp);
+ printf("VirPixel = %d\r\n", VirPixelX);
+ printf("AiPixel = %d\r\n", AiPixelX);
+ printf("BiPixel = %d\r\n", BiPixelX);
+ printf("BiScale = %d\r\n", BiScaleX);
+ printf("2^BiScale = %f\r\n", (powf(2.0,BiScaleX)));
+ printf("1 << BiScale = %d\r\n", (1 << BiScaleX));
+ printf("Ta-25.0 = %f\r\n", (TaXX - 25.0f));
+ printf("BiPix/2^BiScale = %f\r\n", (BiPixelX / powf(2.0,BiScaleX)));
+ printf("AiP+BiP/2^BiScale)*(Ta-25= %f\r\n", (AiPixelX + BiPixelX / powf(2.0,BiScaleX) * (TaXX - 25.0f)));
+ printf("VirPixel_off_comp again = %f\r\n", (VirPixelX - (AiPixelX + BiPixelX / powf(2.0,BiScaleX) * (TaXX - 25.0f))));
+ printf("VirPixel_off_comp2 step = %f\r\n", VirPixel_off_comp2);
+ printf("VirPixel_tgc_comp = %f\r\n", VirPixel_tgc_comp);
+ printf("elipsonf = %f\r\n", elipsonf);
+ printf("VirPixel_comp = %f\r\n", VirPixel_comp);
+ printf("theta28 = %f << double print problem\r\n", (theta28 * 100000000.0)); //<<< can't print a double
+ printf("TempPxl = %f\r\n", TempPxl);
+*/
+ return(TempPxl);
+}
+
+
+
+