# Calculation of logarithm based on digital analog conversion input

Discussion in 'Embedded Systems and Microcontrollers' started by tomaytos, May 18, 2014.

1. ### tomaytos Thread Starter New Member

May 18, 2014
2
0
I try to simulate a solar cell and I want to calculate the voltage of the cell based on its current. This is done with the formula:
Since the calculation of a logarithm is needed, i have to work with variables of the type double.

The code below won't run. (Light at port RD7 remains off) I discovered that it runs if I don't use the measured value of the D/A conversion module but replace it with a fixed value.
If I shorten the code, it also works.

I don't know what the problem might be.

I use a pic18f4550, the coding is done with mikroc and the testing is done with proteus.

Code ( (Unknown Language)):
1. unsigned long read_analog_channel(unsigned char ch);
2. double Tc;
3. double doub;
4. unsigned long lon;
5. unsigned char ch;
7. unsigned char leds;
8. unsigned long test;
9.
10. // Input
11. unsigned char  idf=1; // ideality factor
12. double Iph=8.57; // Photo current
13. double I0=1e-10; // reverse saturation current
14. double Rs=0.01; // Shunt resistance
15. double Ic;
16.
17. // Constants
18. double kde = 8.617332e-5; // boltzmann constant divided through Electron charge
19.
20.  // Output
21. double Vc; // Desired output of cell.
22.
23. main(void) {
24.
25.   TRISD = 0x00 ;                  // PORT B Setting: Set all the pins in port B to Output.
26.
27.   Tc=(double)64;
28.
30.
31.   ADCON1 |= 0x00; // last 4 bits: configure all A input parts as analog.
33.   ADCON2 |= 0x38; // bit 5-3: 111: acquisition time = 20 Tad
34.   ADCON2 |= 0x06; // last 3 bits: Fosc/16
35.
36.   while(1){
37. //Vc=(double) k*Tc/e*log(((double) Iph+I0- Ic/1000)/I0)+Rc*Ic; formula to calculate
38.
40.
41.         doub=(Iph-Ic/1000.0)/I0+1.0;
42.          Vc=kde*Tc*log(doub)+Rs*Ic;// This only works when I don't use the measured Ic.
43.
44.          //The following steps are always excecuted with Ic from the adc input.
45.           //Vc=log(Iph-Ic*1e-3); // Here the led is 1 second on and then stays off.
46.                                  // when I divide through 1e3 it doesn't work.
47.           // Vc=log(Iph-Ic*1e-3+1.0); //same
48.           // Vc=kde*Tc*log(Iph); // led is 1 second on and then very short off...
49.           // Vc=Tc*log(Iph-Ic*1e-3+1.0); // This doesn't work
50.
51.         PORTD=0b10000000;
52.         delay_ms(1000);
53.         PORTD=0;
54.         delay_ms(1000);
55.
56. }
57.
58.  unsigned long read_analog_channel(unsigned char ch)
59.     {
60.     ADCON0 |= 0x0F&ch; // select chanel
61.     //Auto acquisition time
63.
66.
69.
70.     return (unsigned long) 5000*answer/1023   ;
71.     // return 5000*answer/1023; // This one works but then the output is wrong. (tread as integer)
72.     //return 0x0DAC;  // 3500 mA, This one works too.
73.     }

File size:
91.2 KB
Views:
14
2. ### ErnieM AAC Fanatic!

Apr 24, 2011
7,443
1,628
First off I would suggest seeking any way possible to avoid using any float types. Since the input comes from a 10 bit A2B you have a maximum possible 1024 outcomes from your measurement and calculation. A table read would certainly be faster and possibly even shorter then doing such calculations.

I've never used Proteus but it seems it has "extensive debugging features, including breakpoints, single stepping and variable display for a neat design prior to hardware prototyping."

You should single step your code and see what values are being produced. This may entail breaking the equation into many many little pieces to see which one is going wrong.

3. ### tomaytos Thread Starter New Member

May 18, 2014
2
0
I solved the problem by using mplab x ide instead of mikroc. Now the code runs normally.