|
|
View previous topic :: View next topic |
Author |
Message |
misaeldv
Joined: 10 Nov 2005 Posts: 11
|
Linear actuator - Sinusoidal motion |
Posted: Tue Jul 31, 2007 9:06 am |
|
|
Hi, I'm using a linear stepper motor (stepper motor coupled to a lead screw) to drive a certain load and everything is working fine, however I'm getting a triangular wave when I am really interested in a sinusoidal pattern. Right now the pattern is doing different displacements per time (but the time is limited to around 1 second). So I'm basically making the motor take 350 steps (which gives me a displacement of 1 mm) in one sec, and then it goes reverse, but this gives me a triangular wave. Is there any routine available or easily implemented so that I can have the motor take a series of faster single steps in order to approach a sinusoidal wave? Thanks in advance. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Jul 31, 2007 11:31 am |
|
|
Look at the various CCS examples that use a lookup table to generate
a sine function:
c:\program files\picc\examples\ex_usb_scope.c
c:\program files\picc\examples\ex_dtmf.c
c:\program files\picc\examples\ex_sine.c |
|
|
misaeldv
Joined: 10 Nov 2005 Posts: 11
|
|
Posted: Wed Sep 12, 2007 7:40 pm |
|
|
Ok, I finally got it to approximate a sinusoid, however my current test code is giving me some problem which I cannot reason out. Basically the curve going down is just the opposite of the one up, so I decided to make a lookup table with only half of the values that I need for the one going up, then I have a loop that calls values from 0-14 (forward), then another loop calling values from 14-0, but somehow that second loop does not drive my motor. I know for a fact that it is running thru the loop because it goes up, then it delays for the amount of time it should be going down, then it goes up again. Here is the code that currently does work (i.e. it only goes up and down). However I have four lookup tables instead of just two.
Code: |
#include <16F874A.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz)
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode FOR ICD
#FUSES LVP //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#FUSES BROWNOUT //Reset when brownout detected
#use delay(clock=10000000)
#use fast_io (A)
#use fast_io (B)
#include <math.h>
#define RAND_MAX 1000 //Rand_max needs to be defined before stdlib.h is inserted
#include <stdlib.h>
INT16 i, index, index2, steps, delay;
INT16 CONST delay_default[15] = {
1219, 1233, 1261, 1304, 1367, 1452, 1567, 1722, 1935, 2236, 2683, 3399, 4706, 7786, 23274};
INT16 CONST steps_default[15] = {
41, 41, 40, 38, 37, 34, 32, 29, 26, 22, 19, 15, 11, 6, 2};
INT16 CONST delay_default2[15] = {
23274, 7786, 4706, 3399, 2683, 2236, 1935, 1722, 1567, 1452, 1367, 1304, 1261, 1233, 1219};
INT16 CONST steps_default2[15] = {
2, 6, 11, 15, 19, 22, 26, 29, 32, 34, 37, 38, 40, 41, 41};
/*INT16 CONST sin_default[15] [2] = {
1219, 1233, 1261, 1304, 1367, 1452, 1567, 1722, 1935, 2236, 2683, 3399, 4706, 7786, 23274,
41, 41, 40, 38, 37, 34, 32, 29, 26, 22, 19, 15, 11, 6, 2
};*/
VOID move (INT16 delay, INT16 steps)
{
//Motor motion (forward and reverse)
FOR (i = 0; i <= steps; ++i)
{
//Pin B2 provides the clock (f = 1/T)
//T = 2 * delay
output_high (PIN_B2);
delay_us (delay);
output_low (PIN_B2);
delay_us (delay);
} //end FOR CW
}//end move
VOID main ()
{
setup_adc_ports (NO_ANALOGS);
setup_adc (ADC_OFF);
setup_psp (PSP_DISABLED);
setup_spi (FALSE);
setup_timer_0 (RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1 (T1_DISABLED);
setup_timer_2 (T2_DISABLED, 0, 1);
setup_comparator (NC_NC_NC_NC);
setup_vref (FALSE);
//.0254 mm / step
// TODO: USER CODE!!
set_tris_a (0xFF); //sets complete port A as inputs (A0 - A5)
set_tris_b (0x00); //Makes port b7 - b0 function as outputs
output_b (0x00); //Makes all of port B outputs low
output_high (PIN_B5); //Enables the L297 stepper driver chip
output_high (PIN_B6); //Selects current control to act on ABCD lines, instead of inhibit lines
output_high (PIN_B1); //Selects half step operation
output_high (PIN_B0); //Pulls reset input high so driver does not reset by mistake
WHILE (true)
{
IF (input (PIN_A0))
{
//---------------Going up----------------------
output_high (PIN_B4); //selects CW rotation
for(index=0; index<=14; ++index)
{
move(delay_default[index], steps_default[index]);
}
//---------------Going down-----------------------
output_low (PIN_B4); //selects CCW rotation
for(index2=0; index2<=14; ++index2)
{
move(delay_default2[index2], steps_default2[index2]);
}
//--------------Dead Time-------------------------
delay_ms (2000);
}//end if
} //end while
}//end main
|
What I would like, and tried but did not work is the following
Code: |
//---------------Going up----------------------
output_high (PIN_B4); //selects CW rotation
for(index=0; index<=14; ++index)
{
move(delay_default[index], steps_default[index]);
}
//---------------Going down-----------------------
output_low (PIN_B4); //selects CCW rotation
for(index2=14; index2>=0; --index2)
{
move(delay_default[index2], steps_default[index2]);
}
|
However the above section of code does not move the motor in the downward direction (second loop).
Am I violating any basic rules or something?
Thanks |
|
|
libor
Joined: 14 Dec 2004 Posts: 288 Location: Hungary
|
|
Posted: Thu Sep 13, 2007 3:56 am |
|
|
The index2>=0 condition in your second loop is always true. This loop never ends. |
|
|
misaeldv
Joined: 10 Nov 2005 Posts: 11
|
|
Posted: Thu Sep 13, 2007 7:21 am |
|
|
So what you're saying is that I am not allowed to decrement, or that int16 doesn't go negative?
Thanks |
|
|
kevcon
Joined: 21 Feb 2007 Posts: 142 Location: Michigan, USA
|
|
Posted: Thu Sep 13, 2007 7:39 am |
|
|
Since index2 is unsigned the answer is no.
but if you change your loop to.
Code: |
for(index2=14; index2 != 0xFFFF ; --index2)
|
it should work |
|
|
misaeldv
Joined: 10 Nov 2005 Posts: 11
|
|
Posted: Thu Sep 13, 2007 9:14 am |
|
|
Thanks, just a couple more questions to clarify my issue. I just looked in the compiler help and it says that by default the only signed type is long, but that int16 can also be declared as signed if declared as followed
Code: |
signed int16 index2;
|
So, if I declared my variable as above it should do it, right? I would try it, but do not have my motor with me right now.
Thanks |
|
|
|
|
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
|