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;
    6. unsigned int answer;
    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.  
    29.   ADCON0.ADON = 1; // Turns adc on
    30.  
    31.   ADCON1 |= 0x00; // last 4 bits: configure all A input parts as analog.
    32.   ADCON2.ADFM = 1; // 0= left justified
    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.  
    39.          Ic=read_analog_channel(0);
    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
    62.     ADCON0.GO = 1;   //Starts ADC conversion
    63.  
    64.     while (ADCON0.GO) continue;   //wait till ADC conversion is over
    65.     answer=0x0000;
    66.  
    67.     answer=(char) ADRESH;
    68.     answer=(answer << 8) + (char) ADRESL;   //Merging the MSB and LSB
    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.     }
     
  2. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,392
    1,606
    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.
     
Loading...