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.

[SOLVED] Multi tasking with PIC controller for stepper motors

Status
Not open for further replies.

Ranbeer Singh

Full Member level 5
Joined
Jul 30, 2015
Messages
259
Helped
22
Reputation
44
Reaction score
22
Trophy points
1,298
Location
Faridabad India
Activity points
3,266
Hello

In my project i have 16x2 LCD, 3 button Keyboard, 3 stepper motors, 2 temperature sensor & 2 heaters. I have tested my project with out motor control codes. But when i was writing codes for motor control i found that motor codes run every time. i mean if i execute other codes motor controlling output pulse disturb. Because my all program in series. Extra time delay disturb motor controlling sequence.

LCD display take 60ms for write a character to display.
2 ADC & other calculations takes time.
Menu enter takes 5 sec. and more.

Please help to handle it.
 

Zip and post your complete project files.

Solution:L It is time to learn and use Timer Interrupts.
 

That is why every one uses RTOS like https://www.freertos.org/
To handle multiple things at once inside microcontrollers in a elegant manner.
 

Zip and post your complete project files.
Sorry

I do not have my code at this time because i work on it at the home. I will put Zip file tomorrow.
Can you explain me how to use timer for parallel tasking.

i was writing like bellow.
Code:
void runMotor1() {
          PORTC = 0x03;
          delay(According_ADC)
          PORTC = 0x06;
          delay(According_ADC)
          PORTC = 0x0c;
          delay(According_ADC)
          PORTC = 0x09;
          delay(According_ADC)
}

and in Main function infinite loop


Code:
while(1)
     {
          ALL_ADC();
          Display_temp();                       // 60ms for every character 
          Control_Heater();
          if(Menu_Button) MenuEnter();     // Wait for 3 sec continues press menu button and after enter in Menu_edit() 
                                                          and work until user use this function.
          Control_Motor1();
          Control_Motor2();
          Control_Motor3();
     }
 

create a timer interrupt which calls below function
runMotor1()
 
The whole stepper code has to be implemented in Timer ISR or you can set a flag in Timer ISR and then check if this flag is true in while(1) loop and if true, update the stepper using a counter and switch statement.

- - - Updated - - -

To Provide you an example code you have to mention what PIC and what frequency Crystal you are using. Also mention the Compiler used.
 
To Provide you an example code you have to mention what PIC and what frequency Crystal you are using. Also mention the Compiler used.

I am using PIC18f45k20, C18 and frequency is 20 Mhz.

This is perfect for single motor but i want to run three motors at a time (with variable speed). Would i use three timers for three motors? because every motor has separate ADC channel.
 

No, One timer is enough but I have to see what delays are you suing in the Control_Motor_x() functions. Please post the code inside one Motor Control function.

I need to know the delays in ms used between providing the step control sequence to the motor X. You need three flags to start or stop individual motors.
 

Indeed I was confused for described problem so i did'not write codes for motor control sequence. I have 24V/3A unipolar stepper motor and want to run 0-50 rpm.
 

Ok. What is the Step angle of your motors ? Does all 3 steppers have same Step angle ?
 

Such task can be performed only with interrupts. RTOS is too much for so simple task and requeres a lot of resurces.
First and important rule - don't use delays. Delays allowed only during initialization. 'main' should be looped in cycle, where you just checking the flags and performs simple things like change pin state or buffer handling. Interrup routines should be as faster as possible - only change flag statets.
 

You need to provide 167 steps per second for each motor.

Step angle = 1.8

For 360 degrees (1 revolution) steps required is 200.

For 50 RPM steps required is 10000.

approx 167 steps in 1 sec (1000 ms)

So, time for each step is 5.988 ms
 
Last edited:
First and important rule - don't use delays. Delays allowed only during initialization.

Easyrider83 Thanks for your interest

How can control motor steps without delay?
 

Create a timer interrupt of 5.988 ms and assign the 4 or 8 step values one on each interrupt to the motor in sequence.
 

But i am using delays inside the function. But timer call to function at interrupt time.

as per my function :-

0011

Delay

0110

Delay

1100

Delay

1001

Delay
 

I can it with sifting on every calling.

- - - Updated - - -

Haaaa....Yes I will not do this anymore.

- - - Updated - - -

Code:
char data=0;     // global variable
void runMotor1() 
{
      PORTC = data+3;
      if(data==12) data = 0;
}

- - - Updated - - -

Are these codes right?
 

Try this code. You have to only modify the code inside

Code:
InitTimer1()

and

Code:
Interrupt()

according to your C18 Compiler syntax.

This code only works if you don't have any delays in while(1) loop code. If other things in while(1) loop consume time then it is better to put the whole stepper code inside the Timer ISR.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
//Assuming Steppers use PORTB, PORTC and PORTD lower 4 bits
 
typedef struct bitFields {
   unsigned char B0:1;
   unsigned char B1:1;
   unsigned char B2:1;
   unsigned char B3:1;
   unsigned char B4:1;
   unsigned char B5:1;
   unsigned char B6:1;
   unsigned char B7:1;
}BIT_FIELD_TYPE;
 
struct BIT_FIELD_TYPE myFlags;
 
char step_number[4] = {0xC0, 0x06, 0x03, 0x09};
                         
char i = 0, j = 0, k = 0;
 
#define FALSE 0
#define TRUE 1
 
#define CLEAR 0
#define SET 1
 
#define STEPPER_MOTOR_1_PORT PORTB
#define STEPPER_MOTOR_2_PORT PORTC
#define STEPPER_MOTOR_3_PORT PORTD
 
#define update_stepper_sequence_flag myFlags.B0;
#define stepper_1_on_off_flag myFlags.B1
#define stepper_2_on_off_flag myFlags.B2
#define stepper_3_on_off_flag myFlags.B3
 
//Timer1
//Prescaler 1:1; TMR1 Preload = 35596; Actual Interrupt Time : 5.988 ms
//Place/Copy this part in declaration section
void InitTimer1(){
    T1CON = 0x01;
    TMR1IF_bit = 0;
    TMR1H = 0x8B;
    TMR1L = 0x0C;
    TMR1IE_bit = 1;
    INTCON = 0xC0;
}
 
void Interrupt() {
    if(TMR1IF_bit) {
      TMR1IF_bit = 0;
      TMR1H = 0x8B;
      TMR1L = 0x0C;
      //Enter your code here
      update_stepper_sequence_flag = TRUE;
    }
}
 
 
void main() {
 
    TRISB = 0x00;
    TRISC = 0x00;
    TRISD = 0x00;
 
    InitTimer1();
 
    while(1) {
    
          if(update_stepper_sequence_flag == TRUE) {
                if(stepper_1_on_off_flag == TRUE) {
                      STEPPER_MOTOR_1_PORT = step_number[i++];
                      if(i >= 4)i = 0;
                }
                
                if(stepper_2_on_off_flag == TRUE) {
                      STEPPER_MOTOR_2_PORT = step_number[j++];
                      if(j >= 4)j = 0;
 
                }
                
                if(stepper_3_on_off_flag == TRUE) {
                      STEPPER_MOTOR_3_PORT = step_number[k++];
                      if(k >= 4)k = 0;
                }
                
                update_stepper_sequence_flag = CLEAR;
          }
    }
}

 
Last edited:
Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top