Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Pic18f4520 pwm

Status
Not open for further replies.
yeah, but then again I don't know why my code only works with Hitech's C18 or XC8 and not MPLAB's C18

Because they ARE different compilers..... BUT!! they do both spout ANSI compatibility so modifying the code should be easy to do...
 
I will try it out later, but you know I'm still going to ask you for the code you used :) thanks for all your help. Everyone here's been great.
 
I've run into another little issue. The below code works fine until I go below 80 or over 97 limits on the second if statement. Basically what I want is the PWM output to be set to 0 when not within the range, but the problem is if I go over 97 for example the PWM does drop to 0, but then when returning back to below 97 the PWM stays at 0 and doesn't return to normal operation.

Code:
if (TempFi > 15 && TempFi < 115) //to make sure the thermistor is reaading something
{
    if (TempFi >= 80 && TempFi <= 97)
    {
    Duty_cycle = (int)(5.0*TempF - 390.0); //Uses the y = mx + b equation.
    }
       else
           {
           Duty_cycle = 0;
           }
}
 
THe 18F4431

I know this is not a direct reply to your question.

The 18F4431 is a micro with an special peripheric (power control module) able to produce a PWM otput even lower than 50 Hz

If you compare that module with the common PWM of 18F family, you will see that the first has an additional scaler allowing to reach your 50 Hz (and even less, as I said, maybe 38 Hz from the top of my head).

If you like to understand this once for all, just check how the period is calculated in the PWM module and how it is in the power control module.

Additional comments (not an attempt to derail the thread):

The 18F4431 served well other than controlling motors, i. e. source of clocks for an LMF100 filter and many more.

Pity is that even in the 18F4431 all PWM signals use the same clock so their frequency is the same.
 
Last edited:
Thanks for the recomendations ferrari. Below is the full code of what I'm trying to do as I explained abode. The below code works fine, but when I go off the high or low limits in the
Code:
if (TempFi >= 80 && TempFi <= 97)
I'm trying to turn off the PWM, but it's not working properly, and when returning back to normal operation within the range the fan doesn't turn on.

Code:
#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;
}
 
Sorry but I am not C conversant.
 
Ok... I checked it out ( I had to use my own LCD libraries as yours weren't available..)

When the temp goes above 97 degrees the PWM goes to 0 When it goes below 80 degrees the PWM goes to 0

Both directions up and down work for me...
 
something must be wrong with mine then, because when I go below 80 the pwm does go to 0, but if I trying to return above 80 the pwm never turns back on :(
 
Status
Not open for further replies.

Latest threads

Back
Top