Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.
|
Forum Index : Microcontroller and PC projects : PicoMite Thermal Camera
Page 1 of 4 | |||||
Author | Message | ||||
Volhout Guru Joined: 05/03/2018 Location: NetherlandsPosts: 4223 |
This thread is about a Thermal Camera based on PicoMite and a MLX90641 camera module that can be purchased around 20 dollar at Digikey or the likes. The proto is running on VGA, but will have to be tested for a while before I release the code. The final product will run on LCD (handheld). The idea is to create a plug in for the Game*Mite expansion connector. So this is just a heads up of what is coming, using the limited color palette of the VGA Picomite. The camera is 16x12 pixels, and this has been upscaled to 31x23 pixels. The screen refresh rate is 0.5 seconds. Volhout PicomiteVGA PETSCII ROBOTS |
||||
Gizmo Admin Group Joined: 05/06/2004 Location: AustraliaPosts: 5078 |
Watching with interest. Glenn The best time to plant a tree was twenty years ago, the second best time is right now. JAQ |
||||
OA47 Guru Joined: 11/04/2012 Location: AustraliaPosts: 926 |
COOL 0A47 |
||||
Amnesie Guru Joined: 30/06/2020 Location: GermanyPosts: 396 |
Cool, I like the VGA version too! For stationary use this is also good. I am sure there is a lot of math involved (interpolation?). Greetings Daniel |
||||
Volhout Guru Joined: 05/03/2018 Location: NetherlandsPosts: 4223 |
The interpolation is simple code. The complex math is in the conversion from ADC values per pixel, to temperature. Where there is dependency on emission coeficient, 3.3V voltage, ambient temperature, compensation pixel behaviour, linearization... and this all per pixel. It took me days to implement it from the Melexis MLX90641 datasheet (look at it, 54 pages mainly filled with math and examples). Currently the camera itself is set to an update rate of 2Hz. And the current code uses 190ms to read the pixel data through I2C (100kHz), 70ms to do all the math (mainly useing MATH array commands in MMBasic), 190ms to do the up-scaling and pixel display (BOX command). The camera can work faster, the I2C can go to 400kHz, so I might be able to get to 4Hz by squeezing every last bit out of the performance. But for now, let's first make it work correctly. My ambient temperature calculation is few degrees off. So need to search into the math if somewhere I repaced a "+" with a "-"....?? Volhout PicomiteVGA PETSCII ROBOTS |
||||
karlelch Senior Member Joined: 30/10/2014 Location: GermanyPosts: 172 |
Cool project! Some time ago I played with an 8x8 thermal camera and Micropython. I remember optimizing the code was tricky. I was interested in blob detection (Video) and ended up writing C code for some routines (Description, German only, sorry). Thomas |
||||
Martin H. Guru Joined: 04/06/2022 Location: GermanyPosts: 1113 |
nice Project, the discription Google translated to dutch Edited 2024-05-23 04:57 by Martin H. 'no comment |
||||
Volhout Guru Joined: 05/03/2018 Location: NetherlandsPosts: 4223 |
This is the status quo of the PicoMite Thermal Camera. - 0.5 sec update rate (@252MHz CPU speed) - "s" will make a screenshot - 2 markers (X=higest temp, O=centre pixel) - "c" zero's the screen (*) Code MLX90641_dev_09.zip The code is compatible with VGA and ILI9341 320x240 LCD. Control is through keyboard ATM. Support for Game*Mite controls and filesystem is next on the list. Unit in operation (VGA), my finger is in front of the camera module. I use a Seedstudio Grove IR camera module with MLX90641 with 110 degrees opening angle. Final design will use the 60 degrees opening angle part (software compatible). This message is short, because my long message took too long, and I was kicked out of the forum, and lost all the message. Volhout Edited 2024-05-31 21:56 by Volhout PicomiteVGA PETSCII ROBOTS |
||||
Volhout Guru Joined: 05/03/2018 Location: NetherlandsPosts: 4223 |
Zero-ing. Zeroing the screen is not really needed when temperature differences are large. But the small differences between individual pixels can be equalized. This is done by holding a piece of metal (at room temperature) in front of the camer and pressing "c". I use an old heatsink, so I know it is same temperature over the whole surface. Volhout PicomiteVGA PETSCII ROBOTS |
||||
Volhout Guru Joined: 05/03/2018 Location: NetherlandsPosts: 4223 |
The current code upscales a 16x12 array to 31x23 by simply calculating the pixels in between in MMBasic by linear interpolation. Since there are only 16 colors in the VGA and in the framebuffer (needed to get speed to the LCD updates mainly) this gives a blocky screen. But it is the maximum that can be done in MMBasic in a refresh rate of 2Hz. Painting 700+ BOX'es and drawing the text etc.. If you see this (using probably the MLX90640 32x24 pixel array) and a piece of C code, you can start painting individual pixels. demo code The video is realy nice. Using all the colors, and calculating pixel RGB values using a fast algorithm, and immediately pushing the pixel out to the screen. Still a lot can be improved in MMBasic code, but I may need to work on a CSUB to do get closer to this demo. Volhout PicomiteVGA PETSCII ROBOTS |
||||
Volhout Guru Joined: 05/03/2018 Location: NetherlandsPosts: 4223 |
Experiment with 4x upscaling... The calculation and plotting takes more time 2x upscaling : 190ms 4x upscaling : 730ms So the total update rate goes to 1 second. Volhout PicomiteVGA PETSCII ROBOTS |
||||
stanleyella Guru Joined: 25/06/2022 Location: United KingdomPosts: 2120 |
I went and bought a camera that looks like a kit for £26. no instructions. can't read as usb drive. could it be hacked for data ? |
||||
stanleyella Guru Joined: 25/06/2022 Location: United KingdomPosts: 2120 |
it could be a premade adafruit board with lcd and battery. figured usb and scroll through saved images. half full mug of coffee Edited 2024-06-01 07:34 by stanleyella |
||||
Volhout Guru Joined: 05/03/2018 Location: NetherlandsPosts: 4223 |
All, Yesterday played with matrix multiplication for up-scaling. It is 2-3x faster than doing the math cell by cell, but it is consuming too much memory. For 2x up-scaling it is roughly 7kbyte, but for 4x up-scaling it is 20kbyte extra in arrays that contain the up-scaling constants. Since up-scaling was not the dominant factor(*), it is back to standard math. Volhout (*) dominant factor upscaling 4x is writing 2790 BOX'es each frame, and re-drawing some text (=480ms). And I currently see no alternative way. I knwo many have the same color, but finding that out, and blit fewer larger boxes, costs also time. Maybe someting can be gained by determining the median color in the array, plotting the whole screen in median color, then plotting only the boxes that are different. Edited 2024-06-04 17:42 by Volhout PicomiteVGA PETSCII ROBOTS |
||||
Amnesie Guru Joined: 30/06/2020 Location: GermanyPosts: 396 |
Hello Volhout, If the memory problem could be solved, why not leave the upscaling as an option, maybe there are applications in which the refresh time isn't too crictical? Greetings Daniel Edited 2024-06-04 18:08 by Amnesie |
||||
Volhout Guru Joined: 05/03/2018 Location: NetherlandsPosts: 4223 |
Hi Daniel, That is the idea. Upscaling 2x is working fine (also with fast matrix math). It is the upscaling 4x that causes the problem. I have improved the screen update from 480ms to 350ms for 4x. Now the cell based up-scaling math becomes a player with 260ms. I am trying to squeeze the code, and remove everything that is not needed. I expect that the RAM is also used as a scratch-pad during matrix multiplications. As if Peter is doing the math MATH M_MULT in1(),in2(),out() in a copy of the out() array, and when done copies that into actual destination array. That means RAM memory should hold 2 copies of the (large) out() array (22kb size). Since the scaling using matrix math is a 2 pass action (first up-scale horizontal, then vertical) I calculated I can save another 2 kbyte RAM by doing vertical first (the conversion matrices get smaller). Last resort: up-scaling 3x (not 4x) A lot of tech bla-bla.... Volhout Edited 2024-06-04 18:57 by Volhout PicomiteVGA PETSCII ROBOTS |
||||
Amnesie Guru Joined: 30/06/2020 Location: GermanyPosts: 396 |
Volhout, I read in the "PicoMite V5.09.00 release candidates" topic, that you've made huge progress regarding the speed thanks to Peters new implementations / adjustmens. This is great. I am happy to built this project too and would like to ask what thermal camera module I should buy for it. I will only use it with a VGA monitor. There are two devices: MLX90641 with an 16x12 array and MLX90641 with an 32×24 array other than that the Operating Temperature is different. Also there are different view angles, I think this isn't cirical from your software point of view? What thermal camera would you suggest, or is the code with the 32×24 array different? Greetings Daniel |
||||
Volhout Guru Joined: 05/03/2018 Location: NetherlandsPosts: 4223 |
Hi Daniel, The 32x24 array is the MLX90640, not the MLX90641. I am currently using the MLX90641 (16x12 array). It can be purchased with 2 opening angles, 55(-BCB) degrees and 110(-BCA) degrees. I have (up to this moment) used the BCA version (110 degrees), simply because it is mounted on the SeedStudio Grove module. But I plan to build a Game*Mite adapter PCB that has the BCB unit on it. But it depends on the application you plan to use it for. 110 degrees is wide angle. The software is independent of the opening angle. I saved another 1.8kbyte RAM (1 array shared between functions), and have to save another 2.2 kbyte to benefit from the BOX draw. But it is getting more and more difficult. Volhout P.S. Do not purchase the MLX90640 if you want to use my code. The MLX90640 has 4 times the pixels, so you do not need to scale 4x, as 2x is sufficient for the same result. But the 8 arrays that hold pixel calibration values are 4x as large also. It will present its own set of memory restrictions, and will definitely not run on my code. Edited 2024-06-05 22:32 by Volhout PicomiteVGA PETSCII ROBOTS |
||||
Amnesie Guru Joined: 30/06/2020 Location: GermanyPosts: 396 |
Thank you very much for this information! I just odered the MLX90641 (16x12 array), like suggested. Can't wait to try it Impressive work! Geetings Daniel |
||||
Volhout Guru Joined: 05/03/2018 Location: NetherlandsPosts: 4223 |
Hi Daniel, Just for your convenience, this is the status quo. It has an update rate of 750ms in 4x up-scaling. When you plan to use it, make sure you have the I2C bus set correct. I wired the camera chip to GP0/GP1 (I2C), but you can configure for GP14/GP15 (I2C2) in line 7. IN my archive this is archived as MLX90641_dev_14.bas 'MLX90641 IR camera support '-------------------- generic program defines ------------------------ const SA=&h33 'I2C 7 bit slave address is &h5A I2Cport=1 'I2C2=2 anything other is I2C scalefactor=4 '2=16x12 to 31x23 num_colors=16 '6 or 8 'define video interface dim i,x,y as integer 'in stead of replacing all i with i% '-------------------------system initialisation ---------------------- vga%=instr(mm.device$,"VGA") '0 or not 0 if vga% then mode 2 else font 7 endif framebuffer create 'use framebuffer when LCD faster screen framebuffer write F 'use framebuffer when LCD faster screen 'I2C bus open at 400kHz if I2Cport=2 then 'assume system I2C on GP14/GP15 'setpin gp14,gp15,I2C2 'I2C2 open 400,100 else setpin gp0,gp1,I2C I2C open 400,100 end if 'arrays with values per pixel dim Po1(191) 'offset subbank 1 dim Po0(191) 'offset subbank 0 dim Pa(191) 'alpha dim Pkt(191) 'temperature impact dim Pkv(191) 'voltage impact dim Vir(191) 'voltage from sensor element and after conversion temperature dim Toffs(191):math set 2,Toffs()'Temperature offsets for manual calibration 'debugging how much memory left 'dim vzz(250) '2kb 'define the colors if num_colors=6 then 'colors dim col%(5) = (rgb(blue),rgb(cerulean),rgb(red),rgb(orange),rgb(yellow),rgb(white)) 'tile colors else if num_colors=8 then '8 colors dim col%(7) = (rgb(magenta),rgb(blue),rgb(cyan),rgb(green),rgb(yellow),rgb(orange),rgb(red),rgb(white)) else '16 colors dim col%(15)=(0,&h4000,&h8000,&hff,&h40ff,&h80ff,&hff00ff,&hff40ff,&hff80ff,&hff0000,&hff4000,&hff8000,&hFFFF00,&hFF00,&hFFFF,&hFFFFFF) end if 'scaling buffers and math matrices if scalefactor=2 then Dim scrn(31,22) '16*2-1,12*2-1 = 31x23 screen pixels + 1 dummy else 'scalefactor = 4 (uses matrix math) dim Toa(15,11) 'this is Vir() in 2D form dim b(61,15),c(15,44),d(11,44) 'arrays for matrix math fill_bd_4 'conversion matrices dim scrn(61,44) '16*4-3 x 12*4-3 = 61x45 screen pixels + 1 dummy column end if memory 'debug '--------------------------- read camera constants ------------------- get_res_corr dummy=get_vdd() get_cal get_Kta_Kv get_Po0_Po1 get_Pa get_Vir get_conf get_stat '---------------------------- screen setup ----------------------------- 'place the legend on screen box 310,47,10,179,1,0,0 'bar graph frame v_size = 179 \ num_colors for i=0 to num_colors-1 box 311,48+i*v_size,8,v_size,1,col%(num_colors-1-i),col%(num_colors-1-i) next text 0,232,"PicoMite Thermal Camera, C = cal, S = save, Q = quit",,8 '-------------------------- MAIN LOOP ------------------------------- 'this is based on MLX90641 datasheet chapter 10.5 without STEP mode 'the MLX90641 runs autonomous at 500ms (2Hz) default speed do 'wait for new data by checking data available flag do pause 10 status% = get_reg(&h8000) loop until (status% and 8) = 8 'get actual subpage where data is available page% = (status% and 1) 'get data (takes roughly 190ms) get_vir(page%) 'clear data ready bit (just write the page bit back) set_reg(&h8000,page%) 'convert IR readings to temperature according datasheet temp_conv 'check if we need to re-calibrate if a$="c" then cal_array 'calibrate the measured values to the reference math c_sub Vir(),Toffs(),Vir() 'calculate extremes tmax=math(max Vir(),pix%):tmin=math(min Vir()) Tlow=min(tmin,Ta-2):Thigh=max(tmax,Tlow+10) 'show the colorfull picture on screen if scalefactor=2 then scale_up else scale_4 end if 'show the legend box 260,0,60,16,1,rgb(white),rgb(black) 'peak value in view text 270,4,"X "+str$(tmax,3,1),,,,rgb(white),rgb(black) box 260,17,60,16,1,rgb(white),rgb(black) 'centre screen value text 282,21,str$(Vir(88),3,1),,,,rgb(white),rgb(black) circle 272,24,5,,,rgb(pink) box 280,34,40,13,1,rgb(black),rgb(white) 'high value text 284,37,str$(Thigh,3,1),,,,rgb(black),rgb(white) box 280,226,40,14,1,rgb(black),rgb(blue) 'low value text 284,229,str$(Tlow,3,1),,,,rgb(white),rgb(blue) 'the marker's text 20*(pix% mod 16)-2,20*(pix%\16)-3,"X",,1 'cross circle 162,102,10,,,rgb(pink) 'ring 'debug text 0,0,str$(timer,3,0):timer=0 'fast copy of framebuffer to screen framebuffer copy f,n 'do we want to save the current image ? if a$="s" then save image "screenshot.bmp" a$=inkey$ loop while a$<>"q" end sub temp_conv local f_t(191) 'scratchpad temp local f_v(191) 'scratchpad voltage 'process data according 11.2.2 from datasheet Vdd=get_vdd() 'get Vdd 11.2.2.2 Ta=get_ta() 'get Ta 11.2.2.3 math scale vir(),Kgain,vir() 'scale gain 11.2.2.5.1 'IRdatcomp 11.2.2.5.3 math scale pkt(),Ta-25,f_t() 'calc 1+Kta*(Ta-T25) math add f_t(),1,f_t() math scale pkv(),vdd-3.3,f_v() 'calc 1+Kv*(Vdd-3.3) math add f_v(),1,f_v() math c_mul f_v(),f_t(),f_v() 'multiply and result in f_v() if page% then 'compensate for page offset math c_mul f_v(),Po1(),f_v() else math c_mul f_v(),Po0(),f_v() end if math c_sub Vir(),f_v(),Vir() 'and add to pixel voltage 'emissivity comp 11.2.2.5.4 and IR gradient comp 11.2.2.7 math add Vir(),-tgc*cp_pix_os,Vir() math scale Vir(),1/em,Vir() 'this is Vir_compensated() 'Sensitivity normalize 11.2.2.8 and put values in f_t() for temp conversion math add Pa(),-tgc*alpha_cp,f_t() math scale f_t(),1+ksta*(Ta-25),f_t() 'this is alpha_comp() 'Temp conversion (0-80C) 11.2.2.9 Tark4=calc_tark() 'since there are no math commands for square root and raise to the power 'this is still in a loop, needs 55ms @ 252MHz (all above math is only 10ms) for i=0 to 191 Sx=KsTo_3*( ( Vir(i)*(f_t(i)^3) + (f_t(i)^4)*Tark4 )^(1/4) ) Vir(i)=((tark4 + Vir(i)/(f_t(i)*(1-KsTo_3*273.15)+Sx))^(1/4))-273.15 next end sub '--------------------------- display routines ------------------------------- 'these routines perform the visual representation of the data in Tob() 'show 192 temperatures on screen in a grid of 31x23 interleaved sub scale_up '2x local bc%,xm% 'timer=0 'seed the measurement data Tob()on the screen window scrn() 'scaling math takes roughly 65ms this way for y=0 to 11 for x=0 to 15 scrn(2*x,2*y)=Vir(x+16*y) next next 'interleave the horizontal even lines for y=0 to 22 step 2 for x=1 to 29 step 2 scrn(x,y)=(scrn(x-1,y)+scrn(x+1,y))/2 next next 'interleave the horizontal odd lines for y=1 to 21 step 2 for x=0 to 30 scrn(x,y)=(scrn(x,y-1)+scrn(x,y+1))/2 next next 'convert to colors (only picomite 5.08.00 and newer) math window scrn(),0,num_colors-1,scrn() '6 or 8 colors 'block size for 31x23 pixels on 320x240 screen size%=10 '? timer, 'show screen on mode 2 on picomite (takes roughly 130ms) 'box 0,0,310,220,1,col%(com_col%),col%(com_col%) for x=0 to 30 xm%=x*size% for y=0 to 22 bc%=col%(scrn(x,y)) box x*size%,y*size%,size%,size%,1,bc%,bc% next next 'put some default values in the array math set Thigh,scrn():scrn(31,0)=Tlow '? timer end sub 'show 192 temperatures on screen in a grid of 61x45 interleaved sub scale_4 local bc%,xm% 'timer=0 'copy linear array into 16x12 array, and perform math to scale up (38ms) for y=0 to 11 for x=0 to 15 Toa(x,y)=Vir(x+16*y) next next math m_mult d(),Toa(),c() 'c() is correct vertical resolution math m_mult c(),b(),scrn() 'set the pixels in the dummy column to smooth the screen colors when no 'delta T is visible for i=1 to 44:scrn(61,i)=Thigh:next :scrn(61,0)=Tlow 'convert to colors (only picomite 5.08.00 and newer) math window scrn(),0,num_colors-1,scrn() '8 colors 'block size for 61x45 pixels on 320x240 screen size%=5 '? timer, 'show screen on mode 2 on picomite (takes roughly 350ms) for x=0 to 60 xm%=x*size% for y=0 to 44 bc%=col%(scrn(x,y)) box xm%,y*size%,size%,size%,1,bc%,bc% next next '? timer end sub sub cal_array math add Vir(),-Ta,Toffs() end sub ' ------------------- get pixel cal data from the chip ---------------------- 'these functions read data from the MLX90641 and do some formatting 'get status register sub get_stat 'get value Reg8000%=get_reg(&h8000) end sub 'get config register sub get_conf 'get value Reg800D%=get_reg(&h800D) end sub 'get voltages for the pixel array from subpage n (0 or 1) sub get_vir n local i,j,yoff,xoff as integer xoff=n*&h20 for j=0 to 5 'all 6 banks yoff=j*&h40 for i=0 to 31 'of 32 pixels 'get value Vir(i+j*32)=get_reg_16_2(&h400 + i + yoff + xoff) next next end sub 'get alpha(i) and adjust for row (0-5) sub get_Pa local i as integer 'adjust per row (32 pix) according 11.2.2.8 for i=0 to 31 Pa(i)=a_ref_row_1*get_reg_11(&h2500+i)/2047 next for i=32 to 63 Pa(i)=a_ref_row_2*get_reg_11(&h2500+i)/2047 next for i=64 to 95 Pa(i)=a_ref_row_3*get_reg_11(&h2500+i)/2047 next for i=96 to 127 Pa(i)=a_ref_row_4*get_reg_11(&h2500+i)/2047 next for i=128 to 159 Pa(i)=a_ref_row_5*get_reg_11(&h2500+i)/2047 next for i=160 to 191 Pa(i)=a_ref_row_6*get_reg_11(&h2500+i)/2047 next end sub 'get Kta(i) and Kv(i) and scale them to be used for math sub get_Kta_Kv local x,i as integer for i=0 to 191 'all 192 pixels x=&h25c0+i 'get value Pkt(i)=(get_reg(x) and &h7e0)/32 if Pkt(i)>31 then inc Pkt(i),-64 'scale Pkt(i)=(Pkt(i)*(2^kta_scale_2) + kta_avg) / (2^kta_scale_1) 'get value Pkv(i)=get_reg(x) and &h1f if Pkv(i)>15 then inc Pkv(i),-32 'scale Pkv(i)=(Pkv(i)*(2^kv_scale_2) + kv_avg) / (2^kv_scale_1) next end sub 'get Offset(i) for 0 and 1 compensated as in 11.2.2.5.2 sub get_Po0_Po1 local x,i as integer for i=0 to 191 'all 192 pixels x=&h2440+i 'get value Po0(i) = get_reg_11_2(x) 'scale Po0(i) = (Po0(i) * 2^scale_os_r1) + pix_os_av next for i=0 to 191 'all 192 pixels x=&h2680+i 'get value Po1(i) = get_reg_11_2(x) 'scale Po1(i) = (Po1(i) * 2^scale_os_r2) + pix_os_av next end sub 'determine Tambient function get_Ta() local dv,vbe,vptat,vptat_art as float dv = get_vdd()-3.3 vbe = get_reg_16_2(&h580) vptat = get_reg_16_2(&h5a0) vptat_art = (vptat / (vptat*alpha_ptat + vbe)) * 2^18 'formula from datasheet 11.1.2 get_Ta = (((vptat_art/(1+kv_ptat*dv))-ptat)/kt_ptat)+25 end function function calc_tark() Tr=Ta-5 'from datasheet in absence of better local tvk4=(Tr+273.15)^4 calc_tark=tvk4-(tvk4-(Ta+273.15)^4)/em end function ' ------------------- get specific data from the chip ------------------------ 'these functions read data from the MLX90641 and do some formatting 'resolution correction from the ADC sub get_res_corr RC = (get_reg(&h2433) and &h600)>>9 RC = RC/((get_reg(&h800D) and &hC00)>>10) if debug then print "RC = ";RC end sub 'actual Vdd measured by the chips ADC function get_vdd() as float local v=get_reg_16_2(&h5aa), k=get_reg_11_2(&h2427), va=get_reg_11_2(&h2426) va=va*32 : k=k*32 get_vdd = 3.3 + (RC*v - va)/k if debug then print "Vdd = ";get_vdd end function 'this sub extracts calibration values from the chips EEPROM and formats these 'for use in the math 'formula's are derived from MLX90641 data sheets sub get_cal local x local scale_row1,row1_max local scale_row2,row2_max local scale_row3,row3_max local scale_row4,row4_max local scale_row5,row5_max local scale_row6,row6_max local alpha_cp_sc, kta_cp_sc, kv_cp_sc x=get_reg_11(&h2410) scale_os_r1 = x>>5 : scale_os_r2 = x and 31 x= get_reg_11_2(&h2411) * 32 pix_os_av = get_reg_11_2(&h2412) : inc pix_os_av, x kta_avg = get_reg_11_2(&h2415) x=get_reg_11(&h2416) kta_scale_1 = x>>5 : kta_scale_2 = x and 31 kv_avg = get_reg_11_2(&h2417) x=get_reg_11(&h2418) kv_scale_1 = x>>5 : kv_scale_2 = x and 31 x=get_reg_11(&h2419) scale_row_1 = (x>>5) + 20 : scale_row_2 = (x and 31) + 20 x=get_reg_11(&h241A) scale_row_3 = (x>>5) + 20 : scale_row_4 = (x and 31) + 20 x=get_reg_11(&h241B) scale_row_5 = (x>>5) + 20 : scale_row_6 = (x and 31) + 20 row1_max=get_reg_11(&h241C) row2_max=get_reg_11(&h241D) row3_max=get_reg_11(&h241E) row4_max=get_reg_11(&h241F) row5_max=get_reg_11(&h2420) row6_max=get_reg_11(&h2421) a_ref_row_1 = row1_max / (2^scale_row_1) a_ref_row_2 = row2_max / (2^scale_row_2) a_ref_row_3 = row3_max / (2^scale_row_3) a_ref_row_4 = row4_max / (2^scale_row_4) a_ref_row_5 = row5_max / (2^scale_row_5) a_ref_row_6 = row6_max / (2^scale_row_6) ksta = get_reg_11_2(&h2422) / 32768 'emissivity em = get_reg_11_2(&h2423) / 512 'general gain gain = get_reg_11(&h2424) * 32 x = get_reg_11(&h2425) : inc gain,x Kgain = gain / get_reg_16_2(&h058A) 'ptat ptat = get_reg_11(&h2428) * 32 x = get_reg_11(&h2429) : inc ptat,x kt_ptat = get_reg_11(&h242A) / 8 kv_ptat = get_reg_11(&h242B) / 4096 alpha_ptat = get_reg_11(&h242C) / 128 'control pixel alpha_cp_sc = get_reg_11(&h242E) alpha_cp = get_reg_11(&h242D) / (2 ^ alpha_cp_sc) x = get_reg_11(&h242F) * 32 offset_cp = get_reg_11(&h2430) : inc offset_cp,x : map_16_2(offset_cp) gain_cp = get_reg_16_2(&h0588) * Kgain x = get_reg_11(&h2431) kta_cp_sc = x>>6 kta_cp = x and 63 : if kta_cp > 31 then inc kta_cp,-64 kta_cp = kta_cp / (2^kta_cp_sc) x = get_reg_11(&h2432) kv_cp_sc = x>>6 kv_cp = x and 63 : if kta_cp > 31 then inc kta_cp,-64 kv_cp = kv_cp / (2^kv_cp_sc) cp_pix_os = gain_cp - offset_cp*(1+kta_cp*(Ta-25))*(1+Kv_cp*(get_vdd()-3.3)) 'IR gradient compensation TGC = (get_reg(&h2433) and &h1ff) / 64 RC_cal = (get_reg(&h2433) and &h600)>>9 'Object temperature scaling KsTo_sc = get_reg_11(&h2434) KsTo_1 = get_reg_11_2(&h2435) / (2^KsTo_sc) KsTo_2 = get_reg_11_2(&h2436) / (2^KsTo_sc) KsTo_3 = get_reg_11_2(&h2437) / (2^KsTo_sc) KsTo_4 = get_reg_11_2(&h2438) / (2^KsTo_sc) KsTo_5 = get_reg_11_2(&h2439) / (2^KsTo_sc) KsTo_6 = get_reg_11_2(&h243B) / (2^KsTo_sc) KsTo_7 = get_reg_11_2(&h243D) / (2^KsTo_sc) KsTo_8 = get_reg_11_2(&h243F) / (2^KsTo_sc) CT6 = get_reg_11(&h243A) CT7 = get_reg_11(&h243C) CT8 = get_reg_11(&h243E) end sub ' ------------------- conversion functions ----------------------------- 'this function makes use of the fact that changes in variable x reflect in 'source variable sub map_16_2(x) '16 bit 2'th complement if x>32767 then inc x,-65536 end sub ' ------------------- read chip functions ----------------------------- 'these functions read data from the MLX90641 and do some formatting 'return 16 bit value read from MLX90641 registers n, MSB first function get_reg(n) as integer get_reg = read_reg(n) end function 'return an 11 bit value (remove hamming code) from MLX90641 register n function get_reg_11(n) as integer get_reg_11 = read_reg(n) and &h7ff end function 'return a 2'th complement 11 bit value (remove hamming code) from MLX90641 register n function get_reg_11_2(n) as integer get_reg_11_2 = read_reg(n) and &h7ff if get_reg_11_2>1023 then inc get_reg_11_2,-2048 end function 'return a 16 bit 2'th complement value from MLX90641 register n function get_reg_16_2(n) as integer get_reg_16_2 = read_reg(n) if get_reg_16_2>32767 then inc get_reg_16_2,-65536 end function function read_reg(n) as integer local a%(1)) if I2Cport=2 then i2c2 write SA, 1, 2, n\256, n and 255 i2c2 read SA,0,2,a%() else i2c write SA, 1, 2, n\256, n and 255 i2c read SA,0,2,a%() end if read_reg=a%(1)+256*a%(0) end function ' ------------------- write chip functions ----------------------------- 'this functions writes a 16 bit value v to MLX90641 register n 'write 16 bit value to MLX90641 registers n, MSB first sub set_reg n,v if I2Cport=2 then i2c2 write SA,0,4,n\256,n and 255,v\256,v and 255 else i2c write SA,0,4,n\256,n and 255,v\256,v and 255 end if end sub '-----------------------matrices for math ----------------------------- 'this sections fills the multiplication matrics that do the up-scaling sub fill_bd_4 local i 'matrix b(61,15) for scaling up 2x horizontal, column 61 is not programmed for i=0 to 15 : b(4*i,i)=1 : next for i=0 to 14 : b(4*i+2,i)=0.5 : b(4*i+2,i+1)=0.5 : next for i=0 to 14 : b(4*i+1,i)=0.75 : b(4*i+1,i+1)=0.25 : next for i=0 to 14 : b(4*i+3,i)=0.25 : b(4*i+3,i+1)=0.75 : next if debug then math m_print b():print 'matrix d(11,44) for scaling up 2x vertical for i=0 to 11 : d(i,4*i)=1 : next for i=0 to 10 : d(i,4*i+2)=0.5 : d(i+1,4*i+2)=0.5 : next for i=0 to 10 : d(i,4*i+1)=0.75 : d(i+1,4*i+1)=0.25 : next for i=0 to 10 : d(i,4*i+3)=0.25 : d(i+1,4*i+3)=0.75 : next if debug then math m_print d() end sub Edited 2024-06-06 00:08 by Volhout PicomiteVGA PETSCII ROBOTS |
||||
Page 1 of 4 |
Print this page |