Problema de salida de datos en PIC18F4520

0

He programado el PIC18F4520 con MPLAB, MCC18 y Pickit2. Mi código se pega a continuación:

#include <p18f4520.h>
#include <math.h>
#include <adc.h>
#include <delays.h>

#pragma config OSC = INTIO67                //HSPLL
#pragma config WDT = OFF
#pragma config LVP = OFF
#pragma config DEBUG = OFF

#define TRUE    1
#define FALSE   0
#define ON      1
#define OFF     0

//Defining internal clock of 32Mhz
#define FOSC 32000000L
#define TCY 8                       //Which is 4/32Mhz = 1/8Mhz.

//#define Reset() {__asm__ volatile ("reset");}

//***** Constants *****
#define Q       1.6e-19
#define K       1.38e-23
#define Rs      0.05            //Series Resistance
#define Rsh     200             //Shunt resistance
#define N       1.3
#define NS      40

double temperature = 274.0;
double short_circuit_current = 0;
double open_circuit_voltage = 0;
double IL_1 = 0.0;
double Q_1 = 0.0;
double M_1 = 0.0;
double IO_1 = 0.0;

typedef far struct 
{
    double Pmax;
    double Imax;
    double Vmax;
    double Gmax;
    double Rmax;
} Result;

far Result result_parallel;
far Result result_series;
double Rmax = 0.0;

#define ARRAY_SIZE 576
#pragma udata DATA
//double V_1[ARRAY_SIZE/2];
double I_1[ARRAY_SIZE];
#pragma udata

/****** Prototype methods **********/
float abs(auto float x);
void delay_usec(unsigned int);
void delay_msec(unsigned int);
double read_adc(unsigned char);
void switch_port(unsigned char, const unsigned char);

Result compute(const double,const double);
int max(const double, const double*, int length);

float abs(auto float x)
{
    return (x < 0) ? (x*-1.0f) : x;
}

void delay_usec(unsigned int usec)
{
    int delay = usec * TCY / 10;
    Delay10TCYx(delay);
}

void delay_msec(unsigned int msec)
{
    int delay = msec * 1000 * TCY / 100;
    if (delay > 255) 
    {
        delay = msec * 1000 * TCY / 10000;
        Delay1KTCYx(delay);
    }
    else
    {
        Delay100TCYx(delay);
    }
}

double read_adc(unsigned char channel)
{
    SetChanADC(channel);
    ConvertADC();
    while (BusyADC());
    return ((ReadADC() + 40)/1024.0 * 5.0);
    //return ReadADC();
}

void switch_port(unsigned char port, const unsigned char state)
{
    port = state;
    delay_msec(2);
}

Result compute(const double Voc, const double Isc) 
{
    int i = 0;
    int maxPoint = 0;
    int arrayLength = ARRAY_SIZE;
    double V_1 = 0.0;
    Result result;

    //Calculation time
    IL_1 = Isc;
    Q_1 = (Q*Voc)/(N*K*temperature);
    M_1 = Voc / Rsh;
    IO_1 = ((double)abs(Isc - M_1))/(((double)exp(Q_1)) - 1.0);

    for (i = 0; i < arrayLength; i++)
    {
        V_1 = ((double)i)*(Voc/(double)arrayLength);
        I_1[i] = IL_1 - IO_1 * (exp(Q * V_1/ (NS * N * K * temperature)) - 1.0) - V_1/Rsh;
    }

    maxPoint = max(Voc, I_1, arrayLength);
    result.Imax = I_1[maxPoint];
    result.Vmax = ((double)maxPoint)*(Voc/(double)arrayLength); //V_1[maxPoint];
    result.Pmax = result.Vmax*result.Imax;
    result.Gmax = result.Imax/result.Vmax;
    result.Rmax = result.Vmax/result.Imax;

    return result;
}

int max(const double Voc, const double* I_1, int length)
{
    double V_1 = 0.0;
    double V_1index = 0.0;
    double P_prev = 0.0;
    double P = 0.0;
    int index = 0;
    int i = 0;

    for (i = 0; i < length; i++)
    {
        V_1 = ((double)i)*(Voc/(double)length);
        V_1index = ((double)index)*(Voc/(double)length); 
        P = V_1 * I_1[i];
        if (i > 0)
        {
            if (P < P_prev && P_prev > (V_1index * I_1[index])) 
            {
                index = i - 1;
            }
        }

        P_prev = P;
    }

    return index;
}


void main(void)
{
    //Set clock frequency
    OSCCON |= 0x70;                         //8 Mhz clock, primary clock
    OSCTUNEbits.PLLEN = 1;                  //4x Multiplier, thus we have 32 Mhz clock
    while (!OSCCONbits.IOFS);               //Wait until INTOSC is stable.

    //Enable TRISA as analog input (For ADC)
    TRISA = 0x2F;

    //PIN Outputs
    TRISB = 0;                              //Make PORTD as output
    //PORTBbits.RB0 = 0;

    //Set ADC
    OpenADC(ADC_FOSC_32 &                   //Fosc/32
         ADC_RIGHT_JUST &
         ADC_4_TAD,                         //4xTAD
         ADC_CH0 &
         ADC_REF_VDD_VSS &
         ADC_INT_OFF, ADC_5ANA);            //ADC Initialized

    //Begin
    while (TRUE)
    {
        short_circuit_current = (read_adc(ADC_CH0) - 2.5) * 6 / 0.625;
        //Delay 1 millisecond
        //delay_msec(1);
        open_circuit_voltage = read_adc(ADC_CH1) * 14/3;

        //compute
        result_parallel = compute(open_circuit_voltage * 5.0, short_circuit_current * 2.0);
        result_series = compute(open_circuit_voltage * 10.0, short_circuit_current);
        Rmax = (result_parallel.Pmax > result_series.Pmax) ? result_parallel.Rmax : result_series.Rmax; 

        if (Rmax >= 0 && Rmax <= 21.0)
        {
            switch_port(PORTB, OFF);
            switch_port(PORTBbits.RB3, ON);
            switch_port(PORTBbits.RB5, ON);
        }
        else if (Rmax > 21.0 && Rmax <= 42.0)
        {
            switch_port(PORTB, OFF);
            switch_port(PORTBbits.RB3, ON);
        }
        else
        {
            switch_port(PORTB, OFF);
            switch_port(PORTBbits.RB4, ON);
        }
    }

    CloseADC();                     //Closing ADC
}

Mi problema es que cuando "veo" la variable Rmax (en esta línea Rmax = (result_parallel.Pmax > result_series.Pmax) ? result_parallel.Rmax : result_series.Rmax; ), dice NaN . Intenté establecer la estructura en near pero obtengo un problema de compilación. Lo puse a far pero obtengo el mismo problema de NaN .

Preguntas:

  • ¿Qué me estoy perdiendo?
  • ¿Qué es near , far cuando intento establecerlo en struct ?

Gracias.

Oh, sí, agregué DATABANK y SECTION DATA para la matriz grande, en el enlazador PIC18F4520.

Actualización: veo que la siguiente línea I_1[i] = IL_1 - IO_1 * (exp(Q * V_1/ (NS * N * K * temperature)) - 1.0) - V_1/Rsh; es una "Memoria restringida" (cuando se usa SIM SIM MPLAB). Cuando el cálculo de result para Vmax , obtengo un NaN ya que la división es cero. ¿Qué está causando esto?

    
pregunta Buhake Sindi

2 respuestas

0

Incluso cuando usa un compilador, necesita leer la hoja de datos del PIC. Si recuerdo bien, el compilador C18 considera el banco de acceso NEAR y la memoria almacenada LEJOS. Si una variable se encuentra en la memoria cercana o lejana no debe afectar la lógica del programa, pero acceder a la memoria cercana puede requerir menos ciclos y palabras de instrucción.

Su declaración "Hice una asignación de memoria adicional para udata DATA en el enlazador PIC 18F4520 " no tiene sentido. Primero, el inglés es tan malo que no está claro lo que realmente quieres decir. En segundo lugar, jugar con el archivo enlazador es solo para cuando sabes exactamente lo que estás haciendo. Mágicamente no se puede hacer más memoria mintiendo al enlazador. Eso solo lo hará para que el enlazador no pueda decir que se ha desbordado una región de memoria. El PIC todavía tiene las regiones de memoria que tiene sin importar lo que le digas al vinculador. El archivo de enlace predeterminado debe contener regiones de memoria que cubran toda la memoria útil.

Otro error falso al jugar con el diseño de RAM en el archivo del vinculador es que si deja que una región de memoria cruce un límite del banco, alguna estructura o variable de múltiples bytes puede colocarse a través de ese límite del banco. Si el compilador asume que la estructura está totalmente en un banco, podría producir un código incorrecto para acceder a partes de ella. Hay formas de evitar esto si necesita matrices grandes, pero ese es un concepto avanzado en el que no vale la pena meterse a menos que ese sea realmente su problema.

Además, ¿realmente necesitas punto flotante de precisión doble? A menos que tenga una aplicación muy inusual, la respuesta es no.

    
respondido por el Olin Lathrop
0

Estoy un poco confundido por el motivo por el que vuelves a definir las funciones matemáticas estándar "abs" y "max".

Una función máxima que actúa como la función matemática de la biblioteca estándar de C

Cuando quiero algún tipo de función máxima que actúe como las funciones matemáticas de la biblioteca estándar de C, Utilizo las funciones matemáticas de la biblioteca estándar de C, escribiendo algo como esto:

#include math.h

// ... then much later ...

z = fmax( x, y );
a = fabs( z ) ;

// The above which seems clearer to me than, say,
// z = ( x > y ) ? x : y;
// a = ( a > 0 ) ? a : -a;

Una función máxima que no actúa como la función matemática de la biblioteca estándar de C

Cuando necesito encontrar algún tipo de función máxima que no esté cubierta por la biblioteca matemática estándar de C, escribo una función para hacerlo. Sin embargo, creo que darle a esta nueva función exactamente el mismo nombre que otra función que ya se encuentra en la biblioteca matemática estándar "math.h" C, como "max", está pidiendo problemas, así que invento un nuevo nombre más específico .

    
respondido por el davidcary

Lea otras preguntas en las etiquetas