From dc2897e7838d4ef2e5b02d3d09e2e4653de90090 Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Sun, 21 Sep 2025 21:32:01 +0300 Subject: [PATCH] It works! --- F3:F303/MLX90640/Readme.md | 35 ++++++++++++ F3:F303/MLX90640/i2c.h | 2 +- F3:F303/MLX90640/main.c | 10 +++- F3:F303/MLX90640/mlx90640.bin | Bin 19388 -> 14284 bytes F3:F303/MLX90640/mlx90640.c | 11 ++-- F3:F303/MLX90640/mlx90640.creator.user | 2 +- F3:F303/MLX90640/mlx90640.h | 1 + F3:F303/MLX90640/mlx90640_regs.h | 2 + F3:F303/MLX90640/mlxproc.c | 74 +++++++++++++++++++++++-- F3:F303/MLX90640/mlxproc.h | 6 ++ F3:F303/MLX90640/proto.c | 54 +++++++++++++++++- F3:F303/MLX90640/proto.h | 2 +- F3:F303/MLX90640/version.inc | 4 +- 13 files changed, 185 insertions(+), 18 deletions(-) create mode 100644 F3:F303/MLX90640/Readme.md diff --git a/F3:F303/MLX90640/Readme.md b/F3:F303/MLX90640/Readme.md new file mode 100644 index 0000000..aef3897 --- /dev/null +++ b/F3:F303/MLX90640/Readme.md @@ -0,0 +1,35 @@ +Works with single MLX90640 sensor +================================= + +When attached, udev will create symlink /dev/mlx_sensor0. This is the udev rule: + +``` + +ACTION=="add", ENV{USB_IDS}=="0483:5740", ATTRS{interface}=="?*", PROGRAM="/bin/bash -c \"ls /dev | grep $attr{interface} | wc -l \"", SYMLINK+="$attr{interface}%c", MODE="0666", GROUP="tty" + +``` + +Protocol: + +``` + +aa - change I2C address to a (a should be non-shifted value!!!) +c - continue MLX +d - draw image in ASCII +i0..4 - setup I2C with speed 10k, 100k, 400k, 1M or 2M (experimental!) +p - pause MLX +r0..3 - change resolution (0 - 16bit, 3 - 19-bit) +t - show temperature map +C - "cartoon" mode on/off (show each new image) +D - dump MLX parameters +G - get MLX state +Ia addr - set device address +Ir reg n - read n words from 16-bit register +Iw words - send words (hex/dec/oct/bin) to I2C +Is - scan I2C bus +T - print current Tms + + +``` + +To call this help just print '?', 'h' or 'H' in terminal. diff --git a/F3:F303/MLX90640/i2c.h b/F3:F303/MLX90640/i2c.h index 8692481..f525880 100644 --- a/F3:F303/MLX90640/i2c.h +++ b/F3:F303/MLX90640/i2c.h @@ -43,7 +43,7 @@ int i2c_busy(); uint8_t *i2c_read(uint8_t addr, uint16_t nbytes); uint8_t i2c_read_dma16(uint8_t addr, uint16_t nwords); -uint16_t *i2c_read_reg16(uint8_t addr, uint16_t reg16, uint16_t nbytes, uint8_t isdma); +uint16_t *i2c_read_reg16(uint8_t addr, uint16_t reg16, uint16_t nwords, uint8_t isdma); uint8_t i2c_write(uint8_t addr, uint16_t *data, uint8_t nwords); uint8_t i2c_write_dma16(uint8_t addr, uint16_t *data, uint8_t nwords); diff --git a/F3:F303/MLX90640/main.c b/F3:F303/MLX90640/main.c index 05f1464..c042d24 100644 --- a/F3:F303/MLX90640/main.c +++ b/F3:F303/MLX90640/main.c @@ -44,7 +44,7 @@ int main(void){ i2c_setup(I2C_SPEED_100K); USB_setup(); USBPU_ON(); - uint32_t ctr = Tms; + uint32_t ctr = Tms, Tlastima = 0; while(1){ if(Tms - ctr > 499){ ctr = Tms; @@ -66,5 +66,13 @@ int main(void){ } } mlx_process(); + if(cartoon){ + uint32_t Tnow; + fp_t *i = mlx_getimage(&Tnow); + if(i && Tnow != Tlastima){ + U("Timage="); USND(u2str(Tnow)); drawIma(i); + Tlastima = Tnow; + } + } } } diff --git a/F3:F303/MLX90640/mlx90640.bin b/F3:F303/MLX90640/mlx90640.bin index be149a0784531f9175500b3e3ce70baa55f14d6c..35d519e574b8519eb84eea0c79d2fccd25b541fe 100755 GIT binary patch literal 14284 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

RKtuZ+Ub+4=fS&0RAZGffD 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 literal 19388 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 diff --git a/F3:F303/MLX90640/mlx90640.c b/F3:F303/MLX90640/mlx90640.c index af9f235..4fb95ef 100644 --- a/F3:F303/MLX90640/mlx90640.c +++ b/F3:F303/MLX90640/mlx90640.c @@ -24,6 +24,7 @@ #include "mlx90640.h" #include "mlx90640_regs.h" +#include "mlxproc.h" // static const char *OK = "OK\n", *OKs = "OK ", *NOTEQ = "NOT equal!\n", *NOTEQi = "NOT equal on index "; @@ -57,15 +58,17 @@ void drawIma(const fp_t im[MLX_PIXNO]){ } } fp_t range = max_val - min_val; + U("RANGE="); USND(float2str(range, 3)); + U("MIN="); USND(float2str(min_val, 3)); + U("MAX="); USND(float2str(max_val, 3)); if(fabsf(range) < 0.001) range = 1.; // solid fill -> blank // Generate and print ASCII art iptr = im; - newline(); for(int row = 0; row < MLX_H; ++row){ for(int col = 0; col < MLX_W; ++col){ fp_t normalized = ((*iptr++) - min_val) / range; // Map to character index (0 to 15) - int index = (int)(normalized * (GRAY_LEVELS-1) + 0.5); + int index = (int)(normalized * GRAY_LEVELS); // Ensure we stay within bounds if(index < 0) index = 0; else if(index > (GRAY_LEVELS-1)) index = (GRAY_LEVELS-1); @@ -259,9 +262,7 @@ fp_t *process_subpage(MLX90640_params *params, const int16_t Frame[MLX_DMA_MAXLE #define IMD_VAL(reg) Frame[IMD_IDX(reg)] // 11.2.2.1. Resolution restore // temporary: - fp_t resol_corr = (fp_t)(1<resolEE) / (1<<2); // calibrated resol/current resol - //fp_t resol_corr = (fp_t)(1<resolEE) / (1<<((reg_control_val[subpageno]&0x0C00)>>10)); // calibrated resol/current resol - //DBG("resolEE=%d, resolCur=%d", params->resolEE, ((reg_control_val[subpageno]&0x0C00)>>10)); + fp_t resol_corr = (fp_t)(1<resolEE) / (1<vdd25; diff --git a/F3:F303/MLX90640/mlx90640.creator.user b/F3:F303/MLX90640/mlx90640.creator.user index 3b0ec84..61a21ac 100644 --- a/F3:F303/MLX90640/mlx90640.creator.user +++ b/F3:F303/MLX90640/mlx90640.creator.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/F3:F303/MLX90640/mlx90640.h b/F3:F303/MLX90640/mlx90640.h index c689868..2dbc4f0 100644 --- a/F3:F303/MLX90640/mlx90640.h +++ b/F3:F303/MLX90640/mlx90640.h @@ -59,6 +59,7 @@ typedef struct{ // full amount of IMAGE data + EXTRA data (counts of uint16_t!) #define MLX_DMA_MAXLEN (834) +int ch_resolution(uint8_t newresol); int get_parameters(const uint16_t dataarray[MLX_DMA_MAXLEN], MLX90640_params *params); fp_t *process_subpage(MLX90640_params *params, const int16_t Frame[MLX_DMA_MAXLEN], int subpageno, int simpleimage); void dumpIma(const fp_t im[MLX_PIXNO]); diff --git a/F3:F303/MLX90640/mlx90640_regs.h b/F3:F303/MLX90640/mlx90640_regs.h index 273c0ca..43e9d77 100644 --- a/F3:F303/MLX90640/mlx90640_regs.h +++ b/F3:F303/MLX90640/mlx90640_regs.h @@ -43,6 +43,8 @@ #define REG_CONTROL_SUBPSEL (1<<3) #define REG_CONTROL_DATAHOLD (1<<2) #define REG_CONTROL_SUBPEN (1<<0) +#define REG_MLXADDR 0x8010 +#define REG_MLXADDR_MASK (0xff) // default value #define REG_CONTROL_DEFAULT (REG_CONTROL_CHESS|REG_CONTROL_RES18|REG_CONTROL_REFR_2HZ|REG_CONTROL_SUBPEN) diff --git a/F3:F303/MLX90640/mlxproc.c b/F3:F303/MLX90640/mlxproc.c index 0d3fdba..0f0590a 100644 --- a/F3:F303/MLX90640/mlxproc.c +++ b/F3:F303/MLX90640/mlxproc.c @@ -21,6 +21,10 @@ #include "i2c.h" #include "mlxproc.h" #include "mlx90640_regs.h" +//#include "usb_dev.h" +//#include "strfunc.h" + +extern volatile uint32_t Tms; // current state and state before `stop` called static mlx_state_t MLX_state = MLX_NOTINIT, MLX_oldstate = MLX_NOTINIT; @@ -29,6 +33,8 @@ static int parsrdy = 0; static fp_t *ready_image = NULL; // will be pointer to `mlx_image` after both subpages process static uint8_t MLX_address = 0x33 << 1; static int errctr = 0; // errors counter - cleared by mlx_continue +static uint32_t Tlastimage = 0; +static uint8_t resolution = 2; // default: 18bit // get current state mlx_state_t mlx_state(){ return MLX_state; } @@ -36,6 +42,7 @@ mlx_state_t mlx_state(){ return MLX_state; } int mlx_setaddr(uint8_t addr){ if(addr > 0x7f) return 0; MLX_address = addr << 1; + Tlastimage = Tms; // refresh counter for autoreset I2C in case of error return 1; } // temporary stop @@ -60,12 +67,14 @@ void mlx_continue(){ } void mlx_process(){ - //static int subpageno = 0; // wait for given subpage + static int subpageno = 0; // wait for given subpage + // static uint32_t Tlast = 0; switch(MLX_state){ case MLX_NOTINIT: // start reading parameters - if(i2c_read_reg16(MLX_address, REG_CALIDATA, MLX_DMA_MAXLEN, 1)) + if(i2c_read_reg16(MLX_address, REG_CALIDATA, MLX_DMA_MAXLEN, 1)){ + errctr = 0; MLX_state = MLX_WAITPARAMS; - else ++errctr; + }else ++errctr; break; case MLX_WAITPARAMS: // check DMA ends and calculate parameters if(i2c_dma_haderr()) MLX_state = MLX_NOTINIT; @@ -74,6 +83,7 @@ void mlx_process(){ if(buf){ if(len != MLX_DMA_MAXLEN) MLX_state = MLX_NOTINIT; else if(get_parameters(buf, &p)){ + errctr = 0; MLX_state = MLX_WAITSUBPAGE; // fine! we could wait subpage parsrdy = 1; } @@ -81,14 +91,40 @@ void mlx_process(){ } break; case MLX_WAITSUBPAGE: // wait for subpage N ready - ; + {uint16_t *got = i2c_read_reg16(MLX_address, REG_STATUS, 1, 0); + if(got && *got & REG_STATUS_NEWDATA){ + if(subpageno == (*got & REG_STATUS_SPNO)){ + if(i2c_read_reg16(MLX_address, REG_IMAGEDATA, MLX_DMA_MAXLEN, 1)){ + errctr = 0; + MLX_state = MLX_READSUBPAGE; + //U("spstart="); USND(u2str(Tms - Tlast)); + }else ++errctr; + } + }} break; case MLX_READSUBPAGE: // wait ends of DMA read and calculate subpage - ; + if(i2c_dma_haderr()) MLX_state = MLX_NOTINIT; + else{ + uint16_t len, *buf = i2c_dma_getbuf(&len); + if(buf){ + //U("spread="); USND(u2str(Tms - Tlast)); + if(len != MLX_DMA_MAXLEN) MLX_state = MLX_WAITSUBPAGE; + else if((ready_image = process_subpage(&p, (int16_t*)buf, subpageno, 2))){ + errctr = 0; + MLX_state = MLX_WAITSUBPAGE; // fine! we could wait subpage + //U("spgot="); USND(u2str(Tms - Tlast)); + if(subpageno){ Tlastimage = Tms; + /*U("imgot="); USND(u2str(Tms - Tlast)); Tlast = Tms; */ + } + subpageno = !subpageno; + } + } + } break; default: return; } + if(MLX_state != MLX_RELAX && Tms - Tlastimage > MLX_I2CERR_TMOUT){ i2c_setup(i2c_curspeed); Tlastimage = Tms; } if(errctr > MLX_MAX_ERRORS) mlx_stop(); } @@ -99,6 +135,32 @@ int mlx_getparams(MLX90640_params *pars){ return 1; } -fp_t *mlx_getimage(){ +fp_t *mlx_getimage(uint32_t *Tgot){ + if(Tgot) *Tgot = Tlastimage; return ready_image; } + +uint8_t mlx_getresolution(){ + return resolution; +} + +int mlx_sethwaddr(uint8_t addr){ + if(addr > 0x7f) return 0; + uint16_t data[2], *ptr; + if(!(ptr = i2c_read_reg16(MLX_address, REG_MLXADDR, 1, 0))) return 0; + data[0] = REG_MLXADDR; + data[1] = (*ptr & ~REG_MLXADDR_MASK) | addr; + if(!i2c_write(MLX_address, data, 2)) return 0; + return 1; +} + +int mlx_setresolution(uint8_t newresol){ + if(newresol > 3) return 0; + uint16_t data[2], *ptr; + if(!(ptr = i2c_read_reg16(MLX_address, REG_CONTROL, 1, 0))) return 0; + data[0] = REG_CONTROL; + data[1] = (*ptr & ~REG_CONTROL_RESMASK) | (newresol << 10); + if(!i2c_write(MLX_address, data, 2)) return 0; + resolution = newresol; + return 1; +} diff --git a/F3:F303/MLX90640/mlxproc.h b/F3:F303/MLX90640/mlxproc.h index 8cf9610..1b56df5 100644 --- a/F3:F303/MLX90640/mlxproc.h +++ b/F3:F303/MLX90640/mlxproc.h @@ -24,6 +24,8 @@ // maximal errors number to stop processing #define MLX_MAX_ERRORS (11) +// if there's no new data by this time - reset bus +#define MLX_I2CERR_TMOUT (5000) typedef enum{ MLX_NOTINIT, // just start - need to get parameters @@ -39,3 +41,7 @@ void mlx_stop(); void mlx_continue(); void mlx_process(); int mlx_getparams(MLX90640_params *pars); +fp_t *mlx_getimage(uint32_t *Tgot); +int mlx_setresolution(uint8_t newresol); +uint8_t mlx_getresolution(); +int mlx_sethwaddr(uint8_t addr); diff --git a/F3:F303/MLX90640/proto.c b/F3:F303/MLX90640/proto.c index 35d6543..4f6a141 100644 --- a/F3:F303/MLX90640/proto.c +++ b/F3:F303/MLX90640/proto.c @@ -30,12 +30,20 @@ static uint16_t locBuffer[LOCBUFFSZ]; static uint8_t I2Caddress = 0x33 << 1; extern volatile uint32_t Tms; +uint8_t cartoon = 0; // "cartoon" mode: refresh image each time we get new static const char *OK = "OK\n", *ERR = "ERR\n"; const char *helpstring = "https://github.com/eddyem/stm32samples/tree/master/F3:F303/mlx90640 build#" BUILD_NUMBER " @ " BUILD_DATE "\n" " management of single IR bolometer MLX90640\n" - "i0..3 - setup I2C with speed 10k, 100k, 400k, 1M or 2M (experimental!)\n" + "aa - change I2C address to a (a should be non-shifted value!!!)\n" + "c - continue MLX\n" + "d - draw image in ASCII\n" + "i0..4 - setup I2C with speed 10k, 100k, 400k, 1M or 2M (experimental!)\n" + "p - pause MLX\n" + "r0..3 - change resolution (0 - 16bit, 3 - 19-bit)\n" + "t - show temperature map\n" + "C - \"cartoon\" mode on/off (show each new image)\n" "D - dump MLX parameters\n" "G - get MLX state\n" "Ia addr - set device address\n" @@ -65,6 +73,26 @@ TRUE_INLINE const char *setupI2C(char *buf){ return NULL; } +TRUE_INLINE const char *chhwaddr(const char *buf){ + uint32_t a; + if(buf && *buf){ + const char *nxt = getnum(buf, &a); + if(nxt && nxt != buf) if(!mlx_sethwaddr(a)) return ERR; + } else return ERR; + return OK; +} + +TRUE_INLINE const char *chres(const char *buf){ + uint32_t r; + if(buf && *buf){ + const char *nxt = getnum(buf, &r); + if(nxt && nxt != buf) if(!mlx_setresolution(r)) return ERR; + } + r = mlx_getresolution(); + U("MLXRESOLUTION="); USND(u2str(r)); + return NULL; +} + TRUE_INLINE const char *chaddr(const char *buf){ uint32_t addr; const char *nxt = getnum(buf, &addr); @@ -187,10 +215,15 @@ TRUE_INLINE void getst(){ const char *parse_cmd(char *buf){ if(!buf || !*buf) return NULL; + uint32_t u32; if(buf[1]){ switch(*buf){ // "long" commands + case 'a': + return chhwaddr(buf + 1); case 'i': return setupI2C(buf + 1); + case 'r': + return chres(buf + 1); case 'I': buf = omit_spaces(buf + 1); switch(*buf){ @@ -212,7 +245,26 @@ const char *parse_cmd(char *buf){ } } switch(*buf){ // "short" (one letter) commands + case 'c': + mlx_continue(); return OK; + break; + case 'd': + {fp_t *i = mlx_getimage(&u32); + if(i){ U("Timage="); USND(u2str(u32)); drawIma(i); } + else U(ERR);} + break; case 'i': return setupI2C(NULL); // current settings + case 'p': + mlx_stop(); return OK; + break; + case 'r': return chres(NULL); + case 't': + {fp_t *i = mlx_getimage(&u32); + if(i){ U("Timage="); USND(u2str(u32)); dumpIma(i); } + else U(ERR);} + break; + case 'C': + cartoon = !cartoon; return OK; case 'D': dumpparams(); break; diff --git a/F3:F303/MLX90640/proto.h b/F3:F303/MLX90640/proto.h index 72c0e7d..1d48512 100644 --- a/F3:F303/MLX90640/proto.h +++ b/F3:F303/MLX90640/proto.h @@ -18,5 +18,5 @@ #pragma once +extern uint8_t cartoon; char *parse_cmd(char *buf); - diff --git a/F3:F303/MLX90640/version.inc b/F3:F303/MLX90640/version.inc index 48efeab..3ef587e 100644 --- a/F3:F303/MLX90640/version.inc +++ b/F3:F303/MLX90640/version.inc @@ -1,2 +1,2 @@ -#define BUILD_NUMBER "22" -#define BUILD_DATE "2025-09-20" +#define BUILD_NUMBER "38" +#define BUILD_DATE "2025-09-21"