|
|
View previous topic :: View next topic |
Author |
Message |
mcmsat
Joined: 25 May 2018 Posts: 51 Location: Nigeria
|
NTC FAN Controller With PIC16F690 |
Posted: Mon Apr 15, 2019 7:47 am |
|
|
Hello All!
As a beginner in Embedded System, I got hooked in an experiment with PIC16F690 PWM.
I wrote a code to see how it will work on hardware, controlling an ATX 12V Fan and Battery Level control. Then while testing it, I noticed that the CCP1 PWM signal does not show correctly on my digital multi-meter. Though the fan seems to be working according to the code but I don't know why the signal can't show correctly on my meter. While testing it, I tried many many PWM control ICs and even some astable 555 circuits and they all show their duty cycle correctly on the same meter but still the 16F690 PWM signal refuse to show correctly. It only show between 98% to 100% no matter the status of the system.
The fan suppose to change speed according to the temperature of the 10K NTC. There are three preset points and they all work with the NTC and the fan speed.
Please can someone notice if there are things written wrongly in my code?
Code: |
#include <16F690.h>
#device ADC = 10
#FUSES NOWDT, INTRC_IO, PUT, NOPROTECT, NOMCLR, NOCPD, NOBROWNOUT,NOIESO, FCMEN,
#use delay(clock = 8000000)
#define HIGH_START 0xFF -250 //500us INT_RTCC
#define LVD PIN_C1
#define HVD PIN_C3
int DL2_2s,DL2_3s,DL1_5s,DL2_5s, DL1_10s,DL_11s,
SDL2_2s,SDL2_3s,SDL1_5s,SDL2_5s,SDL1_10s,SDL_11s;
long BS,NTC,CDL2_3s,CDL1_5s,CDL2_5s,CDL1_10s,CDL_11s;
void init() // Hardware initialization
{
setup_adc(ADC_CLOCK_INTERNAL); // 8Tosc ADC conversion time
setup_adc(ADC_CLOCK_DIV_8); // Set ADC conversion time to 8Tosc
setup_adc_ports(sAN3 | sAN10); // Select Analog Inputs
setup_comparator(NC_NC_NC_NC); // disable comparator module
setup_ccp1(CCP_PWM); // Configure CCP1 as standard PWM
setup_timer_2(T2_DIV_BY_16,255,1); // Set PWM frequency to 489Hz
delay_ms(10); // Wait 10ms
SDL2_2s=false;
SDL2_3s=false;
SDL1_5s=false;
SDL2_5s=false;
SDL1_10s=false;
SDL_11s=false;
DL2_2s=false;
DL2_2s=false;
DL2_3s=false;
DL2_5s=false;
DL1_10s=false;
DL_11s=false;
set_rtcc(HIGH_START);
setup_counters(RTCC_INTERNAL, RTCC_DIV_4);
enable_interrupts(INT_RTCC);
enable_interrupts(global);
}
// the timer is incremented (8000000/4)/4 or 500000 times a sond (2 us).
// 250 x 2us = 500us
#INT_RTCC
void clock_isr()
{
set_rtcc(HIGH_START);
//if (input(TestPin))
// Start Delay///////////////////////////////////////////////////////////
{
if (SDL2_3s)
{
if (++CDL2_3s>=(3000*2))
{
SDL2_3s=false;
DL2_3s=true;
}
}
else CDL2_3s=0;
if (SDL1_5s)
{
if (++CDL1_5s>=(5000*2))
{
SDL1_5s=false;
DL1_5s=true;
}
}
else CDL1_5s=0;
if (SDL2_5s)
{
if (++CDL2_5s>=(5000*2))
{
SDL2_5s=false;
DL2_5s=true;
}
}
else CDL2_5s=0;
if (SDL1_10s)
{
if (++CDL1_10s>=(10000*2))
{
SDL1_10s=false;
DL1_10s=true;
}
}
else CDL1_10s=0;
if (SDL_11s)
{
if (++CDL_11s>=(11000*2))
{
SDL_11s=false;
DL_11s=true;
}
}
else CDL_11s=0;
}
}
void main (void)
{
init(); // Configure peripherals/hardware
while(1)
{
////HVD&LVD SETTINGS/////HVD&LVD SETTINGS///////HVD&LVD SETTINGS///////
{
set_adc_channel(10); // Select channel AN10
delay_ms(1); // Wait 1ms
BS = read_adc(); // Read from AN10 and store in BS
delay_ms(1); // Wait 1ms
if(BS >= 295)// (1.44V) (33V) // Battery High
{
SDL2_3s=true; // Delay 3s before activation
if(DL2_3s)
{
output_high (HVD);
DL2_3s=false;
}
}
else SDL2_3s=false;
if(BS <=241) // (1.18V) 27V
//if(BS <=250) // (1.22V) 28V // Battery high Recovery
{
SDL2_5s=true; // Delay 5s before deactivation
if(DL2_5s)
{
output_low(HVD);
DL2_5s=false;
}
}
else SDL2_5s=false;
if(BS <= 189) //(0.924V) 21V // Battery Low
{
SDL1_10s=true; // Delay 10s before activation
if(DL1_10s)
{
output_high (LVD);
DL1_10s=false;
}
}
else SDL1_10s=false;
if(BS <= 176) //(0.859V) 19.5V // Battery Too Low
{
SDL1_5s=true; // Delay 5s before activation
if(DL1_5s)
{
output_high (LVD);
DL1_5s=false;
}
}
else SDL1_5s=false;
if(BS <= 158) //(0.770V) 17.5V // Battery Terribly Low
{
SDL2_2s=true; // Delay 2s before activation
if(DL2_2s)
{
output_high (LVD);
DL2_2s=false;
}
}
else SDL2_2s=false;
if(BS >=241) // (1.18V) 27V // Battery low Recovery
{
SDL_11s=true; // Delay 11s before deactivation
if(DL_11s)
{
output_low(LVD);
DL_11s=false;
}
}
else SDL_11s=false;
}
//////NTC10K FAN Control//////NTC10K FAN Control//////NTC10K FAN Control///////
{
set_adc_channel(3); // Select channel AN3
delay_ms(1); // Wait 1ms
NTC = read_adc(); // Read from AN3 and store in NTC
delay_ms(1); // Wait 1ms
if (NTC <= 593) //2.9V NTC Sense Voltage
{
set_pwm1_duty(128);//50%
}
if (NTC >= 614 && NTC <=675) //>=3V && <=3.3VNTC Sense Voltage
{
set_pwm1_duty(204);//80%
}
if (NTC >= 675)////3.3V NTC Sense Voltage
{
set_pwm1_duty(255);//100%
}
}
//*****************************************************************************
}
} |
I have tried changing the Duty as 10-bit value and to my surprise, it still work the same!
I don't understand why it worked as below:
"
Code: | if (NTC <= 593) //2.9V NTC Sense Voltage
{
set_pwm1_duty(512);//50%
}
if (NTC >= 614 && NTC <=809) //>=3V && <=3.3VNTC Sense Voltage
{
set_pwm1_duty(204);//80%
}
if (NTC >= 675)////3.3V NTC Sense Voltage
{
set_pwm1_duty(1024);//100%
} |
_________________ All is well even in the well!
Last edited by mcmsat on Mon Apr 15, 2019 9:05 am; edited 1 time in total |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Apr 15, 2019 8:41 am |
|
|
The comment is wrong:
Quote: | setup_timer_2(T2_DIV_BY_16, 255, 1); // Set PWM frequency to 7800Hz
|
The PWM frequency formula is:
Code: |
Crystal Frequency
PWM Freq = -------------------------------------
(PR2 + 1) * (Timer2 Prescaler) * 4
|
This gives:
Code: |
8000000
PWM freq = --------------------
(255 +1) * 16 * 4
|
That reduces to:
Code: |
8000000
PWM freq = --------- = 488.28125 Hz
16384
|
My advice is to get rid of all your control code and make a test program
that tests PWM only. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19590
|
|
Posted: Mon Apr 15, 2019 12:56 pm |
|
|
and the change to 10bit value, is explained by how the pwm_duty
behaves. It is an overloaded function.
If the value given is 8bit, it is effectively multiplied by 4, and fed to the
PWM hardware. If it is a 16bit value, it is fed directly to the hardware.
So:
set_pwm1_duty(128);
gives exactly the same result as:
set_pwm1_duty(512);
The way to make them behave differently is to force the number size
set_pwm1_duty(128L);
will give a 12.5% duty.
As PCM_programmer says, simplify. Just experiment with the PWM
only first. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9271 Location: Greensville,Ontario
|
|
Posted: Mon Apr 15, 2019 7:07 pm |
|
|
Aonther point to consider...with respect to the ADC clock choice...
From the datasheet of your PIC..
"When the device frequency is greater than 1 MHz, the FRC clock source is only recommended if the
conversion will be performed during Sleep."
With an 8MHz system clock, you've got 2 choices for the ADC clock. Which one you choose, is up to you to decide, based upon performance. Check table 9-1,page 109
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19590
|
|
Posted: Tue Apr 16, 2019 11:21 am |
|
|
In fact he is selecting the standard clock, not the FRC clock, but
'by accident'.
On the following lines:
Code: |
setup_adc(ADC_CLOCK_INTERNAL); // 8Tosc ADC conversion time
setup_adc(ADC_CLOCK_DIV_8); // Set ADC conversion time to 8Tosc
|
Only the second is actually used.
Setup_adc lines can't be used 'successively'. Only the second line will
actually be applied, so the RC clock isn't actually being used.... |
|
|
mcmsat
Joined: 25 May 2018 Posts: 51 Location: Nigeria
|
Re: NTC FAN Controller With PIC16F690 |
Posted: Tue Apr 23, 2019 3:38 am |
|
|
Can I finally reply to this post? _________________ All is well even in the well! |
|
|
mcmsat
Joined: 25 May 2018 Posts: 51 Location: Nigeria
|
Re: NTC FAN Controller With PIC16F690 |
Posted: Tue Apr 23, 2019 3:50 am |
|
|
Ttelmah wrote: | In fact he is selecting the standard clock, not the FRC clock, but
'by accident'.
On the following lines:
Code: |
setup_adc(ADC_CLOCK_INTERNAL); // 8Tosc ADC conversion time
setup_adc(ADC_CLOCK_DIV_8); // Set ADC conversion time to 8Tosc
|
Only the second is actually used.
Setup_adc lines can't be used 'successively'. Only the second line will
actually be applied, so the RC clock isn't actually being used.... |
That was a mistake. It is like the code I posted was the raw raw code.
I actually used only "setup_adc(ADC_CLOCK_DIV_8); // Set ADC conversion time to 8Tosc" _________________ All is well even in the well! |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|