Skip to content

Commit 2ff5d46

Browse files
committed
MLX90640: Driver and 32x32 LED matrix example
1 parent 1317f2e commit 2ff5d46

File tree

11 files changed

+312
-1
lines changed

11 files changed

+312
-1
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,6 @@
2222
path = drivers/vl53l5cx/src
2323
url = https://github.com/ST-mirror/VL53L5CX_ULD_driver
2424
branch = no-fw/lite/en
25+
[submodule "drivers/mlx90640/src"]
26+
path = drivers/mlx90640/src
27+
url = https://github.com/melexis/mlx90640-library

drivers/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,5 @@ add_subdirectory(sh1107)
4242
add_subdirectory(st7567)
4343
add_subdirectory(psram_display)
4444
add_subdirectory(inky73)
45-
add_subdirectory(shiftregister)
45+
add_subdirectory(shiftregister)
46+
add_subdirectory(mlx90640)

drivers/mlx90640/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include(mlx90640.cmake)
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#include "src/headers/MLX90640_I2C_Driver.h"
2+
#include "mlx90640.hpp"
3+
4+
#include "stdio.h"
5+
6+
7+
static pimoroni::I2C *i2c;
8+
9+
void MLX90640_I2CConfigure(pimoroni::I2C *i2c_instance) {
10+
i2c = i2c_instance;
11+
}
12+
13+
void MLX90640_I2CInit()
14+
{
15+
// i2c->init(); // Called in constructor
16+
}
17+
18+
int MLX90640_I2CGeneralReset(void)
19+
{
20+
return 0;
21+
}
22+
23+
int MLX90640_I2CRead(uint8_t slaveAddr, uint16_t startAddress, uint16_t nMemAddressRead, uint16_t *data)
24+
{
25+
uint8_t cmd[2] = {(char)(startAddress >> 8), (char)(startAddress & 0xFF)};
26+
27+
// Set 16-bit register pointer
28+
i2c->write_blocking(slaveAddr, cmd, sizeof(cmd), true);
29+
// Read result
30+
i2c->read_blocking(slaveAddr, (uint8_t*)data, nMemAddressRead * sizeof(uint16_t), false);
31+
32+
for(auto n = 0u; n < nMemAddressRead; n++) {
33+
data[n] = __builtin_bswap16(data[n]);
34+
}
35+
36+
return 0;
37+
}
38+
39+
void MLX90640_I2CFreqSet(int freq)
40+
{
41+
// We can't assume we own the I2C instance and can wiggle the baudrate ad-hoc
42+
}
43+
44+
int MLX90640_I2CWrite(uint8_t slaveAddr, uint16_t writeAddress, uint16_t data)
45+
{
46+
uint8_t cmd[4] = {(char)(writeAddress >> 8), (char)(writeAddress & 0x00FF), (char)(data >> 8), (char)(data & 0x00FF)};
47+
i2c->write_blocking(slaveAddr, cmd, sizeof(cmd), false);
48+
return 0;
49+
}
50+

drivers/mlx90640/mlx90640.cmake

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
set(DRIVER_NAME mlx90640)
2+
add_library(${DRIVER_NAME} INTERFACE)
3+
4+
target_sources(${DRIVER_NAME} INTERFACE
5+
${CMAKE_CURRENT_LIST_DIR}/src/functions/MLX90640_API.cpp
6+
${CMAKE_CURRENT_LIST_DIR}/MLX90640_RP2040_I2C_Driver.cpp
7+
${CMAKE_CURRENT_LIST_DIR}/mlx90640.cpp
8+
)
9+
10+
target_link_libraries(${DRIVER_NAME} INTERFACE pico_stdlib hardware_i2c pimoroni_i2c)
11+
12+
target_include_directories(${DRIVER_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR})
13+
target_include_directories(${DRIVER_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR}/src/headers)

drivers/mlx90640/mlx90640.cpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
#include <stdint.h>
2+
#include <iostream>
3+
#include <cstring>
4+
#include <fstream>
5+
#include <chrono>
6+
#include <thread>
7+
#include <math.h>
8+
#include "src/headers/MLX90640_API.h"
9+
#include "mlx90640.hpp"
10+
11+
12+
13+
namespace pimoroni {
14+
MLX90640::MLX90640_Error MLX90640::setup(int fps){
15+
MLX90640_I2CConfigure(i2c_instance);
16+
//MLX90640_SetDeviceMode(i2c_address, 0);
17+
//MLX90640_SetSubPageRepeat(i2c_address, 0);
18+
19+
switch(fps){
20+
case 1:
21+
MLX90640_SetRefreshRate(i2c_address, 0b001);
22+
break;
23+
case 2:
24+
MLX90640_SetRefreshRate(i2c_address, 0b010);
25+
break;
26+
case 4:
27+
MLX90640_SetRefreshRate(i2c_address, 0b011);
28+
break;
29+
case 8:
30+
MLX90640_SetRefreshRate(i2c_address, 0b100);
31+
break;
32+
case 16:
33+
MLX90640_SetRefreshRate(i2c_address, 0b101);
34+
if(i2c_instance->get_baudrate() < 1000000) {
35+
return INVALID_BAUDRATE;
36+
}
37+
break;
38+
case 32:
39+
MLX90640_SetRefreshRate(i2c_address, 0b110);
40+
if(i2c_instance->get_baudrate() < 1000000) {
41+
return INVALID_BAUDRATE;
42+
}
43+
break;
44+
case 64:
45+
MLX90640_SetRefreshRate(i2c_address, 0b111);
46+
if(i2c_instance->get_baudrate() < 1000000) {
47+
return INVALID_BAUDRATE;
48+
}
49+
break;
50+
default:
51+
#ifdef DEBUG
52+
printf("Unsupported framerate: %d", fps);
53+
#endif
54+
return INVALID_FPS;
55+
}
56+
//MLX90640_SetChessMode(i2c_address);
57+
MLX90640_SetInterleavedMode(i2c_address);
58+
//MLX90640_SetResolution(i2c_address, 0);
59+
MLX90640_DumpEE(i2c_address, eeMLX90640);
60+
MLX90640_ExtractParameters(eeMLX90640, &mlx90640);
61+
62+
return OK;
63+
}
64+
65+
int MLX90640::get_image(void){
66+
MLX90640_I2CConfigure(i2c_instance);
67+
68+
MLX90640_GetFrameData(i2c_address, frame0);
69+
sleep_us(1000);
70+
MLX90640_GetFrameData(i2c_address, frame1);
71+
72+
MLX90640_GetImage(frame0, &mlx90640, mlx90640To);
73+
MLX90640_GetImage(frame1, &mlx90640, mlx90640To);
74+
75+
return 0;
76+
}
77+
78+
int MLX90640::get_frame(void){
79+
MLX90640_I2CConfigure(i2c_instance);
80+
81+
MLX90640_GetFrameData(i2c_address, frame0);
82+
sleep_us(1000);
83+
MLX90640_GetFrameData(i2c_address, frame1);
84+
85+
int tr0 = MLX90640_GetTa(frame0, &mlx90640) - reflected_temperature;
86+
MLX90640_CalculateTo(frame0, &mlx90640, emissivity, tr0, mlx90640To);
87+
int tr1 = MLX90640_GetTa(frame1, &mlx90640) - reflected_temperature;
88+
MLX90640_CalculateTo(frame1, &mlx90640, emissivity, tr1, mlx90640To);
89+
90+
return 0;
91+
}
92+
}

drivers/mlx90640/mlx90640.hpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#include "src/headers/MLX90640_API.h"
2+
#include "common/pimoroni_i2c.hpp"
3+
4+
void MLX90640_I2CConfigure(pimoroni::I2C *i2c_instance);
5+
6+
#define MLX90640_DEFAULT_I2C_ADDRESS 0x33
7+
8+
namespace pimoroni {
9+
class MLX90640 {
10+
public:
11+
enum MLX90640_Error {
12+
OK = 0,
13+
INVALID_BAUDRATE = 1,
14+
INVALID_FPS = 2,
15+
};
16+
17+
float mlx90640To[768] = {0.0f};
18+
float emissivity = 1.0f;
19+
float reflected_temperature = 8.0f;
20+
21+
MLX90640(pimoroni::I2C *i2c_instance, uint i2c_address=MLX90640_DEFAULT_I2C_ADDRESS) : i2c_instance(i2c_instance), i2c_address(i2c_address) {};
22+
MLX90640_Error setup(int fps);
23+
int get_image(void);
24+
int get_frame(void);
25+
private:
26+
pimoroni::I2C *i2c_instance;
27+
uint i2c_address = MLX90640_DEFAULT_I2C_ADDRESS;
28+
paramsMLX90640 mlx90640;
29+
uint16_t eeMLX90640[832] = {0};
30+
uint16_t frame0[834] = {0};
31+
uint16_t frame1[834] = {0};
32+
};
33+
}

drivers/mlx90640/src

Submodule src added at 4dbbc56

examples/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ add_subdirectory(breakout_scd41)
2424
add_subdirectory(breakout_vl53l5cx)
2525
add_subdirectory(breakout_pms5003)
2626
add_subdirectory(breakout_oled_128x128)
27+
add_subdirectory(breakout_mlx90640)
2728

2829
add_subdirectory(pico_display)
2930
add_subdirectory(pico_display_2)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
set(OUTPUT_NAME mlx90460_demo)
2+
3+
add_executable(
4+
${OUTPUT_NAME}
5+
demo.cpp
6+
)
7+
8+
# Pull in pico libraries that we need
9+
target_link_libraries(${OUTPUT_NAME} pico_stdlib mlx90640 hub75_legacy hardware_vreg)
10+
11+
# create map/bin/hex file etc.
12+
pico_add_extra_outputs(${OUTPUT_NAME})

0 commit comments

Comments
 (0)