|
|
View previous topic :: View next topic |
Author |
Message |
betobrito
Joined: 27 Nov 2014 Posts: 3 Location: Maceió, Alagoas
|
Urgent doubt |
Posted: Sat Nov 29, 2014 11:21 am |
|
|
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: 19539
|
|
Posted: Sat Nov 29, 2014 12:03 pm |
|
|
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
|
|
Posted: Sat Nov 29, 2014 1:00 pm |
|
|
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: 19539
|
|
Posted: Sat Nov 29, 2014 3:11 pm |
|
|
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
|
|
Posted: Sat Nov 29, 2014 4:11 pm |
|
|
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
|
Re: Urgent doubt |
Posted: Sat Nov 29, 2014 5:22 pm |
|
|
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
|
|
Posted: Sat Nov 29, 2014 7:41 pm |
|
|
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: 19539
|
|
Posted: Sun Nov 30, 2014 1:37 am |
|
|
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: 19539
|
|
Posted: Sun Nov 30, 2014 3:50 am |
|
|
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. |
|
|
|
|
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
|