Dr_Doggy
Well-Known Member
The first one of these i bought was a 8x1, which was really nice since all i needed to do was a 12c lookup in eeprom registers, this 16x4 needs multiple reads and processing before the temperature in the array can be resolved, so first i took the source code provided for adruino, and changed it over to be compatible with my PIC source code and variables, after that i cut out the subroutines and trimmed the code best i could:
unsigned char i2c_readIR(void){
int i;
long IR[64];
double VIRCOMP[64], vircp, alpha[64];
double tmp;
double eC;
double Vth = 0.0;
double Kt1 = 0.0;
double Kt2 = 0.0;
int Air, Bir;
double eX = pow(2.0, EEPROM[0xD9]);
int Acp = EEPROM[0xD4];
int Bcp = EEPROM[0xD5];
double result, result2;
int TGC = EEPROM[0xD8];
double eZ = (EEPROM[0xE5]*256.0 + EEPROM[0xE4])/32768.0;
double e1 = (EEPROM[0xE1]*256.0 + EEPROM[0xE0]) / (pow(2.0, EEPROM[0xE2]));
double e2 = pow(2.0, EEPROM[0xE3]);
i2c_start(); // read ptat value
ack = i2c_write(address); ack = i2c_write(0x02);
ack = i2c_write(0x90); ack = i2c_write(0x00);
ack = i2c_write(0x01); i2c_restart();
ack = i2c_write(address + 1);
PTAT = i2c_readLOOP(0);PTAT += (i2c_readLOOP(0) * 256);
i2c_stop(); i2c_start(); // read Compensation pixel value
ack = i2c_write(address); ack = i2c_write(0x02);
ack = i2c_write(0x91); ack = i2c_write(0x00);
ack = i2c_write(0x01); i2c_restart();
ack = i2c_write(address + 1);
COMPENSATION = i2c_readLOOP(0); COMPENSATION += (i2c_readLOOP(0) * 256);
if(COMPENSATION > 32767L) COMPENSATION -= 65536L;
i2c_stop();
// Load Temperature array from ram
i2c_start();
i2c_write(address);
i2c_write(0x02);
i2c_write(0x00);
i2c_write(0x01);
i2c_write(0x40);
i2c_restart();
i2c_write(address + 1);
for(int c2=0x00;c2<(0x40);c2+=0x01){
IR[c2] = i2c_readLOOP(0);
IR[c2] += i2c_readLOOP(0) * 256;
IRDATuncoded[c2] = IR[c2];
if(IR[c2] > 32767L) IR[c2] -= 65536L;
}
i2c_stop();
if((Vth = EEPROM[0xDB]*256.0 + EEPROM[0xDA]) > 32767.0) Vth -= 65536.0;
if((Kt1 = EEPROM[0xDD]*256.0 + EEPROM[0xDC]) > 32767.0) Kt1 -= 65536.0; Kt1 = Kt1/1024.0;
if((Kt2 = EEPROM[0xDF]*256.0 + EEPROM[0xDE]) > 32767.0) Kt2 -= 65536.0; Kt2 = Kt2/1048576.0;
INTTEMP = ((-1)*Kt1 + sqrt(pow(Kt1, 2) - 4*Kt2*(Vth - PTAT))) / (2*Kt2);
//////////////
//////////////// INTTEMP = pow(Kt1, 2);
////////////////
////////////////// result2 = 0;
////////////////// result2 = Vth - PTAT;
////////////////// result2 = result2 * 4;
////////////////// result2 = result2 * Kt2;
////////////////// INTTEMP = INTTEMP - result2;
////////////////
//////////////
////////////// INTTEMP = sqrt( INTTEMP );
////////////// INTTEMP = INTTEMP + (-1)*Kt1;
////////////// INTTEMP = INTTEMP / (2*Kt2);
INTTEMP += 25.0;
if(Acp > 127) Acp -= 256;
if(Bcp > 127) Bcp -= 256;
vircp = COMPENSATION - (Acp + ((Bcp/(pow(2.0, EEPROM[0xD9]))) * (INTTEMP - 25.0)));
if(TGC > 127) TGC -= 256;
result = (double)(TGC/32.0);
eC = pow(INTTEMP + 273.15, 4);
for(i=0; i<64; i++)
{
Air = EEPROM;
Bir = EEPROM[0x40+i];
if(Air > 127) Air -= 256;
if(Bir > 127) Bir -= 256;
VIRCOMP = IR - (Air + ((Bir/eX) * (INTTEMP - 25.0)));
VIRCOMP = VIRCOMP - (result * vircp);
VIRCOMP = VIRCOMP/eZ;
alpha = e1 + (EEPROM[0x80+i]/e2);
tmp = VIRCOMP/alpha + eC;
//// tmp = mySQRT(tmp);
tmp = sqrt(tmp);
tmp = sqrt(tmp);
IRDAT = tmp - 273.15;
}
xxx=1;
return 1;
}
yes, this is the simplified version, and does all calculations OK, however there is something going on here where i am getting a delay on my interrupt , INT0 is my 9600 baud 232 rx receiver and due to the delay on the interrupt firing my rx bytes are returning with wrong values.
using more rem statements ( // ), i have narrowed it down to this line being a problem:
INTTEMP = ((-1)*Kt1 + sqrt(pow(Kt1, 2) - 4*Kt2*(Vth - PTAT))) / (2*Kt2);
and by breaking that line down to simpler components :
// INTTEMP = ((-1)*Kt1 + sqrt(pow(Kt1, 2) - 4*Kt2*(Vth - PTAT))) / (2*Kt2);
INTTEMP = pow(Kt1, 2);
result2 = 0;
result2 = Vth - PTAT;
result2 = result2 * 4;
result2 = result2 * Kt2;
INTTEMP = INTTEMP - result2;
INTTEMP = sqrt( INTTEMP );
INTTEMP = INTTEMP + (-1)*Kt1;
INTTEMP = INTTEMP / (2*Kt2);
I have discovered that the problem is in one of these following lines, if i rem them out buffer receives ok, but even re - adding the first line (result2 = 0, or any other of them causes the error:
result2 = 0;
result2 = Vth - PTAT;
result2 = result2 * 4;
result2 = result2 * Kt2;
INTTEMP = INTTEMP - result2;
osccon and osctune are setup during initialization , i cant think of anything else that would effect it, but i cant see that line (result2 = 0 being the problem either.
Ideas?
unsigned char i2c_readIR(void){
int i;
long IR[64];
double VIRCOMP[64], vircp, alpha[64];
double tmp;
double eC;
double Vth = 0.0;
double Kt1 = 0.0;
double Kt2 = 0.0;
int Air, Bir;
double eX = pow(2.0, EEPROM[0xD9]);
int Acp = EEPROM[0xD4];
int Bcp = EEPROM[0xD5];
double result, result2;
int TGC = EEPROM[0xD8];
double eZ = (EEPROM[0xE5]*256.0 + EEPROM[0xE4])/32768.0;
double e1 = (EEPROM[0xE1]*256.0 + EEPROM[0xE0]) / (pow(2.0, EEPROM[0xE2]));
double e2 = pow(2.0, EEPROM[0xE3]);
i2c_start(); // read ptat value
ack = i2c_write(address); ack = i2c_write(0x02);
ack = i2c_write(0x90); ack = i2c_write(0x00);
ack = i2c_write(0x01); i2c_restart();
ack = i2c_write(address + 1);
PTAT = i2c_readLOOP(0);PTAT += (i2c_readLOOP(0) * 256);
i2c_stop(); i2c_start(); // read Compensation pixel value
ack = i2c_write(address); ack = i2c_write(0x02);
ack = i2c_write(0x91); ack = i2c_write(0x00);
ack = i2c_write(0x01); i2c_restart();
ack = i2c_write(address + 1);
COMPENSATION = i2c_readLOOP(0); COMPENSATION += (i2c_readLOOP(0) * 256);
if(COMPENSATION > 32767L) COMPENSATION -= 65536L;
i2c_stop();
// Load Temperature array from ram
i2c_start();
i2c_write(address);
i2c_write(0x02);
i2c_write(0x00);
i2c_write(0x01);
i2c_write(0x40);
i2c_restart();
i2c_write(address + 1);
for(int c2=0x00;c2<(0x40);c2+=0x01){
IR[c2] = i2c_readLOOP(0);
IR[c2] += i2c_readLOOP(0) * 256;
IRDATuncoded[c2] = IR[c2];
if(IR[c2] > 32767L) IR[c2] -= 65536L;
}
i2c_stop();
if((Vth = EEPROM[0xDB]*256.0 + EEPROM[0xDA]) > 32767.0) Vth -= 65536.0;
if((Kt1 = EEPROM[0xDD]*256.0 + EEPROM[0xDC]) > 32767.0) Kt1 -= 65536.0; Kt1 = Kt1/1024.0;
if((Kt2 = EEPROM[0xDF]*256.0 + EEPROM[0xDE]) > 32767.0) Kt2 -= 65536.0; Kt2 = Kt2/1048576.0;
INTTEMP = ((-1)*Kt1 + sqrt(pow(Kt1, 2) - 4*Kt2*(Vth - PTAT))) / (2*Kt2);
//////////////
//////////////// INTTEMP = pow(Kt1, 2);
////////////////
////////////////// result2 = 0;
////////////////// result2 = Vth - PTAT;
////////////////// result2 = result2 * 4;
////////////////// result2 = result2 * Kt2;
////////////////// INTTEMP = INTTEMP - result2;
////////////////
//////////////
////////////// INTTEMP = sqrt( INTTEMP );
////////////// INTTEMP = INTTEMP + (-1)*Kt1;
////////////// INTTEMP = INTTEMP / (2*Kt2);
INTTEMP += 25.0;
if(Acp > 127) Acp -= 256;
if(Bcp > 127) Bcp -= 256;
vircp = COMPENSATION - (Acp + ((Bcp/(pow(2.0, EEPROM[0xD9]))) * (INTTEMP - 25.0)));
if(TGC > 127) TGC -= 256;
result = (double)(TGC/32.0);
eC = pow(INTTEMP + 273.15, 4);
for(i=0; i<64; i++)
{
Air = EEPROM;
Bir = EEPROM[0x40+i];
if(Air > 127) Air -= 256;
if(Bir > 127) Bir -= 256;
VIRCOMP = IR - (Air + ((Bir/eX) * (INTTEMP - 25.0)));
VIRCOMP = VIRCOMP - (result * vircp);
VIRCOMP = VIRCOMP/eZ;
alpha = e1 + (EEPROM[0x80+i]/e2);
tmp = VIRCOMP/alpha + eC;
//// tmp = mySQRT(tmp);
tmp = sqrt(tmp);
tmp = sqrt(tmp);
IRDAT = tmp - 273.15;
}
xxx=1;
return 1;
}
yes, this is the simplified version, and does all calculations OK, however there is something going on here where i am getting a delay on my interrupt , INT0 is my 9600 baud 232 rx receiver and due to the delay on the interrupt firing my rx bytes are returning with wrong values.
using more rem statements ( // ), i have narrowed it down to this line being a problem:
INTTEMP = ((-1)*Kt1 + sqrt(pow(Kt1, 2) - 4*Kt2*(Vth - PTAT))) / (2*Kt2);
and by breaking that line down to simpler components :
// INTTEMP = ((-1)*Kt1 + sqrt(pow(Kt1, 2) - 4*Kt2*(Vth - PTAT))) / (2*Kt2);
INTTEMP = pow(Kt1, 2);
result2 = 0;
result2 = Vth - PTAT;
result2 = result2 * 4;
result2 = result2 * Kt2;
INTTEMP = INTTEMP - result2;
INTTEMP = sqrt( INTTEMP );
INTTEMP = INTTEMP + (-1)*Kt1;
INTTEMP = INTTEMP / (2*Kt2);
I have discovered that the problem is in one of these following lines, if i rem them out buffer receives ok, but even re - adding the first line (result2 = 0, or any other of them causes the error:
result2 = 0;
result2 = Vth - PTAT;
result2 = result2 * 4;
result2 = result2 * Kt2;
INTTEMP = INTTEMP - result2;
osccon and osctune are setup during initialization , i cant think of anything else that would effect it, but i cant see that line (result2 = 0 being the problem either.
Ideas?