#include <p18f4520.h>
#include <delays.h>
#include <stdio.h>
#include <math.h>
#include "XLCD/xlcd.h"
#pragma config OSC = INTIO67 //Use internal Oscillator
#pragma config WDT = OFF //Watchdog timer off
#pragma config LVP = OFF //Low voltage ICSP disabled
#pragma config BOREN = OFF //Brown-out reset disabled
#pragma config PBADEN = OFF //Port B A/D digital on reset
void ccpisr_hand(void);
void ReadTemp (void);
void ADCInit(void);
int ADCRead (unsigned char ch);
float PID_Control(float set_point, float measured_value);
#define PWM1_OUT LATCbits.LATC2
#define PWM1_DIR TRISCbits.TRISC2
#define PWM2_OUT LATCbits.LATC1
#define PWM2_DIR TRISCbits.TRISC1
volatile int temp;
volatile char Duty_cycle;
float temp_error;
#pragma code ccpisr_int = 0x08
void ccp_int (void)
{
_asm GOTO ccpisr_hand _endasm
}
#pragma code
#pragma interrupt ccpisr_hand
void ccpisr_hand()
{
if(PIR1bits.CCP1IF == 1)
if(PWM1_OUT == 1) //Will be 1 if we are at end of pulse
{
PWM1_OUT = 0;
CCPR1 = 5000 - temp; //Off time
}
else
{
temp = 50 * (int) Duty_cycle;
PWM1_OUT = 1;
CCPR1 = temp; //On time
}
if(Duty_cycle == 0)
{
PWM1_OUT = 0;
}
if(Duty_cycle == 100)
{
PWM1_OUT = 1;
}
PIR1bits.CCP1IF = 0; //Clear int flag
return;
}
#pragma code
void main()
{
OSCCON = 0xF2; //Osc = 8MHz
while(!OSCCONbits.IOFS); //Wait for OSC to stabilize
PWM1_DIR = 0; //Make bit 0 output
PWM1_OUT = 0; //Output off
T1CON = 0b10110001; //Timer 1 on with Pre = 8
PIR1bits.TMR1IF = 0; //Clear the interrupt flag
CCP1CONbits.CCP1M = 0b1011; //Special event trigger
RCONbits.IPEN = 0; //Dissable interrupt priority
INTCONbits.GIE = 1; //Enable glogal interrupts
INTCONbits.PEIE = 1; //Enable peripheral interrupts
PIE1bits.CCP1IE = 1; //Enable CCP1 interrupt
CCPR1 = 2500; //Set CCP initial value
PWM1_OUT = 1; //Turn on output
ADCInit(); //Initialize the ADC
XLCDInit(); //Initialize the LCD display
XLCDClear(); //Clear the LCD display
while(1)
{
ReadTemp();
}
}
void ReadTemp (void)
{
const float coeffA = 1.12503e-3;
const float coeffB = 2.35058e-4;
const float coeffC = 7.85661e-8;
int TempCi, TempFi;
char line[16]; //16row LCD Disp
float Rt, TempC, TempF, ADCVal, logRt, logRt3;
ADCVal = (float)ADCRead(7);
//10000 is the value of resistor used in divider circuit with thermistor, but
//in place I'm using a 20K Potentiometer to calibrate the temperature.
Rt = (1024.0/(ADCVal)-1)*10000.0;
logRt = log(Rt);
logRt3 = (exp(logRt),3);
//Steinhart-Hart Thermistor equation
TempC = (1/(coeffA + coeffB * logRt + coeffC * logRt3)) -273.15;
TempF = (TempC * 1.8) + 32; //Convert Celcius to Farenheit.
XLCDL1home();
XLCDPutRomString(" TEMP :: ");
TempCi = (int)TempC;
TempFi = (int)TempF;
if (TempFi > 15 && TempFi < 115) //to make sure the thermistor is reaading something
{
sprintf(line,"%d",TempFi);
XLCDPutRamString(line);
XLCDPut(223); //Send degree symbol
XLCDPut('F');
XLCDPutRomString(" ");
if (TempFi >= 80 && TempFi <= 97)
{
XLCDL2home();
XLCDPutRomString(" PWM: ");
Duty_cycle = (int)(5.0*TempF - 390.0); //Uses the y = mx + b equation.
sprintf(line," %d", (int)Duty_cycle);
XLCDPutRamString(line);
XLCDPutRomString(" ");
}
else
{
Duty_cycle = 0;
}
}
else
{
XLCDPutRomString("ERR"); //Temp out of range.
Duty_cycle = 0;
}
}
void ADCInit(void)
{
/*
* ADCON1 Settings:
* VREF- source = Vss
* VREF+ source = Vdd
*/
ADCON1 = 0b00001111; //Initialize all pins as Digital Inputs.
/*
* Configuring Tad (ADC Clock) [ADCON2:ADCS]
* Fosc = 8MHz
* Tosc = (1 / 8Mhz) = (Tcy / 4) = 125nS
* Tad = 16 * Tosc = 2uS
*
* Configuring Aquisition Time [ADCON2:ACQT]
* ACQT = Tad * 2
* = 2uS * 2 = 4uS
*ADCON2 Settings:
*ADC Result Right Justified.
*Acquisition Time = 2 * TAD
*Conversion Clock = Fosc / 16
*/
ADCON2 = 0b10001101;
}
int ADCRead (unsigned char ch)
{
int ADC_Val;
ADCON1 = 0b00000000; //Set all pins as analog inputs.
ADCON0 = (ch << 2);
ADCON0bits.ADON = 1; //Enable ADC Module
ADCON0bits.GO_DONE = 1; //Stard ADC Conversion
while(ADCON0bits.GO_DONE); //Wait for convertion fo complete
ADC_Val = ADRES; //Read ADC value
ADCON0bits.ADON = 0; //Disable ADC Module
ADCON1 = 0b00001111; //Set all pins back to digital inputs.
return ADC_Val;
}