|
|
View previous topic :: View next topic |
Author |
Message |
ozturkhuseyin
Joined: 26 Jan 2024 Posts: 9
|
Variable initialization error |
Posted: Fri Jan 26, 2024 6:44 am |
|
|
Code: |
float en1 = 0.0;
float en2 = 0.0;
float en3 = 0.0;
en1 = ReadFloatEepromBackup(EE_ADDR_INDEX_ENERGY1_0);
en2 = ReadFloatEepromBackup(EE_ADDR_INDEX_ENERGY2_0);
en3 = ReadFloatEepromBackup(EE_ADDR_INDEX_ENERGY3_0);
energyL1 = en1;
energyL2 = en2;
energyL3 = en3;
DEBUG("READING ENERGY L1: %.8f \n", en1);
DEBUG("READING ENERGY L2: %.8f \n", en2);
DEBUG("READING ENERGY L3: %.8f \n", en3);
|
In this code block, i read last values from internal eeprom and update energyL1,2,3 variables, after systems reads energy consumption and writes it to energyL1,2,3 as shown below
Code: |
energyL1 = energyL1 + (((float)energyL1tmp) / 1702000.0);
energyL2 = energyL2 + ((float)energyL2tmp) / 1702000.0;
energyL3 = energyL3 + ((float)energyL3tmp) / 1702000.0;
|
But this isn't work, energyL1,2,3 are always 0, i tested eeprom read/write operations they worked. But when initializing energyL1 = en1; if data readen from eeprom on start is commented systems works and i can see exact consumption values on variable via uart debug.
energyL1,2,3 variables are defined in a header file of lib. |
|
|
gaugeguy
Joined: 05 Apr 2011 Posts: 303
|
|
Posted: Fri Jan 26, 2024 9:19 am |
|
|
Please post the full code of what you are doing. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Fri Jan 26, 2024 10:51 am |
|
|
curious am i....
as I don't use floating points....
this format...
%.8f
to me says display a floating point number BUT only the 'fractional part, to eight places .
say n=12.34567890
you would only see .34567890 ???
I'd think. %11.8f to get 12.34567890 ?? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Fri Jan 26, 2024 11:59 am |
|
|
I'm worried about his referring to 'lib'. Does this imply multiple compilaon
untis are being used?. If so, a misdeclaration of the import/export could
easily result in the values not correctly being transferred between parts,
Also, why not debug yourself? You are displayng the 'en' values, why not
display the 'energyL' values at this point? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Fri Jan 26, 2024 4:02 pm |
|
|
energyL1 = energyL1 + (((float)energyL1tmp) / 1702000.0);
hmm, wonder where energyl1tmp comes from ?
it'd be easier if we saw a complete program.
agree that displaying the intermediate values and calculations would point to the problem. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Sat Jan 27, 2024 12:11 pm |
|
|
and also what compiler version, and chip.
The compiler version is vital, since there have been two maths errors, one at
about 5.085, and another in the low 5.10x's, which could cause this behaviour.
Both were fixed quickly, and versions released with the fixes, but if he
has one of the faulty versions, this would explain everything.
In fact the casts are not needed, and on some chips will waste code space.
Code: |
energyL1 = energyL1 + (energyL1tmp / 1702000.0);
|
is all that is needed. The division by a float, implicitly converts the tmp
value into a float.
However how energyL1tm is actually declared, and how the value is
put into it, is vital. |
|
|
ozturkhuseyin
Joined: 26 Jan 2024 Posts: 9
|
|
Posted: Mon Jan 29, 2024 1:56 am |
|
|
chip is PIC18F46K22, complier version is 5.104
energyL1tmp is unsigned int32, readen from adc chip via I2C. EnergyL1 is float.
I am reading ADC chip with 100ms period. And after each read i update EnergyL1 with adding new temp value. Systems backups EnergyL1 value to eeprom 5mins period. My problem is here is that when system start i read eeprom to update latest EnergyL1 value but when i do this like below code block it doesnt work.
Code: |
float en1 = 0.0;
float en2 = 0.0;
float en3 = 0.0;
en1 = ReadFloatEepromBackup(EE_ADDR_INDEX_ENERGY1_0);
en2 = ReadFloatEepromBackup(EE_ADDR_INDEX_ENERGY2_0);
en3 = ReadFloatEepromBackup(EE_ADDR_INDEX_ENERGY3_0);
energyL1 = en1;
energyL2 = en2;
energyL3 = en3;
DEBUG("READING ENERGY L1: %.8f \n", en1);
DEBUG("READING ENERGY L2: %.8f \n", en2);
DEBUG("READING ENERGY L3: %.8f \n", en3);
|
If i comment energyL1 = en1; initialization system works but i cant update latest energy value. EnergyL1 remains at 0. I checked ADC chip it reads values but doesnt update EnergyL1 value.
Btw energyL1 is defined in ADC chip's header file. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Mon Jan 29, 2024 4:41 am |
|
|
Er.
"unsigned int32".
Your value is perpetually going to grow. This can never give a value lower
than zero, so every addition will make your sum larger. There is a huge issue
here. I'm guessing this is actually a signed value read from the ADC, so
needs to actually be put into a signed int value before the cast.
Long term you will have the issue as outlined here:
[url]
http://www.ccsinfo.com/forum/viewtopic.php?t=59059&highlight=cast
[/url]
You are mixing case on EnergyL1 and energyL1. Is it possible you have
case sensitivity enabled?. If so, these are not the same variable..... |
|
|
ozturkhuseyin
Joined: 26 Jan 2024 Posts: 9
|
|
Posted: Mon Jan 29, 2024 5:51 am |
|
|
They are same variable just i writed wrong here. Just energyL1.
Unsigned int32 value is a register inside ADC ic and it resets when i read.
Code: |
energyL1tmp = readI2CDoubleWord(SLAVE_DEV_ADDR,0xE400);
|
Then dividing it to ratio and adding it to energyL1 variable as float. So value doesnt get large. |
|
|
ozturkhuseyin
Joined: 26 Jan 2024 Posts: 9
|
|
Posted: Mon Jan 29, 2024 5:59 am |
|
|
Systems works well if i commented energyL1 initialization from eeprom reading but cant start with latest energyL1 value with this.
Code: |
float en1 = 0.0;
float en2 = 0.0;
float en3 = 0.0;
en1 = ReadFloatEepromBackup(EE_ADDR_INDEX_ENERGY1_0);
en2 = ReadFloatEepromBackup(EE_ADDR_INDEX_ENERGY2_0);
en3 = ReadFloatEepromBackup(EE_ADDR_INDEX_ENERGY3_0);
//energyL1 = en1;
//energyL2 = en2;
//energyL3 = en3;
DEBUG("READING ENERGY L1: %.8f \n", en1);
DEBUG("READING ENERGY L2: %.8f \n", en2);
DEBUG("READING ENERGY L3: %.8f \n", en3);
|
If energyL1 initialization at system start is commented system works with correct values. But when i undo my comments system doesnt update energyL1 variable. I am debugging via uart.
Code: |
read_adc();
DEBUG("|V1: %.3lf |C1: %.3lf |APP1: %.3lf |VAR1: %.3lf |PHI1: %.3lf |EN1: %.8f |ACTIVE1: %.3lf\n", vL1 / 11558.0 , cL1 / 112388.0, appL1 / 151.50181, varL1 / 151.50181, pfL1 / 1.0, energyL1 / 1.0, activeL1 / 151.50181);
|
If i initialize energyL1 with a random value as energyL1 = 1234.5; system works also, but when i try to update it from eeprom backup its value doesnt change on runtime even i got values from adc ic. |
|
|
ozturkhuseyin
Joined: 26 Jan 2024 Posts: 9
|
|
Posted: Mon Jan 29, 2024 6:55 am |
|
|
my adc read function is as below
Code: |
energyL1tmp = readI2CDoubleWord(SLAVE_DEV_ADDR,0xE400);
energyL2tmp = readI2CDoubleWord(SLAVE_DEV_ADDR,0xE401);
energyL3tmp = readI2CDoubleWord(SLAVE_DEV_ADDR,0xE402);
/* other adc readings */
energyL1 = energyL1 + ((float)energyL1tmp) / 1702000.0;
energyL2 = energyL2 + ((float)energyL2tmp) / 1702000.0;
energyL3 = energyL3 + ((float)energyL3tmp) / 1702000.0;
DEBUG("kWh (tmp)...E1:%.6f, E2:%.6f, E3:%.6f ...\n",((float)energyL1tmp) / 1702000.0 ,((float)energyL2tmp) / 1702000.0, ((float)energyL3tmp) / 1702000.0);
DEBUG("kWh E1:%.6f, E2:%.6f, E3:%.6f ...\n",energyL1 ,energyL2, energyL3);
|
DEBUG output is :
kWh (tmp)E1:0.000058, E2:0.000000, E3:0.000000 -> printed from inside lib
kWh E1:0.000000, E2:0.000000, E3:0.000000 -> printed from inside lib
|V1: 225.608 |C1: 2.925 |APP1: 674.071 |VAR1: -54.428 |PHI1: 67.000 |EN1: 0.00000000 |ACTIVE1: 423.328 -> printed in main.c
kWh (tmp)E1:0.000058, E2:0.000000, E3:0.000000
kWh E1:0.000000, E2:0.000000, E3:0.000000
|V1: 225.563 |C1: 2.925 |APP1: 674.460 |VAR1: -54.791 |PHI1: 72.000 |EN1: 0.00000000 |ACTIVE1: 423.123
kWh (tmp)E1:0.000059, E2:0.000000, E3:0.000000
kWh E1:0.000000, E2:0.000000, E3:0.000000
|V1: 225.621 |C1: 2.923 |APP1: 674.671 |VAR1: -55.642 |PHI1: 64.000 |EN1: 0.00000000 |ACTIVE1: 422.443
kWh (tmp)E1:0.000058, E2:0.000000, E3:0.000000
kWh E1:0.000000, E2:0.000000, E3:0.000000
|V1: 225.631 |C1: 2.926 |APP1: 675.774 |VAR1: -56.540 |PHI1: 67.000 |EN1: 0.00000000 |ACTIVE1: 422.305
kWh (tmp)E1:0.000058, E2:0.000000, E3:0.000000
kWh E1:0.000000, E2:0.000000, E3:0.000000
|V1: 225.729 |C1: 2.923 |APP1: 675.199 |VAR1: -56.157 |PHI1: 69.000 |EN1: 0.00000000 |ACTIVE1: 422.833
kWh (tmp)E1:0.000058, E2:0.000000, E3:0.000000
kWh E1:0.000000, E2:0.000000, E3:0.000000
|V1: 225.632 |C1: 2.927 |APP1: 675.120 |VAR1: -56.052 |PHI1: 69.000 |EN1: 0.00000000 |ACTIVE1: 423.084
kWh (tmp)E1:0.000058, E2:0.000000, E3:0.000000
kWh E1:0.000000, E2:0.000000, E3:0.000000
MCU reads ADC from i2c with correct values(energyL1tmp) but cant update energyL1 value with them.
Code: |
energyL1 = energyL1 + ((float)energyL1tmp) / 1702000.0;
|
if i comment lines in system start as shown
Code: |
float en1 = 0.0;
float en2 = 0.0;
float en3 = 0.0;
en1 = ReadFloatEepromBackup(EE_ADDR_INDEX_ENERGY1_0);
en2 = ReadFloatEepromBackup(EE_ADDR_INDEX_ENERGY2_0);
en3 = ReadFloatEepromBackup(EE_ADDR_INDEX_ENERGY3_0);
/* this lines */
//energyL1 = en1;
//energyL2 = en2;
//energyL3 = en3;
|
system updates energyL1 value correctly but i have to read last values and initialize system on start with them. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Mon Jan 29, 2024 8:40 am |
|
|
First, this:
Code: |
read_adc();
DEBUG("|V1: %.3lf |C1: %.3lf |APP1: %.3lf |VAR1: %.3lf |PHI1: %.3lf |EN1: %.8f |ACTIVE1: %.3lf\n", vL1 / 11558.0 , cL1 / 112388.0, appL1 / 151.50181, varL1 / 151.50181, pfL1 / 1.0, energyL1 / 1.0, activeL1 / 151.50181);
|
Makes no sense at all. You are calling the read_adc function, and not storing
the result from this.
Then do what has already been suggested. Change your debug after the
EEPROM read, and display both the en1 value, and the energyL1 value.
Then post your ReadFloatEepromBackup function.
You also have not answered the question about whether you are using
multiple compilation units?.
Do you have access to a slightly older compiler?. 5.104, was one where
there was a maths problem. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Mon Jan 29, 2024 1:25 pm |
|
|
It'd be real nice to know what ADC is being used.
I'm kinda confused as, if it's a 'double word' ( 32 bit ?) from the ADC , why convert to floating point and do FP math ?
Surely scaled integers would be a LOT faster and easier as PICs HATE floating point numbers.
Also eventually adding the new reading into a 32bit variable, it'll overflow.
It might be easier to reduce the code to test on ONE ADC channel ? It looks like it's a '3 phase power ' program and having similar named variables,easy to mistype,make a mistake that way ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Tue Jan 30, 2024 12:03 pm |
|
|
I have to also suggest you re-code all your printf formats to actually be
legal C.
Understand that in C, the number in fromnt of the decimal on the printf,
is the total output field width, The number after the decimal is the
digits to display after the decimal, The number in front is _not_ the
width in front of the decimal.
So yoru format is sayong to print with a zero output length, and then
to print 8 decimals. Illegal.
Now noramlly the printf will overflow, and realise it has to output the
number of digits youy are asking for, but there was an issue about the
compiler version you have, where overflowing the field width resulted
in numbers being displayed incorrectly.
It'd be really silly if it was your printf format that was causing thiings to
go wrong.
%9.8f |
|
|
ozturkhuseyin
Joined: 26 Jan 2024 Posts: 9
|
|
Posted: Thu Feb 01, 2024 1:56 am |
|
|
temtronic wrote: | It'd be real nice to know what ADC is being used.
I'm kinda confused as, if it's a 'double word' ( 32 bit ?) from the ADC , why convert to floating point and do FP math ?
Surely scaled integers would be a LOT faster and easier as PICs HATE floating point numbers.
Also eventually adding the new reading into a 32bit variable, it'll overflow.
It might be easier to reduce the code to test on ONE ADC channel ? It looks like it's a '3 phase power ' program and having similar named variables,easy to mistype,make a mistake that way ? |
It is ADE7878 adc chip. You are right about not doing floating point math but library i used is designed with floating points and i must not change library. Readings from chip are not that big to overflow variables. I am just testing on channel 1 already. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|