Functions with Priorities

Hello people!

I would like to write a simple program that takes function priorities into account, and after some consideration and Googling, I can't come up with any feasible methods to make this work. Does anyone have some pointers to share?

The program could include just two functions, one (lets call it "A") with higher priority than the other. A has to perform a task (e.g. multiplication) after every arbitrary time period (e.g. 1ms). At all other times, the other function ("B") can perform whatever it needs to do. So B can be interrupted (English sense of the word) halfway through so A can be performed, and resumes after A is complete.

This can be achieved with interrupts (stick A into the handler), but this approach cannot be expanded for use in a project where A is more than just a simple operation. Moreover, this method will limit the program to having only two different levels of priority (while A is running, no higher priority function can take over).

Any thoughts? Thanks in advance!

NO. You are talking about modern day general purpose microprocessors. Microcontrollers are totally different things than microprocessors. MCUs have only one task to do most of the time. Your requirement needs a 80386 or better. Maybe a more powerful MCU like those in tablets can do task switching or privileges or both.

Sure, write a blink without delay type program that cycles thru a loop executing A every 1mS or whatever.
At the end of A, B can be allowed to run for the balance of time, then must stop and wait for A to happen again, then B can pick up where it was, etc.
Tricky part will be writing B so that it can be done in pieces if it takes that long. Maybe B is just checking an input to see if new data is ready for A to multiply.

I have a fencing machine that does something similar. A big loop runs, every pass thru time is checked to see if a second has gone by. Most of the time it hasn't, so the loop continues to see if a command was received over RF, most of which are ignored unless time is not running. It also checks if a serial message was received saying a touch was scored, and stops the time and turns on the touch lights
If 1 second has passed, the time digits are updated and a set of SPI commands are issued to update the time digits.

So depending on your 2 functions, your request could be doable.

Thanks for replying!

So in general, there's no clean way to accomplish this unless I use a more capable processor (I'm playing with an LPC1768 too). But if it's a somewhat simple program, it can still be done. Interesting!

CrossRoads: This sounds like using an interrupt to set a flag when it's time for A, and check it very frequently throughout the program. I'm not sure how long it takes for a boolean comparison to complete, but if speed is not a factor, sticking the flag checking code in every other line will probably work! :sweat_smile:

How fast do you need to check?
I have another program that checks for fencing touches - every 100uS it toggles an output bit, and checks to see if it came back on another pin, indicating switch closure - it does that for 2 signals, checking to see if switch closure was maintained for 30 loops thru to call it a good touch. Once a touch is detected, the 2nd fencer must score within 40mS or be locked out.
No interrupts used. You can complete a lot of instructions in 100uS - like 1600 insruction cycles.
What's the thing that A needs to do?

I originally thought about implementing something like this for my quadrotor project, which uses two atmega328ps communicating with each other over SPI.

Simplified, A will include reading registers off 3 sensors, running rather computationally intensive attitude heading and reference system algorithms, running 4 PID loops and sending the output to other microcontrollers (in the ESCs).

B will include other functions which are important but do not need strict time keeping like checking battery voltages, telemetry, etc.

Currently, the functions in B are manually assigned to run after A and tested such that the time taken for A+B is still short enough for A to be executed at a specific frequency (400Hz currently). The program can potentially be made to be more efficient with a robust priority control algorithm!

One of my friends did a similar project. He ended up making a shield with MCU on it to read the onboard 6 degree of freedom sensors so his main MCU does the motor control.

I initially considered using that method. However, running the AHRS algorithms on one MCU then passing the data over to another MCU for motor control will mean the 2nd MCU receives data that is "older" than if both MCUs operate in parallel or if they use distributed algorithms (which is the method I'm using currently). Although it's a lot more difficult to implement, the motor control response can be based on data around 1ms "younger".

Still, I'll be able to stuff more auxiliary functions in if prioritized functions can be accomplished cleanly!

I don't think you can or should respond to 1ms change. The motors themselves store rotational energy and that won't drop to zero at the moment you cut power to them. Most accelerometers don't even work at 1KHz anyway. If you respond to that kind of change, you're going to respond to noise more than signal. If you remember your electric circuit course, LCR circuits need time to get rid of energy (resistor damps oscillations) so does the mechanism inside accelerometer, even if it's already critically damped it needs time to settle.

That's definitely true. The 1ms freshness in data is probably not even noticeable. But when deciding between the two methods, it makes more sense to me to choose the one that will provide the smallest lag between sensor readings to motor control, just in case 1ms really does affect the performance and also to give a little more room to breathe with the algorithms. Then again, I was no in hurry to get the project up and running!

400 Hz is 2.5mA, 40,000 instruction cycles. Is that not enough?

Considering the fact that floating point arithmetic emulation is used most of the time, 40,000 really isn't all that many even though I'm using relatively computationally efficient quaternion attitude estimation algorithms. Of course, I can rewrite my entire code to use fixed point arithmetic, which I have explored, but that will be for next time.

It really only gets intense during the additional calculations required for drift compensation (from integrating gyro signals). This is taking into account how reading each sensor via I2C takes 180+us (if I remember correctly). If I use one MCU, there will be certain points where two sensor reads must be executed within the same 2.5ms period.

So, are you using Magdwick quaternion code?
Its pretty fast, with very small optimizations it can run at 333Hz in a bog standard atmega328p, with some aggressive optimizations and smartness, and a bump from 16Mhz to 20Mhz it can be speed-up to probably the needed 450Hz, but what are you controlling that need such speed?

If it is an UAV like a plane it cant response as fast as 450Hz, and a quadcopter cant also do it, because the motors/props have a ratter big inertia, so its nice to have quaternions at 1Khz, but there is no purpose to that, and remember the bandwidth of your sensors

Hello Senso, I wrote my own code but some parts are similar to Madgwick's. Mine's pretty decent too I suppose, but I've never tried it on a single atmega328p. The read times for the sensors are too long so I didn't even bother. I use it to control a quadrotor. It's only nearing completion, so I don't know how the frequency of the control loop will affect the stability. Having read some forums, I decided 450Hz would be a relatively safe choice.

I'm building the quadrotor to learn the process (I'm waiting to go to college anyway), so I designed all the hardware and software such that it can be improved in the future. I'm under the impression smaller aircraft will benefit from higher frequency control loops (impression spawned from unknown sources), so everything's designed with that in mind. I might even be changing over to using an ARM processor, which will eliminate all the tedious work with synchronising the two atmegas setup I have right now, plus have a huge performance increase such that I can use more complex algorithms if necessary.

Regarding the sensors, I still haven't found the need to use the maximum bandwidth!

Anyway, we seemed to have deviated from the main topic by quite a bit! XD

What sensors are you using?
If I'm not mistaken the ITG3200 that is a common gyro cant even go up to 1kHz, the accelerometers usually can do it but not the gyros as they have much lower natural resonant frequencies.

I have also tried to use ARM for some time, but fighting with CodeSourcery, Makefiles, and having to steal linker scripts, loaders and startup code from commercial IDE's made me give up on the thing, at least for now, maybe I will try them again using a free version of keil or something along those lines.

Yep I'm using the ITG3200. By 1kHz, do you mean read frequency or bandwidth or something else?

ARM is indeed tedious. I took something like 2 days to get the LED blinking with timers as compared to 1 minute with Arduino. I'm using Yagarto with Eclipse though. The BlueBoard LPC1768-H comes with a nice secondary bootloader which I'm currently using since I haven't purchased a JTAG adapter. All the problems others talk about with OpenOCD etc make me quite hesitant about taking that path at this point.

Then again, a 100MHz, 32bit MCU capable of single cycle integer multiplication is simply irresistible.