How to use library Adafruit_MLX90640?

While the Adafruit_MLX90640 library (Adafruit_MLX90640) looks like the official one, it doesn't have a specific src folder, so I guess I can't just download a ZIP-file and unzip it into my project's lib-folder.
How should I install this library?

Hey, what if you create the folders and unzip inside src?
Example:

/lib/Adafruit_MLX90640/src

Unsure if it will work but that's what I would try.
Best,

Thx @gusgonnet, I tried this and also many other combinations, following among other these instructions and similar forum posts, but have not been successful. I'll start over and do it more systematically.
I'll post the error messages at some point, generally they've been about missing one header file or another.

I see.
I noticed in the past that Adafruit libs have different layers and import other libs in turn.
In this case, you'll need also this one:

#include <Adafruit_I2CDevice.h>

Did you download it too?
There might be others needed, I took a quick look.

Thx for your input!

I happened to notice the missing Adafruit_I2CDevice.h yesterday and downloaded it. Started today from a clean slate, and more or less only progress is that VS Code is not red underlining the #include anymore.

Below the beginning of the output, as you see I've put some files in several places. I don't know how the library files should be structured...

The current error is Library Adafruit_MLX90640 not found

Compiling code for b5som
Targeting version: 6.1.1

Including:
    lib\Adafruit_MLX90640\Adafruit_MLX90640.cpp
    lib\Adafruit_MLX90640\Adafruit_MLX90640.h
    lib\Adafruit_MLX90640\headers\Adafruit_MLX90640.cpp
    lib\Adafruit_MLX90640\headers\Adafruit_MLX90640.h
    lib\Adafruit_MLX90640\headers\MLX90640_API.h
    lib\Adafruit_MLX90640\headers\MLX90640_I2C_Driver.h
    lib\Adafruit_MLX90640\src\Adafruit_I2CDevice.cpp
    lib\Adafruit_MLX90640\src\Adafruit_I2CDevice.h
    lib\Adafruit_MLX90640\src\Adafruit_MLX90640.cpp
    lib\Adafruit_MLX90640\src\Adafruit_MLX90640.h
    lib\Adafruit_MLX90640\src\MLX90640_API.h
    lib\Adafruit_MLX90640\src\MLX90640_I2C_Driver.h
    lib\Adafruit_MLX90640\src\headers\Adafruit_MLX90640.cpp
    lib\Adafruit_MLX90640\src\headers\Adafruit_MLX90640.h
    lib\Adafruit_MLX90640\src\headers\MLX90640_API.h
    lib\Adafruit_MLX90640\src\headers\MLX90640_I2C_Driver.h
    lib\Adafruit_MLX90640\utility\MLX90640_API.cpp
    lib\Adafruit_MLX90640\utility\MLX90640_I2C_Driver.cpp
    lib\Adafruit_MLX90640\utility\MLX90640_SWI2C_Driver.cpp
    project.properties
    src\fire_place2.cpp

Compile failed: Checking library Adafruit_MLX90640...
Library Adafruit_MLX90640 not found
make -C ../modules/b5som/user-part all
make[1]: Entering directory `/firmware/modules/b5som/user-part'

.......a lot of verbiage, then ending with:

dafruit_MLX90640.cpp:195: undefined reference to `Adafruit_MLX90640::MLX90640_CalculateTo(unsigned short*, paramsMLX90640 const*, float, float, float*)'
collect2: error: ld returned 1 exit status
make[1]: *** [target/workspace.elf] Error 1

Btw, here's the main program, I just copied the content from one of the examples in the Github-repo MLX90640_simpletest.ino into the Particle shell program.

/* 
 * Project myProject
 * Author: Your Name
 * Date: 
 * For comprehensive documentation and examples, please visit:
 * https://docs.particle.io/firmware/best-practices/firmware-template/
 */

// Include Particle Device OS APIs
#include "Particle.h"

// Let Device OS manage the connection to the Particle Cloud
SYSTEM_MODE(AUTOMATIC);

// Run the application and system concurrently in separate threads
SYSTEM_THREAD(ENABLED);

// Show system, cloud connectivity, and application logs over USB
// View logs with CLI using 'particle serial monitor --follow'
SerialLogHandler logHandler(LOG_LEVEL_INFO);

#include <Wire.h>

#include <Adafruit_MLX90640.h>

Adafruit_MLX90640 mlx;
float frame[32*24]; // buffer for full frame of temperatures

// uncomment *one* of the below
//#define PRINT_TEMPERATURES
#define PRINT_ASCIIART




// setup() runs once, when the device is first turned on
void setup() {
 while (!Serial) delay(10);
  Serial.begin(115200);
  delay(100);

  Serial.println("Adafruit MLX90640 Simple Test");
  if (! mlx.begin(MLX90640_I2CADDR_DEFAULT, &Wire)) {
    Serial.println("MLX90640 not found!");
    while (1) delay(10);
  }
  Serial.println("Found Adafruit MLX90640");

  Serial.print("Serial number: ");
  Serial.print(mlx.serialNumber[0], HEX);
  Serial.print(mlx.serialNumber[1], HEX);
  Serial.println(mlx.serialNumber[2], HEX);

  //mlx.setMode(MLX90640_INTERLEAVED);
  mlx.setMode(MLX90640_CHESS);
  Serial.print("Current mode: ");
  if (mlx.getMode() == MLX90640_CHESS) {
    Serial.println("Chess");
  } else {
    Serial.println("Interleave");
  }

  mlx.setResolution(MLX90640_ADC_18BIT);
  Serial.print("Current resolution: ");
  mlx90640_resolution_t res = mlx.getResolution();
  switch (res) {
    case MLX90640_ADC_16BIT: Serial.println("16 bit"); break;
    case MLX90640_ADC_17BIT: Serial.println("17 bit"); break;
    case MLX90640_ADC_18BIT: Serial.println("18 bit"); break;
    case MLX90640_ADC_19BIT: Serial.println("19 bit"); break;
  }

  mlx.setRefreshRate(MLX90640_2_HZ);
  Serial.print("Current frame rate: ");
  mlx90640_refreshrate_t rate = mlx.getRefreshRate();
  switch (rate) {
    case MLX90640_0_5_HZ: Serial.println("0.5 Hz"); break;
    case MLX90640_1_HZ: Serial.println("1 Hz"); break;
    case MLX90640_2_HZ: Serial.println("2 Hz"); break;
    case MLX90640_4_HZ: Serial.println("4 Hz"); break;
    case MLX90640_8_HZ: Serial.println("8 Hz"); break;
    case MLX90640_16_HZ: Serial.println("16 Hz"); break;
    case MLX90640_32_HZ: Serial.println("32 Hz"); break;
    case MLX90640_64_HZ: Serial.println("64 Hz"); break;
  }
}



// loop() runs over and over again, as quickly as it can execute.
void loop() {
  // The core of your code will likely live here.

  // Example: Publish event to cloud every 10 seconds. Uncomment the next 3 lines to try it!
  // Log.info("Sending Hello World to the cloud!");
  // Particle.publish("Hello world!");
  // delay( 10 * 1000 ); // milliseconds and blocking - see docs for more info!

  delay(500);
  if (mlx.getFrame(frame) != 0) {
    Serial.println("Failed");
    return;
  }
  Serial.println("===================================");
  Serial.print("Ambient temperature = ");
  Serial.print(mlx.getTa(false)); // false = no new frame capture
  Serial.println(" degC");
  Serial.println();
  Serial.println();
  for (uint8_t h=0; h<24; h++) {
    for (uint8_t w=0; w<32; w++) {
      float t = frame[h*32 + w];
#ifdef PRINT_TEMPERATURES
      Serial.print(t, 1);
      Serial.print(", ");
#endif
#ifdef PRINT_ASCIIART
      char c = '&';
      if (t < 20) c = ' ';
      else if (t < 23) c = '.';
      else if (t < 25) c = '-';
      else if (t < 27) c = '*';
      else if (t < 29) c = '+';
      else if (t < 31) c = 'x';
      else if (t < 33) c = '%';
      else if (t < 35) c = '#';
      else if (t < 37) c = 'X';
      Serial.print(c);
#endif
    }
    Serial.println();
  }
}



ok, that gives us something to work with.

I ran a search on github for that function, and got this, so you would need to include that file too:

1 Like

Thx, I'll give it a try and revert!
Btw, out of habit I've been using Ctrl-Alt-C = Cloud Compile. Not sure if cloud compiling would work in my case, anyhow tried now with the much slower local compile, it errored similarly.

Local compile, fails, but I'm not sure why, is there any setting to reduce the verbiage?

Edit: Added the file to this folder

Executing task: make -f 'C:/Users/thv/.particle/toolchains/buildscripts/1.16.0/Makefile' compile-all -s 


:::: COMPILING APPLICATION & DEVICE OS

  /cygdrive/c/Users/thv/.particle/toolchains/deviceOS/5.9.0/modules/tron/system-part1/makefile /cygdrive/c/Users/thv/.particle/toolchains/deviceOS/5.9.0/modules/tron/user-part/makefile
../../../build/arm/startup/startup_rtl872x.S: Assembler messages:
../../../build/arm/startup/startup_rtl872x.S:175: Warning: ignoring changed section attributes for .text
   text    data     bss     dec     hex filename
1085930  130760  184754 1401444  156264 ../../../build/target/system-part1/platform-32-m/system-part1.elf
Creating c:/Users/thv/Dropbox/Github/Particle/fire_place2/target/5.9.0/p2/memory_platform_user.ld ...
c:/users/thv/.particle/toolchains/gcc-arm/10.2.1/bin/../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld.exe: ../../../build/target/user/platform-32-m/fire_place2/\libuser.a(Adafruit_MLX90640.o): in function `Adafruit_MLX90640::Adafruit_MLX90640()':
c:/Users/thv/Dropbox/Github/Particle/fire_place2/lib/Adafruit_MLX90640/src/headers/Adafruit_MLX90640.cpp:6: multiple definition of `Adafruit_MLX90640::Adafruit_MLX90640()'; ../../../build/target/user/platform-32-m/fire_place2/\libuser.a(Adafruit_MLX90640.o):c:/Users/thv/Dropbox/Github/Particle/fire_place2/lib/Adafruit_MLX90640/src/Adafruit_MLX90640.cpp:6: first defined here
c:/users/thv/.particle/toolchains/gcc-arm/10.2.1/bin/../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld.exe: ../../../build/target/user/platform-32-m/fire_place2/\libuser.a(Adafruit_MLX90640.o): in function `Adafruit_MLX90640::Adafruit_MLX90640()':
c:/Users/thv/Dropbox/Github/Particle/fire_place2/lib/Adafruit_MLX90640/src/headers/Adafruit_MLX90640.cpp:6: multiple definition of `Adafruit_MLX90640::Adafruit_MLX90640()'; ../../../build/target/user/platform-32-m/fire_place2/\libuser.a(Adafruit_MLX90640.o):c:/Users/thv/Dropbox/Github/Particle/fire_place2/lib/Adafruit_MLX90640/src/Adafruit_MLX90640.cpp:6: first defined here
c:/users/thv/.particle/toolchains/gcc-arm/10.2.1/bin/../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld.exe: ../../../build/target/user/platform-32-m/fire_place2/\libuser.a(Adafruit_MLX90640.o): in function `Adafruit_MLX90640::MLX90640_I2CRead(unsigned char, unsigned short, unsigned short, unsigned short*)':
c:/Users/thv/Dropbox/Github/Particle/fire_place2/lib/Adafruit_MLX90640/src/headers/Adafruit_MLX90640.cpp:52: multiple definition of `Adafruit_MLX90640::MLX90640_I2CRead(unsigned char, unsigned short, unsigned short, unsigned short*)'; ../../../build/target/user/platform-32-m/fire_place2/\libuser.a(Adafruit_MLX90640.o):c:/Users/thv/Dropbox/Github/Particle/fire_place2/lib/Adafruit_MLX90640/src/Adafruit_MLX90640.cpp:52: first defined here
c:/users/thv/.particle/toolchains/gcc-arm/10.2.1/bin/../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld.exe: ../../../build/target/user/platform-32-m/fire_place2/\libuser.a(Adafruit_MLX90640.o): in function `Adafruit_MLX90640::begin(unsigned char, TwoWire*)':
c:/Users/thv/Dropbox/Github/Particle/fire_place2/lib/Adafruit_MLX90640/src/headers/Adafruit_MLX90640.cpp:16: multiple definition of `Adafruit_MLX90640::begin(unsigned char, TwoWire*)'; ../../../build/target/user/platform-32-m/fire_place2/\libuser.a(Adafruit_MLX90640.o):c:/Users/thv/Dropbox/Github/Particle/fire_place2/lib/Adafruit_MLX90640/src/Adafruit_MLX90640.cpp:16: first defined here
c:/users/thv/.particle/toolchains/gcc-arm/10.2.1/bin/../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld.exe: ../../../build/target/user/platform-32-m/fire_place2/\libuser.a(Adafruit_MLX90640.o): in function `Adafruit_MLX90640::MLX90640_I2CWrite(unsigned char, unsigned short, unsigned short)':
c:/Users/thv/Dropbox/Github/Particle/fire_place2/lib/Adafruit_MLX90640/src/headers/Adafruit_MLX90640.cpp:82: multiple definition of `Adafruit_MLX90640::MLX90640_I2CWrite(unsigned char, unsigned short, unsigned short)'; ../../../build/target/user/platform-32-m/fire_place2/\libuser.a(Adafruit_MLX90640.o):c:/Users/thv/Dropbox/Github/Particle/fire_place2/lib/Adafruit_MLX90640/src/Adafruit_MLX90640.cpp:82: first defined here
c:/users/thv/.particle/toolchains/gcc-arm/10.2.1/bin/../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld.exe: ../../../build/target/user/platform-32-m/fire_place2/\libuser.a(Adafruit_MLX90640.o): in function `Adafruit_MLX90640::getMode()':
c:/Users/thv/Dropbox/Github/Particle/fire_place2/lib/Adafruit_MLX90640/src/headers/Adafruit_MLX90640.cpp:113: multiple definition of `Adafruit_MLX90640::getMode()'; ../../../build/target/user/platform-32-m/fire_place2/\libuser.a(Adafruit_MLX90640.o):c:/Users/thv/Dropbox/Github/Particle/fire_place2/lib/Adafruit_MLX90640/src/Adafruit_MLX90640.cpp:113: first defined here
c:/users/thv/.particle/toolchains/gcc-arm/10.2.1/bin/../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld.exe: ../../../build/target/user/platform-32-m/fire_place2/\libuser.a(Adafruit_MLX90640.o): in function `Adafruit_MLX90640::setMode(mlx90640_mode)':       
c:/Users/thv/Dropbox/Github/Particle/fire_place2/lib/Adafruit_MLX90640/src/headers/Adafruit_MLX90640.cpp:121: multiple definition of `Adafruit_MLX90640::setMode(mlx90640_mode)'; ../../../build/target/user/platform-32-m/fire_place2/\libuser.a(Adafruit_MLX90640.o):c:/Users/thv/Dropbox/Github/Particle/fire_place2/lib/Adafruit_MLX90640/src/Adafruit_MLX90640.cpp:121: first defined here
c:/users/thv/.particle/toolchains/gcc-arm/10.2.1/bin/../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld.exe: ../../../build/target/user/platform-32-m/fire_place2/\libuser.a(Adafruit_MLX90640.o): in function `Adafruit_MLX90640::getResolution()':
c:/Users/thv/Dropbox/Github/Particle/fire_place2/lib/Adafruit_MLX90640/src/headers/Adafruit_MLX90640.cpp:133: multiple definition of `Adafruit_MLX90640::getResolution()'; ../../../build/target/user/platform-32-m/fire_place2/\libuser.a(Adafruit_MLX90640.o):c:/Users/thv/Dropbox/Github/Particle/fire_place2/lib/Adafruit_MLX90640/src/Adafruit_MLX90640.cpp:133: first defined here
c:/users/thv/.particle/toolchains/gcc-arm/10.2.1/bin/../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld.exe: ../../../build/target/user/platform-32-m/fire_place2/\libuser.a(Adafruit_MLX90640.o): in function `Adafruit_MLX90640::setResolution(mlx90640_res)':
c:/Users/thv/Dropbox/Github/Particle/fire_place2/lib/Adafruit_MLX90640/src/headers/Adafruit_MLX90640.cpp:140: multiple definition of `Adafruit_MLX90640::setResolution(mlx90640_res)'; ../../../build/target/user/platform-32-m/fire_place2/\libuser.a(Adafruit_MLX90640.o):c:/Users/thv/Dropbox/Github/Particle/fire_place2/lib/Adafruit_MLX90640/src/Adafruit_MLX90640.cpp:140: first defined here
c:/users/thv/.particle/toolchains/gcc-arm/10.2.1/bin/../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld.exe: ../../../build/target/user/platform-32-m/fire_place2/\libuser.a(Adafruit_MLX90640.o): in function `Adafruit_MLX90640::getRefreshRate()':
c:/Users/thv/Dropbox/Github/Particle/fire_place2/lib/Adafruit_MLX90640/src/headers/Adafruit_MLX90640.cpp:149: multiple definition of `Adafruit_MLX90640::getRefreshRate()'; ../../../build/target/user/platform-32-m/fire_place2/\libuser.a(Adafruit_MLX90640.o):c:/Users/thv/Dropbox/Github/Particle/fire_place2/lib/Adafruit_MLX90640/src/Adafruit_MLX90640.cpp:149: first defined here
c:/users/thv/.particle/toolchains/gcc-arm/10.2.1/bin/../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld.exe: ../../../build/target/user/platform-32-m/fire_place2/\libuser.a(Adafruit_MLX90640.o): in function `Adafruit_MLX90640::setRefreshRate(mlx90640_refreshrate)':
c:/Users/thv/Dropbox/Github/Particle/fire_place2/lib/Adafruit_MLX90640/src/headers/Adafruit_MLX90640.cpp:158: multiple definition of `Adafruit_MLX90640::setRefreshRate(mlx90640_refreshrate)'; ../../../build/target/user/platform-32-m/fire_place2/\libuser.a(Adafruit_MLX90640.o):c:/Users/thv/Dropbox/Github/Particle/fire_place2/lib/Adafruit_MLX90640/src/Adafruit_MLX90640.cpp:158: first defined here
c:/users/thv/.particle/toolchains/gcc-arm/10.2.1/bin/../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld.exe: ../../../build/target/user/platform-32-m/fire_place2/\libuser.a(Adafruit_MLX90640.o): in function `Adafruit_MLX90640::getFrame(float*)':
c:/Users/thv/Dropbox/Github/Particle/fire_place2/lib/Adafruit_MLX90640/src/headers/Adafruit_MLX90640.cpp:167: multiple definition of `Adafruit_MLX90640::getFrame(float*)'; ../../../build/target/user/platform-32-m/fire_place2/\libuser.a(Adafruit_MLX90640.o):c:/Users/thv/Dropbox/Github/Particle/fire_place2/lib/Adafruit_MLX90640/src/Adafruit_MLX90640.cpp:167: first defined here
c:/users/thv/.particle/toolchains/gcc-arm/10.2.1/bin/../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld.exe: ../../../build/target/user/platform-32-m/fire_place2/\libuser.a(Adafruit_MLX90640.o): in function `Adafruit_MLX90640::getTa(bool)':
c:/Users/thv/Dropbox/Github/Particle/fire_place2/lib/Adafruit_MLX90640/src/headers/Adafruit_MLX90640.cpp:207: multiple definition of `Adafruit_MLX90640::getTa(bool)'; ../../../build/target/user/platform-32-m/fire_place2/\libuser.a(Adafruit_MLX90640.o):c:/Users/thv/Dropbox/Github/Particle/fire_place2/lib/Adafruit_MLX90640/src/Adafruit_MLX90640.cpp:207: first defined here
collect2.exe: error: ld returned 1 exit status
make[3]: *** [../../../build/module.mk:239: c:/Users/thv/Dropbox/Github/Particle/fire_place2/target/5.9.0/p2/fire_place2.elf] Error 1
make[2]: *** [makefile:51: /cygdrive/c/Users/thv/.particle/toolchains/deviceOS/5.9.0/modules/tron/user-part/makefile] Error 2
make[1]: *** [C:/Users/thv/.particle/toolchains/buildscripts/1.16.0/Makefile:156: make-modules] Error 2
make: *** [C:/Users/thv/.particle/toolchains/buildscripts/1.16.0/Makefile:100: compile-all] Error 2

 *  The terminal process "C:\Users\thv\.particle\toolchains\buildtools\1.1.1\bin\bash.exe '-c', 'make -f 'C:/Users/thv/.particle/toolchains/buildscripts/1.16.0/Makefile' compile-all -s'" terminated with exit code: 2. 

this gets complex here since the compiler is telling you it finds many definitions of something, which may mean an include of a header (.h) is being done in multiple places for instance.

Have you used chatgpt? if you upload the files to it (or copy paste few) it might be able to guide you and tell you exactly what to do.
It may not, but is worth a shot when I'm stuck luck this.

1 Like

Thx, also ChatGPT mentions same thing as you, duplicate definitions. Will look into it.
Yes, ChatGPT is to a degree helpful with debugging, wish it would never hallucinate though.

Cloud compile successful after removing a .CPP-file from the headers-folder!!! Let's see then if it also works.

It's working!! Many many thanks, as mentioned before it's easy to stand on the shoulders of giants!

I'll now start cleaning up bit by bit to avoid file duplicates. The project I'm building will eventually be shared in my Github-account, so others will be able to clone my project should they want to.

Below a thermal "photo" of me in ASCII-art

Don't we all do? :clown_face:

Bingo! that's so cool to hear, and as mentioned before also: giants... and presidents!

1 Like

After fighting yet another war with OLED libraries, I'm able to display the thermal image on a Adafruit 96x64 OLED Display
The 32x24 pixels thermal image is interpolated to 96x64, coldest temperature in the image is blue, hottest red. Speed is adequate, around 0.5-1 Hz.
I look like an alien due to my glasses :sunglasses:, the picture quality in real life is though better than it looks like here.

At some point I might make a write-up of the final solution, whatever it'll be :gift:

2 Likes