Author Topic: PIC: Code for a timer pulses with pause/resume ability  (Read 10051 times)

0 Members and 1 Guest are viewing this topic.

Offline ShaydzmiTopic starter

  • Regular Contributor
  • *
  • Posts: 117
  • Country: ma
PIC: Code for a timer pulses with pause/resume ability
« on: January 30, 2022, 03:55:59 pm »
Hi,
I want to make a timer that can make pulses in intervals, with the ability to continue from last state he was on before the (Run signal) became 0V (After an initial delay that should be after any Run signal become 5V) you see the whole idea in picture attached.
I will use any PIC microcontroller, but I need to understand how to make the code program first, I'm an absolute beginner!


- The numbers in the image are in seconds, they are for demonstration only.
- Timers ONs and OFFs should be adjustable.
- The timer will be set in seconds, from 0.5 second to 1000 seconds approximately.
- The code would be written in C language, using MikroC software.
- I'm following some courses in PIC programming, but I am in the first stages.


If you want more information I'm ready, thank you!

I'm an Arabic speaker; so please forgive my lack of right expression, this is kind of what I want in other words, as Mr ledtester wrote:

1. a timer is set up to produce a clock signal on a GPIO pin
2. when the run signal is HIGH the timer operates normally
3. when the run signal is LOW the timer operation is paused and the GPIO pin is brought LOW
4. when the run signal returns to HIGH the timer operation resumes and the GPIO pin returns to the state is was in at the time the run signal was brought LOW



« Last Edit: January 30, 2022, 07:22:54 pm by Shaydzmi »
 

Offline jpanhalt

  • Super Contributor
  • ***
  • Posts: 4810
  • Country: us
Re: PIC: Code for a timer pulses with pause/resume ability
« Reply #1 on: January 30, 2022, 04:10:41 pm »
In what language?  Have you learned timers and interrupts?  For convenience, are those relative delays in ms, us, or or something else like Tcy (system clock ticks)?
 
The following users thanked this post: Shaydzmi

Offline ShaydzmiTopic starter

  • Regular Contributor
  • *
  • Posts: 117
  • Country: ma
Re: PIC: Code for a timer pulses with pause/resume ability
« Reply #2 on: January 30, 2022, 05:18:00 pm »
Thank you for your reply, I've included answers to your questions in the first thread.
 

Offline jpanhalt

  • Super Contributor
  • ***
  • Posts: 4810
  • Country: us
Re: PIC: Code for a timer pulses with pause/resume ability
« Reply #3 on: January 30, 2022, 05:46:52 pm »
Thanks.  I don't code in C so can't contribute to your code.  Nevertheless, I still don't understant what you want to do.

Consider this:
"I want to make a timer that can make pulses in intervals, with the ability to continue from last state he was on before the (Run signal) became 0"

1) The first condition doesn't explain why or what controls the different length pulses.  That is, what determines when a 20 pulse or 10 pulse is made versus a 30 pulse?
2) "Continue the last state before Run  = 0."  How much before?  Look at this snippet:


The state when Run = 0 is 1, yet you continue as 0?
 
The following users thanked this post: Shaydzmi

Offline perdrix

  • Frequent Contributor
  • **
  • Posts: 825
  • Country: gb
Re: PIC: Code for a timer pulses with pause/resume ability
« Reply #4 on: January 30, 2022, 05:54:24 pm »
If all you want to do is toggle an output pin between 0V and Vcc it's as simple as:

Code: [Select]
        _LATA0 ^= 1;   // toggle pin 2
Obviously the pin needs to be configured as output!

David
 
The following users thanked this post: Shaydzmi

Online ledtester

  • Super Contributor
  • ***
  • Posts: 4208
  • Country: us
Re: PIC: Code for a timer pulses with pause/resume ability
« Reply #5 on: January 30, 2022, 06:11:17 pm »
@Shaydzmi, is this what you mean...

1. a timer is set up to produce a clock signal on a GPIO pin
2. when the run signal is HIGH the timer operates normally
3. when the run signal is LOW the timer operation is paused and the GPIO pin is brought LOW
4. when the run signal returns to HIGH the timer operation resumes and the GPIO pin returns to the state is was in at the time the run signal was brought LOW
 
The following users thanked this post: Shaydzmi

Offline ShaydzmiTopic starter

  • Regular Contributor
  • *
  • Posts: 117
  • Country: ma
Re: PIC: Code for a timer pulses with pause/resume ability
« Reply #6 on: January 30, 2022, 07:29:48 pm »
Quote
jpanhalt
I've answered your questions above. Thank you.

Quote
perdrix
Thank you, you can read my post again, I've added some information.

Quote
ledtester
Thank you, I added your reply to my post, this pretty much what I want.
 

Offline jpanhalt

  • Super Contributor
  • ***
  • Posts: 4810
  • Country: us
Re: PIC: Code for a timer pulses with pause/resume ability
« Reply #7 on: January 30, 2022, 08:35:19 pm »
First impression

1) Clock suspended while RUN=0:

Set up your clock.  In Assembly when I want an alternating high/low you can test a pin, and if high make low and vice versa.  I usually just XOR (exclusive OR).  Let's say, GPIO,0 is the pin you want to toggle.  If GPIO,0 = 0 and GPIO is XOR'd with 0x01, none of the other pins on GPIO will change, except GPIO,0 --> high.   Now, if that is repeated, then GPIO,0 --> low and so forth.

Now assume the "RUN" signal is on a pin with interrupt on change ("IOC").  Set that up to happen on a falling edge.  When that interrupt fires, stop the clock, be sure to preserve its state, and make GPIO,0 low. Change the IOC to "rising edge".  Now on the next interrupt restore the stored clock state on GPIO,0.  The clock's previous state is preserved.  Most PIC's (all of the ones with interrupts that I know of) can alternate falling edge and rising edge for IOC pins.  If you set that up, you will not need to change the edge polarity during an interrupt.

How you preserve the clock's state depends on how that clock is generated.  It may not be necessary to do anything while operation is suspended.  TMR1 acts like that.  Or, you can simply copy GPIO to a register on the falling interrupt. That will preserve the clock state at the moment of interrupt.  You cannot simply restore that state by moving the register to GPIO, as some of the other pins/bits may have changed. You can bit test bit <0> of that register (as given in the example above) and if high, set clock/GPIO,0 high, otherwise, set clock/GPIO,0 low.  (In Assembly, there are ways to do such saves without adding a new register, but in C, they do not work because you do not know everything that happens between the two state changes.) 

2) If clock is not actually suspended, but simply not expressed while RUN is low, then a slightly different solution is needed.
 
The following users thanked this post: Shaydzmi

Offline ShaydzmiTopic starter

  • Regular Contributor
  • *
  • Posts: 117
  • Country: ma
Re: PIC: Code for a timer pulses with pause/resume ability
« Reply #8 on: January 31, 2022, 07:13:10 am »

Quote
First impression
1) Clock suspended while RUN=0:

This is should be the case.
I didn't understand your answer, but I'll study it carefully if no one gives me instructions in C.
Thank you.
 

Offline jpanhalt

  • Super Contributor
  • ***
  • Posts: 4810
  • Country: us
Re: PIC: Code for a timer pulses with pause/resume ability
« Reply #9 on: January 31, 2022, 09:47:24 am »
After sleeping on it myself, perhaps the question put to you is a little different than your understanding of it.  As just one example, let's say the question is, "How long is RUN high?"  That type of thing is easily done with PIC devices and does not require suspending and re-enabling the clock.  In fact, analogies of that are quite commonly done.

What led me to wonder about that was your reference to a "timer," but its pulses appear to be irregular.  Can you post the actual question/challenge you are trying to answer?
 

Online ledtester

  • Super Contributor
  • ***
  • Posts: 4208
  • Country: us
Re: PIC: Code for a timer pulses with pause/resume ability
« Reply #10 on: January 31, 2022, 10:36:31 am »
What led me to wonder about that was your reference to a "timer," but its pulses appear to be irregular.  Can you post the actual question/challenge you are trying to answer?

When the RUN signal is constant the pulses appear to be very regular -- for instance see the latter portion of the signal graph in the first post.

Here is my interpretation of the problem expressed in Arduino-ish code. In a real implementation you would want to use hardware timers and perhaps interrupts.

Code: [Select]
void main() {

    pinMode(RUN_SIGNAL:, INPUT);
    pinMode(OUTPUT_GPIO, OUTPUT);
    digitalWrite(OUTPUT_GPIO, 0);
 
    bool running = 0;
    bool gpio_state = 0;
    uint timer = MAX_TIMER;
   
    while (1) {
        if (running) {
            if (--timer == 0) {
                // toggle the output and reset the timer
                digitalWrite(OUTPUT_GPIO, !digitalRead(OUTPUT_GPIO));
                timer = MAX_TIMER;
            }
            if (!digitalRead(RUN_SIGNAL)) {
                running = 0;
                gpio_state = digitalRead(OUTPUT_GPIO);
                digitalWrite(OUTPUT_GPIO, 0);
            }
            // maybe delay here for a while?
        } else {
            if (digitalRead(RUN_SIGNAL)) {
                running = 1;
                digitalWrite(OUTPUT_GPIO, gpio_state);
            }
        }
    }
}
« Last Edit: January 31, 2022, 10:39:25 am by ledtester »
 

Offline jpanhalt

  • Super Contributor
  • ***
  • Posts: 4810
  • Country: us
Re: PIC: Code for a timer pulses with pause/resume ability
« Reply #11 on: January 31, 2022, 11:10:42 am »
When the RUN signal is constant the pulses appear to be very regular -- for instance see the latter portion of the signal graph in the first post.

That's not what I see.  First "half," clock high = 20; second "half," clock high = 30.

I still think a clear description of the actual question is needed.
 

Offline ShaydzmiTopic starter

  • Regular Contributor
  • *
  • Posts: 117
  • Country: ma
Re: PIC: Code for a timer pulses with pause/resume ability
« Reply #12 on: January 31, 2022, 11:50:19 am »
I agree with Mr. Ledtester, the Clock pulses should be regular, it is my mistake in the graph.

 

Offline jpanhalt

  • Super Contributor
  • ***
  • Posts: 4810
  • Country: us
Re: PIC: Code for a timer pulses with pause/resume ability
« Reply #13 on: January 31, 2022, 12:16:14 pm »
My interpretation is that you are simply trying to measure the RUN time (that is, the length of time RUN is high).   PIC's that have a CCP or ECCP module (Compare, Capture, PWM) allow a process called "capture" for Timer1.  That allows a timer to run continuously and "capture" time stamps for a defined event.  In your case, that would be alternate rising and falling edges of RUN.  One can also start and stop TMR1, but I prefer the continuous run mode. 

Reading TMR1 on the fly, that is without capture while it is running, is a little more complicated as you need to take extra steps to ensure a rollover was not pending.  For example, if you read the low register first, then the high register, you need to check that the low register didn't rollover during the time it took to read the high register.  Starting and stopping TMR1 can introduce similar lost counts.  In Assembly, that can be accounted for by adding a constant.  I don't think that would work well in C.

Capture is what I would do.  If TMR1 is 16-bit, you can set your pre- and post-scaling so as to have not more than one rollover during the timed interval.  Rollovers are handled by the math.  If you cannot do that, then you need to count rollovers.  Rollovers can be detected by an interrupt or interrupt flag.

At this point, it might help to know which PIC you are using.  A previous post (see:perdrix) refers to the LAT (latch) registers.  Not all PIC's have them.

EDIT: BTW, TMR1 can run from the system clock or external clock (e.g., a lower frequency clock crystal).  Since the periods you are measuring are long compared to what the system clock probably is, you probably want an external clock for TMR1.
« Last Edit: January 31, 2022, 12:23:53 pm by jpanhalt »
 

Offline ShaydzmiTopic starter

  • Regular Contributor
  • *
  • Posts: 117
  • Country: ma
Re: PIC: Code for a timer pulses with pause/resume ability
« Reply #14 on: January 31, 2022, 01:06:33 pm »
1- Thank you for following along.
2- I think that you have forgotten the fact that I am an absolute beginner in this field, so 95% of your writing is not understood to me.
3- I think that you have gone too far from what I need to do.
4- What I need to do is to run an oil pump lubricator in intervals while the machine is running. The machine doesn't have a constant running, it may stop after 1 hour, sometimes it stops after just 30 seconds, or even less.
I hope that I am clear now.
 

Offline jpanhalt

  • Super Contributor
  • ***
  • Posts: 4810
  • Country: us
Re: PIC: Code for a timer pulses with pause/resume ability
« Reply #15 on: January 31, 2022, 01:23:05 pm »
That could be really simple.  Just set the lubricator to be driven by timed pulses (done).  Start and stop whatever is driving the lubricator by sensing whether the pump is running (done).  Obviously, you do not want to lubricator to run when the pump is not running. 

However, I see no reason it needs to recognize and recover its state when the pump stopped.  Just stop it and restart it from the stopped state. 

I mistakenly thought this was a school assignment to introduce you to doing accurate timings.
 

Offline ShaydzmiTopic starter

  • Regular Contributor
  • *
  • Posts: 117
  • Country: ma
Re: PIC: Code for a timer pulses with pause/resume ability
« Reply #16 on: January 31, 2022, 02:11:57 pm »
No, it's a pump lubricating a machine. A simple timer won't work a I want it to be. Say I set it like this:
5 minutes OFF.
0.5 minutes ON.
So when the machine stops often before reaching 5 min, will be no oil. Because the timer will start from OFF state every time. If I make the timer start ON first, will go too much oil to the machine.
So, the right thing to do is continue counting from where it stopped.
 

Offline jpanhalt

  • Super Contributor
  • ***
  • Posts: 4810
  • Country: us
Re: PIC: Code for a timer pulses with pause/resume ability
« Reply #17 on: January 31, 2022, 02:59:30 pm »
OK, I get it.  My experience was with motors that effectively had continuous lubrication or needed lubrication much less frequently, say twice a year.

Problem 1: How to tell the microcontroller (MCU) the pump is on or off.  For that, I don't have a solution.  Some options could be a current monitor or extra set of contacts on the motor relay.  In any event, I would probably use an interrupt.  That is an interrupt when pump goes on and another when it turns off.  Your interrupt service routine (ISR) would need to determine whether the pump was turning on or off.  Simply relying on alternating states may be more susceptible to noise.  You could also use polling as this seems to be a mostly dedicated MCU.

Problem 2: How to run the lubricator.  Here is where a timer comes into play.  It would be quite simple to program a 30 second "on" and 5 minute "off" cycle.  One could simply do that by delays, but such simple delays are called "blocking" as the MCU is 100% occupied with doing the counting.  A better way is to use a timer, such as Timer 1 (TMR1).  It's 16-bit on lower end PIC's.  A 32.768 kHz crystal for clocking the timer will give 2-second "rollovers"  (2^16 = 65536 = 2x32,768).  Each rollover can fire an interrupt.  5 min = 300 seconds = 150 rollovers.  30 second = 15 rollovers.  Just keep track of the rollovers and start or stop the lubricator alternately as indicated. 

Now, if you start and stop TMR1 (bit<0> in T1CON register), it and whatever register you use to keep track of rollovers will retain their counts.  So, for instance, if the lubricator had been running 15 s before it was stopped, then it will start and run 15 s more.  If it had been off for 3 minutes, before the pump stopped., it will start with a 2 minute wait before starting to pump lubricant.  A nice thing about TMR1 is that you can write to its registers, THR1H:THR1L.  You can also write to the rollover count register.  Let's say time had run 3 minutes (off period) before being turned off and on again. You could adjust the subsequent delayed start time , if you wanted to.

If you go a little more complex, TMR1 also operates in power saving modes and can wake the MCU on a rollover.

Problem 3:  Interface between MCU and lubricator.  You can use a relay or mosfet switch. The relay requires more current, so you may want to use a latching relay to avoid having to keep that pin asserted.

Hope that helps.  Note, interrupts are helpful, but are not required.  Pretty much anything they do can also be done by polling.


 
« Last Edit: January 31, 2022, 03:04:30 pm by jpanhalt »
 

Offline ShaydzmiTopic starter

  • Regular Contributor
  • *
  • Posts: 117
  • Country: ma
Re: PIC: Code for a timer pulses with pause/resume ability
« Reply #18 on: January 31, 2022, 03:44:35 pm »
I need to explain my words again:

i have two things: 1 A machine needs to be oiled every now and then.
                           2- An Oiler oiling the machine.
I need to program an MCU to get this job (oiling) done.
(Forget about the lubricator and the pump)


Quote
Problem 1: How to tell the microcontroller (MCU) the MACHINE is on or off.

The machine has a relay contact that closes when it's running, I will use it to tell the MCU that the machine is running when it is doing so.

Quote
Problem 2: How to run the OILER.

The oiler has an input that makes it inject oil when it (the input pin) is high, so the MCU will do this job via an intermediate.

Quote
Problem 3:  Interface between MCU and lubricator.

It is an easy job, I'll take care of this myself. The problem is the code.
 

Offline ShaydzmiTopic starter

  • Regular Contributor
  • *
  • Posts: 117
  • Country: ma
Re: PIC: Code for a timer pulses with pause/resume ability
« Reply #19 on: January 31, 2022, 03:55:24 pm »
Also, I want to be able to adjust On/Off times via pushbuttons and see the setting and the counting on a 7-segment display.
 

Offline jpanhalt

  • Super Contributor
  • ***
  • Posts: 4810
  • Country: us
Re: PIC: Code for a timer pulses with pause/resume ability
« Reply #20 on: January 31, 2022, 04:03:46 pm »
Your first posts gave the impression that you wanted to do it yourself in C but didn't know where to start.  I was trying to give you some direction of where to start.  Now, if you want someone to do the coding for you and add an adjustable user interface, I cannot do that for you in C.  Maybe someone else will.

Good luck.
 
The following users thanked this post: Shaydzmi

Offline ShaydzmiTopic starter

  • Regular Contributor
  • *
  • Posts: 117
  • Country: ma
Re: PIC: Code for a timer pulses with pause/resume ability
« Reply #21 on: January 31, 2022, 04:13:23 pm »
No, I do want to do it myself, I need guidance only along the way.

Quote
I was trying to give you some direction of where to start.
Thank you very much, I appreciate your help, I hope you don't stop it.
 

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 11282
  • Country: fi
Re: PIC: Code for a timer pulses with pause/resume ability
« Reply #22 on: January 31, 2022, 05:26:54 pm »
As your time scale is sloooow, and I'm assuming it doesn't need to be super exact, I'd suggest you start by writing an infinite while(1) loop, inside which you call a blocking delay function (like _delay_ms(1000) in AVR library; I'm sure something pre-existing is available on PIC, too, but I don't personally PIC).

Then, turn general purpose output pins high and low in that loop and see what happens.

Add a variable like
int32_t count = 0;

and
count++;
on every round.

Start adding if-else logic like if (count > 10), to turn the outputs on and off as you like.

Work from there, little by little.
 
The following users thanked this post: Shaydzmi

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3550
  • Country: ca
Re: PIC: Code for a timer pulses with pause/resume ability
« Reply #23 on: February 01, 2022, 04:32:27 pm »
The logic is very simple:

Code: [Select]
while (1) { // do what is inside brackets forever

  if (run) { // do what is inside brackets if run is high, don't do it if it's low
    output_pin = 1;   // turn the output on
    delay (on_time);  // wait the "on time" keeping the output high

    output_pin = 0;   // turn the output off
    delay (off_time);  // wait the "off time" keeping the output low
  }
}

This will do it. The minor difference to your scheme is this: if the run signal goes low during the on-pulse, the on-pulse will run to the end. If this is a problem, you can correct this when you become more familiar with the programming.
 
The following users thanked this post: Siwastaja, Shaydzmi

Offline ShaydzmiTopic starter

  • Regular Contributor
  • *
  • Posts: 117
  • Country: ma
Re: PIC: Code for a timer pulses with pause/resume ability
« Reply #24 on: March 20, 2022, 09:37:09 pm »
Hi,

It has been a longtime worth of thinking and learning, but still I didn't succeed in achieving my goal!
To simplify the problem, I'll try to blink the LED while using the push button (BTN) as a control.

I want to do a code that can turn an LED ON and OFF as the following:
while BTN=0 : LED_OFF xx seconds
              LED_ON xx seconds
if BTN=1 :   LED_OFF immidiatly , but when BTN=0 again, LED resumes its blinking from last state it was upon before BTN=1, not counting from the beginning.
 
For example:

LED off 100s. 
LED on 10s.

 If the LED had been OFF 60 s before BTN=1, then it will be OFF for 40 s more when BTN=0.  If the LED had been ON 7 s before BTN=1, then it will be ON for 3 s more when BTN=0.

1444561-0

This is one of my tries:
Code: [Select]
#define LED PORTA.F0
#define BTN PORTB.F0
unsigned int cnt;
 //Timer0
//Prescaler 1:64; TMR0 Preload = 6; Actual Interrupt Time : 8 ms

void InitTimer0(){
  OPTION_REG = 0x05;
  TMR0 = 6;
  INTCON = 0b10110000;
}

void Interrupt(){
  if (TMR0IF_bit)
  {
     cnt++;
     TMR0IF_bit = 0;
     TMR0 = 6;

  }

}

void main() {
OPTION_REG = 0x05;
INTCON = 0b10110000;
    TRISA.F0=0;
    TRISB.F0=1;
    TRISB.F1=0;
    TRISA.F1=0;
    PORTA.F1=0;
    LED=0;
    do      {
                     if(BTN==0)   LED=0;
                     if(BTN==1 && cnt==125) LED=0;
                     if(BTN==1 && cnt==250) LED=1;
                     if(cnt==500) cnt=0;
             }
     while(1) ;
     
}

Can you help me about what's wrong with this code? And how to solve the problem?
« Last Edit: March 20, 2022, 09:41:05 pm by Shaydzmi »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf

 

-->