View previous topic :: View next topic |
Author |
Message |
shan1923
Joined: 12 Oct 2015 Posts: 8
|
Read RS232, Read ADC, PWM output |
Posted: Mon Oct 12, 2015 3:07 am |
|
|
Guys please help me!
I'm stuck in a loop, Embarrassed plz help me!
First I'll tell my program briefly.
* I want to control the brightness of LED. (Day and Night mode) through POT
* I'll receive HEX value through RS232.
- if I receive 0x30, it is night mode. so LED brightness should be 0-50%. POT minimum is 0 and max is 50%.
- if I receive 0x39, it is Day mode. so LED brightness should be 50%-100%. POT minimum is 50% and max is 100%.
* I have done these things through PWM.
My problem is, if I'm receiving the date and it is true, I'm stuck into the loop and I'm not able to come back and check the rs232 data again so I'm not able to change the mode.
NOTE: DATA RECEIVED THROUGH RS232 is not continuous. USER DEPENDENT.
Code: |
#include <16f877A.h>
#device adc=8
#fuses HS,NOLVP,NOWDT
#use delay (clock=20000000)
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7)
unsigned int value;
void main()
{
unsigned int pwm1;
setup_adc(ADC_CLOCK_DIV_32); // Enable the A/D and use the internal clock
setup_port_a(AN0);
setup_ccp1(CCP_PWM);
setup_timer_2(T2_DIV_BY_4, 254, 1);
set_adc_channel(0);
while(1)
{
value=getc();
if(value==0x30)
{
while(1)
{
pwm1 = read_adc();
delay_ms(20);
set_pwm1_duty((pwm1/2)); // night 0 to 2.5 v
}
}
if(value==0x39)
{
while(1)
{
pwm1 = read_adc();
delay_ms(20);
if(pwm1>=128)
set_pwm1_duty(pwm1);
else
set_pwm1_duty(128);
}
}
}
}
|
Plz help me. Urgent requirement. My friend told me to put in a interrupt but I don't know how to make it. I'm new to this.
_________________
+1923+ _________________ +1923+
Last edited by shan1923 on Mon Oct 12, 2015 4:28 am; edited 2 times in total |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
Re: READ RS232, READ ADC, PWM OUTPUT. |
Posted: Mon Oct 12, 2015 3:31 am |
|
|
Use the code button - it is there so we can read your code easily.
You need to sit back and think this through. There are multiple problems.
Problem 1:
You perform a getc() at the start of your main loop. This may be intended but of course if there is no character in the uart receive buffer then the code is stuck inside this loop until a character is received. Perhaps this was your intention.
Problem 2:
You have several instance in your code of:
Code: | while (1) {
...
...
} |
You would typically expect to see this construct used only once. In the mainline code, once you have initialised the application and want to repeat continuously the main execution loop.
There are exceptions, you could for example use break (you haven't) in order to break out of a while loop.
Lets say for example the value you read was 0x30. You pass into another while (1) loop with no way to break out of this. So the PIC stays in this endless loop.
Problem 3:
(Same as problem 2) if the value read was 0x39 you will enter an endless loop.
Perhaps you should draw out a flow chart - then you would get a better understanding of what you have coded versus what you thought you were coding. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
Last edited by asmallri on Mon Oct 12, 2015 4:16 am; edited 1 time in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Mon Oct 12, 2015 4:08 am |
|
|
Lets make another couple of comments.
The internal serial buffer, is just two characters. At 9600bps, you can receive 19 characters in 20mSec. Though you say the input is 'USER DEPENDENT', if multiple characters did come in the delays, this would hang the UART.
Either ensure the UART will not be hung (Look at what the keyword 'ERRORS' does in #use RS232), or use software serial buffering (either using the version built in to #use rs232 now, or ex_sisr.c).
Asmallri has pointed out the other big killer. |
|
|
shan1923
Joined: 12 Oct 2015 Posts: 8
|
|
Posted: Mon Oct 12, 2015 4:18 am |
|
|
thank u asmallri for your reply.
" PROBLEM 1: " - My intention is to wait until the data receive through RS232.
NOTE: I ll receive data from subsystem for every 30ms. so no problem for me.
" PROBLEM 2:" - I ll get 0x30 or 0x39 only once when the user press button.
also if i wont put while loop, i cant read ADC value continuously and i fail to update the PWM value when user rotate the POT.
NOTE: if i put break; I'll come out form the loop and i have to wait for 0x30 or 0x39 to update the PWM value
_________________ +1923+ |
|
|
shan1923
Joined: 12 Oct 2015 Posts: 8
|
|
Posted: Mon Oct 12, 2015 4:24 am |
|
|
thanks for your valuable comment Ttelmah. I ll consider it. _________________ +1923+ |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Mon Oct 12, 2015 5:06 am |
|
|
You are missing the point slightly. Waiting for the data is one thing, never exiting a loop is another. Once one character is seen, it's never going to leave it's loop....
Remember the PWM _keeps_ generating it's output. It doesn't matter if you leave the loop. |
|
|
shan1923
Joined: 12 Oct 2015 Posts: 8
|
|
Posted: Mon Oct 12, 2015 5:45 am |
|
|
@ Ttelmah. what I have to do now?
continuously I have to read ADC value and check the RS-232. this is my condition. should I change the conditions?
I have no clue to make it out. if you have any sample program plz give me or else plz correct my program and revert it back. I ll be thank full _________________ +1923+ |
|
|
ezflyr
Joined: 25 Oct 2010 Posts: 1019 Location: Tewksbury, MA
|
|
Posted: Mon Oct 12, 2015 8:03 am |
|
|
Hi shan1923,
This is a "help you" forum, NOT a "do it for you" forum. With that in mind, you should make the following changes to YOUR program, and see what happens:
1. Add the 'Errors' keyword to the #use rs232 directive. See the CCS manual entry for the #use rs232 directive if you don't know what this means.
2. Get rid of the two inner 'while(1)' loops. Inside the remaining while(1) loop, check for a character, read the A/D, and then do your evaluation of 'Value' with an 'If' statement. As was already pointed out, you don't need to do this continuously - once the PWM is set, it will run continuously.
3. In Main(), above the 'while(1)', set the PWM to some default value. This will set the PWM to *something* before the first command is received.
BTW, is this a *real* hardware project, or a Proteus simulation? _________________ John
If it's worth doing, it's worth doing in real hardware! |
|
|
shan1923
Joined: 12 Oct 2015 Posts: 8
|
|
Posted: Tue Oct 13, 2015 12:09 am |
|
|
@ezflyr. it is a real hardware project but right now im checking it in Proteus simulation.
I have checked what you said. still the same issue.
Code: |
while(1)
{
pwm1 = read_adc();
delay_ms(20);
}
set_pwm1_duty(pwm1); |
my pwm is not updating when the adc value change. _________________ +1923+ |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Tue Oct 13, 2015 12:27 am |
|
|
Of course it wouldn't.
You are sitting reading the ADC forever. Nothing else.
I really think you need to get a basic 'C' primer, and spend some time learning the language. |
|
|
shan1923
Joined: 12 Oct 2015 Posts: 8
|
|
Posted: Wed Oct 14, 2015 1:26 am |
|
|
thanks guys! finally I got it with all your help.
in simulation it is working fine but in simulation log it is showing " simulation is not running in real time due to excessive cpu load"
so have to check in real hardware.
Code: |
#include <16f877A.h>
#device adc=8
#fuses HS,NOLVP,NOWDT
#use delay (clock=20000000)
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7,errors)
void main()
{
unsigned int day, night;
unsigned int value;
unsigned char pwm1;
setup_adc(ADC_CLOCK_DIV_32);
setup_port_a(AN0);
setup_timer_2(T2_DIV_BY_4, 254, 1);
set_adc_channel(0);
setup_ccp1(CCP_PWM);
pwm1=200;
while(1)
{
if(kbhit())
{
value=getc();
if(value==0x30)
{night=1;day=0;}
if(value==0x39)
{day=1;night=0;}
}
if(night==1) // rs232-night
{
pwm1 = read_adc();
delay_ms(10);
set_pwm1_duty((pwm1/2)); // night 0 to 2.5 v
}
if(day==1) // rs232 -day
{
pwm1 = read_adc();
delay_ms(10);
if(pwm1>=128) // day 2.5 to 5v
set_pwm1_duty(pwm1);
else
set_pwm1_duty(0x80);
}
}
} |
_________________ +1923+ |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Wed Oct 14, 2015 2:10 am |
|
|
That is the CPU load in the PC.
It can't keep up with what the PIC is doing.
Why have two variables for night and day?.
Think about it the code is _either_ in 'night' mode, _or_ in 'day' mode.
Code: |
#define NIGHT 1
#define DAY 0
int1 time_of_day = DAY;
while(1)
{
delay_ms(10); //only one delay needed to slow the loop a little
if(kbhit())
{
value=getc();
if(value==0x30)
time_of_day=NIGHT;
if(value==0x39)
time_of_day=DAY;
}
if(time_of_day==NIGHT) // rs232-night
{
pwm1 = read_adc();
set_pwm1_duty((pwm1/2)); // night 0 to 2.5 v
}
else
{
pwm1 = read_adc();
if (pwm1>=128) // day 2.5 to 5v
set_pwm1_duty(pwm1);
else
set_pwm1_duty(0x80);
}
}
|
There is also something 'odd' about your PWM values.
You are sending 128 maximum to the PWM. This will give you just fractionally over 50% duty cycle. This is not '5v'. |
|
|
shan1923
Joined: 12 Oct 2015 Posts: 8
|
|
Posted: Wed Oct 14, 2015 4:09 am |
|
|
Thank you for your code Ttelmah
I'm planning to control FET base with the help of PWM Pulse. I think I'll do it.
I have a doubt in one statement. plz clear me
Code: | set_pwm1_duty(0x80); |
Why I should not put 128? _________________ +1923+ |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Wed Oct 14, 2015 7:54 am |
|
|
No reason at all.
The point is that you lose the whole bottom half of your pot travel.
Currently you will turn the pot through the bottom half of it's travel, and the PWM will stay at 128. Then only on the top half of it's travel will the output PWM start to change.
So instead of getting 2.5 to 5v for the entire pot travel, you get 2.5......2.5......5. as the pot turns.
You really want something like:
Code: |
else //for the day output
{
pwm1 = read_adc();
set_pwm1_duty(pwm1/2+128);
}
|
This will then give:
2.5................5
as the pot turns.
You had 0x80 in your original code. Entirely 'up to you' what format you use. Generally hex is useful when dealing with numbers that have a binary significance. |
|
|
shan1923
Joined: 12 Oct 2015 Posts: 8
|
|
Posted: Sat Oct 17, 2015 2:55 am |
|
|
@Ttelmah. Thanks a lot. _________________ +1923+ |
|
|
|