Open Berkajerk opened 3 years ago
Figured out the Ta difference. That's just the shift that isn't subtracted from MLX90640_GetTa() when called inside MLX90640_CalculateTo().
Can't figure out where the temperature calculations are going wrong though.
Frame data seems OK. Can you please share the dump of the EEPROM?
Some remarks regarding the function calls:
Best regards
MLX90640 const arrays.txt MLX90640_25Feb data out.txt
I attached the const arrays I calculated after getting the EEPROM data stored as a constant. The alpha, offset, kta, and kv had to calculated separately due to memory constraints. There is also an example of the data I'm getting. I'm going to redump the EEPROM and try out your suggestions. Really appreciate the help.
refresh rate is 2Hz, I2C is 400k
register 0x800D returns 0x1901
Everything seems OK at first glimpse. In MLX90640_25Feb data out.txt I see "FrameData using my EEPROm 25Feb 14:25 facing my desk scan says 24.2C". What does the 24.2C part mean?
Best regards
redid the EEPROM dump and I get the same values for all 832 words
The 24.2C is just my own reference for what my cheap laser temperature gun gives me so I can compare the temperatures.
My current code. It just runs once on each key press. iStatus = MLX90640_TriggerMeasurement(TEMP_ADDR);
iStatus = MLX90640_SynchFrame(TEMP_ADDR); //DEBUG: possible infinite loop
//get data for sub-page 0
iStatus = MLX90640_GetFrameData(TEMP_ADDR, aFrameData16);
printf("\nDEBUG: GetFrameData subpage0 status: %i",iStatus);
MLX90640_GetImage(aFrameData16,¶mMLX90640,fTempResult);
//wait for data to be available or delay
__delay_ms(RR_DELAY_2HZ);
//whole frame data should be stored now
iStatus = MLX90640_GetFrameData(TEMP_ADDR, aFrameData16);
printf("\nDEBUG: GetFrameData subpage1 status: %i",iStatus);
MLX90640_GetImage(aFrameData16,¶mMLX90640,fTempResult);
Output:
fTempResult[0] 5.7969722E8 0x4E0A35E9
the calculated results vary across 768 words from 1.99E8 to 1.18E9 with the sensor facing a warm light with a ceiling behind it. So I'm pretty convinced my frame data is good. Just getting the output scaled seems to be where I'm stuck.
The EEPROM data and the FrameData both seem OK. The calculated Ta value also looks OK. I do not see where you call the CalculateTo function. Normally, the GetImage function is intended to give back a temperature image faster than the calculateTo function, but it does not calculate the temperatures - you only have normalized values. If you want to have a frame with calculated object temperatures you need to call MLX90640_CalculateTo() instead of MLX90640_GetImage().
Okay I will give that a try. I was rechecking my parameters and noticed the KsTo[5] was coming back with infinity and a couple others were being calculated properly. I fixed the other ones to calculate close to the example the but KsTo doesn't want to calculate write. My EEPROM[61] = 0x00bf Example = 0x0EC00 EEPROM[62] = 0xf300 Example = 0x9797 EEPROM[63] = 0x9ec5 Example = 0x9797 KsTo[0-4] = Infinity KsTo[5] = -0.00020 So i coded all the KsTo array to be -0.00020 to match the example.
Which gives me this now: 11.8,18.5,15.8,20.7,17.0,21.9,17.4,22.6,18.1,23.3,17.8,23.5,18.5,23.8,18.3,23.6,18.5,23.7,18.4,23.6,18.0,23.3,17.9,22.8,17.8,22.4,16.7,21.6,16.3,20.7,13.7,20.7,17.8,13.3,21.3,15.5,22.8,16.3,23.1,17.8,23.9,17.9,23.5,18.1,24.3,18.3,24.1,18.0,24.2,18.0
With KsTo calculated with my EEPROM values (Note: not the exact same pixels) 28.4,29.8,-27.6,29.8,-28.9,29.8,-27.6,29.8,-28.0,29.8,-27.1,29.8,-28.0,29.8,-25.8,29.8,-26.7,29.8,-25.8,29.8,-26.2,29.8,-27.1,29.8,-25.8,29.8,29.8,-29.6,29.8,-28.5,29.8,-29.6,29.8,-29.6,29.8,-30.7,29.8,-29.6,29.8,-30.0,29.8,-30.0,29.8,-30.4,29.8,-30.0,29.8,-30.0,29.8,-29.
So I think I'm close. My EEPROM values are stored in ROM and not read on startup do to memory limitations of the PIC18. Are there any specific EEPROM values that should checked on powerup?
I think I have an idea what might be wrong - probably the int type of the PIC18 is 16-bit and the kstoScale variable which is specified as int simply overflows and becomes 0 - that is why you get the infinity in ksto. Could you please update your MLX90640_API.cpp and give it a try?
Best regards
I changed KsToScale to int32_t but still got infinity for KsTo[0..3] and KsTo[4] is -0.0002
Some of my output with KsTo as inifnity: 27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,27.64,27.82,
some of my output with KsTo[0..4] set as -0.0002 .49,20.59,20.43,19.52,18.82,18.79,18.64,18.56,19.19,22.40,22.32,23.70,24.34,25.19,21.92,22.11,21.20,18.99,17.46,16.12,16.45,21.23,17.77,22.01,17.62,20.11,18.28,22.10,19.31,21.05,19.54,21.37,21.17,22.02,20.56,20.57,20.11,19.39,19.76,20.88,19.37,21.19,21.88,24.66,24.86,24.72,25.54,21.26,21.47,19.87,19.77,17.35,19.61,16.56,14.87,17.09,15.82,17.62,16.47,18.37,17.52,19.05,18.54,19.83,19.76,20.17,19.18,18.61,18.70,18.66,18.24,18.36,18.86,19.48,20.88,21.16,23.36,23.55,21.86,20.21,19.16,18.77,18.46,17.16,17.04,23.86,19.28,24.79,18.23,21.56,19.78,23.18,20.11,21.11,20.37,22.42,21.75,22.06,20.72,21.14,20.70,19.71,19.69,20.01,20.44,21.06,21.08,23.79,23.97,22.56,23.61,21.17,19.79,19.05,20.29,19.35,19.34,15.50,10.72,16.89,15.17,18.94,16.56,17.76,17.69,18.88,17.69,19.43,18.61,19.07,18.16,18.97,18.06,17.93,17.83,18.38,18.56,19.10,20.06,20.78,20.66,20.61,19.08,19.39,18.44,18.96,17.59,15.99,13.96,42.39,25.40,36.50,24.55,28.94,24.24,32.46,24.94,25.97,24.48,29.53,23.92,24.01,23.32,27.11,23.88,21.76,22.74,24.23,24.05,22.48,24.43,27.35,25.20,22.29,24.02,26.92,23.03,23.45,23.86,23.63,28.47,
That is strange: mlx90640->ksTo[i] = mlx90640->ksTo[i] / KsToScale; - looks like the only way to get infinity is if kstoScale is 0. Can you share all of the paramsMLX90640 to see if there are other 'strange' values?
Best regards
Here's the parameter dump just after MLX90640_ExtractParameters().
I have definitely been moving some things around as I'm well over my memory limit pushing the kv, kva, alpha, offset, and eeprom arrays as constants. But I am calculating Kva, kv, and alpha on powerup just not the parts that push to the arrays. Just the alphaScale, for example.
In ExtractKsToParameters() I am doing an I2C read to get the EEPROM fresh from 0x2461 and 0x2462. But everything else is from my const EEPROM array.
The parameters also look OK. The only strange thing is the ksto. For your device ksto[0]=0, ksto[1] = -0.000198, ksto[2] = -0.0009 and ksto[3] = -0.001495, but -0.0002 is a good approximation and should not give too big of an error. I would still like to sort that ksto = infinity issue. Are you sure you are correctly passing the parameters to the functions?
Best regards
I only have the one variable for the parameters structure.
MLX90640_ExtractParameters(EEPROM_Dump,¶mMLX90640);
void ExtractKsToParameters(uint16_t eeData, paramsMLX90640 mlx90640) { //int KsToScale; //force to large int int32_t KsToScale;
int8_t step;
//my code
uint16_t eeKsTo[2];
step = ((eeData[63] & 0x3000) >> 12) * 10;
mlx90640->ct[0] = -40;
mlx90640->ct[1] = 0;
mlx90640->ct[2] = (eeData[63] & 0x00F0) >> 4;
mlx90640->ct[3] = (eeData[63] & 0x0F00) >> 8;
mlx90640->ct[2] = mlx90640->ct[2]*step;
mlx90640->ct[3] = mlx90640->ct[2] + mlx90640->ct[3]*step;
mlx90640->ct[4] = 400;
KsToScale = (eeData[63] & 0x000F) + 8;
KsToScale = 1 << KsToScale;
MLX90640_Read(TEMP_ADDR, 0x2461, 2, eeKsTo);
mlx90640->ksTo[0] = eeData[61] & 0x00FF;
mlx90640->ksTo[1] = (eeData[61] & 0xFF00) >> 8;
mlx90640->ksTo[2] = eeData[62] & 0x00FF;
mlx90640->ksTo[3] = (eeData[62] & 0xFF00) >> 8;
for(int i = 0; i < 4; i++)
{
if(mlx90640->ksTo[i] > 127)
{
mlx90640->ksTo[i] = mlx90640->ksTo[i] - 256;
}
mlx90640->ksTo[i] = mlx90640->ksTo[i] / KsToScale;
}
mlx90640->ksTo[4] = -0.0002;
}
I did not realize you changed the code. I think you should modify your code:
MLX90640_Read(TEMP_ADDR, 0x243D, 2, eeKsTo); // The EEPROM address is 0x243D (61st EEPROM address). Also I hope this '2' in the parameters means 2 address = 4 bytes
mlx90640->ksTo[0] = eeKsTo[0] & 0x00FF; //You should use the data you just read from the device - other wise you never write anything in the eeData and you get some random values mlx90640->ksTo[1] = (eeKsTo[0] & 0xFF00) >> 8; mlx90640->ksTo[2] = eeKsTo[1] & 0x00FF; mlx90640->ksTo[3] = (eeKsTo[1] & 0xFF00) >> 8;
Best regards
I will give that a shot. Double checking that address I definitely added 61d to 2400h. No wonder the ksTo is off.
I only have enough memory to read a couple EEPROM values on each power up. Next iteration I plan on a more powerful microcontroller.
Edit: Yes the 2 is actually reading 4 bytes.
Still getting infinity values for ksTo. My fresh EEPROM reads from 0x243D are 0xF300 and from 0x243E are 0x93C5.
MLX90640_Read(TEMP_ADDR, 0x243D, 2, eeKsTo); //gets two words
mlx90640->ksTo[0] = eeKsTo[0] & 0x00FF;
mlx90640->ksTo[1] = (eeKsTo[0] & 0xFF00) >> 8;
mlx90640->ksTo[2] = eeKsTo[1] & 0x00FF;
mlx90640->ksTo[3] = (eeKsTo[1] & 0xFF00) >> 8;
Register 0x800D, in sensor RAM, is consistently 0x9901 now. Before it was 0x1901. What is the 16th bit for? It's not in the data sheet. My EEPROM reads 0x1901 during operation and in my const array.
KsToScale uses data from eeData[63} (address 0x243F). Can you check what is the value you have there? What is the KsToScale value that you get.
Reading the MS bit as '1' in the register at address 0x800D means that you are writing it. Note that setting that bit to 1 should not influence the calculations, but could mean that you are writing to it instead of some write you wanted to do to some other register.
Best regards
at 0x243f i get 0x2558
The EEPROM value you get is correct, but is that same value in eeData[63] in your code?
KsToScale = (eeData[63] & 0x000F) + 8; KsToScale = 1 << KsToScale;
What is the KsToScale value after executing those 2 lines?
Best regards
DEBUG: Extracting Parameters...please wait DEBUG: eeData[63] 0x2558 // printf("\nDEBUG: eeData[63] %#06x\n",eeData[63]); DEBUG: KsToScale middle: 16 //in between the two assignments to KsToScale DEBUG: KsToScale 0 //printf("\nDEBUG: KsToScale %i\n",KsToScale);
I'm still getting a large variation in temperatures across the sensor.
Is there a formula to calculate my Celcius values from the raw sensor data? Like 0xFFab == x in celcius? I need to prove to my professor, this is a school capstone project, that the Celsius output is accurate.
Latest data (this is just the bottom half or so of the output) held against a paperbox. Would my fingers touching it throw off the temperature that much? 28.5 28.2 28.6 27.5 27.9 28.2 27.9 27.1 27.5 28.1 26.0 25.9 25.7 27.0 24.7 24.5 22.3 27.2 26.9 26.0 29.2 26.4 27.2 28.2 30.1 27.7 27.7 29.6 31.3 28.2 28.9 29.9 30.8 30.1 28.1 29.4 29.9 29.6 27.9 29.8 28.9 29.1 25.4 29.2 27.0 27.6 24.2 29.3 24.5 29.8 25.1 21.4 25.5 24.2 26.6 24.6 27.6 26.2 27.9 26.6 28.4 28.0 28.5 27.3 28.6 28.4 28.2 27.8 28.3 28.2 27.8 27.7 27.8 27.7 26.7 26.8 26.7 27.8 25.6 31.1 23.6 28.8 26.2 26.1 30.8 26.2 27.5 28.1 31.0 28.3 28.0 29.7 30.7 29.9 28.6 30.4 31.6 30.1 28.3 30.3 31.0 30.1 28.1 30.5 29.7 29.8 26.6 30.6 28.3 29.2 24.7 29.1 25.2 30.6 28.0 22.9 27.0 25.0 28.1 24.7 28.2 27.1 28.8 27.1 29.0 28.3 29.5 28.2 28.9 28.8 29.0 27.9 29.0 28.8 28.8 27.6 28.3 28.2 26.9 26.9 26.7 28.0 26.4 26.2 23.9 29.8 30.4 29.0 33.8 29.0 30.6 29.2 33.0 29.8 30.5 30.9 32.3 30.6 30.5 31.5 32.2 31.4 29.7 31.7 32.2 30.8 28.9 31.5 30.8 30.5 26.6 30.6 29.2 29.0 25.7 30.9 27.3 32.8 28.9 23.3 28.3 25.3 29.2 25.5 29.1 27.2 28.9 27.6 29.7 28.8 29.3 27.8 29.5 29.3 29.4 28.7 29.7 29.1 28.9 27.9 28.3 28.8 27.9 27.0 27.1 27.7 26.6 25.3 24.2 30.7 33.4 31.6 35.9 31.0 32.9 31.2 35.0 30.4 31.2 32.3 33.8 32.8 31.4 32.5 33.5 31.7 30.3 32.6 33.1 31.8 29.5 31.8 31.5 31.2 27.2 31.4 29.6 30.8 26.5 30.9 28.9 33.8 30.3 23.0 28.6 25.2 29.9 25.4 29.6 28.3 29.1 27.8 30.5 28.8 29.4 28.1 30.0 29.3 29.4 28.1 29.8 30.4 28.6 27.7 28.5 29.3 27.5 26.7 27.0 29.3 26.8 26.1 24.2 30.3 36.4 31.7 38.6 30.8 34.0 31.8 37.5 33.1 31.4 34.1 36.4 33.0 31.4 32.6 34.1 32.7 30.7 33.3 34.5 32.7 28.9 32.6 32.2 32.6 27.5 31.4 30.3 32.2 27.3 32.7 27.1 35.3 34.2 23.6 31.4 25.9 31.7 26.2 30.0 28.2 31.4 27.6 30.1 29.2 31.5 28.6 30.2 29.8 29.2 28.4 29.8 30.4 29.5 28.1 28.7 29.2 27.4 26.4 27.1 27.9 26.4 25.4 23.9 29.9 46.5 38.2 47.0 35.0 38.6 35.2 42.5 35.7 37.2 34.6 37.4 35.0 34.6 34.4 36.5 35.5 31.4 35.1 37.2 34.2 31.4 33.8 34.3 33.9 28.9 33.1 32.2 31.3 27.9 33.9 29.6 36.9 39.6 25.4 34.5 27.7 33.3 26.1 32.7 28.7 32.4 28.4 31.9 30.6 31.8 28.3 31.1 31.1 30.0 28.6 29.9 31.0 30.2 28.1 28.4 29.4 27.9 27.8 28.4 28.5 25.4 25.1 22.4 27.2 57.5 45.4 54.9 38.9 43.5 40.0 46.6 38.1 39.2 38.0 42.3 38.4 37.2 37.3 40.2 38.1 33.9 37.0 37.4 36.8 33.4 36.0 36.1 36.2 31.8 37.3 36.2 33.7 28.7 34.7 32.5 36.4 46.4 20.1 37.4 29.0 36.8 27.1 33.5 30.7 32.9 28.1 34.0 31.2 31.7 28.4 33.5 31.0 29.3 28.9 30.3 30.6 29.4 28.2 29.7 29.2 28.6 25.7 29.0 28.0 28.5 23.7 24.5 27.1 103.1 70.2 82.8 57.5 61.9 53.7 68.1 51.5 51.4 50.3 60.0 48.3 46.1 47.2 54.9 48.6 41.1 46.9 48.5 46.7 39.8 45.8 50.8 46.2 37.8 45.8 51.9 45.6 43.3 49.4 54.7 37.6 Highest temp: 103.10 at 736 Lowest temp: 14.32 at 1 Average (including bad pixels and outliers: 29.31 //I haven't run the functions for badpixels or outliers Measured ambient with offset eTa: 25.895675
The formula is implemented in the driver. If you want to do the calculations externally, you can refer to the MLX90640 datasheet : https://www.melexis.com/-/media/files/documents/datasheets/mlx90640-datasheet-melexis.pdf . Touching the sensor is not a good idea as it creates thermal gradients and spoils the performance. How much time after POR are you taking your measurements? Did you put the appropriate decoupling capacitors as described in the datasheet?
I wonder why KsToScale=0 after executing KsToScale = 1 << KsToScale;. Did you make sure that KsToScale is 32 bit int?
Best regards
My temperature average seems to stay about 2C from expected. I'm going to run the code on a beefier chip to see if it's just this micro that can't calculate fast enough between frames.
KsToScale = 1 << KsToScale;
The type of the expression 1 << KsToScale
is defined by the type of the constant 1
.
On a 16 bit MCU, the 1
is 16 bit.
You might want to use something similar to:
KsToScale = 1ul << KsToScale;
1ul
is 1 but with type unsigned long
, which is, I believe, 32 bit on a 16 bit system.
my 2 cents.
I get data similar, see below, but when I call GetTa() or CalculateTo() I get garbage data that definitely doesn't match me pointing the sensor at a desk or piece of paper that should be close to the same temp. Using the example data I get most of the same parameters calculated back out except for alpha (uint16), kv (int8) and kta (int8) are different because the example data are in decimals. My ksTo doesn't calculate properly for some reason other but even hard-coding -0.0002 hasn't helped. Ambient Ta comes out around 22.5, which makes sense but the Ta inside MLX906490_To() is 30.6?
My order of function calls is: MLX90640_SynchFrame() MLX90640_GetFrameData() MLX90640_GetVdd() MLX90640_ClearNewDataBit() //my own MLX90640_GetTa() MLX90640_CalculateTo() while(!MLX90640_CheckNewFrame) //my own //loop through twice as per the Melexis data sheet Measurement flow
RAM data 0xff94,0xffaf,0xffac,0xffac,0xffa8,0xffa3,0xff9f,0xff9e,0xff9c,0xff95,0xff8e,0xff8f,0xff8d,0xff8c,0xff80,0xff87,0xff81,0xff81,0xff79,0xff86,0xff7c,0xff83,0xff7a,0xff88,0xff7f,0xff89,0xff7d,0xff8f,0xff86,0xff92,0xff89,0xffa3,0xff9f,0xffbb,0xffae,0xff9f,0xff9c,0xff8f,0xff99,0xff91
Calculated values from MLX90640_GetImage() display with printf("%6.1f,", fTempResult[i]); 592.0,338272480.0,362236960.0,451677376.0,385740224.0,357841664.0,352839072.0,475474240.0,376040288.0,442351360.0,466023392.0,582827584.0,461466912.0,553721088.0,547306240.0,868710400.0,2073485824.0,1457174016.0,1639923584.0,1062499648.0,1117048576.0,1007729472.0,1176669312.0,879932992.0,835734784.0,817753600.0,914897472.0,799963840.0,703102208.0,733174976.0,809205696.0,751047872.0,584132416.0,718254464.0,727529920.0,732689984.0,592247680.0,722966720.0,742125504.0,791069504.0,623380992.0,879549504.0,863016000.0,849186432.0,711014208.0,1036032896.0,1065976704.0,1397301376.0,1953519232.0,717029248.0,930322368.0,625610176.0,823806528.0,471457376.0,657431424.0,563241280.0,568958144.0,422298112.0,595941056.0,526872288.0,473833376.0,384111200.0,546840512.0,500078720.0,364202208.0,400743552.0,427827680.0,505806528.0,415574816.0,424173664.0,465272864.0,537820032.0,476969216.0,450454080.0,583294464.0,651005760.0,669964096.0,614491712.0,835286528.0,1300244608.0,5021978112.0,3191158272.0,2957620480.0,1885567488.0,1862405376.0,1625331584.0,2040611968.0,1472667904.0,1337811456.0,1350845952.0,1630382464.0,1237255168.0,1087828608.0,1179745408.0,1401025536.0,1229205760.0,901572352.0,1152956672.0,1189396608.0,1176895488.0,904684224.0,1178945664.0,1352280704.0,1265989760.0,935620992.0,1309102336.0,1523960960.0,1398909568.0,1321256064.0,1681935104.0,2320309248.0,323784160.0
Calculated values from MLX90640_CalculateTo() display with printf("%6.1f,", fTempResult[i]); -273.1, -273.1, -273.1, -273.1, -273.1, -273.1, -273.1, -273.1, -273.1, -273.1, -273.1, -273.1, -273.1, -273.1, -273.1, -273.1, -273.1, -273.1, -273.1, -273.1, 9291.8, -273.1, -273.1, -273.1, 11478.3, -273.1, -273.1, -273.1, -273.1, -273.1, -273.1, 5429.8, -273.1, -273.1, -273.1, -273.1, -273.1, -273.1, -273.1, -273.1, -273.1, -273.1, -273.1, -273.1, -273.1, -273.1, -273.1, -273.1, -273.1, -273.1