View previous topic :: View next topic |
Author |
Message |
delifadzli
Joined: 12 Apr 2010 Posts: 27
|
asking for clarification |
Posted: Fri May 07, 2010 10:37 am |
|
|
Here I would to ask for your opinion regarding my code and diagram.
The code is basically PWM controlling speed of dc motor.
compile = no error
Code: |
#include <16F877A.h>
#device ADC=10
#fuses HS,NOWDT,NOPROTECT,PUT,BROWNOUT,NOLVP
#use Delay(clock=20000000)
#include "C:\Users\deli\Desktop\pwx2\brum\Flexlcd2.c"
#define cel20 30
#define cel50 125
#define medium 120
#define slow 25
#define fast 175
main()
{
int16 pwm_duty;
int16 temp_adc;
float temp;
setup_adc(ADC_CLOCK_DIV_8);
setup_adc_ports(PIN_A1);
set_adc_channel(1); //read analog input from channel 1
output_low(PIN_C2); // Set CCP1 output low
setup_ccp1(CCP_PWM); // Configure CCP1 as a PWM
setup_timer_2(T2_DIV_BY_4, 249, 1); // 5khz
set_pwm1_duty(medium); // Set for 50% duty cycle
lcd_init();
lcd_putc("\ftemperature is:\n");
while(1);
{
temp_adc = read_adc();
temp = 5.00*temp_adc*100.00/1023.00;
if ( temp_adc < cel20)
{
temp_adc=slow;
}
if ( ( temp_adc > cel20) & ( temp_adc < cel50) )
{
temp_adc=medium;
}
if ( temp_adc > cel50)
{
temp_adc=fast;
}
set_pwm1_duty(temp_adc); //Change duty cycle and adjust
//delay_ms(100); //Wait for adjusting (Optional and may be left out)
lcd_gotoxy(1,2);
printf(lcd_putc,"%f",temp);
delay_ms(3000);
}
}
|
Isn't true? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19559
|
|
Posted: Fri May 07, 2010 12:08 pm |
|
|
Your duty cycles are wrong.
You have Timer2, counting to 250 (249+1). The PWM, updates _four times_ for each count. So the pwm values run from 0 to 1000. 50% duty cycle will be 500, not 120 - _when the value is stored in an int16_. The compiler looks at the value handed to set_pwm_duty, and if it is an int8, automatically multiplies it by 4 for the set_pwm_duty function. So:
set_pwm_duty(medium);
will basically give just under 50% duty, but:
temp_adc=medium;
set_pwm_duty(temp_adc);
Will give just under 12% duty.
Do the following:
Update your constants, as:
#define medium (500L)
#define slow (100L)
#define fast (700L)
This will force the compiler to treat the numbers as 16bity, no matter what the value.
Best Wishes |
|
|
delifadzli
Joined: 12 Apr 2010 Posts: 27
|
|
Posted: Sat May 08, 2010 12:35 am |
|
|
Thanks for explanation. Can you explain a little bit on how to get 50% duty cycle? I assume 125/249= 0.5 isn't true. Sorry for my weakness.
Then how about cel 20 and cel 50 ...?
Isn't need to replace it? like cel 20 = 250L and cel 50= 600L ?? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19559
|
|
Posted: Sat May 08, 2010 4:41 am |
|
|
The PWM, counts to the value you set for timer2 _plus one_, in '1/4' counts. So with Timer2=249, the PWM accepts values from 0 to 1000. With '1000' being 'fully on' (no pulse, signal fully high), and '0' being 'fully off' (signal fully low). The half way point, is 1000/2 = 500. Pulse on 1/4 time, is 250, etc..
Best Wishes |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19559
|
|
Posted: Sat May 08, 2010 7:26 am |
|
|
Your 'cel' values, are the value you are reading from the ADC, nothing to do with the PWM values.
The values you need here, will; depend on what you are doing with the ADC.
You don't need to use the 'L' designation for these, since nothing you are doing makes any 'distinction' between 8bit integers, and long (16bit) integers.
The point is that the PWM code _does_ make a distinction. If it receives a 'long' integer (a value >255, a value stored in an int16, _or_ a value with 'L' appended), then it uses this value directly. If it receives an 8bit value, then it automatically multiplies it by 4, assuming that you only want to set the top 8 bits of the 10bit PWM value. This is documented in the manual.
Best Wishes |
|
|
delifadzli
Joined: 12 Apr 2010 Posts: 27
|
|
Posted: Sun May 09, 2010 3:20 pm |
|
|
Here is a little improvement that I had managed to compile it without any error...
Code: |
#include <16F877A.h>
#device ADC=10
#fuses HS,NOWDT,NOPROTECT,PUT,BROWNOUT,NOLVP
#use Delay(clock=20000000)
#include "C:\Users\deli\Desktop\pwx2\brum\Flexlcd2.c"
#define medium 500L
#define slow 100L
#define fast 700L
void main(void)
{
int16 temp_adc;
float temp;
int16 pwm_duty;
setup_adc(ADC_CLOCK_DIV_8);
setup_adc_ports(PIN_A1);
set_adc_channel(1); //read analog input from channel 1
output_low(PIN_C2); // Set CCP1 output low
setup_ccp1(CCP_PWM); // Configure CCP1 as a PWM
setup_timer_2(T2_DIV_BY_4, 249, 1); // 5khz
set_pwm1_duty(medium); // Set for 50% duty cycle
lcd_init();
lcd_putc("\ftemperature is:\n");
while(1)
{
temp_adc = read_adc();
temp = 5.00*temp_adc*100.00/1023.00;
lcd_gotoxy(1,2);
printf(lcd_putc,"%f",temp);
delay_ms(3000);
}
{
if ( temp_adc < 58)
{
temp_adc=slow;
}
if ( ( temp_adc > 58) & ( temp_adc < 70) )
{
temp_adc=medium;
}
if ( temp_adc > 70)
{
temp_adc=fast;
}
set_pwm1_duty(temp_adc); //Change duty cycle and adjust
}
}
|
The problem is, when I run it, the LCD does produce the result- actual temperature in Celsius...but the fan doesn't work at all.
Hope for your response.
Here is simple diagram...on how I interface dc motor with the pic.
The motor I used:
http://img.directindustry.com/images_di/photo-g/ac-or-dc-fan-359065.jpg
http://images.elektroda.net/22_1273439913.png |
|
|
delifadzli
Joined: 12 Apr 2010 Posts: 27
|
|
Posted: Sun May 09, 2010 3:21 pm |
|
|
the component 2sj48 i replace it with IRF9540...sorry for that one... |
|
|
delifadzli
Joined: 12 Apr 2010 Posts: 27
|
|
Posted: Mon May 10, 2010 2:37 am |
|
|
anyone?...please help..me...i quite new is this area...actually.....sorry for my weakness |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon May 10, 2010 3:20 am |
|
|
Hint: fix the layout of your code. Now the indentation goes left and right at random.
When you have fixed this, look at where the while-loop ends. Do you think this is correct? |
|
|
delifadzli
Joined: 12 Apr 2010 Posts: 27
|
|
Posted: Mon May 10, 2010 3:33 am |
|
|
#include <16F877A.h>
#device ADC=10
#fuses HS,NOWDT,NOPROTECT,PUT,BROWNOUT,NOLVP
#use Delay(clock=20000000)
#include "C:\Users\deli\Desktop\pwx2\brum\Flexlcd2.c"
#define medium 125L
#define slow 63L
#define fast 240L
void main()
{
int16 temp_adc;
float temp;
int16 pwm_duty;
setup_adc(ADC_CLOCK_DIV_8);
setup_adc_ports(PIN_A1);
set_adc_channel(1); //read analog input from channel 1
output_low(PIN_C2); // Set CCP1 output low
setup_ccp1(CCP_PWM); // Configure CCP1 as a PWM
setup_timer_2(T2_DIV_BY_4, 249, 1); // 5khz
set_pwm1_duty(medium); // Set for 50% duty cycle
lcd_init();
lcd_putc("\ftemperature is:\n");
while(1)
{
temp_adc = read_adc();
temp = 5.00*temp_adc*100.00/1023.00;
lcd_gotoxy(1,2);
printf(lcd_putc,"%f",temp);
delay_ms(3000);
if ( temp_adc < 58)
{
temp_adc=slow;
}
if ( ( temp_adc > 58) & ( temp_adc < 70) )
{
temp_adc=medium;
}
if ( temp_adc > 70)
{
temp_adc=fast;
}
set_pwm1_duty(temp_adc); //Change duty cycle and adjust
}
like this?
i truly sorry if i'm wrong...i'm still newbie.... |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon May 10, 2010 3:59 am |
|
|
Use the 'code' buttons when posting code. Now it is very difficult to read.
More or less. Does it work?
I Think you created a compile error, or the last line of your program got lost during copy/paste. |
|
|
delifadzli
Joined: 12 Apr 2010 Posts: 27
|
|
Posted: Mon May 10, 2010 5:14 am |
|
|
Code: | #include <16F877A.h>
#device ADC=10
#fuses HS,NOWDT,NOPROTECT,PUT,BROWNOUT,NOLVP
#use Delay(clock=20000000)
#include "C:\Users\deli\Desktop\pwx2\brum\Flexlcd2.c"
#define medium 125L
#define slow 63L
#define fast 240L
void main()
{
int16 temp_adc;
float temp;
int16 pwm_duty;
setup_adc(ADC_CLOCK_DIV_8);
setup_adc_ports(PIN_A1);
set_adc_channel(1); //read analog input from channel 1
output_low(PIN_C2); // Set CCP1 output low
setup_ccp1(CCP_PWM); // Configure CCP1 as a PWM
setup_timer_2(T2_DIV_BY_4, 249, 1); // 5khz
set_pwm1_duty(medium); // Set for 50% duty cycle
lcd_init();
lcd_putc("\ftemperature is:\n");
while(1)
{
temp_adc = read_adc();
temp = 5.00*temp_adc*100.00/1023.00;
lcd_gotoxy(1,2);
printf(lcd_putc,"%f",temp);
delay_ms(3000);
if ( temp_adc < 58)
{
temp_adc=slow;
}
if ( ( temp_adc > 58) & ( temp_adc < 70) )
{
temp_adc=medium;
}
if ( temp_adc > 70)
{
temp_adc=fast;
}
set_pwm1_duty(temp_adc); //Change duty cycle and adjust
}
|
here is the code...compile without error...but still the fan doesn't work... |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon May 10, 2010 5:56 am |
|
|
Code: | if ( ( temp_adc > 58) & ( temp_adc < 70) ) | Change '&' to '&&'.
A single '&' means 'binary AND'
A double '&&' means 'logical AND'
You also have to change the '> 58' to '>= 58' because the other test is testing '< 58' and your code is doing nothing when temp_adc == 58.
Same for testing '70'.
Your code will be easier to read and faster to execute if you code it like: Code: | if (temp_adc < 58)
{
temp_adc = slow;
}
else if ( (temp_adc >= 58) && (temp_adc < 70) )
{
temp_adc = medium;
}
else
temp_adc = fast;
|
|
|
|
|