Tuesday, October 29, 2013

Setting PWM to control speed fan

By using the L298 as a PWM driver to control the voltage on the motor or speed fan.

The PIC16F877A PWM Module:
16F877a includes two PWM modules included in the CCP1,CCP2 modules (CCP stands for Capture-Compare-PWM), and there are 3 steps for using those modules:

  1. Set the desired CCP module to PWM mode.
  2. Setup The TIMER2 module, which controls the frequency and the base of your PWM signal.
  3. Set your duty cycle, rely on the equations below to select it properly.
We'll be using CCS PIC-C compiler to explain those steps, if you have a question on using other compilers to set it, post a comment.
To set The CCP1 module to PWM mode, we'll use the code line:
setup_ccp1(CCP_PWM);
 and the first step is done.
Now setting up Timer2 module using PIC-C is a bit easy, use the code line: setup_timer_2(divider,preload,postscalar).
the divider and the preload values determines the frequency of the PWM signal by the following function:
Signal Frequency = (Crystal/4) / (divider * (preload+1))
The divider takes the values : T2_DIV_BY_1, T2_DIV_BY_4, T2_DIV_BY_16.
the preload is 8Bits and takes the values 0-255
So let us say we have 4MHz crystal and we set Timer2 like this:
setup_timer_2( T2_DIV_BY_1, 255, 1);
thus, our signal frequency is (4MHz/1)/(4 * 256) =  3.9KHz

Now the final step is to set your duty cycle using the function: set_pwm1_duty(duty_parameter);
to get the duty_parameter of your desired duty cycle, note the following:
the maximum value of duty_paramter (MAX) = ((preload+1)*4) -1
so in our case the maximum value is ((255+1)*4)-1 = 1023 and it represents a 100% duty cycle.
now if we need a duty cycle of 50% it would be 1023*0.5 = 512, and a duty cycle of 25% would be 1023*0.25 = 256, thus,

set_pwm1_duty(1023L); ---> 100% duty (Full Speed)
set_pwm1_duty(512L);  ----> 50% duty
set_pwm1_duty(256L);  ----> 25% duty
set_pwm1_duty(0);        ----> 0% duty (OFF)



So this is the program to control the PWM driver, from the value of the temperature it will convert the value to the PWM driver

#include <16f877a.h>
#device adc=10    // Set ADC resolution to 10Bit
#fuses XT,NOLVP,NOWDT,NOPROTECT
#use delay(clock=4000000)


#include "LCD.c"
#define LCD_DB4   PIN_D4
#define LCD_DB5   PIN_D5
#define LCD_DB6   PIN_D6
#define LCD_DB7   PIN_D7

#define LCD_E     PIN_D0
#define LCD_RS    PIN_D1
#define LCD_RW    PIN_D2
#define Wire1     PIN_B6

#define  LOAD1  PIN_B5
#define  LOAD3  PIN_B7

#define  THRES1 28.0     // load switching threshold in Celsius
#define  THRES2 36.0     // load switching in Celcius
#define  THRES3 42.0     // load switching in Celcius



int16 digital_reading,duty_cycle=1023;  // ADC resolution is 10Bit, an 8Bit integer is not enough to hold the reading
float temp;

void main()
{
   /* ADC Initialization */
   setup_adc(ADC_CLOCK_INTERNAL); // initialize ADC with a sampling rate of Crystal/4 MHz
   setup_adc_ports(RA0_ANALOG);   // set PIN_A0 as analog input channel
   set_adc_channel(0);            // point ADC to channel 0 for ADC reading
   delay_ms(1);                   // ADC module is slow, needs some time to adjust.
   
   /* Peripherals Configurations */
   lcd_init();                   // Turn LCD ON, along with other initialization commands
   output_low(LOAD1);             // the load is initially OFF
   lcd_gotoxy(1,1);              // point LCD cursor to col1 row1
   lcd_putc("Temperature is:");  // print on LCD
  
    /* PWM Configurations */
   setup_timer_2(T2_DIV_BY_1,255,1); // Set PWM frequency
   setup_ccp1(CCP_PWM); // Configure CCP1 to PWM mode
   set_pwm1_duty(1023L); // default duty cycle = 100% (Full Speed)
  
  
   while(1) // infinite loop
   {
      digital_reading = read_adc();    // capture current temperature reading
      delay_us(100);                   // 0.1ms delay for ADC stabilization
      temp = digital_reading * 0.4883; // convert reading to Celsius
      lcd_gotoxy(1,2);                 // point LCD cursor to col1 row2
      printf(lcd_putc,"%2.1f C",temp); // print value on LCD
    
      
        
      
         if((temp>=THRES1)&&(temp<THRES2));
            {
               output_toggle(Wire1);
               duty_cycle=437.5; // increase the duty cycle(70%)
               set_pwm1_duty(duty_cycle); // set the duty cycle
            }
        
        
         if ((temp>=THRES2)&&(temp<=THRES3));
            {
               output_toggle(Wire1);
               duty_cycle=531.25; // increase the duty cycle(850%)
               set_pwm1_duty(duty_cycle); // set the duty cycle
            } 
        
        
         if (temp>THRES3);
            {
               output_toggle(Wire1);
               duty_cycle=625; // increase the duty cycle(100%)
               set_pwm1_duty(duty_cycle); // set the duty cycle
            }  
              
         delay_ms(100);
        
           // 1 second delay between readings
          
        
   }



however my program cant work because it cant match to the PWM program.

 

Monday, October 7, 2013

Completed Circuit for my project

So this is the circuit that i use PROTEUS (ISIS) to assemble my completed circuit.

There have 3 main source to control the level of speed fan depend on the temperature, here is the statement for the temperature and voltage to the speed fan.

1. when temperature is 28C ~ 35C = 5volt to the speed fan
2. when temperature is 36C ~ 42C = 9volt to the speed fan
3 when temperature is more than 42 = 12volt to the speed fan