|
|
View previous topic :: View next topic |
Author |
Message |
wangine
Joined: 07 Jul 2009 Posts: 98 Location: Curtea de Arges, Romania
|
On/Off actions delay with timers [SOLVED] |
Posted: Mon Nov 28, 2022 2:43 pm |
|
|
Hello everyone, long time no see, seems I'm back to the origin's
I build myself for my home a climatic environment from some electronic broken air conditioners with help of water condensation. The system work in server mode under Linux. The problem is sometimes the system going crazy, switching my relays way faster than i programmed (i want to have min/max 3 min delay between actions. So i want to put in series with my relays a PIC like safety thing (any PIC can do the job).
I don't have any idea how to do that I'm lost, really. I didn't touch programming for years.
My stupid test code below, don't work so well.
Code: |
#include <main.h>
int16 timp_motor_on = 0;
int16 timp_motor_off = 0;
int16 timp_normal_run = 0;
int16 timp_normal_pause = 0;
int1 flag_motor_on = FALSE;
int1 flag_motor_off = TRUE;
int1 flag_int_fan = FALSE;
int1 flag_ext_fan = FALSE;
int1 flag_normal_run = FALSE;
int1 flag_normal_pause = FALSE;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void motor()
{
if(timp_motor_on >= 180)
{
output_high(pin_d0);
flag_motor_on = FALSE;
flag_motor_off = TRUE;
}
//delay_ms(100);
if(timp_motor_off >= 180)
{
output_low(pin_d0);
timp_motor_off = 0;
flag_motor_off = FALSE;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#INT_TIMER0
void TIMER0_isr(void)
{
timp_motor_on++; // 1 sec
timp_motor_off++; // 1 sec
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#INT_TIMER1
void TIMER1_isr(void)
{
if((timp_motor_on || timp_motor_off) > 6000)
{
timp_motor_on = 0;
timp_motor_off = 0;
}
//~~~~~~~~~~~~
if(!input_state(pin_b0))
{
if(flag_motor_off == FALSE)
{
flag_motor_off = FALSE;
flag_motor_on = TRUE;
timp_motor_on = 0;
set_timer0(0);
output_high(pin_d0);
}
}
else if(flag_motor_on == TRUE)
{
timp_motor_off = 0;
// set_timer0(0);
}
else if(flag_motor_off == TRUE)
{
// flag_motor_off = TRUE;
output_low(pin_d0);
timp_motor_on = 0;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void main()
{
port_b_pullups(0xFF);
setup_adc_ports(NO_ANALOGS, VSS_VDD);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_128); //1.0 s overflow
setup_timer_1(T1_INTERNAL|T1_DIV_BY_2); //32.7 ms overflow
enable_interrupts(INT_TIMER0);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
//output_high(pin_d1);
while(TRUE)
{
motor();
}
}
|
I change the code in different ways, of course without "delay " function.
This one work but at each 180 sec, in off mode, the On function start for a second. Mess me up, really.
The goal is, when the input pin is true the output should be true. Even the input change his state, the output need to stay true 3 minutes. On every input state change from true to false and true again (in that 3 min interval), the counter should be reset to count from 0.
For Off function is the same story. If the output was false, the input
don't need to be able to start it below 3 min.
Any suggestions are welcome.
Thanks to everyone, the beer come after.
_________________ patience is key
Last edited by wangine on Thu Dec 01, 2022 11:08 am; edited 1 time in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Tue Nov 29, 2022 10:57 am |
|
|
You seem to be describing something vastly simpler than your code tries
to be.
Input signal, and an output signal.
If the input changes high, turn on the output, and ignore the input for
180 seconds.
If the input changes low, turn off the output, and again ignore the input
for 180 seconds.
Now the key is that since both times are the same and can only happen
one at a time, a single timer is all that is needed.
So, something like:
Code: |
#include <main.h>
int16 timer = 0;
int1 last_input=0;
#define INPUT_PIN pin_b0
#define MOTOR_OUT pin_d0
#INT_TIMER0
void TIMER0_isr(void)
{
if (timer>0)
--timer; //only decrement timer when non zero
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void main()
{
port_b_pullups(0xFF);
setup_adc_ports(NO_ANALOGS, VSS_VDD);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_128); //1.0 s overflow
enable_interrupts(INT_TIMER0); //1Hz tick
enable_interrupts(GLOBAL);
last_input=!input(INPUT_PIN); //this makes input test happen at boot.
//If you don't want this then set last_input=input(INPUT_PIN)
while(TRUE)
{
if (timer==0)
{ //Do not look at the inputs if the timer is running
if (input(INPUT_PIN)==1 && last_input==0)
{ //here pin has changed to low since last test.
last_input=1;
output_high(MOTOR_OUT);
timer=179;
}
if (input(INPUT_PIN)==0 && last_input==1)
{ //here pin has changed to high.
last_input=0;
output_low(MOTOR_OUT);
timer=179;
}
}
}
}
|
Your code as posted, inverted the output pin. If this is what you want
then just invert the outputs here. |
|
|
wangine
Joined: 07 Jul 2009 Posts: 98 Location: Curtea de Arges, Romania
|
|
Posted: Tue Nov 29, 2022 7:49 pm |
|
|
Well .... ok, simple and elegant. Thank you. I bet with my wife, you will answer first, i won
The thing who mess me up, was : as scenario...
My system going crazy for some bug or just power grid fail, (happen some weeks ago) and the command to my motor start on/off twice as second, fortunately was a analog timer in series with my relays set on 100sec (max on that timer) and at on command the big relay was unable to turn on the motor, otherwise motor was broken for sure.
When i start to write the little fail safe code, i was thinking on same solution to ignore the input for some time, but after idea become "input is on, the motor is on and the input going off for 100 sec, and after on again for 100 sec, i was trying to reset the timer at default count from last input state (180sec as example)."
And in that moment mess me up. Usual simple things destroy anyone's world.
For the moment i don't have the rs485 connected from my ambient thermostat to the system (no time to code). I use the relay output of thermostat in the system, and the PID of the system decide when to turn off and on the motor.
Thats why i was thinking, resetting the timer on last input condition ++180sec will help me at PID control. If i open two windows twice at 5 min the PID going crazy.
Thank you man _________________ patience is key |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Thu Dec 01, 2022 6:36 am |
|
|
His post reminds me of a 'one shot' function where once triggered, output stays high for a fixed period of time.
Microchip had a 'tips and tricks' booklet, eons ago......., that showed how to code in assembler, the various forms of relay functions that Mr. T's link talks about
Most PLCs have those relay functions built into them. I know the K-M ones did 3 decades ago. One PLC ($200 back then ) saved a client $14,000 in excess heating costs the 1st year ! |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Thu Dec 29, 2022 7:59 pm |
|
|
temtronic wrote: | his post reminds me of a 'one shot' function where once triggered, output stays high for a fixed period of time.
Microchip had a 'tips and tricks' booklet, eons ago......., that showed how to code in assembler, the various forms of relay functions that Mr. t's link talks about
Most PLCs have those relay functions built into them. I know the K-M ones did 3 decades ago. One PLC ($200 back then ) saved a client $14,000 in excess heating costs the 1st year ! |
Yes, I had got the same remembering after reading this thread, I'm agree with both regarding this.
Just I want to share the old "Tips & Tricks" from Microchip that should be a must in our data resource:
https://ww1.microchip.com/downloads/en/DeviceDoc/01146B.pdf
Best wishes _________________ Humber |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Fri Dec 30, 2022 1:50 am |
|
|
I've stuck a link to this thread in the 'best of' forum, since like most
of the 'old hands' here, I know this is an invaluable resource. |
|
|
|
|
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
|