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

Urgent doubt

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
betobrito



Joined: 27 Nov 2014
Posts: 3
Location: Maceió, Alagoas

View user's profile Send private message

Urgent doubt
PostPosted: Sat Nov 29, 2014 11:21 am     Reply with quote

Good afternoon, guys, I'm creating a clock using 3 stepper motors, I have a problem, I'm using timer0 to count the seconds, but as it generates an interrupt to count 60 seconds and the second motor starts moving the engine of the second stands still, is there any way to get the engine of the second working independently of the other way, because as it is the time base, the same can not stop.


Thank you all.
Ttelmah



Joined: 11 Mar 2010
Posts: 19553

View user's profile Send private message

PostPosted: Sat Nov 29, 2014 12:03 pm     Reply with quote

You need to rethink how you are working.
The master 'tick' interrupt should be at the maximum frequency you need to update the stepper (or more). You output one stepper pattern on each of these interrupts, using a count to say whether the pattern should change. You start changing the pattern every ten interrupts (say), then reduce the number of interrupts between each change update, to accelerate the motor. To stop the motor you decelerate and then set the count to some 'max' value, which it takes as a code to say "don't change". This interrupt runs whatever your code is doing.
Then the motor is continuously updated (even if the 'update' does nothing), and just controlled by what your main code sets it to do.
betobrito



Joined: 27 Nov 2014
Posts: 3
Location: Maceió, Alagoas

View user's profile Send private message

PostPosted: Sat Nov 29, 2014 1:00 pm     Reply with quote

Ttelmah wrote:
You need to rethink how you are working.
The master 'tick' interrupt should be at the maximum frequency you need to update the stepper (or more). You output one stepper pattern on each of these interrupts, using a count to say whether the pattern should change. You start changing the pattern every ten interrupts (say), then reduce the number of interrupts between each change update, to accelerate the motor. To stop the motor you decelerate and then set the count to some 'max' value, which it takes as a code to say "don't change". This interrupt runs whatever your code is doing.
Then the motor is continuously updated (even if the 'update' does nothing), and just controlled by what your main code sets it to do.


Thanks for the answer, but you would have a sample code for me to take a look? this is really hard for me to understand the operation.
Ttelmah



Joined: 11 Mar 2010
Posts: 19553

View user's profile Send private message

PostPosted: Sat Nov 29, 2014 3:11 pm     Reply with quote

Seriously, that is the program....

It depends on so many things:

How the motors are driven?. Direct drive or step/direction?. Bipolar or unipolar?. How fast you drive them?. Whether you accelerate them or just step at a slow speed?. etc. etc.. Once the motor driver as a standalone entity is written the rest of the program only becomes a handful of lines.
betobrito



Joined: 27 Nov 2014
Posts: 3
Location: Maceió, Alagoas

View user's profile Send private message

PostPosted: Sat Nov 29, 2014 4:11 pm     Reply with quote

Ttelmah wrote:
Seriously, that is the program....

It depends on so many things:

How the motors are driven?. Direct drive or step/direction?. Bipolar or unipolar?. How fast you drive them?. Whether you accelerate them or just step at a slow speed?. etc. etc.. Once the motor driver as a standalone entity is written the rest of the program only becomes a handful of lines.


The project I'm doing is a clock, it will be divided into 3 stepper motors, the first take care of seconds that will be our time basis, because you can never be stopped, he's a certain amount of steps every second. The second motor is driven so that the first 60 seconds to complete, moving a certain number of steps it passed through the third and is triggered according to the second motor, so complete 60 minutes, he walks a certain number of steps reported.

As I said my problem is that by completing 60 seconds and the second engine is being fired the first still not counting the seconds, waiting for the second motor finish to continue to tell. I do not know if there is any way to do this with only a PIC microcontroller, I is already planning on doing this with 3 Pic's.
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

Re: Urgent doubt
PostPosted: Sat Nov 29, 2014 5:22 pm     Reply with quote

betobrito wrote:
Good afternoon, guys, I'm creating a clock using 3 stepper motors, I have a problem, I'm using timer0 to count the seconds, but as it generates an interrupt to count 60 seconds and the second motor starts moving the engine of the second stands still, is there any way to get the engine of the second working independently of the other way, because as it is the time base, the same can not stop.


Thank you all.

You're not giving us much to work on.
No code, no schematics, nothing.

There's no right way to do your job, just loads of ones which work.
You seem to be stuck on getting a PIC to do several tasks in sequence, (seconds motor, minutes motor, hours motor).
Yet you want all three to appear to happen simultaneously.

One way goes like this.
Create a tick at a regular interval. On each tick:-
1) Perform a little of the seconds motor task.
2) Perform a little of the minutes motor task.
3) Perform a little of the hours motor task.
4) Wait for the next tick.

Motors are slow, they'll not notice that they're only working part time.

Mike
gpsmikey



Joined: 16 Nov 2010
Posts: 588
Location: Kirkland, WA

View user's profile Send private message

PostPosted: Sat Nov 29, 2014 7:41 pm     Reply with quote

Not sure I completely understand the original post, but a couple of things come to mind - are you sure your your power supply is up to driving 3 motors at the same time (like when seconds rolls over into minutes which rolls over to advance the hour hand). Do you have a plan to allow you to set all the motors to a known state so the hour, minute and second hands are in the correct position relative to each other (at 0 minutes, the hour hand should be on an hour mark etc.) If your power supply is not sufficient, when you try to run two motors at the same time, the voltage will drop and cause problems - that may be what you are describing.

mikey
_________________
mikey
-- you can't have too many gadgets or too much disk space !
old engineering saying: 1+1 = 3 for sufficiently large values of 1 or small values of 3
Ttelmah



Joined: 11 Mar 2010
Posts: 19553

View user's profile Send private message

PostPosted: Sun Nov 30, 2014 1:37 am     Reply with quote

I suspect he has the 'tick' interrupt doing timings, and then a 'mainline' code that steps the motors. When one motor is stepping, the other can't easily be. Hence the problem.
He needs to move the motor operations into the timer, so it updates the steps automatically.
However how to do this will depend on a huge amount of factors (as already outlined).
Ttelmah



Joined: 11 Mar 2010
Posts: 19553

View user's profile Send private message

PostPosted: Sun Nov 30, 2014 3:50 am     Reply with quote

Now, this is going to be of no use to you without a lot of thought.
This is setup to drive two unipolar motors using the high and low bits of port B. Half stepping, at a maximum rate of 1000steps per second. It starts one, then the other, then stops the first, then the other. It accelerates the motor over 11 cycles, from an initial step rate of 50Hz to the 1000Hz rate, when asked to stop it does the opposite.

The code in the interrupt, looks very long (it is...). However it only goes through about 1/10th of the code on each interrupt. Most is simply skipped.

Code:

//Put your preprocessor definitions here. Code if configured for a chip
//at 20MHz
#include <18F4520.h>
#use delay(crystal=20000000)

unsigned int16 time=0; //master one second clock

#define TICKS_PER_SECOND 5000
#define START_POSN 0b00010001 //start phase pattern
unsigned int phases[] = {0b0001,0b0011,0b0010,0b0110,0b0100,0b1100,0b1000,0b1001};
#define MAX_POS 7
//eight phase patterns for unipolar half-step stepper
//code actually steps through these in reverse order

unsigned int profile[] = {5,6,8,11,16,22,30,45,70,100,140,250};
#define SLOW 11 //slowest speed.
//acceleration profile for stepper motor
//250 interrupts between first two steps, then 140, etc..

enum action {still,start,accel,hold,stop,decel,stopped} to_do[2] = {still,still};
//motor action commands

#USE FAST_IO(B)

//macros to handle the two nibbles
#define MASK_MOTOR1 port_pattern = (port_pattern & 0xF0) | mask //low four bits
#define MASK_MOTOR2 port_pattern = (port_pattern & 0x0F) | swap(mask) //high four bits

//macro to increment the position through the phase table
#define UPDATE_POSN(x) if (posn[x]) --posn[x]; else posn[x]= MAX_POS

#INT_TIMER2 //5000Hz interrupt
void tick(void)
{
   static int16 fast_tick=TICKS_PER_SECOND-1;
   static unsigned int8 port_pattern=START_POSN;
   static unsigned int8 motor[2] = {SLOW,SLOW};
   static unsigned int8 motor_tick[2];
   static unsigned int8 posn[2] = {0,0}; //motor position
   static unsigned int8 mask;
   //generate 1/second clock
   if (fast_tick)
      --fast_tick;
   else
   {
      fast_tick=TICKS_PER_SECOND-1;
      time++; //once per second
   }
   //end of clock routine - now handle steppers
   //Two steppers using half stepping drives on PortB
   switch(to_do[0]) //action for first motor
   {
   case still:
      break;
   case start:
      //here motor needs to start
      motor[0]=SLOW; //speed
      motor_tick[0]=profile[motor[0]]; //load timing needed
      mask=phases[posn[0]]; //data pattern for motor;
      UPDATE_POSN(0); //advance to next pattern
      MASK_MOTOR1;
      output_b(port_pattern);
      to_do[0]=accel;
      break;
   case accel:
      //now motor is accelerating.
      if (motor_tick[0])
      {
         --motor_tick[0];
         break; //need break so I can drop through below
      }
      else
      {
         //now output the next bit pattern and adjust timing
         if (motor[0])
         {
            --motor[0]; //next speed required
            motor_tick[0]=profile[motor[0]];
            mask=phases[posn[0]];
            UPDATE_POSN(0); //advance to next pattern
            MASK_MOTOR1;
            output_b(port_pattern);
            break;
         }
         //here motor is at full speed
         to_do[0]=hold;
      }
   case hold:
      //now at full speed so hold
      if (motor_tick[0])
      {
         --motor_tick[0];
      }
      else
      {
         //now output the next bit pattern and adjust timing
         motor_tick[0]=profile[motor[0]];
         mask=phases[posn[0]];
         UPDATE_POSN(0); //advance to next pattern
         MASK_MOTOR1;
         output_b(port_pattern);
      }
      break;
   case stop:
      //given command to stop
      motor[0]++; //slower speed
      motor_tick[0]=profile[motor[0]]; //load timing needed
      mask=phases[posn[0]]; //data pattern for motor;
      UPDATE_POSN(0); //advance to next pattern
      MASK_MOTOR1;
      output_b(port_pattern);
      to_do[0]=decel;
      break; 
   case decel:
      //now slowing
      if (motor_tick[0])
      {
         --motor_tick[0];
         break; //need break so I can drop through below
      }
      else
      {
         //now output the next bit pattern and adjust timing
         if (motor[0]<=SLOW)
         {
            ++motor[0]; //next speed required
            motor_tick[0]=profile[motor[0]];
            mask=phases[posn[0]];
            UPDATE_POSN(0); //advance to next pattern
            MASK_MOTOR1;
            output_b(port_pattern);
            break;
         }
         //here motor is at lowest speed
         to_do[0]=stopped;
      }
   case stopped:
      //drop through to here when update has to stop
      to_do[0]=still;
      break;
   }     
   switch(to_do[1]) //same action for second motor
   {
   case still:
      break;
   case start:
      //here motor needs to start
      motor[1]=SLOW; //speed
      motor_tick[1]=profile[motor[1]]; //load timing needed
      mask=phases[posn[1]]; //data pattern for motor;
      UPDATE_POSN(1); //advance to next pattern
      MASK_MOTOR2;
      output_b(port_pattern);
      to_do[1]=accel;
      break;
   case accel:
      //now motor is accelerating.
      if (motor_tick[1])
      {
         --motor_tick[1];
         break; //need break so I can drop through below
      }
      else
      {
         //now output the next bit pattern and adjust timing
         if (motor[1])
         {
            --motor[1]; //next speed required
            motor_tick[1]=profile[motor[1]];
            mask=phases[posn[1]];
            UPDATE_POSN(1); //advance to next pattern
            MASK_MOTOR2;
            output_b(port_pattern);
            break;
         }
         //here motor is at full speed
         to_do[1]=hold;
      }
   case hold:
      //now at full speed so hold
      if (motor_tick[1])
      {
         --motor_tick[1];
      }
      else
      {
         //now output the next bit pattern and adjust timing
         motor_tick[1]=profile[motor[1]];
         mask=phases[posn[1]];
         UPDATE_POSN(1); //advance to next pattern
         MASK_MOTOR2;
         output_b(port_pattern);
      }
      break;
   case stop:
      //given command to stop
      motor[1]++; //slower speed
      motor_tick[1]=profile[motor[1]]; //load timing needed
      mask=phases[posn[1]]; //data pattern for motor;
      UPDATE_POSN(1); //advance to next pattern
      MASK_MOTOR2;
      output_b(port_pattern);
      to_do[1]=decel;
      break; 
   case decel:
      //now slowing
      if (motor_tick[1])
      {
         --motor_tick[1];
         break; //need break so I can drop through below
      }
      else
      {
         //now output the next bit pattern and adjust timing
         if (motor[1]<=SLOW)
         {
            ++motor[1]; //next speed required
            motor_tick[1]=profile[motor[1]];
            mask=phases[posn[1]];
            UPDATE_POSN(1); //advance to next pattern
            MASK_MOTOR2;
            output_b(port_pattern);
            break;
         }
         //here motor is at lowest speed
         to_do[1]=stopped;
      }
   case stopped:
      //drop through to here when update has to stop
      to_do[1]=still;
      break;
   }
   delay_cycles(1);
}
//Note that using 'hard defined' indexes for the arrays in most cases, and
//repeating the code twice, is _quicker_ than using a loop.

void main()
{
   //Program fast interrupt
   setup_timer_2(T2_DIV_BY_4,249,1); //Interrupt at 5000Hz (20MHz/(4*4*250))
   output_b(START_POSN); //initial start position
   set_tris_b(0); //turn drivers on
   enable_interrupts(INT_TIMER2);
   enable_interrupts(GLOBAL);
   while(TRUE)
   {
      time=0; //reset timer so code can loop
      //Now motors are both stationary.
      //You can start either by setting 'to_do' to start
      to_do[0]=start;
      //the motor will aurtomatically accelerate to the maximum
      //speed and continue indefinately.
      //You can delay with a counter delay or timers etc..
      while (time<10) ; //wait ten seconds
      //now start second motor
      to_do[1]=start;
      while (time<20); //wait another ten seconds
      //now stop first motor
      to_do[0]=stop;
      while (time<40); //wait twenty seconds
      to_do[1]=stop;
      //and stop first motor
      while (time<60); //now wait with motors stopped till one minute   
      //and start again.   
   }
}


Not properly tested, but for the correct hardware layout should be very close.

Layout is two unipolar (four wire) steppers. One connected to B0 to B3, and the other on B4 to B7. Phases sequentially round the motor on the pins.

Shows one motor running, then both, then the second on it's own, then both stopped.
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