|
|
View previous topic :: View next topic |
Author |
Message |
moksan
Joined: 19 Oct 2015 Posts: 1
|
VID29 stepper motor control problem |
Posted: Mon Oct 19, 2015 3:38 am |
|
|
Hi, I'm trying to VID29 stepper motor control with 16F1937. But I have a problem. Motor does not turn as I wanted. Frequency enter the RB0 and internal ext. Motor based on the value of the frequency I want to convert back and forth. Motor pins(coil) connected to port c.
Code: | #include <main.h>
#fuses XT,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD
#use delay(clock=20M)
#use fast_io(b)
#use fast_io(c)
unsigned long long int t,new=0;
float f;
const int back[]={0x06,0x02,0x0B,0x09,0x0D,0x04};
const int forth[]={0x04,0x0D,0x09,0x0B,0x02,0x06};
int old=0
void main()
{
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
enable_interrupts(INT_TIMER1);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
set_timer1(0);
set_tris_c(0x00);
set_tris_b(0x03);
output_c(0);
output_b(0);
while(1)
{
f=t*0.0000016;
f=1/f;
f=f/5;
new=f;
if(new>old)
{
while(old<new)
{
for(i=0;i<=6;i++)
{
output_c(forth[i]);
delay_ms(30);
}
old++;
}
}
if(old>new)
{
while(old>new)
{
for(i=0;i<=6;i++)
{
output_c(back[i]);
delay_ms(30);
}
old--;
}
}
}
}
#int_ext
void timer1_kesme()
{
disable_interrupts(GLOBAL);
t=get_timer1();
set_timer1(0);
enable_interrupts(GLOBAL);
}
#int_timer1
void ext_kesmesi()
{
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Oct 19, 2015 4:41 am |
|
|
Your code has several bugs:
Quote: | #fuses XT,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD
#use delay(clock=20M) |
This indicates you are probably running this in Proteus. That's because
Proteus doesn't care about oscillator fuses. In real hardware, you need
the HS fuse to run the oscillator at 20 MHz.
Quote: |
const int back[]={0x06,0x02,0x0B,0x09,0x0D,0x04};
const int forth[]={0x04,0x0D,0x09,0x0B,0x02,0x06};
for(i=0;i<=6;i++)
{
output_c(forth[i]);
delay_ms(30);
}
for(i=0;i<=6;i++)
{
output_c(back[i]);
delay_ms(30);
}
|
Your arrays have 6 elements, which are numbered from 0 to 5 in the C
language. But your for() loops are using "less than or equal to 6" as
the test. This means your loop will run for indexes (i) from 0 to 6, which
is 7 array elements. You are running past the ends of your arrays.
If you want a loop counter that does 6 iterations and starts at 0, use
"less than" as the test. This will count from 0 to 5 and will do 6 passes
through the loop. Example:
Quote: |
for(i=0;i<6;i++)
{
}
|
This is true in the whole of C programming. Always remember this one.
If you ever have any doubts about how a for() loop works, run a simple
test program in MPLAB simulator, or run it in hardware. The program
below has the following output. You can see that the "i <= 6" test makes
the loop have 7 passes, from 0 to 6. That's bad if your arrays have
only 6 elements.
Quote: | i = 0
i = 1
i = 2
i = 3
i = 4
i = 5
i = 6 |
Test program:
Code: | #include <18F4620.h>
#fuses INTRC_IO, NOWDT
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS)
//=============================
void main()
{
int8 i;
for(i=0;i<=6;i++)
{
printf("i = %u \r", i);
}
while(TRUE);
} |
Quote: | #int_ext
void timer1_kesme()
{
disable_interrupts(GLOBAL);
t=get_timer1();
set_timer1(0);
enable_interrupts(GLOBAL);
} |
This is probably copied from some other compiler. Don't do this (in bold)
in CCS. Delete those two lines. These two lines are handled by the PIC
hardware and by the compiler. If you put in those lines, your program
will eventually crash when the timer1 interrupt occurs while your program
is in the exit code of the CCS interrupt handler. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Mon Oct 19, 2015 8:09 am |
|
|
I'd have to actually say it might well be for a different chip, rather than just a different compiler!...
It is _vital_ that an interrupt can't occur inside itself.
Different chips handle "how not to enable interrupts till you are actually 'out of' the handler" in different ways.
On some chips, the 'enable interrupt' instruction does not enable interrupts till the _next_ instruction. So you can code the last two instructions of the interrupt handler, as:
enable_interrupt
return
(in the particular syntax for the chip obviously), and the actual interrupt does not get enabled till after the return.
I'd suspect the code has been copied from a chip where this is the case.
The PIC instead has a special 'return from interrupt' instruction, that automatically enables the interrupts after it executes. |
|
|
|
|
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
|