CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Best way to update Timer 2 to avoid unwelcome glitches

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
lindsay.wilson.88



Joined: 11 Sep 2024
Posts: 40

View user's profile Send private message

Best way to update Timer 2 to avoid unwelcome glitches
PostPosted: Fri Sep 27, 2024 1:43 pm     Reply with quote

Hi,

Sort of touched on this in another discussion, but figured I'd start a fresh one.

Brief background. PIC18F4520 at ~39MHz. I have Timer 2 running and its interrupts enabled. In each interrupt loop, the program sends a pulse to a stepper motor driver (it does a bit more than that, but that's enough for the purposes of this problem). The user can specify a desired frequency over the UART and the program works out the best settings for Timer 2's prescaler, postscaler and period.

For example, the loop might be set to run at anywhere between 1kHz-10kHz.

I initially used setup_timer_2(yadayada), but this will also automatically turn Timer 2 on, which might not be desirable (it can be switched off/on elsewhere in the code). I also had concerns about the possibility of a stray "fast" loop occurring if I happened to try and update the settings part-way through, if that makes sense. This would result in an extra very fast pulse being sent to the stepper motor, which it might not be able to keep up with.

Here's the code I'm currently using (the various registers and bit are previously defined with #byte and #bit):

Code:
is_tmr2_on=TMR2ON; // Make a note of whether TMR2 is on or not
TMR2ON=0; // Turn TMR2 off
T2CON=((tmr2_best_postscaler-1)<<3)|tmr2_best_prescaler_conv; // Write the new prescaler and postscaler to T2CON
PR2=tmr2_best_period; // Write the new period value
if(is_tmr2_on){TMR2ON=1;} // If TMR2 was on before, turn it back on again


And here's a screenshot of some scope traces showing a change in action:

https://imgur.com/a/2khz-to-10khz-DcW9SmZ

Top is pulses being produced by the interrupt loop, bottom is a pulse produced when the timer settings are changed. Nice transition from 2kHz to 10kHz.

I'd be grateful for anyone's thoughts on whether this is the best way to change the Timer 2 settings "on the fly", or if there's some snag that I'm missing here!

Thanks,

Lindsay
newguy



Joined: 24 Jun 2004
Posts: 1909

View user's profile Send private message

PostPosted: Mon Sep 30, 2024 9:08 am     Reply with quote

Enable the timer 2 interrupt. When a command to change settings is received, instead of changing the timer settings immediately, set a flag: new settings are available.

Inside the ISR, if that flag is TRUE, go ahead and change the settings. If not, exit.

Oversimplification, but you'll get the idea. Since T2 controls that pulsetrain, the safest time to alter it is just after a complete pulse has been generated. That's tied to T2.
lindsay.wilson.88



Joined: 11 Sep 2024
Posts: 40

View user's profile Send private message

PostPosted: Mon Sep 30, 2024 9:20 am     Reply with quote

Thanks - I did try something similar to that, basically setting the parameters every time the interrupt loop fires. Unfortunately, whenever T2CON is written (to update the pre and post scalers multipliers), that also resets both the pre and post scaler counters, and this screws up the timing. Things are ok if it's just PR2 that's being updated, but not when the pre/post scalers are updated as well.
newguy



Joined: 24 Jun 2004
Posts: 1909

View user's profile Send private message

PostPosted: Mon Sep 30, 2024 10:49 am     Reply with quote

Then just load the period register (PR2) only.

Code:
#byte PR2 = getenv("SFR:PR2")


And inside your ISR, if appropriate,

Code:
PR2 = new_PR2_value;
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Tue Oct 01, 2024 5:14 am     Reply with quote

I do have to ask why you don't use the PWM to do this???.
The key big thing about the PWM, is when a new time is specified, it
automatically updates on the next reload. Makes glitches impossible.
lindsay.wilson.88



Joined: 11 Sep 2024
Posts: 40

View user's profile Send private message

PostPosted: Tue Oct 01, 2024 7:22 am     Reply with quote

@Ttelmah Mainly laziness and inertia - I've mostly just used timer 1 or 2 in the past for things like this and never even looked at the CCP module 🤣🤣 I went and had a play with it, and things are indeed a lot easier.

The actual PWM mode isn't so good, since the PWM period is still determined by the 8-bit PR2 plus prescaler, so the frequency resolution isn't as good as I'd like (yeah, probably overthinking again, but that's me). Plus I'd have to modify the PCB to use the CCP output pin to drive the stepper drive as it's currently connected to something else.

However, using it in compare mode works great. The 16-bit CCPRx means I only need to do a simple calc to find the best setting for a desired frequency, and the resolution is excellent. Thanks for prompting me into trying it!

Something else which is nagging me. Suppose I've got the interrupt running at 5kHz, so 200us period. My current approach, in the interrupt, is to FIRST read stuff, do calculations (remember that stuff I was doing about the integer multiplication...), and THEN output a step pulse if one is required. Say the amount of time this takes to work out is 20-40us. I.e. it's small, but is variable. The result of this would be a slight variation in the period, between 180-220us, corresponding to the frequency varying between about 4.5-5.5 kHz. I'm trying to decide whether this would be a problem or not.

The alternative is to instead output the step pulse FIRST in the interrupt loop, based on the status of a flag, and use the subsequent calculations to set/clear the flag to determine whether the pulse is output on the next loop. This would make the period between pulses much more consistent, although the position would inevitably then be one step behind where it should be.

Maybe I'm analysing this too much but I'd appreciate your thoughts.
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Tue Oct 01, 2024 7:38 am     Reply with quote

Yes. This is where choosing the PIC carefully comes in (as does having the
flexibility to choose any chip).
If you look at the PIC24's and up, some of these have PWM's where the
frequency is adjustable with a 16bit value, as well as the period. Makes
these brilliant for the sort of needs you have.....
I have quadruple stepper controller boards using these, that are a doddle.
lindsay.wilson.88



Joined: 11 Sep 2024
Posts: 40

View user's profile Send private message

PostPosted: Tue Oct 01, 2024 8:46 am     Reply with quote

I'm beginning to realise that like with most things I'm a bit behind the curve! There's probably lots of amazing things that the 24's could do which I'm missing out on. I've never been that hot on programming and usually prefer hardware - e.g. part of this current project involves interacting with a 2Mhz-clocked 16-bit serial data stream, essentially SPI. Need to both decode what an external device is sending, and also spoof a fixed value to send back. No doubt all this could be done by a fancier micro, but I couldn't get my head around it so went with a bunch of 6 shift registers instead 🤣 They're happily doing their thing and I don't have to worry about programming it. Plus more chips on a board looks cooler.

With the PWM output, what would be the simplest way of "blanking" off the output signal depending on whether or not a step pulse is needed? Set/clear the appropriate TRIS bit?

Also, when in PWM mode, it doesn't look like it generates an interrupt, so presumably there would need to be separate loop running to keep track of positions etc?

I did a quick test to see if any random jitter in pulse period affects the motor and fortunately it doesn't seem to be an issue - I tried about +/-15% random jitter and the motor still tracks position nicely.
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Tue Oct 01, 2024 10:24 am     Reply with quote

Seeing the period to 0 gives a fixed low output.
Sounds as if you don't have to worry about a little jitter.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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