View previous topic :: View next topic |
Author |
Message |
nerdnicky
Joined: 02 Aug 2013 Posts: 13
|
help on valve on off through timer needed |
Posted: Mon Sep 16, 2013 12:06 pm |
|
|
I need to control a valve on-off time through timer of 12f675 ....the on off timings of valve are
valve off time ------- valve on time
6 minutes ---------- 0.5 seconds
8 minutes ---------- 0.8 seconds
10 minutes ---------- 1.5 seconds
There are two buttons one for shuffling between the off time and the other for shuffling between the on time.
The on and off time could be anything between the available preferences..
say 6 minutes and 0.5 seconds or 1.5 seconds....etc.
My problem is that the code that i have written is not reliable sometimes it performs and other times it skips the minutes on pressing the buttons....
Someone please help me................thank you a lot.....
Code: |
#include <12f675.h>
#use delay(clock=4M)
#fuses NOMCLR,INTRC
unsigned int16 i=1386;
unsigned int16 j=64; //500ms delay
unsigned int16 timer1_counter=0;
unsigned int16 timer0_counter=0;
#INT_TIMER0
void timer0_isr()
{
timer0_counter++;
if(timer0_counter >= j)
{
timer0_counter=0;
output_low(PIN_A2);
}
}
#INT_TIMER1
void timer1_isr(void)
{
timer1_counter++;
if(timer1_counter >= i) // trips in 6 minutes by default
{
timer1_counter=0;
output_high(PIN_A2);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_32);
enable_interrupts(INT_TIMER0);
}
}
void main()
{
int k;
setup_timer_1(T1_INTERNAL|T1_DIV_BY_4);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
clear_interrupt(INT_TIMER0);
do
{
if((input(PIN_A0)==0)&&(i=1386))
{
setup_timer_1(T1_INTERNAL|T1_DIV_BY_4);
i=1850; //8 minutes delay
}
else
if((input(PIN_A0)==0)&&(i=1850))
{
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
i=900; //10 minutes delay
}
else
{
setup_timer_1(T1_INTERNAL|T1_DIV_BY_4);
i=1386;
}
if((input(PIN_A1)==0)&&(j=64))
{
j=105; //0.8 second delay for timer0
}
else
if((input(PIN_A1)==0)&&(j=105))
{
j=199; //1.5 second delay for timer0
}
else
j=64; //0.5 second delay for timer0
}while(1==1);
}
|
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Mon Sep 16, 2013 12:56 pm |
|
|
Assuming PIN_A0 and PIN_A1 are connected to buttons or switches, you need to 'debounce' the signal.
You can easily either do that in hardware using r/c filters, or software using timedelays. You can even do both to optimise overall performance.
Try using the 'search' feature of this forum keyword 'debounce' and you'll get several hits. How you proceed it up to you. I use both HW and SW.
hth
jay |
|
|
stinky
Joined: 05 Mar 2012 Posts: 99 Location: Central Illinois
|
|
Posted: Mon Sep 16, 2013 1:21 pm |
|
|
Code: | if((input(PIN_A0)==0)&&(i=1386)) |
Also, would double check if this is actually what you intended. This line assigns the value 1386 to variable i. |
|
|
nerdnicky
Joined: 02 Aug 2013 Posts: 13
|
help on valve on off through timer needed |
Posted: Tue Sep 17, 2013 7:59 am |
|
|
thanks stinky and temtronic for your kind attention
i changed the
if((input(PIN_A0)==0)&&(i=1386))
to
if((input(PIN_A0)==0)&&(i==1386))
and provided a delay of 20ms for buttons to debounce
delay_ms(20);
but it still doesn't work up.the timing that i am getting is still 6 minutes even on pressing the shuffle button for minute....... should i write the values to the timer location or is my current approach ok...????
i am pretty much in urgency ....please help me..... |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Tue Sep 17, 2013 9:25 am |
|
|
you might profitably rethink how you do this, so as to use a SINGLE timer with a common increment value and ON/OFF count storage Vars -
in conjunction with using a state machine approach.
The two timer "solution" with inconstant divisors and varying comparisons with your latent INT enabling is hard to analyze , and sure makes this boy's head spin.... |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
Re: help on valve on off through timer needed |
Posted: Tue Sep 17, 2013 9:29 am |
|
|
nerdnicky wrote: | i changed the
if((input(PIN_A0)==0)&&(i=1386))
to
if((input(PIN_A0)==0)&&(i==1386)) | You fixed the same bug in the 3 other locations as well, I hope?
Without looking too deep into your code here are a few other remarks for improvement:
- Use the variable names i,j,k only for simple loop counters. Your variables have a different purpose so give them a meaningful name reflecting that purpose.
- Same naming applies to PIN_A1 and the other pins. Now I have no clue as to what the intention of these inputs is. In a proper program that would be clear. For example you can write: Code: | #define PIN_A1 RESET_BUTTON
#define PIN_A2 FIRE_NUCLEAR_MISSILE_BUTTON
if (input(RESET_BUTTON))
{
// Do reset stuff here
} |
- A few more lines of comment will be helpful. For example at the start of each function a short description what the function is to do.
Code: | setup_timer_1(T1_INTERNAL|T1_DIV_BY_4);
i=1850; //8 minutes delay
}
else
if((input(PIN_A0)==0)&&(i=1850))
{
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
i=900; //10 minutes delay
| This can't be right....
The value of i for 8 minutes is larger than the value for 10 minutes. Even when I take into account the different settings for Timer1 in both situations.
Besides, you make it more difficult to yourself by using different configurations in every delay setting.
At 4MHz and a setting T1_DIV_BY_4 your Timer1 will overflow:
4MHz / 4 / 4 / 16bit_max = 3.81 times per second
Or in 1 minute: 3.81 * 60 = 228.9 times ~= 229 times
Code: | #define TIMER1_MINUTE 229
...
do
{
your stuff
// set new time
i = 8 * TIMER1_MINUTE;
more code
} while(TRUE); | Much easier to read and instead of a 'magic' value 1850 other programmers now directly see it is 8 * 1 minute. Note that 1850 is a bit too high, the correct value is closer to 1831.
To help you further we need more information as I don't understand the details of your project. Is it like:
1) the valve is off for a fixed time (user can choose from 3 settings) and then on for a fixed time (user can again choose from 3 settings).
or
2) It is a programmable sequence? Like:
8 minutes off, on for 0.7sec
2 minutes off, on for 1.5 sec
6 minutes off, on for 0.8 sec
and then to the first step again. |
|
|
nerdnicky
Joined: 02 Aug 2013 Posts: 13
|
help on valve control |
Posted: Tue Sep 17, 2013 11:45 am |
|
|
Thanks ckielstra for your precious advice.. i have changed the prescalar of timer and added description of the program..
Actually i need to design a valve opener for oxygen cylinder so that the amount of gas could be controlled based on user settings. The volume consumption is directly affected according to the prescribed timings. This is why i need two back to back timers for independently controlling the on and off time. But right now my knowledge is just useless....and i am in need of an urgent help....
Code: |
#include <12f675.h>
#use delay(clock=4M)
#fuses NOMCLR,INTRC
unsigned int16 set_min=1386; // for 6 minutes default delay
unsigned int16 set_sec=64; //500ms default delay
unsigned int16 timer1_counter=0;
unsigned int16 timer0_counter=0;
#INT_TIMER0
void timer0_isr() // PIN_A0 is for shuffling b/w minutes
{
timer0_counter++; // PIN_A1 is for shuffling b/w seconds
if(timer0_counter>=set_sec)
{
timer0_counter=0;
output_low(PIN_A2);
}
}
#INT_TIMER1
void timer1_isr(void)
{
timer1_counter++;
if(timer1_counter>=set_min) // trips in 6 minutes by default
{timer1_counter=0;
output_high(PIN_A2);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_32);
enable_interrupts(INT_TIMER0);
}
}
void main()
{
setup_timer_1(T1_INTERNAL|T1_DIV_BY_4);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
clear_interrupt(INT_TIMER0);
do
{
if((input(PIN_A0)==0)&&(set_min=1386))
{
delay_ms(20);
set_min=1831; // 8 minutes delay
}
if((input(PIN_A0)==0)&&(set_min=1831))
{
delay_ms(20);
set_min=2289; // 10 minutes delay
}
if((input(PIN_A0)==0)&&(set_min=2289))
{
delay_ms(20);
set_min=1386; // by default 6 minutes delay
} // if minutes button is not pressed
if((input(PIN_A1)==0)&&(set_sec=64)) // or if it is pressed thrice
{
delay_ms(20);
set_sec=105; // 800ms delay for timer0
}
if((input(PIN_A1)==0)&&(set_sec=105))
{
delay_ms(20);
set_sec=199; // 1.5 second delay with timer0
}
if((input(PIN_A1)==0)&&(set_sec=199))
{
delay_ms(20);
set_sec=64; // 500 ms delay with timer0
}
}while(1==1);
}
|
please...please help |
|
|
ezflyr
Joined: 25 Oct 2010 Posts: 1019 Location: Tewksbury, MA
|
|
Posted: Tue Sep 17, 2013 2:31 pm |
|
|
Hi,
You were already told that the coding in this (example) line is both poor form, and plain wrong!
Code: |
if((input(PIN_A0)==0)&&(set_min=1386))
|
It's poor form because we have no idea what is connected to 'PIN_A0', and it's plain wrong because 'set_min=1386' does not
mean "if set_min is equal to 1386", it means "set_min equals 1386'! This is basic, basic 'C' programming, so rather than jumping in
here an pleading for 'Urgent' help, why don't you read the help already provided, and read up on 'C' programming!
Something like this is much better:
Code: |
if((input(Enter_Btn)==0) && (set_min==1386))
|
Note: you need to make these changes everywhere in your code!
John |
|
|
nerdnicky
Joined: 02 Aug 2013 Posts: 13
|
help on valve control |
Posted: Tue Sep 17, 2013 7:32 pm |
|
|
sorry i mde the changes but it seems that i copied here the unchanged version of the code.....extremely sorry for that ....but my problem is still not solved......
Code: |
#include <12f675.h>
#use delay(clock=4M)
#fuses NOMCLR,INTRC
unsigned int16 set_min=1386; // for 6 minutes default delay
unsigned int16 set_sec=64; //500ms default delay
unsigned int16 timer1_counter=0;
unsigned int16 timer0_counter=0;
#INT_TIMER0
void timer0_isr() // PIN_A0 is a button for shuffling b/w minutes
{
timer0_counter++; // PIN_A1 is a button for shuffling b/w sec
if(timer0_counter>=set_sec)
{
timer0_counter=0;
output_low(PIN_A2);
}
}
#INT_TIMER1
void timer1_isr(void)
{
timer1_counter++;
if(timer1_counter>=set_min) // trips in 6 minutes by default
{timer1_counter=0;
output_high(PIN_A2);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_32);
enable_interrupts(INT_TIMER0);
}
}
void main()
{
setup_timer_1(T1_INTERNAL|T1_DIV_BY_4);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
clear_interrupt(INT_TIMER0);
do
{
if((input(PIN_A0)==0)&&(set_min==1386))
{
delay_ms(20);
set_min=1831; // 8 minutes delay
}
if((input(PIN_A0)==0)&&(set_min==1831))
{
delay_ms(20);
set_min=2289; // 10 minutes delay
}
if((input(PIN_A0)==0)&&(set_min==2289))
{
delay_ms(20);
set_min=1386; // by default 6 minutes delay
} // if minutes button is not pressed
if((input(PIN_A1)==0)&&(set_sec==64)) // or if it is pressed thrice
{
delay_ms(20);
set_sec=105; // 800ms delay for timer0
}
if((input(PIN_A1)==0)&&(set_sec==105))
{
delay_ms(20);
set_sec=199; // 1.5 second delay with timer0
}
if((input(PIN_A1)==0)&&(set_sec==199))
{
delay_ms(20);
set_sec=64; // 500 ms delay with timer0
}
}while(1==1);
} |
|
|
|
alan
Joined: 12 Nov 2012 Posts: 357 Location: South Africa
|
|
Posted: Tue Sep 17, 2013 10:23 pm |
|
|
You have to check for a state of change on your input buttons. Right now when you press the button it will advance to the next setting every 20ms. And no way you will press in less than 20ms.
Also your timer interrupts will not be synchonised, Timer0 counts and keep on counting and interrupting regardless of the state of PIN_A2, rather do both counts in 1 interrupt by only, couting sec only if PIN_A2 high for instance.
Regards |
|
|
nerdnicky
Joined: 02 Aug 2013 Posts: 13
|
help on valve control |
Posted: Thu Sep 19, 2013 6:22 am |
|
|
guys please help me how to dynamically change the TIMER REGISTER values
i have been sticking to this project for a month now and don't wanna drop it...please provide guidance in the code.... |
|
|
ezflyr
Joined: 25 Oct 2010 Posts: 1019 Location: Tewksbury, MA
|
|
Posted: Thu Sep 19, 2013 6:34 am |
|
|
Hi,
How are you testing this? My guess is that you are taking a 'black box' approach, and simply running the code and looking for the expected output
on your LED's? If so, that's not going to cut it! You really need to be able to see what is going on at intermediate stages of the code execution. I
like to dedicate a spare pin to send diagnostic messages to my PC for this purpose. There are other methods, but this works for me!
This is basic troubleshooting 101. It's really not effective to just sit back and say 'it doesn't work, please help'..... The project is right there in front of you,
so you are in the best position to debug it if you do it effectively!
John |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
Testing testing testing |
Posted: Fri Sep 20, 2013 1:40 am |
|
|
It's down to testing.
With your present set up you've no idea what's going on and/or you're not telling us.
How do you know;-
1) What the settings are for the valve timings?
2) Where abouts you are in a sequence?
3) Your fundamental logic/state-sequence works?
4) ..........................
For starters I'd speed up the whole thing, so that the entire process repeats in much less than 1s.
That way you:-
a) Can see what's happening on a 'scope.
b) Don't fall asleep waiting for a complete sequence.
c) Will know quickly which things are right/wrong.
It's up to you, you're the one with the kit in front of you.
Mike
EDIT
As I see it you've got 6 I/O pins
1) Button to shuffle on times.
2) Button to shuffle off times.
3) Drive for valve.
And diagnostics
4) Pin to show on time setting. (done as a group of n pulses.)
5) Pin to show off time setting. (also done as a group of pulses.)
6) Spare pin for something else. When you get round to real time testing. |
|
|
|