chipKIT® Development Platform

Inspired by Arduino™

Need testers for SoftPWMServo library

Created Thu, 18 Aug 2011 03:46:42 +0000 by EmbeddedMan


EmbeddedMan

Thu, 18 Aug 2011 03:46:42 +0000

I just got done writing a PWM and Servo output library for MPIDE/PIC32. It allows one to do analogWrite() style output, as well as RC Servo output, on all pins simultaneously (up to 85 at once). It is pretty easy to use, and hopefully will be useful to some people.

It does not us any timers, but runs completely in the background by hooking into the CoreTimer interrupt. It is double buffered for glitchless transitions. The internal resolution of the PWM and Servo pulses is 25ns, although (obviously) this is not an accuracy and can't be guaranteed because this is just a software implementation. However, you should be able to get your pulses to within about 500ns of where you want them worst case.

I think. That's where the testing comes in. <grin> I need some help testing it out before making it final.

Here's a little movie of it running 10 RC servos at the same time (all pins are actually outputting RC servo pulses, but I only had 10 working servos) : [url]http://www.youtube.com/watch?v=q2GlwfWwr3w[/url]

If you'd like, you can download it from here : [url]http://www.schmalzhaus.com/UBW32/SoftPWMServo_v1_0.zip[/url] To install, you need to do two things:

  1. Take the wiring.c and wiring.h files and copy them into your /mpide-022-win-20110809-test/hardware/pic32/cores/pic32/ folder (copy over the existing files that are there).

  2. Then copy the SoftPWMServo folder from the zip file into /mpide-022-win-20110809-test/hardware/pic32/libraries/ and then re-start MPIDE.

(Obviously modify the paths for your own installation of MPIDE)

Let me know if you find any problems, or have any questions. Also, read the README.TXT file. It explains a lot about how the library works, and what the timing restrictions are, and the jitter too.

There are five examples that you can load up and start running too.

*Brian


Addidis

Fri, 19 Aug 2011 19:06:30 +0000

I am noticing some undesired movement every few minutes. Still playing around with it , over all nice work. But every 3-5 mins it moves 20 degrees and back.


EmbeddedMan

Fri, 19 Aug 2011 19:22:14 +0000

Ok, good. That's the kind of feedback I'm looking for.

Can you post the simplest sketch that exhibits the problem? Does it change if you have more or less pins enabled? Does it only happen with certain servo pulse durations?

Thanks!!

*Brian


Addidis

Fri, 19 Aug 2011 20:45:32 +0000

Just the simple servo example. I switched to pin 2. It does it regardless of possition , but im only really using 2 , full open full closed. I was going to hot glue a servo to the door lock.

my goal was to get it to work asap, quick and dirty.... Im pretty sure the serial is overflowing but w/e. It works twice then needs a reset. Quick and dirty,

#include <SoftPWMServo.h>

int pos = 0; // variable to store the servo position, in microseconds const int pin = 2; // Choose any pin number on your board int inByte = 0; // incoming serial byte

void setup() { // start serial port at 9600 bps: Serial.begin(9600);

}

void loop() { if (Serial.available() > 0) { // get incoming byte: inByte = Serial.read();

switch (inByte){ case 'u': SoftPWMServoServoWrite(pin, 1000); break; case 'l': SoftPWMServoServoWrite(pin, 2000); break; delay(35); }
inByte =0; } }

UPDATE Works flawlessly with HW pwm.


EmbeddedMan

Sun, 21 Aug 2011 15:54:15 +0000

OK, I've reproduced the bug. I think it happens every 107 seconds when the Core Timer oveflows from 0xFFFFFFFF to 0x00000000.

I'm now adding code to handle this situation, and will provide an updated library shortly.

*Brian


EmbeddedMan

Mon, 22 Aug 2011 14:44:51 +0000

New version ready:

I've released version 1.1 of the SoftPWMServo library. The main change was the fixing of the bug reported above.

You can download the new library from here : [url]http://www.schmalzhaus.com/UBW32/SoftPWMServo_v1_1.zip[/url]

If you are just updating the library, you only need to copy the new SoftPWMServo.cpp and SoftPWMServo.h files over.

Please let me know if you find any bugs with this new version.

*Brian


Addidis

Mon, 22 Aug 2011 15:24:29 +0000

Nice, I will Give it another go shortly.


Dre4mPT

Tue, 29 Nov 2011 18:54:45 +0000

Hi!

It's good if you update always the first post with newer version!

I'm getting the hold version and then when I continue reading the post view v1.1!

Thanks!


EmbeddedMan

Wed, 30 Nov 2011 03:53:12 +0000

Well, all of the latest releases of MPIDE have the latest version of this library already included, so there isn't really a need to download it separately anymore I guess.

*Brian


slayer1991

Wed, 30 Nov 2011 15:17:58 +0000

Take a look at my last post here [url]http://www.chipkit.org/forum/viewtopic.php?f=15&t=590&start=10[/url]. What is your pwm pulse frequency compared to the led fade one?


EmbeddedMan

Wed, 30 Nov 2011 21:31:11 +0000

Where is the fade example code? I'm not familiar with it.

Our SoftPWMServo library outputs PWM pulses at the same rate as analogWrite(), which is 490Hz.

*Brian


edanielreyes

Fri, 17 Feb 2012 19:33:49 +0000

Hello

I'm new using ChipKit32 and I'm having some problems.

I'd be happy if you answer this question. Can I use this library with ChipKit uno32?


EmbeddedMan

Sat, 18 Feb 2012 02:37:40 +0000

Yes, it works great on the Uno32, Max32, UBW32, CUI32, etc.

What types of problems are you seeing?

*Brian


davidESPCI

Thu, 25 Oct 2012 17:05:15 +0000

Hi EmbeddedMan,

I will need to use a PWM output on a Max32. Before seeing your post, I was thinking to use a digital output an to do a PWM signal with the functions digitalWrite(), micros() and/or delayMicroseconds().

What is better between using your library or the previous method ?

Thanks !


EmbeddedMan

Thu, 25 Oct 2012 21:01:59 +0000

Pros for the software method: you can use any I/O pin, you can use all of them at the same time (i.e. lots more simultaneous servos), and doesn't use any hardware resources.

Pros for the standard hardware method: less jitter in servo output (not normally a concern), is the standard way to do servos (so code is already written for it).

*Brian


davidESPCI

Sat, 27 Oct 2012 11:00:57 +0000

In my application, I am just permitted to use one output of the max32 in the same time. Indeed, the output will excite a transistor used in commutation in order to commute 4 darlington in order to inject 8A distributed in 4 different circuits.

Because of the high amount of current in the external circuit and because I don't want to buy a one thousand power supply (!), I just can use one output at each time.

But I will need to generate typically the square signal on the max32 output at a frequency between 1 to 1000 Hz with pulse width of 100µs (will change after certainly).

I think that the software solution is the best one, just in order to keep the flexibility in the change of the value.

Do you think that is a good idea ?


EmbeddedMan

Sat, 27 Oct 2012 13:29:40 +0000

David, I think you should use a hardware PWM. Since only only need one channel output (I think) you can control a single PWM pin with more accuracy than with software PWM.

*Brian


davidESPCI

Sat, 27 Oct 2012 13:53:51 +0000

Thanks Brian for your answer.

Can I change easily the frequency of the PWM with analogWrite() ? I need to use 5 different signals. Four are mono frequency signals from 1Hz to 1kHz. But I have a complex signal that is composed by a train of pulse at 1kHz and just after by a train of pulse at 500Hz (just after means 1ms after). Will it be doable ?

David


EmbeddedMan

Sat, 27 Oct 2012 18:54:32 +0000

No. You will need to read the PIC32 datasheet and write to the PWM (they're called Output Compare) registers directly.

  • Brian

domoarigato

Thu, 22 Nov 2012 15:59:41 +0000

I found a small bug in the SoftPWMServoRawWrite function:

// And if this pin already has this PWM Value, then don't do anything.
    if (Value == Chan[InactiveBuffer][Pin].PWMValue)
    {
        return SOFTPWMSERVO_OK;
    }

should be:

// And if this pin already has this PWM Value, then don't do anything.
    if (Value == Chan[ActiveBuffer][Pin].PWMValue)
    {
        return SOFTPWMSERVO_OK;
    }

You should be checking for a duplicate of the [color=#40BF00]Active[/color] value, not the [color=#FF8000]Inactive[/color] value.

This bug prevents the application from switching between 2 different PWM values alternately.

  • Garrett

EmbeddedMan

Fri, 23 Nov 2012 04:28:12 +0000

Garrett,

Many thanks! I'll put that change into the next MPIDE build.

You must be using the library a lot to have discovered this bug. What project(s) are you using it for?

*Brian


domoarigato

Fri, 23 Nov 2012 14:53:12 +0000

Thanks Brian,

Your library couldn't have come at a better time for me. Thanks a lot for your contribution! I'm building a robot arm with image and distance sensors. The ChipKit PIC32 board with your library is great for this application! :mrgreen:

Garrett


Jacob Christ

Fri, 23 Nov 2012 15:48:30 +0000

Brian,

So, is your SoftPWM code in the core?

Jacob


EmbeddedMan

Fri, 23 Nov 2012 18:37:12 +0000

Jacob,

Well, it all depends on how you define 'core'. <grin>

The SoftPWMServo library has been distributed with MPIDE for quite some time now. However, it is simply still just a library, not inside the PIC32 folder. I don't expect that to change.

*Brian


Jacob Christ

Fri, 23 Nov 2012 19:57:19 +0000

I guess, I meant distributed with MPIDE. Its nice to know that its there. This partially address what I was talking about the other day with analogWrite not working on some pins. Only partially because if your following Arduino documentation you might now know that this soft version exists for chipKIT (As I didn't and I'm pretty tuned in).

Jacob


PICedh

Thu, 20 Dec 2012 23:12:21 +0000

Hello

I want to use this lib with a servo but I can't rotate the servo more than 90°.

I would like to be able to rotate with an angle of 180°, it works with the standard servo lib but not with the SoftPWMServo lib

I think it is an issue with the min and max pulse delay but I don't know how to update them

I use an CHIPKIT UNO

thanks


EmbeddedMan

Fri, 21 Dec 2012 16:36:30 +0000

By default the the max is set to 2.0ms. This is the normal range for most RC servos.

To get an extended range, you need to use the SoftPWMServoSetFrameTime() function to extend the max range of all soft servo outputs. Then you can use the SoftPWMServoServoWrite() function, or the SoftPWMServoRawWrite() function to set the pin's pulse width to whatever you'd like. See SoftPWMServo.h for more complete details.

Also see the ChangeFrameTime example that comes with the library to see how do do this.

*Brian


PICedh

Fri, 21 Dec 2012 16:51:22 +0000

My servo is a standard hobby servo that works fine with the Servo Lib. So I think it needs pulse within 1 and 2 ms as usual.

I think the SoftPWMServo lib doesn't pulse within 1 and 2 ms but maybe between 1.2 and 1.8 ms

where can come the issue?


EmbeddedMan

Fri, 21 Dec 2012 21:53:55 +0000

Have you measured the output of the SoftPWM library? If you do SoftPWMServoServoWrite(pin, 1000); it should output 1.0ms pulse, and SoftPWMServoServoWrite(pin, 2000); should output 2.0ms pulse. If you have measured it and this is not the case, please let me know.

*Brian


PICedh

Sat, 22 Dec 2012 21:54:04 +0000

i have no oscillo so I can't measure the pulse


EmbeddedMan

Sat, 22 Dec 2012 23:03:55 +0000

OK. When I run that code, it gives me the right duration of pulses. So I'm not sure what's different in your case.

*Brian


PICedh

Sun, 23 Dec 2012 14:34:09 +0000

hello,

I have followed your first recommendation, I have increased the frame time from 80000 ticks to 100000 ticks and it works

I still don't understand why it works fine without any change with the standard servo lib

for info SOFTPWMSERVO_DEFAULT_FRAME_TIME = 80000 and CORE_TICKS_PER_US = 40

here my new code:

void setup() { Serial.begin(9600); // initialize serial port }

void loop() { SoftPWMServoSetFrameTime (100000); SoftPWMServoRawWrite(34, 100000,SOFTPWMSERVO_SERVO); // Left delay (5000); SoftPWMServoRawWrite(34, 60000,SOFTPWMSERVO_SERVO); // center delay (5000); SoftPWMServoRawWrite(34, 20000,SOFTPWMSERVO_SERVO); //right delay (5000);


PICedh

Sun, 23 Dec 2012 14:34:09 +0000

hello,

I have followed your first recommendation, I have increased the frame time from 80000 ticks to 100000 ticks and it works

I still don't understand why it works fine without any change with the standard servo lib

for info SOFTPWMSERVO_DEFAULT_FRAME_TIME = 80000 and CORE_TICKS_PER_US = 40

here my new code:

void setup() { Serial.begin(9600); // initialize serial port }

void loop() { SoftPWMServoSetFrameTime (100000); SoftPWMServoRawWrite(34, 100000,SOFTPWMSERVO_SERVO); // Left delay (5000); SoftPWMServoRawWrite(34, 60000,SOFTPWMSERVO_SERVO); // center delay (5000); SoftPWMServoRawWrite(34, 20000,SOFTPWMSERVO_SERVO); //right delay (5000);


danialn

Mon, 18 Mar 2013 19:17:24 +0000

Hello,

I have modified a the ServoTest that comes with the SoftPWMServo Library to run a servo clockwise (1.0 ms pulse) for 3 seconds, stop (1.5 ms pulse) for 1 second, then CCW (2.0 ms pulse) for 3 seconds, finally stop (1.5 ms pulse) for 1 second, then repeat. I checked the output with the scope and the second 1.5 ms pulse does not appear. The 1 second time delay and LD5 goes off for the one second as shown in the code. (I have added code to turn on the LED on the ChipKIT UNO32 (pin 43) when the servo is running and turn off the LED when the servo is supposed to be stopped.) After watching the operation of the servo, The scope shows that everything is fine except for the second 1 second pulse of 1500 ms to stop the servo. I have pasted the code below. can anyone tell me what I might be missing here?

#include <SoftPWMServo.h>

int pos = 0; // variable to store the servo position, in microseconds const int pin = 8; // Choose any pin number on your board const int LEDpin = 43;

void setup() { SoftPWMServoInit(); // not supposed to be necessary, but a good idea.
SoftPWMServoPinEnable(pin,OUTPUT); pinMode(LEDpin,OUTPUT);

}

void loop() { // DIRECTION ClockWise pos = 1000; SoftPWMServoServoWrite(pin, pos);
digitalWrite(LEDpin,HIGH);
delay(3000);

// STOP pos = 1500; SoftPWMServoServoWrite(pin, pos);
digitalWrite(LEDpin,LOW); delay(1000); // waits 1 second before changing positionss

// Direction CounterClockWise pos = 2000; SoftPWMServoServoWrite(pin, pos);
digitalWrite(LEDpin,HIGH); delay(3000);

// STOP
pos = 1500; SoftPWMServoServoWrite(pin, pos);
digitalWrite(LEDpin,LOW); delay(1000); // waits 1 second before changing positionss

}

Thank you,

Dan


EmbeddedMan

Wed, 20 Mar 2013 03:35:30 +0000

Dan, I just ran you code, and I did not see the same problem you are. It worked perfectly for me (always outputting pulses, even during both 1 second long 1.5ms times). I used a Fubarino SD and my scope to verify the output of pin 8.

I'm not sure what could be going wrong with your setup. Can you try a different I/O pin maybe?

*Brian


Andres

Tue, 26 Mar 2013 16:34:22 +0000

Hello, I have a few questions regarding this library:

1.- Wich is the maximum resolution achived for the PWM signals? as I read on the README at github It looks like the tick is just 1 ms, I'm right?

2.- Does It depend so badly to the arduino IDE or structure? I'm trying to compile it for MPLAB X but it has a lot of dependencies from arudino/chipkit libraries. Do you have a core to port it straight to C?

Thank you very much.


EmbeddedMan

Tue, 26 Mar 2013 18:04:22 +0000

Anders,

The ideal resolution (although, NOT guaranteed) is 1/40MHz, or 25ns. That's what gets used to decide when the next edge will occur. However, there are things that will add jitter to each edge and so you can't count on 25ns accurate edges. Because it's a software library, you will have to actually prototype your system and measure it to see what kind of jitter you get when you're running your code. But with just one servo running, it's pretty easy to get close to 25ns accuracy.

I do not have a pure C version of the library, although there are very few things that it depends on that are Arduino specific, so porting it should be pretty easy.

*Brian


mrk3rmit

Wed, 17 Apr 2013 14:00:36 +0000

Excuse me all. Where can i download the libarary?

The link given give me this error "Not Found

The requested URL /UBW32/SoftPWMServo_v1_0.zip was not found on this server.

Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request."

thx in advance :)


EmbeddedMan

Sun, 21 Apr 2013 11:55:27 +0000

Download any recent (in the last year) MPIDE build, and the library comes as part of MPIDE. Go to [url]http://chipkit.net/started/install-chipkit-software/[/url] and download MPIDE. You'll find the SoftPWMServo library in the libraries folder.

*Brian


cobra18t

Thu, 15 Aug 2013 22:52:53 +0000

I am having a similar issue to one previously mentioned. Every 107 seconds, the raw PWM that I use to drive 4 SSRs arranged in an H-bridge fails. After a number of seconds (20-60?), the PWM comes back and I can control my motor again.

This points to a Core Timer overflow issue, but I thought that was addressed in version 1.1 of the library. I am using the SoftPWMServo library bundled with 20120903 MPIDE.

Everything else (LED debugging) in my sketch continues to work when the PWM fails, so I am getting to all the other parts of my code. Since it fails and eventually comes back, it is like the callback is being told the wrong Core Timer count to update.

I have 8 PWM outputs controlling 2 SSR-based H-bridges. I am dealing with low frequencies in the 40-100Hz range on the PWM. PWM duty is updated at a rate around 30Hz.

Any ideas what could cause this?

-Thomas


cobra18t

Thu, 22 Aug 2013 18:17:37 +0000

I upgraded to MPIDE 20130715 hoping that would solve the issue, but no good.

If I am actively driving the motor when 107 seconds passes, PWM continues to work until I disable the PWM pins. When I try to reenable them seconds later, they will not work.

I am controlling the motor PWM via joystick position. If the joystick is near centered, the PWM is disabled. When it goes outside a software defined dead zone, the PWM is reenabled. Maybe the issue is in the Initialize or Disable routines of the library.


EmbeddedMan

Thu, 22 Aug 2013 20:18:51 +0000

I'm not completely surprised by this. The 107s value is when the 32bit Core Timer overflows (at 40MHz). I need to test this out, and figure out the bug in the code when the overflow happens.

Can you create the simplest project you can that exhibits this effect and send it to me or post it to this thread?

Thanks so much for your help-

*Brian


cobra18t

Thu, 22 Aug 2013 21:42:25 +0000

Here is some code that fails after 107s, recovers briefly before failing again after 214s, and so on...

#include &lt;SoftPWMServo.h&gt;

const int LEDPin = 21;

#define PWM_FREQUENCY           (75)
// Number of 40MHz CoreTimer ticks of the default frame time
#define SOFTPWMSERVO_NEW_FRAME_TIME     (F_CPU / 2 / PWM_FREQUENCY)

void setup()
{  
  //outputs
  pinMode(LEDPin, OUTPUT); 
  
  SoftPWMServoPWMWrite(LEDPin,0);
  
  //redefine PWM parameters
  SoftPWMServoSetFrameTime(SOFTPWMSERVO_NEW_FRAME_TIME);
}

void loop()
{
  delay(500);     
  SoftPWMServoPWMWrite(LEDPin,127);
  delay(500); 
  SoftPWMServoPWMWrite(LEDPin,0);
}

cobra18t

Thu, 26 Sep 2013 22:40:16 +0000

Any word on the overflow issue mitigation?

-Thomas


EmbeddedMan

Wed, 02 Oct 2013 13:57:34 +0000

Thomas,

My apologies. I have not had any time to work on this issue. I have the sample code, and I'm sure I can reproduce the problem. I'm just on the tail end of moving to a new location, and am setting up my lab again, which will take a little while. Once that's done, I hope to resume some chipKIT work.

*Brian


illegalbean

Wed, 16 Oct 2013 17:48:43 +0000

Hi Brian,

I was just double checking to see if you had any new information on this issue.

Thanks

Edgard


EmbeddedMan

Sat, 21 Dec 2013 20:33:21 +0000

I believe that the 107s bug is now fixed. If you want to test it out with your system before a new version of MPIDE comes out, simply replace your SoftPWMServo.cpp file with the new one here : [url]https://github.com/chipKIT32/chipKIT32-MAX/raw/master/hardware/pic32/libraries/SoftPWMServo/SoftPWMServo.cpp[/url]

cobra18t - I've also confirmed that with this new version, your example above works properly (at least I can't see any incorrect edges in about 300s of sampling).

*Brian


cobra18t

Mon, 23 Dec 2013 15:56:14 +0000

Outstanding!

I will check this out.

-Thomas


rasmadrak

Sun, 06 Sep 2015 11:23:29 +0000

Hello! Resurrecting an old thread... :)

I've implemented SoftPWMServo and am wondering if there's a way to do the updates manually instead of letting the library use interrupts? This as I need control over my interrupts and the current version interferes with the rendering routine. :) I don't need 100% control for the servos just "good enough", so I figure I could update them on the machine's "spare time" instead of automatically.

There's some really nice code in the library, but I haven't had time to go through it myself. Is there a built in method for this in the library, or need it be custom created? :)

Edit:

Just in case there's nothing built in for manual control, I found this on the interwebs. "Manual control of a servo" - [url]http://blog.zipwhip.com/2012/03/28/manual-control-of-a-servo-on-the-arduino-for-the-zipwhip-textspresso-machine[/url]


majenko

Sun, 06 Sep 2015 15:57:07 +0000

Not really, no - not sure it's possible at all with SoftServoPWM.

The problem is that the waveform is generated using the C0 core timer interrupt. That's part of the chipKIT scheduler system. It's not "updating" the servos, it's actively generating the waveform to set the servo position.

It's not a regular "output this pulse width" event, it's an "is it time to raise or lower this IO line yet?" event.

You could theoretically disable C0 core timer interrupts while you are doing things with critical timing, but who knows what knock-on effect that would have on other things - the C0 core timer is used for millis(), micros(), delay() etc as well as the scheduler.


rasmadrak

Sun, 06 Sep 2015 16:43:07 +0000

I see, servos are a little more complicated than I believed they were. However, since my line-by-line rendering updates at ~15360Hz I believe it should be possible to maintain a steady wave manually for servos inside that function as well. Theoritically it only adds a few lines of code to the rendering (only using two servos) so it should be feasible, and wouldn't interfere with the rendering itself either. :)

Thanks!


EmbeddedMan

Tue, 08 Sep 2015 01:18:52 +0000

Majenko is correct - the way the library is written, it's not possible to tell it when you want the pulses sent on a case-by-case basis.

However, if you want, you can call SoftPWMServoUnload() any time you want all interrupt activity (due to the library) to stop, and then re-start the library after you are done with your vision processing code. Another thing you could do is to make your vision processing interrupt based, and set it to a higher priority than the core timer.

*Brian


rasmadrak

Wed, 09 Sep 2015 07:32:44 +0000

However, if you want, you can call SoftPWMServoUnload() any time you want all interrupt activity (due to the library) to stop, and then re-start the library after you are done with your vision processing code. Another thing you could do is to make your vision processing interrupt based, and set it to a higher priority than the core timer. *Brian

Thanks! I am using a interrupt driven approach with the priority set to 3, what priority does SoftPWM run at? I figure this would be the best way of solving it since the load/unload-routine could possibly take some time to process?

Edit: I'll just go ahead and bump my rendering up to 6-7 and see what happens. :)


majenko

Wed, 09 Sep 2015 10:06:18 +0000

The core timer interrupt (defined in wiring.c) runs at "_CT_IPL_IPC" which is defined (in System_Defs.h) as priority 7.

If you want to get to a higher priority than that you will need to change the CT priority:

setIntPriority(_CORE_TIMER_VECTOR, 4, 0);

That would change the priority to 4 with a sub-priority of 0.

It's anyone's guess what effect that would have on the system though - there' lots that is handled by that CT ISR. You should read through the comments section just above CoreTimerHandler in wiring.c to see what it does:

A CoreTimer Service is a callback routine that will get called when the core timer value equals the last value returned by your service; also known as your requested compare time. When registering a CoreTimerService callback routine, the routine will be called on the next regularly scheduled event currently waiting the CoreTimerHandler. From system start, there is a millisecond CoreTimerService running, so in most cases once you register your callback serivce it should be called within 1 ms of attaching (registering). In some cases if interrupts are diaabled it may be as long as 50 ms before your first call is made. Passed in to your Service is the current value of the CoreTimer count register, this is a rolling count that rolls once every 2^32 / 40000000 ~ 107seconds. The return value from your service should be the next value of count that you want to be notified; logically like setting the compare register; however, CoreTimerHandler is managing several services and will notify you when your value has been hit. You will totally screw up CoreTimerHandler if you set the compare register directly. Here are the rules for writing a CoreTimerService callback routine. The rules:

  1. You do NOT set "compare"!
  2. Do not do anything that could cause CoreTimerHandler to be called recursively. For example, do not enable interrupts as the CT flag is still set and will immeditely cause the system to call CoreTimerHandler.
  3. The value of the count register is passed to you, however this could be several ticks old. Usually this is not a problem. It is allowed for you to read the count register directly, however you must return a compare value that is greater in time (so it can be a uint32 wrapped value than the count value passed to you.
  4. You will NOT be called before your compare value has been hit; however you may be called late should interrupts get disabled.
  5. Unfortunately, because of things like the EEProm writes, you can be called late and you must "catch-up" however best you can and return the next requested "compare" time on your next call.
  6. There are limits to how far in the future you can set your next "compare" time. Right now this is limited to 90 seconds. If you need a longer delay you should be using something other than a CoreTimer Services to do this. You probably should really limit your next "compare" time to less than few seconds.
  7. Your next requested "compare" time MUST be equal to or after (in time) the "current" time as passed in to you. You may add up to 90 seconds to the current time, even if this causes uint32 wrap; but do not subtract from the current time and return that. There is a region known to CoreTimerHandler that is before the current time, but that uint32 "value" is after the current time + 90 seconds.
  8. CoreTimerHandler will keep looping until count is less than whatever the next compare is "after" CT was cleared to insure that CT is not missed. It is possible that you could be called a second time before exiting the CoreTimerHandler ISR if you request a new compare time that is very close to the current time.
  9. After attaching, your service will be called on the next schedule call to CoreTimerHandler. Since there is always a ms service that gets triggered, this will typically mean your first call to your Service will be within 1 ms of attaching, unless interrupts are disabled and you are delayed; it could then be as much as 50ms.
  10. Understand, your callback is being called while executing inside the CoreTimerHandler ISR. Your code should be as fast as possible. If too much time is taken, the ISR may never exit and no sketch will ever run!

So you can see it is a pretty complex and delicate operation and upsetting the balance could have dire consequences; or you may notice no change in the functionality at all. It's a case of "suck it and see". You could end up with your other interrupts causing the CT system to run too slowly, so it causes collisions and crashes. If you use millis() or delay() you could well end up with clock drift and timing inaccuracies (although the "base" clock that it uses is accurate, if the response to the ticks from that clock are delayed or interrupted it can have an effect on the outcome of that response).


rasmadrak

Wed, 09 Sep 2015 15:00:37 +0000

I see... Messing with the core timer is not really desirable, it's something about the word "core" that upsets me. ;) Maybe I can try to change the rendering-routine to draw a single layer (i.e 32 lines) at a time and attach to the CoreTimer instead, with a sub-priority slightly higher than SoftPWMServo.


majenko

Wed, 09 Sep 2015 15:19:33 +0000

It's called "core" because the hardware for it is at the heart of the PIC32. It's actually inside the "Co-Processor 0" which performs various housekeeping tasks including interrupt and exception management, etc. You can't really affect the core timer in any way. You can zero it, and you can query it, and that's about it. It's always running as long as the system clock is running (so not in sleep mode) and always at the same speed (one tick per system clock tick).

With the core timer service in chipKIT you register a core timer service. The core timer handler then looks to see when that service is due to be executed and executes it. You don't have priorities within the core timer services, only "due times". That way things get interleaved between each other. The software PWM is just one of those services that has been registered and gets called at the appropriate intervals.