View previous topic :: View next topic |
Author |
Message |
corgenius
Joined: 27 May 2015 Posts: 18
|
PIC12F675 Delay Question |
Posted: Wed May 27, 2015 8:12 am |
|
|
Dear colleagues,
First of all, thank you for having me.
I've recently started a new project that has the purpose of turning on a "light bulb" for 1 min at the press of a button (one press of the button the circuit is closed, second press the circuit opens again - we call it "non-release" button).
I've successfully did that:). Every time the button is pressed and stays pressed the light stays on for 1 min. When the button is released the circuit opens and of course, the light goes off. My problem is that the delay doesn't stop when the circuit opens, so if someone wants to turn on the light for 30 sec, closes it for 10 sec, and starts it again the delay is still running and the light will be on only for 20 more seconds, not for 1 min.
I'm using a PIC12F675, PCWHD and Proteus 8.
My code is :
Code: | void main()
{
port_a_pullups (0x01);
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_CLOCK_DIV_2);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_comparator(NC_NC);
setup_vref(FALSE);
in: while(!input(PIN_A0))
goto in;
output_HIGH(PIN_A5);
delay_ms(4000);
output_low(PIN_A5);
delay_ms(100);
goto in2;
in2: while (input(PIN_A0))
output_LOW(PIN_A5);
delay_ms(100);
goto in;
} |
Thanks you,
Warm regards,
Eugeniu |
|
|
corgenius
Joined: 27 May 2015 Posts: 18
|
|
Posted: Wed May 27, 2015 8:15 am |
|
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Wed May 27, 2015 8:28 am |
|
|
goto..... Aargh!....
Seriously ignoring everything else, get rid of these....
There _are_ places in some programming, where goto can be sensible/worthwhile. What you are doing is _not_ one of these.
Then you have to re-think your approach.
Have a 'master' loop. Have an interrupt driven timer. Use state machine in the master loop to detect the button operation. Have the button operation change a counter, which is updated for you by the timer. Test this counter to know when the time has finished.
This way pushing the button, resets the counter. |
|
|
corgenius
Joined: 27 May 2015 Posts: 18
|
|
Posted: Wed May 27, 2015 9:18 am |
|
|
Dear Ttelmah,
Sorry, but my knowledge regarding programming is very limited.
If you have the time, and the desire, please write a code that I can modify in order to achieve the desired "delay" by modifying the value of the counter.
Warm regards,
Eugeniu |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Wed May 27, 2015 11:33 am |
|
|
corgenius wrote: | Dear Ttelmah,
Sorry, but my knowledge regarding programming is very limited.
If you have the time, and the desire, please write a code that I can modify in order to achieve the desired "delay" by modifying the value of the counter.
Warm regards,
Eugeniu |
Sorry, this is a help forum not a do it for you one.
A search on this forum, google, CCS manual and PIC manuals will find examples of all you need.
As a useful tip, get rid of Proteus/ISIS. It will waste you more time than it saves.
Mike |
|
|
corgenius
Joined: 27 May 2015 Posts: 18
|
|
Posted: Wed May 27, 2015 11:51 am |
|
|
Dear Mike,
I've tried searching for a "counter delay" for the 12F675 but I didn't found anything.
Do you know where I can find it?
Regards,
Eugeniu |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Wed May 27, 2015 2:35 pm |
|
|
Quite a few things are covered in the supplied examples. If you look at ex_ticks.c, and then realise that this uses TICKS_PER_SECOND/4 (and 6) to give an LED flashing at 4Hz, and 6Hz. What do you think would happen if you used TICKS_PER_SECOND*60 instead?.
It also toggles the LED, rather than simply putting it on/off.
It'd need some tweaking, but shows some of the things needed. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Wed May 27, 2015 3:02 pm |
|
|
I'm not exactly sure I understand what you are trying to do but these look like early programming exercises. Perhaps for school or self study, but the only way you will learn is by trying yourself and making mistakes.
From the code you posted I can see you have just started to learn programming.
As Ttelmah said, the goto-statement is considered a bad programming practice and is best to never be used any more. There are some special cases where the goto-statement is useful but those are for advanced use only and, for now, forget about this instruction.
When you want to make a loop that never exits, then you code something like this: Code: | while (TRUE) {
// your code here
} | The advantage over using the goto-statement here is that your code is easier to read. The code is now 'self documenting' because it 'says' you want to do a loop.
I suggest you do some more reading in your C-language book over the while-loop because you repeat a particular error in your code. For example: Code: | in2: while (input(PIN_A0))
output_LOW(PIN_A5); | The while command will repeat the statement directly following this command. When I rewrite your code I can make this clear: Code: | in2: while (input(PIN_A0))
{
output_LOW(PIN_A5);
} | You are repeatedly setting PIN_A5 low for as long as PIN_A0 is high.
To avoid making mistakes like this it is good practice to always use the '{}' combination in while-loops and for-loops.
Ttelmah's suggestion for using a state machine and timer interrupts is very good but a bit too difficult for your programming knowledge.
Try to think about your problem in a different way by decoupling the switch logic and the timer into two separate steps. For example the next program will light a lamp for 30 seconds after the user releases the button. Code: | #include <12F675.h>
#FUSES XT, NOWDT
#use delay(clock=4MHz)
#define SECONDS_1 (100 * 10) // 100 x 10 ms == 1 second
#define SECONDS_30 (30 * SECONDS_1)
#define LAMP_BUTTON PIN_A0
#define LAMP PIN_A5
void main()
{
int16 lamp_button_counter = 0;
while(TRUE)
{
delay_ms(10);
// If user pressed lamp button
if (input(LAMP_BUTTON))
{
output_high(LAMP);
lamp_button_counter = SECONDS_30;
}
// if lamp timer active
if (lamp_button_counter > 0)
{
// Decrease lamp timer
lamp_button_counter--;
// Has timer expired?
if (lamp_button_counter == 0)
{
output_low(LAMP);
}
}
}
} | You can use this code as a base to expand.
Note how the use of #define makes the program easier to read. |
|
|
corgenius
Joined: 27 May 2015 Posts: 18
|
|
Posted: Wed May 27, 2015 10:27 pm |
|
|
Dear ckielstra,
First of all I want to thank you for your time. This is exactly the type of code that I've been searching for:).
I've compiled it before work but I didn't manage to make the led blink. I will post some result as soon as I get home.
Ttelmah, also thank you for your time.
Warm regards,
Eugeniu |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Thu May 28, 2015 1:58 am |
|
|
One thing to check is the switch logic. In my example program the switch input is high when the switch is pressed. I see your program has this reversed. |
|
|
corgenius
Joined: 27 May 2015 Posts: 18
|
|
Posted: Thu May 28, 2015 8:45 am |
|
|
Dear ckielstra,
I've tried modifying the code in order to make the led blink. I even tried making a simple LED that is connected to PIN_A5 to blink, but with no success. I've tried to turn the LED ON with
Code: | #include <12F675.h>
#FUSES XT, NOWDT
#use delay(clock=4MHz)
#define SECONDS_1 (100 * 10) // 100 x 10 ms == 1 second
#define SECONDS_30 (30 * SECONDS_1)
#define LAMP_BUTTON PIN_A0
#define LAMP PIN_A5
void main()
{
port_a_pullups (0x01);
// If user pressed lamp button
if (!input(PIN_A0))
{
output_HIGH(PIN_A5);
}
}
|
, but also 0 success:(.
Do you have any idea why the code doesn't work?
Regards,
Eugeniu |
|
|
dyeatman
Joined: 06 Sep 2003 Posts: 1934 Location: Norman, OK
|
|
Posted: Thu May 28, 2015 9:46 am |
|
|
The chip won't run without a clock. You are using the XT fuse.
A5 is normally an Xtal input and you don't have an Xtal.
In your fuses change XT to INTRC_IO to enable the
internal osc and make A5 (GP5) an output. You need to read the datasheet. _________________ Google and Forum Search are some of your best tools!!!! |
|
|
corgenius
Joined: 27 May 2015 Posts: 18
|
|
Posted: Thu May 28, 2015 12:25 pm |
|
|
Dear colleagues,
I've modified the code so the LED will "blink", but, for a continuous input (like I have in my project, the LED will not go off :(.
I've tryied changin the
Code: | if (!input(LAMP_BUTTON))
{
output_high(LAMP);
lamp_button_counter = SECONDS_5;
}
// if lamp timer active
if (lamp_button_counter > 0)
{
// Decrease lamp timer
lamp_button_counter--;
// Has timer expired?
if (lamp_button_counter == 0)
{
output_low(LAMP); | into
Code: | while (!input(LAMP_BUTTON))
{
output_high(LAMP);
lamp_button_counter = SECONDS_5;
}
// if lamp timer active
if (lamp_button_counter > 0)
{
// Decrease lamp timer
lamp_button_counter--;
// Has timer expired?
if (lamp_button_counter == 0)
{
output_low(LAMP); |
and many more combinations, but with no result :(. I even added a GOTO expression, but still no result.
My complete code is Code: |
#include <12F675.h>
#FUSES INTRC_IO
#define portOut1 pin_a5
#use delay(clock=4MHz)
#define SECONDS_1 (100 * 10) // 100 x 10 ms == 1 second
#define SECONDS_5 (5 * SECONDS_1)
#define LAMP_BUTTON PIN_A0
#define LAMP PIN_A5
void main()
{
port_a_pullups (0x01);
int8 lamp_button_counter = 0;
while(TRUE)
{
delay_ms(10);
// If user pressed lamp button
if (!input(LAMP_BUTTON))
{
output_high(LAMP);
lamp_button_counter = SECONDS_5;
}
// if lamp timer active
if (lamp_button_counter > 0)
{
// Decrease lamp timer
lamp_button_counter--;
// Has timer expired?
if (lamp_button_counter == 0)
{
output_low(LAMP);
}
}
}
}
|
Thank you again for your time and knowledge.
Regards,
Eugeniu |
|
|
corgenius
Joined: 27 May 2015 Posts: 18
|
|
Posted: Sat May 30, 2015 9:41 am |
|
|
Dear colleagues,
I've tried adding a counter, in order to make the loop run just once when the input is continuously 1, but I didn't had any luck. The loop runs once, even though the input stays 1, but after realizing the button and pressing it again the loop doesn't start again.
My code is:
Code: | #include <12F675.h>
#FUSES INTRC_IO
#define portOut1 pin_a5
#use delay(clock=4MHz)
#define SECONDS_1 (100 * 10) // 100 x 10 ms == 1 second
#define SECONDS_5 (5 * SECONDS_1)
#define LAMP_BUTTON PIN_A0
#define LAMP PIN_A5
void main()
{
port_a_pullups (0x01);
int8 lamp_button_counter = 0;
int counter = 0;
while(counter < 1)
{
delay_ms(10);
// If user pressed lamp button
if (input(LAMP_BUTTON))
{
output_high(LAMP);
lamp_button_counter = SECONDS_5;
}
// if lamp timer active
if (lamp_button_counter > 0)
{
// Decrease lamp timer
lamp_button_counter--;
// Has timer expired?
if (lamp_button_counter == 0)
{
output_low(LAMP);
counter = counter + 1;
}
}
}
while (input(LAMP_BUTTON))
{
counter = 0;
}
}
|
I even tried using the !input in order to make the counter 0 again with
Code: | while (!input(LAMP_BUTTON))
{
output_low(LAMP);
counter = 0;
}
|
No luck.
Any ideas as how I can fix this?
Regards,
Eugeniu |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
|