Author Topic: Long time loops in PIC Micro  (Read 9511 times)

0 Members and 1 Guest are viewing this topic.

Offline ed_reardonTopic starter

  • Regular Contributor
  • *
  • Posts: 131
  • Country: gb
Long time loops in PIC Micro
« on: October 19, 2016, 07:16:53 am »
Hi all,

  I want to know if I'm about to embark on the futile here,  I'm very fresh at this, I'm after pointers but I'm happy to go away and do the work.  I'm just finding very conflicting things online though.
I am fixed to a PIC18F1330.

My aim is to produce the following:

- Output A to run at a certain frequency for 5 minutes.
- Output A to then run at a different frequency indefinitely.
- Output A to run at a different speed if it is interrupted by input A.

I'm fine with everything except this annoying five minute delay which I read conflicting things about whether it is possible to do or not.   I've read that using a for loop with a define second then nesting it with minutes is possible, some saying no matter what you do the watchdog will take precedence.

This delay can be woefully inaccurate, as much as a minute either way presents no problem.

I'll tell you how fresh to this I am,  if a for loop is interupted does it reset or does it carry on when it resumes?  Do I need to add code to clear the loop every time it is quit (forcibly?)

Am I attempting the impossible here?  Any pointers as to how such a thing might be done if it is possible?  I'm not asking for chunks of code but a hint on the rough concept would be ideal?

Cheers,
Ed.
« Last Edit: October 19, 2016, 07:19:08 am by ed_reardon »
 

Offline obiwanjacobi

  • Frequent Contributor
  • **
  • Posts: 988
  • Country: nl
  • What's this yippee-yayoh pin you talk about!?
    • Marctronix Blog
Re: Long time loops in PIC Micro
« Reply #1 on: October 19, 2016, 07:35:03 am »
It all starts with a time base. So setup a timer (overflow interrupt?) that is the basis of your counting. Use prescalers to make the time-out as long as possible.

Then divide the 'ticks' you get from the timer further down by counting...
You can generate the 'specific frequency' with another timer.
The rest is simple after that.

[2c]
[I do not know PIC but these general concepts should be available in your MCU]
Arduino Template Library | Zalt Z80 Computer
Wrong code should not compile!
 
The following users thanked this post: ed_reardon

Offline ed_reardonTopic starter

  • Regular Contributor
  • *
  • Posts: 131
  • Country: gb
Re: Long time loops in PIC Micro
« Reply #2 on: October 19, 2016, 07:39:30 am »
It all starts with a time base. So setup a timer (overflow interrupt?) that is the basis of your counting. Use prescalers to make the time-out as long as possible.

Then divide the 'ticks' you get from the timer further down by counting...
You can generate the 'specific frequency' with another timer.
The rest is simple after that.

[2c]
[I do not know PIC but these general concepts should be available in your MCU]
Thank you for that obiwanjocbi that's very helpful.  I'm currently researching prescaling.

However this leaves me with another dumb question,  if I prescale the timer this will only affect a loop where I call it?  Not the whole program as I need very fast switching for the frequency output.

I'm probably malformed that question,  but basically if I prescale for the loop this won't affect my __delay_us elsewhere in the program?
 

Online Howardlong

  • Super Contributor
  • ***
  • Posts: 5319
  • Country: gb
Re: Long time loops in PIC Micro
« Reply #3 on: October 19, 2016, 07:57:51 am »
I would approach this as follows:

O use a timer to create a tick every millisecond or so
O use an interrupt on the timer to count up a word of memory every tick
O use the PWM peripheral to generate your Output A
O use either an INT interrupt pin for your input A
O run the device in a low power mode waiting for interrupts
O in the super loop, check the INT pin's flag and ticker count

 
The following users thanked this post: ed_reardon

Offline ed_reardonTopic starter

  • Regular Contributor
  • *
  • Posts: 131
  • Country: gb
Re: Long time loops in PIC Micro
« Reply #4 on: October 19, 2016, 08:03:48 am »
Cheers Howardlong!

Much to go away and research here! I'll get there in the end.

A week ago I was convinced I'd never get a pin to flash on and off,  so it's just a matter of chipping away until I get there!

Would I have enough memory to count say five minutes in milliseconds?
 

Offline obiwanjacobi

  • Frequent Contributor
  • **
  • Posts: 988
  • Country: nl
  • What's this yippee-yayoh pin you talk about!?
    • Marctronix Blog
Re: Long time loops in PIC Micro
« Reply #5 on: October 19, 2016, 08:08:15 am »
However this leaves me with another dumb question,  if I prescale the timer this will only affect a loop where I call it?  Not the whole program as I need very fast switching for the frequency output.

I'm probably malformed that question,  but basically if I prescale for the loop this won't affect my __delay_us elsewhere in the program?

There are (probably) lots of prescalers. There is probably also one for the central clock, so that is NOT the one you need. You need to look for a prescaler that clocks the timer/counter (hardware) in your PIC. Reading the datasheet for your specific device may help a lot getting this clear. I know its intimidating at first, just start with the section about timers and go from there. If you read something you don't know or understand, try to look it up in other chapters of the datasheet. That way, you slowly acquaint yourself with your device.

Start simple with just a small part/component of what you're trying to do, for instance, setup the timer (with its prescaler) and let the main-loop dump out the counter value (dump text to the PC or just make a pin toggle and attach a led/scope on that). See how the value-increments change as you change the prescaler. Then try to attach an overflow-interrupt to the timer, etc. Small steps.
Arduino Template Library | Zalt Z80 Computer
Wrong code should not compile!
 

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 12860
Re: Long time loops in PIC Micro
« Reply #6 on: October 19, 2016, 09:05:44 am »
Your chosen PIC has a motor control PWM module with only ONE timebase.   It is capable of generating a squarewave in the background, and as the timebase is a 12 bit counter, it has fairly fine control of the output frequency, but as its only got a single timebase it cant output two different frequencies at the same time.  Also its restricted to six specific pins that the module can control.   

If those restrictions are compatible with your requirements, you can follow Howard's suggestion to use it for the output A,  and use the 16 bit  Timers 0 or 1 for all other timing.
They have  /2N prescalers, and work from a base frequency of Fosc/4.  Timer 0 prescaler can do up to /256 but Timer 1 prescaler only goes up to /8.  If you are using their prescalers, its better to use their natural rollover period as the timebase as every time they are written to the prescaler gets cleared, so you loose a fraction of a tick with every write, and the exact number of Fosc/4 cycles lost depends on the number of instruction cycles since the last increment - very awkward for precision timing.

If you use a slow 'tick' timebase you'll need the frequency change input A to generate an interrupt so that the output frequency can be changed quickly, rather than on the next timebase 'tick'.   If you use a much higher 'tick' rate, greater than the max delay you can tolerate responding to input A you can poll it.

For us to give better advice, you'd need to put some approximate numbers on the frequencies and the max delay responding to input A.
 

Offline 22swg

  • Frequent Contributor
  • **
  • Posts: 274
  • Country: gb
Re: Long time loops in PIC Micro
« Reply #7 on: October 19, 2016, 09:31:17 am »
Run the pic at 32,768 Hz , timer will give you an rtc  count .   
Check your tongue, your belly and your lust. Better to enjoy someone else’s madness.
 

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 12860
Re: Long time loops in PIC Micro
« Reply #8 on: October 19, 2016, 10:03:01 am »
*Dont* do that unless your output frequencies are well under 100Hz as the system clock controls the temporal resolution of the output frequencies you can generate and a 32768 Hz Fosc clock will make it impossible to generate frequencies above about 80Hz with even 10% accuracy apart from a limited set of 'spot' frequencies below approx 2 KHz which are exact divisors of Fosc/4
 

Offline ed_reardonTopic starter

  • Regular Contributor
  • *
  • Posts: 131
  • Country: gb
Re: Long time loops in PIC Micro
« Reply #9 on: October 19, 2016, 10:15:14 am »
Cheers all, thank you all so much for your help and input.

Fortunately I only require one input pin and one output pin, that is the sum total of the device. It's to control a stepper driver so one PWM pin is ideal.

I require frequencies of aprox 1kHz, 2kHz and 7kHz (none of which are desired to be very accurate) so as I understand that bit is covered.

Much to learn, I've got about 14 days at two hours a day to try and come up with something so wish me luck. I'm very new to this but I'm trying to learn as much as I can!

Thanks again,
Ed
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: Long time loops in PIC Micro
« Reply #10 on: October 19, 2016, 10:22:05 am »
Quote
Am I attempting the impossible here?

You are attempting more than you are capable of at this point. Itself not a bad thing but it does make your life easier if you start with the basic.

In this case, try to code a long delay and see if you can do it. there are numerous ways of doing it, each with its advantages and shortcomings. if you can master a few, it will lay a solid ground for your future.
================================
https://dannyelectronics.wordpress.com/
 

Offline ed_reardonTopic starter

  • Regular Contributor
  • *
  • Posts: 131
  • Country: gb
Re: Long time loops in PIC Micro
« Reply #11 on: October 19, 2016, 10:29:45 am »
Quote
Am I attempting the impossible here?

You are attempting more than you are capable of at this point. Itself not a bad thing but it does make your life easier if you start with the basic.

In this case, try to code a long delay and see if you can do it. there are numerous ways of doing it, each with its advantages and shortcomings. if you can master a few, it will lay a solid ground for your future.
Oh I agree Danny!

Only way is to suck it up and learn it!

I shall start 'fiddling!'
 

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 12860
Re: Long time loops in PIC Micro
« Reply #12 on: October 19, 2016, 10:34:02 am »
I'd start by confirming you can program the PWM module to generate each of the frequencies.  You'll want a function to set it up then one to change it to each of the frequencies.  Beware of glitches when changing the frequency, especially when going to a higher frequency as you need to tweak the duty cycle registers to keep it at 50% (or whatever duty cycle you need) - see the UDIS bit (datasheet section 14.13 PWM Update Lockout) for how to prevent incomplete updates.

Then try to do something simple with an external interrupt for input A e.g. light a LED on another pin, and figure out how to act on both edges.  An IOC (interrupt on change) pin may be easier - as it inherently triggers on both edges.

Then all you've got left to do is the timing.   Remember that if you use a long _delay_ms(), once its started you are committed to it.  Yes an interrupt can go off and do something else, but there is no way to cut short the _delay_ms() once its started.  Also _delay_ms() has severe limitations on the maximum time it can handle.  IIRC 179200 instruction cycles, which is only 22.4ms at the maximum Fosc your chip can run at, so there is a strong incentive to learn timer interrupts so you can set up a more reasonable tick rate, and not have your timing distorted by loop overhead.

If you give your word of honour this is not an academic assignment for credit in a MCU course, we can point you at specific code that can ease your timing problems.  However if you are going to be marked on the algorithm you've chosen and its implementation, we have to take a step back and can only point you to general resources, or help you debug code you have written yourself.
« Last Edit: October 19, 2016, 10:38:57 am by Ian.M »
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: Long time loops in PIC Micro
« Reply #13 on: October 19, 2016, 11:27:22 am »
"Only way is to suck it up and learn it!"

Yeah.

At this point, don't worry about the hardware as that's easy to deal with later. Think about instead the logic and basic approach you need

Two typical approached exist and multiple variations of them.

1. Have a timer that generate a signal when the duration is up. The timer can be a hardware one or a software one or a hybrid.

Your code will set, and start the timer and then check for its signal when the desired duration has elapsed.

2. Loop around and count the number of cycled. If the loop is of a known duration, you know the number of cycles you will need to run to waste your desired time duration.

Obviously, you can implement them however you want but that's the gist of it.
================================
https://dannyelectronics.wordpress.com/
 

Offline ed_reardonTopic starter

  • Regular Contributor
  • *
  • Posts: 131
  • Country: gb
Re: Long time loops in PIC Micro
« Reply #14 on: October 19, 2016, 11:28:25 am »
You can have my word and I'll gladly affirm this is for no academic pursuit whatsoever.

However at the moment I need to try and learn this stuff, all I'd ask is that if I posted up some code you'd tell me what I'd got wrong.

I'm trying to avoid bolting together bits of code (although that'd make my life easier!) and try and have a better understanding.

Time to get learning.

Cheers,
Ed
 

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 12860
Re: Long time loops in PIC Micro
« Reply #15 on: October 19, 2016, 12:02:53 pm »
I'll chuck a code snippet at you that will let you do longer software delays than the native delay macros can handle.  Its good out to over a minute.
Code: [Select]
//Just a simple delay, tuned for accuracy
//XC8 v1.35 Free mode @30MHz on PIC18
#define DELTUNE 1.2
#define DELTUNE1 2.666
void DelayMs(unsigned int ms) {
   if(!ms) return; //Handle zero case
   __delay_us(1000-DELTUNE1);
    while(--ms)
       __delay_us(1000-DELTUNE); // Tuning breakpoint here
}
DELTUNE compensates for loop overhead and DELTUNE1 for function entry/exit overhead.  They will need tweaking if you want accuracy. see http://www.microchip.com/forums/m946599.aspx

Here's another snippet for an ISR to implement a 1/10 second 'tick' counter that's as accurate as the crystal over long periods.  Individual ticks jitter about a bit by up to one tick period, but the correction is carried forward from tick to tick.  It rolls over after about 13 1/2 YEARS.  :-DD.  A 16 bit version has a 109 minute rollover.  Bump up the tick rate to 100 per second if you need better accuracy for short periods.
The natural timer rollover rate must be between the tick rate and half the tick rate .
Code: [Select]
#include <stdint.h>
Code: [Select]
volatile uint32_t ticks=0; // tick count in 1/10 s units

#define COUNT100MS 62500UL // for 10Hz tick rate
#define T1ROLLOVER 0x10000UL

#define SECONDS *10
#define MINUTES *600
#define HOURS *36000

//ISR
void interrupt ISR(void) {
static uint16_t excess=0;

if(PIE1bits.TMR1IE && PIR1bits.TMR1IF) {
PIR1bits.TMR1IF=0;
ticks++;
excess+=T1ROLLOVER-COUNT100MS;
if(excess>=COUNT100MS) {
excess-=COUNT100MS;
ticks++;
}
}
}
It was written for a PIC16 so will need some tweaking for a PIC18. COUNT100MS is the number of timer increments per tick. It should be between 32768 and 65535.  N.B. when the correction is applied 'ticks' double increments so never test if it is exactly equal to some number, only use inequaities.

You would have to set up Timer1 and enable its interrupt yourself as the PIC18 version differs too much from the PIC16 version for it to directly help you. 

Also you need to disable interrupts while reading 'ticks' in the main program so you don't get it while its being changed. e.g.:
Code: [Select]
di();
t=ticks; //Read ticks with interrupts disabled
ei();
if(t>5 MINUTES){
   //do whatever here
}
I prefer a macro 'ATOMIC' to handle the di()/ei() so I can simply do:
Code: [Select]
ATOMIC t=ticks;See http://www.microchip.com/forums/m839163.aspx for details. and reasons why you need to disable the interrupts while manipulating a multibyte variable shared with an ISR.
« Last Edit: October 19, 2016, 12:13:12 pm by Ian.M »
 

Online Howardlong

  • Super Contributor
  • ***
  • Posts: 5319
  • Country: gb
Re: Long time loops in PIC Micro
« Reply #16 on: October 19, 2016, 01:52:55 pm »

[/code]
I prefer a macro 'ATOMIC' to handle the di()/ei() so I can simply do:
Code: [Select]
ATOMIC t=ticks;See http://www.microchip.com/forums/m839163.aspx for details. and reasons why you need to disable the interrupts while manipulating a multibyte variable shared with an ISR.

Nice! I've not convinced myself I prefer it over an explicit GIE=0/GIE=1, but it's very neat nevertheless.
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: Long time loops in PIC Micro
« Reply #17 on: October 19, 2016, 02:00:27 pm »
It is a very risky piece of code. I would consider it s bug.

================================
https://dannyelectronics.wordpress.com/
 

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 12860
Re: Long time loops in PIC Micro
« Reply #18 on: October 19, 2016, 02:08:37 pm »
It is a very risky piece of code. I would consider it s bug.
Its documented, so its a FEATURE.  >:D

Sure its risky - if you misuse it.  So are ei() and di().  Any time you interact with the hardware at a lower level than the C language model, bad things can happen if you are careless.  I wrote it to provide a di() ... ei() wrapper for small critical sections. If you wrap a function call or anything else that could conceal another di() ... ei() pair with it or use it from an ISR or before setting up and enabling the interrupts, you are too moronic to be developing for the 8 bit PICs.

How it helps me: I can easily see which statements or small blocks are critical sections. Before I wrote it, I found ei() and di() just get lost in the forest when reading through code, and its all too easy to keep interrupts disabled for longer than is strictly necessary then a few edits later end up with an execution path that fails to reenable them..
« Last Edit: October 19, 2016, 03:00:21 pm by Ian.M »
 

Offline SteveyG

  • Supporter
  • ****
  • Posts: 991
  • Country: gb
  • Soldering Equipment Guru
Re: Long time loops in PIC Micro
« Reply #19 on: October 19, 2016, 02:37:05 pm »
Your chosen PIC has a motor control PWM module with only ONE timebase. 

There are multiple separate timers though, each with prescalers and postscalers. Unless there needs to be any synchronisation with the motor PWM, it shouldn't be difficult.
YouTube Channel: https://www.youtube.com/user/sdgelectronics/
Use code: “SDG5” to get 5% off JBC Equipment at Kaisertech
 

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 12860
Re: Long time loops in PIC Micro
« Reply #20 on: October 19, 2016, 02:55:29 pm »
Yes, (although only the PWM module has a postscaler) and its not particularly difficult. Most of us who are familiar with the toolchain and the PIC18 range could knock it out in an afternoon.

However my point was that it can only generate ONE frequency at a time autonomously, so if the project is going to suffer from feeping creaturitis and need another output, then the simple approach of using the PWM is no longer viable.   You can generate extra frequencies using a timer and a pin toggle and timer reload ISR hung off the high priority vector, and for one more output that's not too bad, but it then gets fuglier for multiple outputs and if they aren't harmonically related, you'll be so far down the rabbit hole it would be better to start over with a chip with enough standard (E)CCP modules.
« Last Edit: October 19, 2016, 02:57:58 pm by Ian.M »
 

Offline ed_reardonTopic starter

  • Regular Contributor
  • *
  • Posts: 131
  • Country: gb
Re: Long time loops in PIC Micro
« Reply #21 on: October 19, 2016, 03:45:20 pm »
All good points taken on board.

This is a modification to an existing system, basically it's to save me a bit of faff at work! This fortunately can't creep any more.

The timer can be crude (to the extent of a minute each way) but I'm going to try to learnt how to do it 'properly' so that the next project where I need critical timing will hopefully be easier!


Thanks again for all the help, much to go away and research!

Cheers,
Ed
 

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 12860
Re: Long time loops in PIC Micro
« Reply #22 on: October 19, 2016, 03:57:06 pm »
That may make it harder if you are stuck with the input and output pins of the existing design.
If you are unlucky, the output pin isn't PWM capable and maybe the input pin isn't interrupt capable either.  You'd have to toggle an arbitrary output pin in the PWM timebase interrupt, and run it at double the frequency you want, polling the input pin in the same ISR.  Still easily doable - just a bit more of a PITA to get working.
 

Offline NivagSwerdna

  • Super Contributor
  • ***
  • Posts: 2495
  • Country: gb
Re: Long time loops in PIC Micro
« Reply #23 on: October 19, 2016, 04:11:31 pm »
Am I attempting the impossible here?  Any pointers as to how such a thing might be done if it is possible?  I'm not asking for chunks of code but a hint on the rough concept would be ideal?
Rather than having a for loop or even a while loop it might be worth rethinking your application and thinking more in terms of the hardware.
As has been pointed out there is a timer from which you can generate an interrupt and use pre-scaling to make that overflow interrupt occur at not too frequent intervals.  Your main program can be as simple as

while (true) {}

and then put the logic in the interrupt routines... e.g. on overflow then increment a timer and if that has reached a certain value change state and behaviour a different way until some other condition has been reached.

The prettiest solution will probably have some very simple logic in the main loop but a good chunk of the logic in the interrupt routines.

Each peripheral will have different nuances and generate different interrupts each... read each section of the datasheet at a time and see what you can get them to do.  The power of the controller is the hardware bits and pieces.

Have fun!
 

Offline NivagSwerdna

  • Super Contributor
  • ***
  • Posts: 2495
  • Country: gb
Re: Long time loops in PIC Micro
« Reply #24 on: October 19, 2016, 04:45:10 pm »
- Output A to run at a certain frequency for 5 minutes.
- Output A to then run at a different frequency indefinitely.
- Output A to run at a different speed if it is interrupted by input A.
Can you be a bit more specific?  What is your clock frequency?  What frequency do you want to generate?  What sort of wave?  Looks like the PWM module, although complex, should make your application very simple.

Try and draw a finite state machine diagram of the modes your application will have and the transitions between each mode.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf