Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Run multiple functions simultaneously μC using C

Status
Not open for further replies.

Solar000

Member level 2
Member level 2
Joined
Feb 6, 2013
Messages
49
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,288
Location
Greece
Activity points
1,649
Hello, i am using microC to program pic16f877a to operate motors and solenoids.
I have some functions making motors move at different space times,for ex. motor1 moves for100ms,stops,moves again for 100ms etc. for 4 loops, motor2 for200ms and so, but i want these functions to start the same time.

Is it possible to do this with micro c for this pic and if not is it possible with another pic or language?
Perhaps i can do it manually like move 2 motors for 100ms, stop, move only 1 motor for another 100ms,stop, but it will take too much code without using loops.

Thank you.
 

you could use timer interrupts (say every 1mSec) with a schedule of events to take place at specified times
are the motors simple ON/OFF, PWM controlled, etc?
 

Right now i am using solenoids so there are on/off operated.
I will search about timer interrupts with schedules, but i dont want the first motor or solenoid to stop when interrupt is executed.

Multithreading in uC ? Are there any uC supporting multithreading ?
 

With a timer system, and a round robin main loop, you can do many things at the 'same' time. Using semaphores to signal status, and states you will have to make all your functions transparent (no software delays and waiting for things to happen.)

You can do this in any type of programming language.

As said, you can also make a interrupt driven event system in the same configuration, but this will also add to the software, and resource overhead.

The timer system will be interrupt driven any way, but normally it is fast enough to use a polled system, via the round robin main loop.
 

Hi,

When you say 100ms ... What precision do you need? Are multiples of 20ms or 10ms ok?

If yes, then run a control loop, timer driven with this timing.

Klaus
 

I think not because i will need more precision but it can work for a start.
Can anyone provide an example or a link with this timer system control loop?

Hi,

When you say 100ms ... What precision do you need? Are multiples of 20ms or 10ms ok?

If yes, then run a control loop, timer driven with this timing.

Klaus


Multithreading is not clear if its possible yet.

Thank you
 

However you do this, a microcontroller can only do one thing at the time.

There will always be a slight difference between occurrences, even if you multithread as you said.

The only way to let several things happen at the same time, is to use synchronizing hardware to execute the pre computed control functions exactly at the same time.

Since you've not said what you want to do with the motors and solenoids, we can't evaluate what your real accuracy or timing should be.
I suppose you know that any mechanical device is far from ideal in its timing. Things does not happen from one nanosecond to the next, even if your code is running that fast. When using a PIC processor, each instruction takes hundreds of nanoseconds to execute, and you really need to count your instructions to get a fast program with timing in the microseconds, if that's your target speed.
 

Hi,

The control loop runs exactly every 10ms (or other value).
* First read all inputs
* Process all data
* Update all outputs

For a motor to run 100ms you just need an integer variable.
Set it to 10 (=10 × 10ms = 100ms)
In control loop decide if it is > 0, if yes: switch motor ON and decrement value; else switch motor OFF.

This are simple tasks for every output. They are absolutely synchronous and exact timing is easy to control.

Klaus

Klaus
 

Think generally a robot when you want to move its right hand up and down every 200ms for a total 2 mins and its left hand up and down every 400 ms for a total again 2 mins.This process should start the same time and time losses will be the same(same construction, at least theoritically).
I will provide more details of my exact project later,its something playing music(drums) but please think it generally as above like any robotic-automated application.

I created functions like music patterns (music time notes) when the song tempo its divided or multiplied so it can produce half notes,eighth notes(1/8),quarter etc.

So basically i want to start something like a thread were
start:
solenoid1 runs functionQuarter(moves up-down every x time) 4 music meters(like 2 mins)
solenoid2 runs functionHalf(moves up-down every 2x time) same
stop

Since you've not said what you want to do with the motors and solenoids, we can't evaluate what your real accuracy or timing should be.


Hope its more clear what i want to do.I can provide some functions later
 

What you have described is referred to as a Time Triggered Architecture (TTA) or more specifically a Time Triggered Event, typically implemented in the form of a scheduler, triggered by a timer and its associated ISR.

One of the best references concerning this topic is Michael J. Pont's Patterns for Time-Triggered Embedded Systems. Although it has been out-of-print for a number of years, new and used copies are still available, also Pont has graciously made the text available free in PDF format, from his PTTES website:

Patterns for Time-Triggered Embedded Systems

The voluminous text is a treasure trove of insights and examples of how to implement various aspects of a TTA embedded system and while the original text and its associated code examples were originally written for the 8051 variants, they have been ported and can be ported to virtually any microcontroller architecture.

I would strong suggest obtaining a copy of the hardback text, while you still can, or at least downloading the PDF version and studying it's contents.

You might also benefit from viewing Pont's introductory course on the topic, fashioned after his other text, Embedded C, available on Youtube:

M01-01 Programming in "Embedded C"

BigDog
 
  • Like
Reactions: xenos

    xenos

    Points: 2
    Helpful Answer Positive Rating
Here are some parts of my functions i want to start running simultaneously

Code:
void Movement(){
TRISD = 0x00;
PORTD = 0x00;

PORTD=0b11111111; //activate the solenoid on port D
Delay_ms(50);
PORTD=0b00000000; //stops it
}

void Movement2(){
TrisC = 0x00;
PortC = 0x00;

PORTC=0b00000110; //activate the solenoid on port C
Delay_ms(50);
PORTC=0b00000000;
}


void Tetarta(const unsigned long Delay,int metra){
int i;
const unsigned long  Tetarto=DelayPBms;
metra=metra*4;

for(i = 0; i < metra; i++){
Delay_ms(Tetarto);
Movement();
}}


void Ogdoa(const unsigned long Delay,int metra){
int i;
metra=metra*4;
const unsigned long  Ogdoo=DelayPBms/2;
for(i = 0; i < metra; i++){
Delay_ms(Ogdoo);
Movement2();
}}


void main(void)
{
const unsigned long DPBms=60000/Tempo;
Tetarta(DPBms,4); Ogdoa(DPBms,4);  //Here is where i want to call these
// two functions to start loops same time on port D and C

}

Can you provide code as an example if its not too much on how can i make it work?
What would you add at main to make these two functions start?
 

Obviously, you need to get rid of the delay functions that are doing nothing until the time has elapsed. It has been already suggested to use interrupt driven timers instead.

There are different ways to handle simulateneous action in terms of C coding.

A real time monitor that dispatches concurrent code can give you a smell of multithreading on a small microcontroller. But PIC16 isn't well suited for event driven task switching due to it's very limited stack.

Similarly, asynchronous time event concepts based on callback functions also suffer from the small stack.

So you'll end up with a topology that scans for pending events in a central scheduler and various "action" routines that perform the respective operation and return after "no time" to the scheduler.
 

Hi,

As said before: you can't run two functions at the same time.

Klaus
 

Ok if FvM wants to post some examples of a central scheduler with events please do as i have difficulties to find ones.

Klaus i think generally you can with posix threads but my pic doesnt support that, so if i dont find schedule events working as i want and cant run two functions then i will just do it manually like :

Code:
PORTC=0b00000110; // practically 
PORTD=0b11111111; // same time activating two ports
Delay_ms(50);
PORTD=0b00000000;
PORTC=0b00000000;
Delay_ms(50);
PORTC=0b00000110;
Delay_ms(50);
PORTC=0b00000000;
Delay_ms(50);
PORTC=0b00000110;
PORTD=0b11111111;
Delay_ms(50);
PORTD=0b00000000;
PORTC=0b00000000;
//etc. (thats very bad way)
 
Last edited:

Hi,

Klaus i think generally you can with posix threads but my pic doesnt support that, so if i dont find schedule events working as i want and cant run two functions then i will just do it manually like :

Or you re-read post#8.

Klaus
 

Is it possible to post a code example based on post 8? because i am not sure i fully understand it.I am afraid that this control loop will activate ports the same times so all motors or solenoids will move every same and its not what i want.
If with this control loop i can activate different ports on different time spaces then please post if you have some code for example if it doesnt take much time to do.
Thank you
 

Hi

will activate ports the same times
It is simply possible to activate/deactivate all desired outputs within 10us. For a motor or solenoid I call this "at the same time"

You should be able to control more than 16 devices independently.

******
First just set up a timer to fire an interrupt every 10ms.

Within the interrupt you could do this:
Code:
* read in all used inputs and store it in variables. ( just to get synchronised input infirmation)
...now process  data like:
* if key1 is pressed: mot1 = 100
* if key2 is pressed AND mot2 = 0 then mot2  =150
* if mot2 = 1 Then valve1=50...
...here only prepare the output port data
* if mot1>0 then: motPort=1, decrement mot1
* if mot2>0 then: motPort=2, decrement mot2
* if valve1>0 then: valvePort=1, decrement valve1
...
Output all prepared port data to the ports
RETI
What does this?
When key1 is pressed the motor1 starts and runs exactly 1 second after key release
When key2 is pressed the motor starts and runs exactely1.5 seconds after key press
Valve1 gets activated 10ms before motor stops and valve stops after exactly 500ms

Klaus
 

I understand your last post but its a difference maybe i didnt say.I dont use buttons to activate solenoids or motors so i can't trigger interrupts externally.
I want to pre program the uC and run it after (without using keys). (
 

You could use a task array
Code:
typedef struct _task_ {
         unsigned short period;
         unsigned short _tmp_countdown;
         boolean (*proc)(void);
} task;
task T[10];

in that case you will have to use a function to set a new 'task' when you want
Code:
void add_task(unsigned short period, boolean (*proc)(void)){
   add proc function to the T[] array and set _tmp_countdown to period
}
On every tmrX interrupt you will set a gobal counter named for example ticks, increased.
During your main loop, you will check if this global counter is greater that zero and:
Code:
while(1){
      ...
      while(ticks){
              disable_interrupt_tmrX
              ticks--;
              enable_interrupt_tmrX
              for every T[]{
                    if(T[i].proc && --T[i]._tmp_countdown == 0){
                          T[i]._tmp_countdown = T[i].period;
                           if( (*(T[i].proc))() == 0)
                                T[i].proc = NULL;//drop this proc
                    }
              }
      }
As you may notice, if proc() returns TRUE, the countdown will start from beginning (with value period), otherwise the proc() is removed from the task array

Of course you will have to implement the various proc procedures, eg
Code:
bool proc_led1(void){
          PORTA ^= 4;//toggle led on RA3
}

ps. pic16 core has limitted high level language functionality. RAM/ROM is also limited. Consider using PIC18 in stead.
 
It looks very helpful, someone else told me to use struct also .I will try to use the example with my code and post parts i may need corrections.
Thank you very much.

I know pic16 is a little old but now i have to finish the project using this, plus it has many outputs i needed.
I wanted to ask (@anyone) for future projects, if you wanted to use latest technology for a robot that its expected and necessery to perform multiple tasks (threads i assume) which uC you will use as the most up to date, contemporary ?
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top