├── .gitignore ├── Documents └── MLX90614_rev001.pdf ├── LICENSE ├── README.md ├── examples ├── Example1_Get_ID │ └── Example1_Get_ID.ino ├── Example2_Get_Temperature │ └── Example2_Get_Temperature.ino ├── Example3_Set_Emissivity │ └── Example3_Set_Emissivity.ino └── Example4_Change_i2c_Address │ └── Example4_Change_i2c_Address.ino ├── keywords.txt ├── library.properties └── src ├── SparkFunMLX90614.cpp └── SparkFunMLX90614.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore list for Eagle, a PCB layout tool 2 | 3 | # Backup files 4 | *.s#? 5 | *.b#? 6 | *.l#? 7 | 8 | # Eagle project file 9 | # It contains a serial number and references to the file structure 10 | # on your computer. 11 | # comment the following line if you want to have your project file included. 12 | eagle.epf 13 | 14 | # CAM files 15 | *.$$$ 16 | *.cmp 17 | *.ly2 18 | *.l15 19 | *.sol 20 | *.plc 21 | *.stc 22 | *.sts 23 | *.crc 24 | *.crs 25 | 26 | *.dri 27 | *.drl 28 | *.gpi 29 | *.pls 30 | 31 | *.drd 32 | *.drd.* 33 | 34 | *.info 35 | 36 | *.eps 37 | -------------------------------------------------------------------------------- /Documents/MLX90614_rev001.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sparkfun/SparkFun_MLX90614_Arduino_Library/a2fb7586eefcb98425f9767c484ba200bfe8e574/Documents/MLX90614_rev001.pdf -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 SparkFun Electronics 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SparkFun MLX90614 Arduino Library 2 | ======================================== 3 | 4 | ![SparkFun Infrared Thermometer Evaluation Board](https://cdn.sparkfun.com//assets/parts/5/6/4/6/10740-01a.jpg) 5 | 6 | [*SparkFun Infrared Thermometer Evaluation Board (SEN-10740)*](https://www.sparkfun.com/products/10740) 7 | 8 | An Arduino library that interfaces with the MLX90614 non-contact infrared thermometer over a 2-wire, I2C-like interface (SMBus). 9 | 10 | Repository Contents 11 | ------------------- 12 | 13 | * **/examples** - Example sketches for the library (.ino). Run these from the Arduino IDE. 14 | * * **/src** - Source files for the library (.cpp, .h). 15 | * **keywords.txt** - Keywords from this library that will be highlighted in the Arduino IDE. 16 | * **library.properties** - General library properties for the Arduino package manager. 17 | 18 | Documentation 19 | -------------- 20 | 21 | * **[Installing an Arduino Library Guide](https://learn.sparkfun.com/tutorials/installing-an-arduino-library)** - Basic information on how to install an Arduino library. 22 | * **[Product Repository](https://github.com/sparkfun/IR_Thermometer_Evaluation_Board-MLX90614)** - Main repository (including hardware files) for the Infrared Thermometer Evaluation Board. 23 | * **[Hookup Guide](https://learn.sparkfun.com/tutorials/mlx90614-ir-thermometer-hookup-guide)** - Basic hookup guide for the Infrared Thermometer Evaluation Board. 24 | 25 | Products that use this Library 26 | --------------------------------- 27 | 28 | * [Infrared Thermometer Evaluation Board - MLX90614](https://www.sparkfun.com/products/10740)- A Arduino-compatible evaluation board for the MLX90614. 29 | * [Infrared Thermometer - MLX90614 ](https://www.sparkfun.com/products/9570) -- The MLX90614 IC itself 30 | 31 | Version History 32 | --------------- 33 | * [V 1.0.0](https://github.com/sparkfun/SparkFun_MLX90614_Arduino_Library/tree/V_1.0.0) - Initial release 34 | 35 | License Information 36 | ------------------- 37 | 38 | This product is _**open source**_! 39 | 40 | The **code** is released under the MIT license. See the included LICENSE file for more information. 41 | 42 | Distributed as-is; no warranty is given. 43 | 44 | - Your friends at SparkFun. 45 | -------------------------------------------------------------------------------- /examples/Example1_Get_ID/Example1_Get_ID.ino: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | MLX90614_Get_ID.ino 3 | Print ID register values stored in the MLX90614 4 | 5 | This example reads from the MLX90614's ID registers, and 6 | prints out the 64-byte value to the serial monitor. 7 | 8 | Hardware Hookup (if you're not using the eval board): 9 | MLX90614 ------------- Arduino 10 | VDD ------------------ 3.3V 11 | VSS ------------------ GND 12 | SDA ------------------ SDA (A4 on older boards) 13 | SCL ------------------ SCL (A5 on older boards) 14 | 15 | Jim Lindblom @ SparkFun Electronics 16 | October 23, 2015 17 | https://github.com/sparkfun/SparkFun_MLX90614_Arduino_Library 18 | 19 | Development environment specifics: 20 | Arduino 1.6.5 21 | SparkFun IR Thermometer Evaluation Board - MLX90614 22 | ******************************************************************************/ 23 | 24 | #include // I2C library, required for MLX90614 25 | #include //Click here to get the library: http://librarymanager/All#Qwiic_IR_Thermometer by SparkFun 26 | 27 | IRTherm therm; // Create an IRTherm object to interact with throughout 28 | 29 | void setup() 30 | { 31 | Serial.begin(115200); // Initialize Serial to log output 32 | Wire.begin(); //Join I2C bus 33 | 34 | if (therm.begin() == false){ // Initialize the MLX90614 35 | Serial.println("Qwiic IR thermometer did not acknowledge! Freezing!"); 36 | while(1); 37 | } 38 | Serial.println("Qwiic IR thermometer acknowledged."); 39 | 40 | if (therm.readID()) // Read from the ID registers 41 | { // If the read succeeded, print the ID: 42 | Serial.println("ID: 0x" + 43 | String(therm.getIDH(), HEX) + 44 | String(therm.getIDL(), HEX)); 45 | } 46 | Serial.println(String(therm.readEmissivity())); 47 | } 48 | 49 | void loop() 50 | { 51 | 52 | } 53 | -------------------------------------------------------------------------------- /examples/Example2_Get_Temperature/Example2_Get_Temperature.ino: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | MLX90614_Serial_Demo.ino 3 | Serial output example for the MLX90614 Infrared Thermometer 4 | 5 | This example reads from the MLX90614 and prints out ambient and object 6 | temperatures every half-second or so. Open the serial monitor and set the 7 | baud rate to 9600. 8 | 9 | Hardware Hookup (if you're not using the eval board): 10 | MLX90614 ------------- Arduino 11 | VDD ------------------ 3.3V 12 | VSS ------------------ GND 13 | SDA ------------------ SDA (A4 on older boards) 14 | SCL ------------------ SCL (A5 on older boards) 15 | 16 | An LED can be attached to pin 8 to monitor for any read errors. 17 | 18 | Jim Lindblom @ SparkFun Electronics 19 | October 23, 2015 20 | https://github.com/sparkfun/SparkFun_MLX90614_Arduino_Library 21 | 22 | Development environment specifics: 23 | Arduino 1.6.5 24 | SparkFun IR Thermometer Evaluation Board - MLX90614 25 | ******************************************************************************/ 26 | 27 | #include // I2C library, required for MLX90614 28 | #include //Click here to get the library: http://librarymanager/All#Qwiic_IR_Thermometer by SparkFun 29 | 30 | IRTherm therm; // Create an IRTherm object to interact with throughout 31 | 32 | void setup() 33 | { 34 | Serial.begin(115200); // Initialize Serial to log output 35 | Wire.begin(); //Joing I2C bus 36 | 37 | if (therm.begin() == false){ // Initialize thermal IR sensor 38 | Serial.println("Qwiic IR thermometer did not acknowledge! Freezing!"); 39 | while(1); 40 | } 41 | Serial.println("Qwiic IR Thermometer did acknowledge."); 42 | 43 | therm.setUnit(TEMP_F); // Set the library's units to Farenheit 44 | // Alternatively, TEMP_F can be replaced with TEMP_C for Celsius or 45 | // TEMP_K for Kelvin. 46 | 47 | pinMode(LED_BUILTIN, OUTPUT); // LED pin as output 48 | } 49 | 50 | void loop() 51 | { 52 | digitalWrite(LED_BUILTIN, HIGH); 53 | 54 | // Call therm.read() to read object and ambient temperatures from the sensor. 55 | if (therm.read()) // On success, read() will return 1, on fail 0. 56 | { 57 | // Use the object() and ambient() functions to grab the object and ambient 58 | // temperatures. 59 | // They'll be floats, calculated out to the unit you set with setUnit(). 60 | Serial.print("Object: " + String(therm.object(), 2)); 61 | Serial.println("F"); 62 | Serial.print("Ambient: " + String(therm.ambient(), 2)); 63 | Serial.println("F"); 64 | Serial.println(); 65 | } 66 | digitalWrite(LED_BUILTIN, LOW); 67 | delay(1000); 68 | } 69 | -------------------------------------------------------------------------------- /examples/Example3_Set_Emissivity/Example3_Set_Emissivity.ino: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | MLX90614_Set_Emissivity 3 | How to read and set the MLX90614's emissivity coefficient 4 | 5 | Emissivity is a relative measure of how efficiently an object 6 | radiates heat. A perfect thermal emitter has a emissivity of 7 | 1.0, but most real-world objects range from 0 to 1. 8 | 9 | For example, human skin has an emissivity of about 0.98. 10 | Shiny metals have a very low emissivity, for example polished 11 | aluminum has an emissivity of 0.05. Painted aluminum has an 12 | emissivity of 0.45. Here's a good reference: 13 | http://www.thermoworks.com/emissivity_table.html 14 | 15 | If you get really wacky values after setting the emissivity, 16 | try cycling power to the MLX90614. 17 | 18 | To set the emissivity, change the value of the 19 | newEmissivity variable above setup(). Allowable values are 20 | between 0.1 and 1.0. 21 | 22 | Hardware Hookup (if you're not using the eval board): 23 | MLX90614 ------------- Arduino 24 | VDD ------------------ 3.3V 25 | VSS ------------------ GND 26 | SDA ------------------ SDA (A4 on older boards) 27 | SCL ------------------ SCL (A5 on older boards) 28 | 29 | An LED can be attached to pin 8 to monitor for any read errors. 30 | 31 | Jim Lindblom @ SparkFun Electronics 32 | October 23, 2015 33 | https://github.com/sparkfun/SparkFun_MLX90614_Arduino_Library 34 | 35 | Development environment specifics: 36 | Arduino 1.6.5 37 | SparkFun IR Thermometer Evaluation Board - MLX90614 38 | ******************************************************************************/ 39 | 40 | #include // I2C library, required for MLX90614 41 | #include //Click here to get the library: http://librarymanager/All#Qwiic_IR_Thermometer by SparkFun 42 | 43 | IRTherm therm; // Create an IRTherm object to interact with throughout 44 | 45 | float newEmissivity = 0.98; 46 | 47 | void setup() 48 | { 49 | Serial.begin(115200); // Initialize Serial to log output 50 | Wire.begin(); // Join I2C bus 51 | 52 | if (therm.begin() == false){ // Initialize the MLX90614 53 | Serial.println("Qwiic IR thermometer did not acknowledge! Freezing!"); 54 | while(1); 55 | } 56 | Serial.println("Qwiic IR thermometer acknowledged."); 57 | therm.setUnit(TEMP_F); // Set the library's units to Farenheit 58 | pinMode(LED_BUILTIN, OUTPUT); // LED pin as output 59 | 60 | Serial.println(); 61 | Serial.println("Please enter the emissivity you would like to set the thermometer to."); 62 | Serial.println("The emissivity of human skin is 0.98."); 63 | Serial.println("Valid emissivity values are between 0.1 and 1.0."); 64 | 65 | while (!Serial.available()) ; 66 | 67 | if (Serial.available()){ 68 | float newEmissivity = Serial.parseFloat(); 69 | 70 | // Edge-case gaurds 71 | if (newEmissivity < 0.1) 72 | newEmissivity = 0.1; 73 | else if (newEmissivity > 1.0) 74 | newEmissivity = 1.0; 75 | 76 | // Call setEmissivity() to configure the MLX90614's 77 | // emissivity compensation: 78 | therm.setEmissivity(newEmissivity); 79 | 80 | // readEmissivity() can be called to read the device's 81 | // configured emissivity -- it'll return a value between 82 | // 0.1 and 1.0. 83 | Serial.println("Emissivity: " + String(therm.readEmissivity())); 84 | } 85 | } 86 | 87 | void loop() 88 | { 89 | digitalWrite(LED_BUILTIN, HIGH); 90 | 91 | // Call therm.read() to read object and ambient temperatures from the sensor. 92 | if (therm.read()) // On success, read() will return 1, on fail 0. 93 | { 94 | // Use the object() and ambient() functions to grab the object and ambient 95 | // temperatures. 96 | // They'll be floats, calculated out to the unit you set with setUnit(). 97 | Serial.print("Object: " + String(therm.object(), 2)); 98 | Serial.println("F"); 99 | Serial.print("Ambient: " + String(therm.ambient(), 2)); 100 | Serial.println("F"); 101 | Serial.println(); 102 | } 103 | digitalWrite(LED_BUILTIN, LOW); 104 | delay(1000); 105 | } 106 | -------------------------------------------------------------------------------- /examples/Example4_Change_i2c_Address/Example4_Change_i2c_Address.ino: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | MLX90614_Set_Address.ino 3 | Configure an MLX90614 to use a new I2C address. 4 | 5 | This example demonstrates the setAddress function. 6 | If an MLX90614 is configured for the default address (0x5A), 7 | it'll change the address to a new address (0x5B). 8 | If the Arduino can communicate with an MLX90614 on the new 9 | address, it'll print the device's ID registers. 10 | 11 | Note: for the new address to take effect, you need to cycle 12 | power to the MLX90614. 13 | 14 | Hardware Hookup (if you're not using the eval board): 15 | MLX90614 ------------- Arduino 16 | VDD ------------------ 3.3V 17 | VSS ------------------ GND 18 | SDA ------------------ SDA (A4 on older boards) 19 | SCL ------------------ SCL (A5 on older boards) 20 | 21 | Jim Lindblom @ SparkFun Electronics 22 | October 23, 2015 23 | https://github.com/sparkfun/SparkFun_MLX90614_Arduino_Library 24 | 25 | Development environment specifics: 26 | Arduino 1.6.5 27 | SparkFun IR Thermometer Evaluation Board - MLX90614 28 | ******************************************************************************/ 29 | 30 | #include // I2C library, required for MLX90614 31 | #include //Click here to get the library: http://librarymanager/All#Qwiic_IR_Thermometer by SparkFun 32 | 33 | IRTherm therm; // Create an IRTherm object to interact with throughout 34 | 35 | void setup() 36 | { 37 | Serial.begin(115200); // Initialize Serial to log output 38 | Wire.begin(); // Join I2C bus 39 | 40 | // check if qwiic IR thermometer will acknowledge over I2C 41 | if (therm.begin() == false) { 42 | Serial.println("Qwiic IR thermometer did not acknowledge! Running I2C scanner."); 43 | } 44 | 45 | else { 46 | Serial.println("Device acknowledged!"); 47 | 48 | Serial.println(); 49 | Serial.println("Enter a new I2C address for the Qwiic IR Thermometer to use!"); 50 | Serial.println("Don't use the 0x prefix. For instance, if you wanted to "); 51 | Serial.println("change the address to 0x5B, you would type 5B in the serial"); 52 | Serial.println("input bar and press enter."); 53 | Serial.println(); 54 | Serial.println("One more thing! Make sure your line ending is set to 'Both NL & CR'"); 55 | Serial.println("in the Serial Monitor."); 56 | Serial.println(); 57 | Serial.println("Note, for the new I2C address to take effect you need to power cycle"); 58 | Serial.println("the MLX90614."); 59 | 60 | // Wait for serial data to be available 61 | while (Serial.available() == 0); 62 | 63 | if (Serial.available()) { 64 | uint8_t newAddress = 0; 65 | String stringBuffer = Serial.readString(); 66 | char charBuffer[10]; 67 | stringBuffer.toCharArray(charBuffer, 10); 68 | uint8_t success = sscanf(charBuffer, "%x", &newAddress); 69 | 70 | if (success) { 71 | if (newAddress > 0x08 && newAddress < 0x77) { 72 | Serial.println("Character received and device address is valid!"); 73 | Serial.print("Attempting to set device address to 0x"); 74 | Serial.println(newAddress, HEX); 75 | 76 | if (therm.setAddress(newAddress) == true) { 77 | Serial.println("Device address set succeeded!"); 78 | } 79 | else { 80 | Serial.println("Device address set failed!"); 81 | } 82 | 83 | delay(100); // give the hardware time to do whatever configurations it needs 84 | 85 | if (therm.isConnected()) { 86 | Serial.println("Device acknowledged on new I2C address!"); 87 | } else { 88 | Serial.println("Device did not acknowledge on new I2C address!"); 89 | } 90 | } 91 | else { 92 | Serial.println("Address out of range! Try an address between 0x08 and 0x77"); 93 | } 94 | } 95 | else { 96 | Serial.println("Invalid text, try again."); 97 | } 98 | } 99 | delay(100); 100 | } 101 | // byte address; 102 | // if (!therm.readID()) // Try reading the ID registers 103 | // { 104 | // // If the read fails, try re-initializing with the 105 | // // new address. Maybe we've already set it. 106 | // therm.begin(newAddress); 107 | // 108 | // if (therm.readID()) // Read from the ID registers 109 | // { // If the read succeeded, print the ID: 110 | // Serial.println("Communicated with new address."); 111 | // Serial.println("ID: 0x" + 112 | // String(therm.getIDH(), HEX) + 113 | // String(therm.getIDL(), HEX)); 114 | // } 115 | // else 116 | // { 117 | // Serial.println("Failed to communicate with either address."); 118 | // } 119 | // } 120 | // else 121 | // { 122 | // // If the read suceeds, change the address to something 123 | // // new. 124 | // if (!therm.setAddress(newAddress)) 125 | // { 126 | // Serial.println("Failed to set new address."); 127 | // } 128 | // else 129 | // { 130 | // Serial.println("Set the address to 0x" + String(newAddress, HEX)); 131 | // Serial.println("Cycle power to try it out."); 132 | // } 133 | // } 134 | } 135 | 136 | void loop() 137 | { 138 | // If no I2C device found or Qwiic IR thermometer is set to new address, 139 | // scan for available I2C devices 140 | byte error, address; 141 | int nDevices; 142 | 143 | Serial.println("Scanning..."); 144 | 145 | nDevices = 0; 146 | for (address = 1; address < 127; address++) { 147 | // The i2c_scanner uses the return value of the Write.endTransmission() 148 | // to see if a device ddi acknowledge to the address. 149 | Wire.beginTransmission(address); 150 | error = Wire.endTransmission(); 151 | 152 | if (error == 0) { 153 | Serial.print("I2C device found at address 0x"); 154 | if (address < 16) 155 | Serial.print("0"); 156 | Serial.print(address, HEX); 157 | Serial.println(" !"); 158 | 159 | nDevices++; 160 | } 161 | else if (error == 4) { 162 | Serial.print("Unknown error at address 0x"); 163 | if (address < 16) 164 | Serial.print("0"); 165 | Serial.print(address, HEX); 166 | } 167 | } 168 | if (nDevices == 0) 169 | Serial.println("No I2C devices found\n"); 170 | else 171 | Serial.println("done\n"); 172 | 173 | delay(5000); // Wait 5 seconds for next scan 174 | } 175 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For SparkFunMLX90614 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | IRTherm KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | begin KEYWORD2 16 | setUnit KEYWORD2 17 | read KEYWORD2 18 | object KEYWORD2 19 | ambient KEYWORD2 20 | readEmissivity KEYWORD2 21 | setEmissivity KEYWORD2 22 | readAddress KEYWORD2 23 | setAddress KEYWORD2 24 | readID KEYWORD2 25 | getIDH KEYWORD2 26 | getIDL KEYWORD2 27 | readRange KEYWORD2 28 | minimum KEYWORD2 29 | maximum KEYWORD2 30 | setMax KEYWORD2 31 | setMin KEYWORD2 32 | sleep KEYWORD2 33 | wake KEYWORD2 34 | 35 | ####################################### 36 | # Constants (LITERAL1) 37 | ####################################### 38 | TEMP_RAW LITERAL1 39 | TEMP_K LITERAL1 40 | TEMP_C LITERAL1 41 | TEMP_F LITERAL1 -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=SparkFun Qwiic IR Thermometer MLX90614 Arduino Library 2 | version=1.1.5 3 | author=SparkFun Electronics 4 | maintainer=SparkFun Electronics 5 | sentence=Library for the SparkFun IR Thermometer Evaluation Board, Qwiic IR Thermometer Board, and the MLX90614 IR thermometer. 6 | paragraph=Library for the SparkFun IR Thermometer Evaluation Board, Qwiic IR Thermometer Board, and the MLX90614 IR thermometer. 7 | category=Sensors 8 | url=https://github.com/sparkfun/SparkFun_MLX90614_Arduino_Library 9 | architectures=* 10 | -------------------------------------------------------------------------------- /src/SparkFunMLX90614.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | SparkFunMLX90614.cpp 3 | Source file for the SparkFun IR Thermometer Library 4 | 5 | Jim Lindblom @ SparkFun Electronics 6 | October 23, 2015 7 | https://github.com/sparkfun/SparkFun_MLX90614_Arduino_Library 8 | 9 | This file defines the SMBus hardware interface(s) for the MLX90614 IR thermometer 10 | and abstracts temperature measurments and other features of the MLX90614 11 | 12 | Development environment specifics: 13 | Arduino 1.6.5 14 | SparkFun IR Thermometer Evaluation Board - MLX90614 15 | ******************************************************************************/ 16 | 17 | #include 18 | 19 | IRTherm::IRTherm() 20 | { 21 | // Set initial values for all private member variables 22 | _deviceAddress = 0; 23 | _defaultUnit = TEMP_C; 24 | _rawObject = 0; 25 | _rawAmbient = 0; 26 | _rawObject2 = 0; 27 | _rawMax = 0; 28 | _rawMin = 0; 29 | } 30 | 31 | bool IRTherm::begin(uint8_t address, TwoWire &wirePort) 32 | { 33 | _deviceAddress = address; // Store the address in a private member 34 | _i2cPort = &wirePort; 35 | 36 | return (isConnected()); 37 | } 38 | 39 | bool IRTherm::isConnected() 40 | { 41 | _i2cPort->beginTransmission(_deviceAddress); 42 | if (_i2cPort->endTransmission() == 0) 43 | return true; 44 | return false; 45 | } 46 | 47 | void IRTherm::setUnit(temperature_units unit) 48 | { 49 | _defaultUnit = unit; // Store the unit into a private member 50 | } 51 | 52 | bool IRTherm::read() 53 | { 54 | // read both the object and ambient temperature values 55 | if (readObject() && readAmbient()) 56 | { 57 | // If the reads succeeded, return success 58 | return true; 59 | } 60 | return false; // Else return fail 61 | } 62 | 63 | bool IRTherm::readRange() 64 | { 65 | // Read both minimum and maximum values from EEPROM 66 | if (readMin() && readMax()) 67 | { 68 | // If the read succeeded, return success 69 | return true; 70 | } 71 | return false; // Else return fail 72 | } 73 | 74 | float IRTherm::ambient(void) 75 | { 76 | // Return the calculated ambient temperature 77 | return calcTemperature(_rawAmbient); 78 | } 79 | 80 | float IRTherm::object(void) 81 | { 82 | // Return the calculated object temperature 83 | return calcTemperature(_rawObject); 84 | } 85 | 86 | float IRTherm::minimum(void) 87 | { 88 | // Return the calculated minimum temperature 89 | return calcTemperature(_rawMin); 90 | } 91 | 92 | float IRTherm::maximum(void) 93 | { 94 | // Return the calculated maximum temperature 95 | return calcTemperature(_rawMax); 96 | } 97 | 98 | bool IRTherm::readObject() 99 | { 100 | int16_t rawObj; 101 | // Read from the TOBJ1 register, store into the rawObj variable 102 | if (I2CReadWord(MLX90614_REGISTER_TOBJ1, &rawObj)) 103 | { 104 | // If the read succeeded 105 | if (rawObj & 0x8000) // If there was a flag error 106 | { 107 | return 0; // Return fail 108 | } 109 | // Store the object temperature into the class variable 110 | _rawObject = rawObj; 111 | return true; 112 | } 113 | return false; 114 | } 115 | 116 | bool IRTherm::readObject2() 117 | { 118 | int16_t rawObj; 119 | // Read from the TOBJ2 register, store into the rawObj variable 120 | if (I2CReadWord(MLX90614_REGISTER_TOBJ2, &rawObj)) 121 | { 122 | // If the read succeeded 123 | if (rawObj & 0x8000) // If there was a flag error 124 | { 125 | return 0; // Return fail 126 | } 127 | // Store the object2 temperature into the class variable 128 | _rawObject2 = rawObj; 129 | return true; 130 | } 131 | return false; 132 | } 133 | 134 | bool IRTherm::readAmbient() 135 | { 136 | int16_t rawAmb; 137 | // Read from the TA register, store value in rawAmb 138 | if (I2CReadWord(MLX90614_REGISTER_TA, &rawAmb)) 139 | { 140 | // If the read succeeds, store the read value 141 | _rawAmbient = rawAmb; // return success 142 | return true; 143 | } 144 | return false; // else return fail 145 | } 146 | 147 | bool IRTherm::readMax() 148 | { 149 | int16_t toMax; 150 | // Read from the TOMax EEPROM address, store value in toMax 151 | if (I2CReadWord(MLX90614_REGISTER_TOMAX, &toMax)) 152 | { 153 | _rawMax = toMax; 154 | return true; 155 | } 156 | return false; 157 | } 158 | 159 | bool IRTherm::readMin() 160 | { 161 | int16_t toMin; 162 | // Read from the TOMin EEPROM address, store value in toMax 163 | if (I2CReadWord(MLX90614_REGISTER_TOMIN, &toMin)) 164 | { 165 | _rawMin = toMin; 166 | return true; 167 | } 168 | return false; 169 | } 170 | 171 | uint8_t IRTherm::setMax(float maxTemp) 172 | { 173 | // Convert the unit-ed value to a raw ADC value: 174 | int16_t rawMax = calcRawTemp(maxTemp); 175 | // Write that value to the TOMAX EEPROM address: 176 | return writeMLXEEPROM(MLX90614_REGISTER_TOMAX, rawMax); 177 | } 178 | 179 | uint8_t IRTherm::setMin(float minTemp) 180 | { 181 | // Convert the unit-ed value to a raw ADC value: 182 | int16_t rawMin = calcRawTemp(minTemp); 183 | // Write that value to the TOMIN EEPROM address: 184 | return writeMLXEEPROM(MLX90614_REGISTER_TOMIN, rawMin); 185 | } 186 | 187 | uint8_t IRTherm::setEmissivity(float emis) 188 | { 189 | // Make sure emissivity is between 0.1 and 1.0 190 | if ((emis > 1.0) || (emis < 0.1)) 191 | return 0; // Return fail if not 192 | // Calculate the raw 16-bit value: 193 | uint16_t ke = uint16_t(65535.0 * emis); 194 | ke = constrain(ke, 0x2000, 0xFFFF); 195 | 196 | // Write that value to the ke register 197 | return writeMLXEEPROM(MLX90614_REGISTER_KE, (int16_t)ke); 198 | } 199 | 200 | float IRTherm::readEmissivity() 201 | { 202 | int16_t ke; 203 | if (I2CReadWord(MLX90614_REGISTER_KE, &ke)) 204 | { 205 | // If we successfully read from the ke register 206 | // calculate the emissivity between 0.1 and 1.0: 207 | return (((float)((uint16_t)ke)) / 65535.0); 208 | } 209 | return 0; // Else return fail 210 | } 211 | 212 | uint8_t IRTherm::readAddress() 213 | { 214 | int16_t tempAdd; 215 | // Read from the 7-bit I2C address EEPROM storage address: 216 | if (I2CReadWord(MLX90614_REGISTER_ADDRESS, &tempAdd)) 217 | { 218 | // If read succeeded, return the address: 219 | return (uint8_t) tempAdd; 220 | } 221 | return 0; // Else return fail 222 | } 223 | 224 | bool IRTherm::setAddress(uint8_t newAdd) 225 | { 226 | int16_t tempAdd; 227 | // Make sure the address is within the proper range: 228 | if ((newAdd >= 0x80) || (newAdd == 0x00)) 229 | return 0; // Return fail if out of range 230 | // Read from the I2C address address first: 231 | if (I2CReadWord(MLX90614_REGISTER_ADDRESS, &tempAdd)) 232 | { 233 | tempAdd &= 0xFF00; // Mask out the address (MSB is junk?) 234 | tempAdd |= newAdd; // Add the new address 235 | 236 | // Write the new addres back to EEPROM: 237 | return writeMLXEEPROM(MLX90614_REGISTER_ADDRESS, tempAdd); 238 | } 239 | return 0; 240 | } 241 | 242 | uint8_t IRTherm::readID() 243 | { 244 | for (int i=0; i<4; i++) 245 | { 246 | int16_t temp = 0; 247 | // Read from all four ID registers, beginning at the first: 248 | if (!I2CReadWord(MLX90614_REGISTER_ID0 + i, &temp)) 249 | return 0; 250 | // If the read succeeded, store the ID into the id array: 251 | id[i] = (uint16_t)temp; 252 | } 253 | return 1; 254 | } 255 | 256 | uint32_t IRTherm::getIDH() 257 | { 258 | // Return the upper 32 bits of the ID 259 | return ((uint32_t)id[3] << 16) | id[2]; 260 | } 261 | 262 | uint32_t IRTherm::getIDL() 263 | { 264 | // Return the lower 32 bits of the ID 265 | return ((uint32_t)id[1] << 16) | id[0]; 266 | } 267 | 268 | void IRTherm::sleep() 269 | { 270 | // Calculate a crc8 value. 271 | // Bits sent: _deviceAddress (shifted left 1) + 0xFF 272 | uint8_t crc = crc8(0, (_deviceAddress << 1)); 273 | crc = crc8(crc, MLX90614_REGISTER_SLEEP); 274 | 275 | // Manually send the sleep command: 276 | _i2cPort->beginTransmission(_deviceAddress); 277 | _i2cPort->write(MLX90614_REGISTER_SLEEP); 278 | _i2cPort->write(crc); 279 | _i2cPort->endTransmission(true); 280 | 281 | // Set the SCL pin LOW, and SDA pin HIGH (should be pulled up) 282 | pinMode(SCL, OUTPUT); 283 | digitalWrite(SCL, LOW); 284 | pinMode(SDA, INPUT); 285 | } 286 | 287 | void IRTherm::wake() 288 | { 289 | // Wake operation from datasheet 290 | _i2cPort->endTransmission(true); // stop i2c bus transmission BEFORE sending wake up request 291 | pinMode(SCL, INPUT); // SCL high 292 | pinMode(SDA, OUTPUT); 293 | digitalWrite(SDA, LOW); // SDA low 294 | delay(50); // delay at least 33ms 295 | pinMode(SDA, INPUT); // SDA high 296 | delay(250); 297 | // PWM to SMBus mode: 298 | pinMode(SCL, OUTPUT); 299 | digitalWrite(SCL, LOW); // SCL low 300 | delay(10); // Delay at least 1.44ms 301 | pinMode(SCL, INPUT); // SCL high 302 | _i2cPort->beginTransmission(_deviceAddress); // reactivate i2c bus transmission AFTER sending wake up request 303 | } 304 | 305 | int16_t IRTherm::calcRawTemp(float calcTemp) 306 | { 307 | int16_t rawTemp; // Value to eventually be returned 308 | 309 | if (_defaultUnit == TEMP_RAW) 310 | { 311 | // If unit is set to raw, just return that: 312 | rawTemp = (int16_t) calcTemp; 313 | } 314 | else 315 | { 316 | float tempFloat; 317 | // First convert each temperature to Kelvin: 318 | if (_defaultUnit == TEMP_F) 319 | { 320 | // Convert from farenheit to Kelvin 321 | tempFloat = (calcTemp - 32.0) * 5.0 / 9.0 + 273.15; 322 | } 323 | else if (_defaultUnit == TEMP_C) 324 | { 325 | tempFloat = calcTemp + 273.15; 326 | } 327 | else if (_defaultUnit == TEMP_K) 328 | { 329 | tempFloat = calcTemp; 330 | } 331 | // Then multiply by 0.02 degK / bit 332 | tempFloat *= 50.0; 333 | rawTemp = (int16_t) tempFloat; 334 | } 335 | return rawTemp; 336 | } 337 | 338 | float IRTherm::calcTemperature(int16_t rawTemp) 339 | { 340 | float retTemp; 341 | 342 | if (_defaultUnit == TEMP_RAW) 343 | { 344 | retTemp = (float) rawTemp; 345 | } 346 | else 347 | { 348 | retTemp = float(rawTemp) * 0.02; 349 | if (_defaultUnit != TEMP_K) 350 | { 351 | retTemp -= 273.15; 352 | if (_defaultUnit == TEMP_F) 353 | { 354 | retTemp = retTemp * 9.0 / 5.0 + 32.0; 355 | } 356 | } 357 | } 358 | 359 | return retTemp; 360 | } 361 | 362 | bool IRTherm::I2CReadWord(uint8_t reg, int16_t * dest) 363 | { 364 | _i2cPort->beginTransmission(_deviceAddress); 365 | _i2cPort->write(reg); 366 | 367 | _i2cPort->endTransmission(false); // Send restart 368 | _i2cPort->requestFrom(_deviceAddress, (uint8_t) 3); 369 | 370 | uint8_t lsb = _i2cPort->read(); 371 | uint8_t msb = _i2cPort->read(); 372 | uint8_t pec = _i2cPort->read(); 373 | 374 | uint8_t crc = crc8(0, (_deviceAddress << 1)); 375 | crc = crc8(crc, reg); 376 | crc = crc8(crc, (_deviceAddress << 1) + 1); 377 | crc = crc8(crc, lsb); 378 | crc = crc8(crc, msb); 379 | 380 | if (crc == pec) 381 | { 382 | *dest = (msb << 8) | lsb; 383 | return true; 384 | } 385 | else 386 | { 387 | return false;; 388 | } 389 | } 390 | 391 | bool IRTherm::writeMLXEEPROM(uint8_t reg, int16_t data) 392 | { 393 | // Clear out EEPROM first: 394 | if (I2CWriteWord(reg, 0) != 0) 395 | return 0; // If the write failed, return 0 396 | delay(10); // Delay tErase at least 5 ms 397 | 398 | uint8_t i2cRet = I2CWriteWord(reg, data); 399 | delay(10); // Delay tWrite at least 5 ms 400 | 401 | if (i2cRet == 0) 402 | return true; 403 | else 404 | return false; 405 | } 406 | 407 | uint8_t IRTherm::I2CWriteWord(uint8_t reg, int16_t data) 408 | { 409 | uint8_t crc; 410 | uint8_t lsb = data & 0x00FF; 411 | uint8_t msb = (data >> 8); 412 | 413 | crc = crc8(0, (_deviceAddress << 1)); 414 | crc = crc8(crc, reg); 415 | crc = crc8(crc, lsb); 416 | crc = crc8(crc, msb); 417 | 418 | _i2cPort->beginTransmission(_deviceAddress); 419 | _i2cPort->write(reg); 420 | _i2cPort->write(lsb); 421 | _i2cPort->write(msb); 422 | _i2cPort->write(crc); 423 | return _i2cPort->endTransmission(true); 424 | } 425 | 426 | uint8_t IRTherm::crc8 (uint8_t inCrc, uint8_t inData) 427 | { 428 | uint8_t i; 429 | uint8_t data; 430 | data = inCrc ^ inData; 431 | for ( i = 0; i < 8; i++ ) 432 | { 433 | if (( data & 0x80 ) != 0 ) 434 | { 435 | data <<= 1; 436 | data ^= 0x07; 437 | } 438 | else 439 | { 440 | data <<= 1; 441 | } 442 | } 443 | return data; 444 | } 445 | -------------------------------------------------------------------------------- /src/SparkFunMLX90614.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | SparkFunMLX90614.h 3 | Header file for the SparkFun IR Thermometer Library 4 | 5 | Jim Lindblom @ SparkFun Electronics 6 | October 23, 2015 7 | https://github.com/sparkfun/SparkFun_MLX90614_Arduino_Library 8 | 9 | This file defines the SMBus hardware interface(s) for the MLX90614 IR thermometer 10 | and abstracts temperature measurments and other features of the MLX90614 11 | 12 | Development environment specifics: 13 | Arduino 1.6.5 14 | SparkFun IR Thermometer Evaluation Board - MLX90614 15 | ******************************************************************************/ 16 | 17 | #ifndef SPARKFUNMLX90164_H 18 | #define SPARKFUNMLX90164_H 19 | 20 | #include 21 | #include 22 | 23 | /////////////////////////////////////////// 24 | // Default I2C PIN for non Atmega Boards // 25 | /////////////////////////////////////////// 26 | #ifndef SDA 27 | #define SDA PIN_WIRE_SDA 28 | #endif 29 | #ifndef SCL 30 | #define SCL PIN_WIRE_SCL 31 | #endif 32 | 33 | ////////////////////////////////// 34 | // MLX90614 Default I2C Address // 35 | ////////////////////////////////// 36 | #define MLX90614_DEFAULT_ADDRESS 0x5A 37 | 38 | /////////////////////////////////////// 39 | // MLX90614 RAM and EEPROM Addresses // 40 | /////////////////////////////////////// 41 | #define MLX90614_REGISTER_TA 0x06 42 | #define MLX90614_REGISTER_TOBJ1 0x07 43 | #define MLX90614_REGISTER_TOBJ2 0x08 44 | #define MLX90614_REGISTER_TOMAX 0x20 45 | #define MLX90614_REGISTER_TOMIN 0x21 46 | #define MLX90614_REGISTER_PWMCTRL 0x22 47 | #define MLX90614_REGISTER_TARANGE 0x23 48 | #define MLX90614_REGISTER_KE 0x24 49 | #define MLX90614_REGISTER_CONFIG 0x25 50 | #define MLX90614_REGISTER_ADDRESS 0x2E 51 | #define MLX90614_REGISTER_ID0 0x3C 52 | #define MLX90614_REGISTER_ID1 0x3D 53 | #define MLX90614_REGISTER_ID2 0x3E 54 | #define MLX90614_REGISTER_ID3 0x3F 55 | #define MLX90614_REGISTER_SLEEP 0xFF // Not really a register, but close enough 56 | 57 | #define I2C_READ_TIMEOUT 1000 58 | 59 | typedef enum { 60 | TEMP_RAW, 61 | TEMP_K, 62 | TEMP_C, 63 | TEMP_F 64 | } temperature_units; 65 | 66 | class IRTherm 67 | { 68 | public: 69 | // Default constructor, does very little besides setting class variable 70 | // initial values. 71 | IRTherm(); 72 | 73 | // begin(
) initializes the Wire library, and prepares 74 | // communication with an MLX90614 device at the specified 7-bit I2C 75 | // address. 76 | // If no parameter is supplied, the default MLX90614 address is used. 77 | bool begin(uint8_t address = MLX90614_DEFAULT_ADDRESS, TwoWire &wirePort = Wire); 78 | 79 | bool isConnected(); 80 | 81 | // setUnit() configures the units returned by the ambient(), 82 | // object(), minimum() and maximum() functions, and it determines what 83 | // units the setMin() and setMax() functions should expect. 84 | // can be either: 85 | // - TEMP_RAW: No conversion, just the raw 12-bit ADC reading 86 | // - TEMP_K: Kelvin 87 | // - TEMP_C: Celsius 88 | // - TEMP_F: Farenheit 89 | void setUnit(temperature_units unit); 90 | 91 | // read() pulls the latest ambient and object temperatures from the 92 | // MLX90614. It will return either 1 on success or 0 on failure. (Failure 93 | // can result from either a timed out I2C transmission, or an incorrect 94 | // checksum value). 95 | bool read(void); 96 | 97 | // object() returns the MLX90614's most recently read object temperature 98 | // after the read() function has returned successfully. The float value 99 | // returned will be in the units specified by setUnit(). 100 | float object(void); 101 | 102 | // ambient() returns the MLX90614's most recently read ambient temperature 103 | // after the read() function has returned successfully. The float value 104 | // returned will be in the units specified by setUnit(). 105 | float ambient(void); 106 | 107 | // readEmissivity() reads the MLX90614's emissivity setting. It will 108 | // return a value between 0.1 and 1.0. 109 | float readEmissivity(); 110 | 111 | // setEmissivity() can set the MLX90614's configured emissivity 112 | // EEPROM value. 113 | // The parameter should be a value between 0.1 and 1.0. 114 | // The function will return either 1 on success or 0 on failure. 115 | uint8_t setEmissivity(float emis); 116 | 117 | // readAddress() returns the MLX90614's configured 7-bit I2C bus address. 118 | // A value between 0x01 and 0x7F should be returned. 119 | uint8_t readAddress(); 120 | 121 | // setAddress() can set the MLX90614's 7-bit I2C bus address. 122 | // The parameter should be a value between 0x01 and 0x7F. 123 | // The function returns 1 on success and 0 on failure. 124 | // The new address won't take effect until the device is reset. 125 | bool setAddress(uint8_t newAdd); 126 | 127 | // readID() reads the 64-bit ID of the MLX90614. 128 | // Return value is either 1 on success or 0 on failure. 129 | uint8_t readID(); 130 | 131 | // After calling readID() getIDH() and getIDL() can be called to read 132 | // the upper 4 bytes and lower 4-bytes, respectively, of the MLX90614's 133 | // identification registers. 134 | uint32_t getIDH(); 135 | uint32_t getIDL(); 136 | 137 | // readRange() pulls the object maximum and minimum values stored in the 138 | // MLX90614's EEPROM. 139 | // It will return either 1 on success or 0 on failure. 140 | bool readRange(void); 141 | 142 | // minimum() and maximum() return the MLX90614's minimum and maximum object 143 | // sensor readings. 144 | // The float values returned will be in the units specified by setUnit(). 145 | float minimum(void); 146 | float maximum(void); 147 | 148 | // setMax() and setMin() configure the MLX90614's 149 | // maximum and minimum object sensor temperatures. 150 | uint8_t setMax(float maxTemp); 151 | uint8_t setMin(float minTemp); 152 | 153 | // sleep() sets the MLX90614 into a low-power sleep mode. 154 | void sleep(); 155 | 156 | // wake() should revive the MLX90614 from low-power sleep mode. 157 | void wake(); 158 | 159 | private: 160 | uint8_t _deviceAddress; // MLX90614's 7-bit I2C address 161 | TwoWire *_i2cPort; 162 | 163 | temperature_units _defaultUnit; // Keeps track of configured temperature unit 164 | 165 | // These keep track of the raw temperature values read from the sensor: 166 | int16_t _rawAmbient, _rawObject, _rawObject2, _rawMax, _rawMin; 167 | 168 | uint16_t id[4]; // Keeps track of the 64-bit ID value 169 | 170 | // These functions individually read the object, object2, and ambient 171 | // temperature values from the MLX90614's RAM: 172 | bool readObject(void); 173 | bool readObject2(void); 174 | bool readAmbient(void); 175 | 176 | // These functions individually read the min and mx temperatures in 177 | // the MLX90614's EEPROM: 178 | bool readMax(void); 179 | bool readMin(void); 180 | 181 | // calcTemperature converts a raw ADC temperature reading to the 182 | // set unit. 183 | float calcTemperature(int16_t rawTemp); 184 | 185 | // calcRawTemperature converts a set unit temperature to a 186 | // raw ADC value: 187 | int16_t calcRawTemp(float calcTemp); 188 | 189 | // Abstract function to write 16-bits to an address in the MLX90614's 190 | // EEPROM 191 | bool writeMLXEEPROM(uint8_t reg, int16_t data); 192 | 193 | // Abstract functions to read and write 16-bit values from a RAM 194 | // or EEPROM address in the MLX90614 195 | bool I2CReadWord(uint8_t reg, int16_t * dest); 196 | uint8_t I2CWriteWord(uint8_t reg, int16_t data); 197 | 198 | // crc8 returns a calculated crc value given an initial value and 199 | // input data. 200 | // It's configured to calculate the CRC using a x^8+x^2+x^1+1 poly 201 | uint8_t crc8 (uint8_t inCrc, uint8_t inData); 202 | }; 203 | 204 | #endif 205 | --------------------------------------------------------------------------------