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 enstruct
?
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?