Author Topic: Long time loops in PIC Micro  (Read 9479 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?
 

Offline Howardlong

  • Super Contributor
  • ***
  • Posts: 5317
  • 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: 12849
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: 12849
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: 12849
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: 12849
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 »
 

Offline Howardlong

  • Super Contributor
  • ***
  • Posts: 5317
  • 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: 12849
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: 987
  • 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: 12849
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: 12849
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.
 

Offline cv007

  • Frequent Contributor
  • **
  • Posts: 824
Re: Long time loops in PIC Micro
« Reply #25 on: October 19, 2016, 05:13:32 pm »
Don't overthink. Keep it simple until simple no longer works.

main(){
   //setup for Output_A freq1
   //wait 5 minutes
   uint32_t ms = 1000*60*5;
   for( ; ms; ms-- ){
     //check for input
     if( check_input_A ) break;
     __delay_ms(1);
   }
   //setup for Output A freq2
   for( ;; );
}


I do like my for loops self contained when possible :)
main(){
   //setup for Output_A freq1
   //wait 5 minutes
   for( uint32_t ms = 1000*60*5;
       ms && !Input_A;
       __delay_ms(1), ms-- );
   //setup for Output A freq2
   for( ;; );
}
« Last Edit: October 19, 2016, 05:26:44 pm by cv007 »
 

Offline ed_reardonTopic starter

  • Regular Contributor
  • *
  • Posts: 131
  • Country: gb
Re: Long time loops in PIC Micro
« Reply #26 on: October 19, 2016, 06:31:15 pm »
Thanks again all.

All great suggestions thankfully I'm left with the PWM pin as the unit is already controlled on this.

Baby-steps I think, let me get to grips with simple PWM setup and I'll worry about the rest later. I'm grasping the data sheet slowly and once I've figured out the PWM stuff I'll start on bolting it together.

I got 'v1' with the two speeds in delay_us, I thought my next brainwave would be relatively easy but alas I have much to get to grips with.

Thanks for helping dullard here. I shall go and have a crack at it once I've finished this pint   ^-^

Cheers again,
Ed
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: Long time loops in PIC Micro
« Reply #27 on: October 19, 2016, 10:22:09 pm »
Quote
Don't overthink.

I would take a similar approach as well:

Code: [Select]
  do {OutputA_at_Initial_Freq();} while (elapsed_time<5 min);
  while (1) {
    if(!interrupted_by_A()) OutputA_at_another_Freq();
    else OutputA_at_different_Freq();
  }

depending on your hardware implementation approach, each of the modules could be different but gist is the same.

Whether you need fancy hardware pwm will be dependent on your frequency requirements.
================================
https://dannyelectronics.wordpress.com/
 

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 12849
Re: Long time loops in PIC Micro
« Reply #28 on: October 19, 2016, 10:33:53 pm »
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.
So he could bit-bang the output, but doing so while handling software timekeeping would be a PITA.

If short of time once the PWM is up and running, there's no problem with simply using delay_ms() in a superloop for the 5 minute timing, polling the input in the same loop. 

Personally, I'd use Timer 0 in 8 bit mode to implement a sandwich delay so I don't have to worry about the loop overhead, but I'm fussy that way as the tolerance on the 5 minutes certainly doesn't demand it.

The more advanced techniques aren't actually needed for the simple 1 input 1 output case.  They become valuable when the number of inputs and outputs goes up and you need to run independent processes sharing the hardware resources.
 

Offline ed_reardonTopic starter

  • Regular Contributor
  • *
  • Posts: 131
  • Country: gb
Re: Long time loops in PIC Micro
« Reply #29 on: October 20, 2016, 07:12:13 am »
Quote
Don't overthink.

I would take a similar approach as well:

Code: [Select]
  do {OutputA_at_Initial_Freq();} while (elapsed_time<5 min);
  while (1) {
    if(!interrupted_by_A()) OutputA_at_another_Freq();
    else OutputA_at_different_Freq();
  }

depending on your hardware implementation approach, each of the modules could be different but gist is the same.

Whether you need fancy hardware pwm will be dependent on your frequency requirements.
This is precisely what I want,  as I've stressed a few times it doesn't even need to be accurate in terms of timing,  frequencies can drift 10% without issue and the timing can go a full minute either side.

Basically it's just to trip a motor/pump to pump a little bit quicker to purge the air when it's turned on,  the pump isn't a controlled dose in a critical application.

The 7kHz frequency is just controlled on a button to run the pump even quicker whilst pressed when changing the pumped solution to prime it through.

Thank you all for your input,  I'm quite touched so many have taken time to reply with such in-depth and insightful posts, I certainly do have a lot to learn!

Cheers,
Ed.
 

Offline ed_reardonTopic starter

  • Regular Contributor
  • *
  • Posts: 131
  • Country: gb
Re: Long time loops in PIC Micro
« Reply #30 on: October 22, 2016, 08:26:17 pm »
Sorry it's Ed again.

Right I've had a play with setting up hardware PWM and I think I've got to grips with it, however I think I've dropped a clacker here.

Can RA0/CMP0 be set to deliver a PWM output?  I was convinced I had an PWM pin to play with (long and short, although my 'scope output looks PWM, it's not a PWM pin.)

Can the Comparitor 0 be used to drive a PWM output or am I talking rubbish here?

Cheers,  as always,
Ed.
 

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 12849
Re: Long time loops in PIC Micro
« Reply #31 on: October 22, 2016, 09:20:34 pm »
No.  Your proverbial pooch is screwed and you will have to resort to toggling that pin in software.   The PIC18F1330 comparator module is input only, so even if you added a link to tie a PWM output to a comparator input, the resulting toggling comparator output is only a bit in a SFR, not a signal on a pin.

However all is not lost.  If you write an ISR that simply toggles the pin:
Code: [Select]
void interrupt high_priority HighISR(void){
   LATA^=0x01; //toggle RA0
   PIR3bits.PTIF=0; //Ctear PWM interrupt
}
you can get it to trigger once every PWM cycle giving you half the PWM frequency on RA0.
You don't actually need to enable any of the PWM pins to do this - just set up the timebase and its interrupt:
Code: [Select]
//Set up pin
ADCON1=7; //No analog pins for ADC
CMCON1=7; //No analog pins for Comparator
LATAbits.LATA0=0; //RA0 is output

//Set up interrupt
PTCON0bits.PTOPS=0; //No postscaler
RCONbits.IPEN=1; //Enable interrupt priorities
IPR3bits.PTIP=1; //Assign PWM interrupt to high priority vector
PIE3bits.PTIE=1; //Enable PWM interrupt
INTCONbits.GIEH=1; //Master interrupt enable
That will leave the low priority vector free for your timer ISR for implimenting a tick counter.  However instead of using ei() or di() you must now set/clear INTCONbits.GIEL to enable/disable the low priority interrupts without affecting the squarewave from RA0 being generated by the high priority ISR.

If you need to stop the pin toggling, simply disable PIE3bits.PTIE, then set LATAbits.LATA0 to the desired pin level.  Re-enable  PIE3bits.PTIE  to resume toggling.
« Last Edit: October 22, 2016, 09:54:27 pm by Ian.M »
 
The following users thanked this post: ed_reardon

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 12849
Re: Long time loops in PIC Micro
« Reply #32 on: October 22, 2016, 09:53:48 pm »
bump: more code for Ed!

I'd like to know what the original designer was smoking when they selected the PIC18F1330 - a chip specialised for motor control PWM - then failed to hook up the circuit's output to any PWM capable pin!  |O Whatever it was, it must have been the good stuff . . .  :-DD
« Last Edit: October 22, 2016, 09:57:44 pm by Ian.M »
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: Long time loops in PIC Micro
« Reply #33 on: October 22, 2016, 11:23:06 pm »
Quote
Can RA0/CMP0 be set to deliver a PWM output? 

For things like that you should do it before finalizing the hardware design - unless the mcu supports pin remapping.

Quote
Can the Comparitor 0 be used to drive a PWM output or am I talking rubbish here?

Yes and no. If the mcu supports interrupt on compare match, and you are not looking for really fast pwm frequencies, it can be done: basically, you set up two compares, and at the first compare, you set the pin and at the 2nd compare, you reset the pin.
================================
https://dannyelectronics.wordpress.com/
 

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 12849
Re: Long time loops in PIC Micro
« Reply #34 on: October 23, 2016, 12:19:51 am »
Quote
Can the Comparitor 0 be used to drive a PWM output or am I talking rubbish here?

Yes and no. If the mcu supports interrupt on compare match, and you are not looking for really fast pwm frequencies, it can be done: basically, you set up two compares, and at the first compare, you set the pin and at the 2nd compare, you reset the pin.
It doesn't.   Microchip PWM modules on the older 8 bit chips only permit interrupting on the period timer reload, not on the duty cycle compare*.   Its possible to use an (E)CCP module to interrupt on compare match when it isn't configured for PWM, but this chip doesn't have any ECCP or CCP modules, only PWM modules.

Hence my recommendation to use the period timer reload interrupt to get half the PWM frequency out.

* You can fake it on PPS capable chips, by internally routing the PWM output to an external interrupt input.
« Last Edit: October 23, 2016, 12:23:38 am by Ian.M »
 

Offline Bruce Abbott

  • Frequent Contributor
  • **
  • Posts: 627
  • Country: nz
    • Bruce Abbott's R/C Models and Electronics
Re: Long time loops in PIC Micro
« Reply #35 on: October 23, 2016, 03:01:31 am »
Can RA0/CMP0 be set to deliver a PWM output?  I was convinced I had an PWM pin to play with
The 18F1330 has 6 pins that can output PWM. Why do you have to use RA0?

 

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 12849
Re: Long time loops in PIC Micro
« Reply #36 on: October 23, 2016, 04:07:50 am »
Can RA0/CMP0 be set to deliver a PWM output?  I was convinced I had an PWM pin to play with
The 18F1330 has 6 pins that can output PWM. Why do you have to use RA0?

This is a modification to an existing system, basically it's to save me a bit of faff at work!
So he's stuck with the original chip and pinout unless he wants to rework every unit.
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: Long time loops in PIC Micro
« Reply #37 on: October 23, 2016, 01:38:27 pm »
I took a look at the 18f1330 datasheet and it doesn't have a compare module.

But it does have an interrupt-on-period functionality. So  you can use the pwm module as a timer: load the period register alternately with the duty cycle count and period - duty cycle count.

Essentially what this module does:

Code: [Select]
//my pwm handler
void mypwm(void) {

if (_pwmdc++ & 0x01) { //test for lsb
//lsb = 1 -> reset
PTPER = PWM_PR - PWM_DC; //reset period
PWM_RESET(); //reset pin
} else {
PTPER = PWM_DC; //load dc
PWM_SET(); //set pin
}
}

Now set up the timer to run periodically:

Code: [Select]
ptmr_init(PWM_PS16x | PWM_PEIODIC); //periodic + prescaler
ptmr_setpr(PWM_DC); //initial period is dc
ptmr_act(mypwm); //install user handler
ei(); //enable global interrupts

The code above sets up the pwm module to run in periodic + 16:1 prescaler mode. load the pwm period register with the duty cycle count and install the mypwm routine as the isr handler once the period is reached.

The output waveform, for PWM_PR = 100 and PWM_DC = PWM_PR / 3:
================================
https://dannyelectronics.wordpress.com/
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: Long time loops in PIC Micro
« Reply #38 on: October 23, 2016, 01:40:11 pm »
the downside with this approach is that since it is done via the isr, you cannot generate fast pwm. 20 - 30 ticks to be your minimum resolution.

BTW, it can be used to generate complimentary output too - not shown here.
================================
https://dannyelectronics.wordpress.com/
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: Long time loops in PIC Micro
« Reply #39 on: October 23, 2016, 01:47:40 pm »
here is the same code producing complimentary output: positive polarity on RA0 and negative polarity and RA1/RA2.
================================
https://dannyelectronics.wordpress.com/
 

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 12849
Re: Long time loops in PIC Micro
« Reply #40 on: October 23, 2016, 02:10:33 pm »
@Dannyf,
What compiler or library is that for? 
The O.P.'s using Microchip XC8 (or a very late version of its predecessor HiTech C for PIC18) and the calls you are using don't correspond to anything in their standard libraries or the C18 compatibility PLIB. Microchip Code Configurator doesn't support the PIC18F1330 so it cant be that
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: Long time loops in PIC Micro
« Reply #41 on: October 23, 2016, 04:38:30 pm »
since the pwm module here is used as a timer, the same can be done easily via a regular timer, with or without compare math.

Here is an example of doing it on the good old TIMER0:

Code: [Select]
ptmr0_init(PWM_PS16x | PWM_PEIODIC); //periodic + prescaler
ptmr0_setpr(PWM_DC); //initial period is dc
ptmr0_act(mypwm); //install user handler
ei(); //enable global interrupts

identical output.

As the whole thing is implemented via the interrupt, the timing is repeatable and the while loop is empty. Once set, the operation is fully transparent to the code and the programmer.
================================
https://dannyelectronics.wordpress.com/
 

Offline ed_reardonTopic starter

  • Regular Contributor
  • *
  • Posts: 131
  • Country: gb
Re: Long time loops in PIC Micro
« Reply #42 on: October 23, 2016, 06:19:54 pm »
Cheers all,

As said I'm 'upgrading' an existing system with a good few thousand units to look after customer won't allow a new board per unit to make my day a bit smoother!

I'll look at this in the week but thank you all so much for your input.

I guess there is no such thing as an adaptor socket to make a physical pin reconfiguration?

I have motor pulse on RA0, direction on RA1 and speed control on RB0.
 

Offline ed_reardonTopic starter

  • Regular Contributor
  • *
  • Posts: 131
  • Country: gb
Re: Long time loops in PIC Micro
« Reply #43 on: October 23, 2016, 06:32:48 pm »
If RA0 was set to high-impedance is there any penalty for making a bodge wire on the PIC socket underside from a PWM pin to RA0.

I know it's a bit 'how ya doin' as Dave would say but it's plausable from my cost/time angle?

 

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 12849
Re: Long time loops in PIC Micro
« Reply #44 on: October 23, 2016, 06:57:25 pm »
As said I'm 'upgrading' an existing system with a good few thousand units to look after customer won't allow a new board per unit to make my day a bit smoother!
I suspected that was the case.
Quote
I guess there is no such thing as an adaptor socket to make a physical pin reconfiguration?

I have motor pulse on RA0, direction on RA1 and speed control on RB0.
If you were going down that road, you'd use a QFN package part on a DIL footprint adapter board.  However the board would be entirely custom. 
If RA0 was set to high-impedance is there any penalty for making a bodge wire on the PIC socket underside from a PWM pin to RA0.

I know it's a bit 'how ya doin' as Dave would say but it's plausable from my cost/time angle?
A bodge wire would let you re-route the real PWM but would be extra work per unit.  Assuming RB4 isn't in use, running it diagonally across the socket would be the simplest option. (or if access to the underside of the board is poor, directly across the top of the chip soldered to the base of its pins).  However there is absolutely no point in changing hardware* for >2K units if it can be done in software, and so far it looks like it can.  Things that could change that would be if the PIC has to simultaneously perform other time-critical functions you haven't mentioned.   

I would personally be entirely satisfied with the toggle arbitrary pin in a high priority PTI  ISR approach if all you need is a 50% duty cycle variable frequency squarewave.  Once set up its nearly as 'fire & forget' as using a PWM pin. The pin output will be jitter free and as accurate as the PIC's clock source and 16 bit period timer allow, and its effect on timekeeping will be negligible amount of extra jitter on the timer interrupt (maybe 20 to 30 Tcy additional latency).

* 2000 x 5 minutes per unit is a month of normal working hours. The software solution should only take a few hours extra to develop ==> a hardware mod just to relocate one PWM doesn't pay for >50 units.
« Last Edit: October 23, 2016, 10:06:25 pm by Ian.M »
 

Offline ed_reardonTopic starter

  • Regular Contributor
  • *
  • Posts: 131
  • Country: gb
Re: Long time loops in PIC Micro
« Reply #45 on: October 23, 2016, 07:37:45 pm »
That's most helpful, cheers Ian M.

The board (for the PIC element) consists of a PIC looking for the pins I've mentioned above, that's the sum total of its connections - fortunately it's through-hole and easy to remove (90s?)

At the moment it bit-bangs a controller with two speeds either the looped "slow" or when the user presses a button it runs faster until they release.

That's the whole shebang!

It drives an off-the-shelf Stepper driver.
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: Long time loops in PIC Micro
« Reply #46 on: October 23, 2016, 09:59:30 pm »
with moderate speeds, it is easier to just use an interrupt to flip RA0. By loading different offsets, you can control the frequency of the pulse train.
================================
https://dannyelectronics.wordpress.com/
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf