|
|
View previous topic :: View next topic |
Author |
Message |
artohautala
Joined: 17 Nov 2011 Posts: 187
|
how to generate pulse train to A4988 stepper driver module |
Posted: Wed Aug 18, 2021 6:06 am |
|
|
Hello everybody,
I'm Arto from Finland Europe. Good afternoon. Clock is here now 3 PM.
I'm trying to get my stepper motor to run 2ms ... 20 ms pulses, 200 pulses /rev. so
stepper runs 400ms ... 4000ms for one rev.
I'm using PIC16F628A chip and I have no idea how to make things work.
I like to use interrupts so software can do other things during interrupts, polling pins and so on.
Pulses go to A488 stepper control module via RB3 pin.
I'll be very pleased if someone can advise me how to do that.
All the best for you all and friendly regards from Finland.
-arto-
Last edited by artohautala on Wed Sep 01, 2021 7:49 am; edited 1 time in total |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Wed Aug 18, 2021 9:58 am |
|
|
this...
http://www.ccsinfo.com/forum/viewtopic.php?t=58715
might help ???
BTW there's a typo in your post 'A488' should be' A4988'...
kinda confused this old guy for a bit......
There may be CCS style code out on the Internet...
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19496
|
|
Posted: Wed Aug 18, 2021 10:06 am |
|
|
At the end of the day, you need to start yourself. Look at the CCS examples
and try some basic programming.
However to just generate a pulse train, need almost nothing. Your
chip has a PWM, and this can be programmed to produce a train at
a specific frequency. Once this is programmed, no code is needed, the
chip will just carry on generating the pulses.
There may be an issue though, a 'stepper' cannot accelerate from
stationary to a speed without 'skipping', so most of the time the pulse
train needs to be slowly ramped to it's full rate. So normally a drive
program needs to slowly increase it's pulse speed to the required rate,
and then to slow down to a stop do the reverse. However your speeds
quoted are so slow (150RPM max), that this may not be needed. The
pulse train can be fed back into the other CCP, to 'count' the pulses,
to stop after a revolution. |
|
|
artohautala
Joined: 17 Nov 2011 Posts: 187
|
|
Posted: Wed Aug 18, 2021 10:51 am |
|
|
thanks for your answer...
typo is not A488 but it is genetate must be generate...
your example code did't help at all ... sorry
all the best for you
-arto- |
|
|
artohautala
Joined: 17 Nov 2011 Posts: 187
|
|
Posted: Wed Aug 18, 2021 10:54 am |
|
|
Ttelmah wrote: | At the end of the day, you need to start yourself. Look at the CCS examples
and try some basic programming.
However to just generate a pulse train, need almost nothing. Your
chip has a PWM, and this can be programmed to produce a train at
a specific frequency. Once this is programmed, no code is needed, the
chip will just carry on generating the pulses.
There may be an issue though, a 'stepper' cannot accelerate from
stationary to a speed without 'skipping', so most of the time the pulse
train needs to be slowly ramped to it's full rate. So normally a drive
program needs to slowly increase it's pulse speed to the required rate,
and then to slow down to a stop do the reverse. However your speeds
quoted are so slow (150RPM max), that this may not be needed. The
pulse train can be fed back into the other CCP, to 'count' the pulses,
to stop after a revolution. |
Thanks for your answer ... is there any examples how to use PWM control ? |
|
|
dyeatman
Joined: 06 Sep 2003 Posts: 1933 Location: Norman, OK
|
|
Posted: Wed Aug 18, 2021 12:03 pm |
|
|
Can find anything on an A488 stepper control module but lots on A4988...
If it is A488 can you provide a link? _________________ Google and Forum Search are some of your best tools!!!! |
|
|
artohautala
Joined: 17 Nov 2011 Posts: 187
|
|
Posted: Wed Aug 18, 2021 12:32 pm |
|
|
dyeatman wrote: | Can find anything on an A488 stepper control module but lots on A4988...
If it is A488 can you provide a link? |
Thank you for your answer ... sure my module is 4988 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19496
|
|
Posted: Thu Aug 19, 2021 3:10 am |
|
|
I have to make a comment that the 628A, is quite an 'old' chip.
It does not offer much speed, or space.
The' INTOSC' oscillator is only 4MHz. Now you should comfortably be able
to do what you want, but the resolution of the pulse trains will be limited,
and if you end up doing quite a few other things, you may find space becomes
short. The PIC16F18444, is the 'more modern' replacement, and this gives
you 8 times the clock rate from the internal oscillator, and twice the ROM
and RAM. It also has two CCP's which makes it possible to have the second
CCP stop to pulse output after a number of counts, rather than having to
manually count.
Now as a very basic starting point:
Code: |
#include <16F628A.h>
#use delay(internal=4000000)
#fuses NOLVP
#fuses NOMCLR
enum {STOPPED, MOVING} pulse_state;
int16 frequency=500;
//outputs 200 pulses at the selected frequency on pin B3 when pulse_state is set to 'MOVING'.
#INT_CCP1
void tick(void)
{
static int pulse_count=0;
set_timer1(0); //reset timer
if (pulse_count!=0 && pulse_state==STOPPED)
{
//handle invalid case where the motor has been stopped
pulse_count=0;
}
if (pulse_count==0 && pulse_state==MOVING)
{
//this implies I have set the 'MOVING' state to start a pulse train for 200 pulse
pulse_count=200;
}
if (pulse_count>0 && pulse_state==moving)
{
//generate a pulse by clearing the pin
setup_CCP1(CCP_OFF);
output_low(PIN_B3);
setup_CCP1(CCP_COMPARE_SET_ON_MATCH);
--pulse_count;
}
if (pulse_count==0 && pulse_state==MOVING)
{
//Now if the count has reached zero, stop
pulse_state=STOPPED;
}
}
void main()
{
int16 selected_frequency=0;
enable_interrupts(GLOBAL);
//start the timer
setup_timer_1(T1_DIV_BY_8|T1_INTERNAL); //125000Hz off the 4Mhz clock
while(TRUE)
{
//Now setup the CCP to give the frequency required.
//Default at boot to 500Hz - 2mSec period
if (selected_frequency!=frequency) //if frequency has changed
{
disable_interrupts(INT_CCP1);
setup_CCP1(CCP_COMPARE_SET_ON_MATCH);
CCP_1=(125000/frequency)-4; //calculate how many counts needed
//It takes aboout 35uSec to enter the interrupt, so use four counts less
set_timer1(0);
selected_frequency=frequency;
enable_interrupts(INT_CCP1);
}
//Then when you want to send a revolaution, just set pulse_state to 'moving'
pulse_state=MOVING;
while (pulse_state==MOVING)
{
//what you have here executes while the motor is rotating
}
//Have the code here to change the frequency you want.
delay_ms(10000); //just stop for 10 seconds as demo
}
}
|
When you set pulse_state to 'moving' the CCP will generate a 200 pulse
train, at the specified 'frequency' (starts at 500Hz, so your 2mSec). |
|
|
artohautala
Joined: 17 Nov 2011 Posts: 187
|
|
Posted: Thu Aug 19, 2021 8:00 am |
|
|
Ttelmah wrote: | Quote: | I have to make a comment that the 628A, is quite an 'old' chip. |
It does not offer much speed, or space.
The' INTOSC' oscillator is only 4MHz. Now you should comfortably be able
to do what you want, but the resolution of the pulse trains will be limited,
and if you end up doing quite a few other things, you may find space becomes
short. The PIC16F18444, is the 'more modern' replacement, and this gives
you 8 times the clock rate from the internal oscillator, and twice the ROM
and RAM. It also has two CCP's which makes it possible to have the second
CCP stop to pulse output after a number of counts, rather than having to
manually count.
Now as a very basic starting point:
Code: |
#include <16F628A.h>
#use delay(internal=4000000)
#fuses NOLVP
#fuses NOMCLR
enum {STOPPED, MOVING} pulse_state;
int16 frequency=500;
//outputs 200 pulses at the selected frequency on pin B3 when pulse_state is set to 'MOVING'.
#INT_CCP1
void tick(void)
{
static int pulse_count=0;
set_timer1(0); //reset timer
if (pulse_count!=0 && pulse_state==STOPPED)
{
//handle invalid case where the motor has been stopped
pulse_count=0;
}
if (pulse_count==0 && pulse_state==MOVING)
{
//this implies I have set the 'MOVING' state to start a pulse train for 200 pulse
pulse_count=200;
}
if (pulse_count>0 && pulse_state==moving)
{
//generate a pulse by clearing the pin
setup_CCP1(CCP_OFF);
output_low(PIN_B3);
setup_CCP1(CCP_COMPARE_SET_ON_MATCH);
--pulse_count;
}
if (pulse_count==0 && pulse_state==MOVING)
{
//Now if the count has reached zero, stop
pulse_state=STOPPED;
}
}
void main()
{
int16 selected_frequency=0;
enable_interrupts(GLOBAL);
//start the timer
setup_timer_1(T1_DIV_BY_8|T1_INTERNAL); //125000Hz off the 4Mhz clock
while(TRUE)
{
//Now setup the CCP to give the frequency required.
//Default at boot to 500Hz - 2mSec period
if (selected_frequency!=frequency) //if frequency has changed
{
disable_interrupts(INT_CCP1);
setup_CCP1(CCP_COMPARE_SET_ON_MATCH);
CCP_1=(125000/frequency)-4; //calculate how many counts needed
//It takes aboout 35uSec to enter the interrupt, so use four counts less
set_timer1(0);
selected_frequency=frequency;
enable_interrupts(INT_CCP1);
}
//Then when you want to send a revolaution, just set pulse_state to 'moving'
pulse_state=MOVING;
while (pulse_state==MOVING)
{
//what you have here executes while the motor is rotating
}
//Have the code here to change the frequency you want.
delay_ms(10000); //just stop for 10 seconds as demo
}
}
|
When you set pulse_state to 'moving' the CCP will generate a 200 pulse
train, at the specified 'frequency' (starts at 500Hz, so your 2mSec). |
Thank for your answer ....
<I have to make a comment that the 628A, is quite an 'old' chip.>
I know but I have few chips and my app. is to make 3 mm dia filament to 1.75 dia for 3d printer
this chip has enough power to make part of my bigger project which is very mechanical ...
I make programming today hole day and I gave up to use PWM instead I use interrupt 1
but I'm wondering why in my code 2ms step is OK in practice but 20 ms step is not ??
all the best for you and good autumn !
Code: |
#include<16F628A.h>
#use delay(clock=11059200)
#fuses INTRC,NOWDT,HS //must be HS xtal mode!
#zero_ram // OK maybe must be here ?
//#define LED_1_ON output_high(PIN_B3);
//#define LED_1_OFF output_low(PIN_B3);
#define dir (PIN_B4); //DIR pin of A4988 stepper drive module
#define step (PIN_B3); //every pulse stepper takes one step,200 steps/rev.
#define sleep (PIN_B2); //SLEEP pin of A4988 stepper drive module
#define stepper_ON_OFF (PIN_A0);
int16 speed ; // this reload number for step time: 11059200/4 = 2764800...so interrupt time is
//(if speed = 0 and setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_1 ); T1_DIV_BY_1)
//time is (1/2764800) * 65536 = 23.7 ms,this is half of the step so step is is 47.4 ms
//if speed = 0 one stepper revolution last 9.480 seconds
//I want one stepper revolution to last min. 400 ms and max. 4000 ms = 4 seconds
//one timer_1 tick is 1/2764800) = 0.3617 microseconds
//2 ms step time load number speed (to interrupt function) number is:
// 65536 - (1ms / 0.3617 microseconds) = 62771 (1ms because one step must be 2 ms)
//20 ms step time load number speed (to interrupt function) number is:
//65536 - (10ms / 0.3617 microseconds) = 27647 (10ms because one step must be 20 ms)
//this number is in theory is OK but in practice it is 27 ms ... I do not know why !!
int16 new_speed ;
void step_isr(void) ;
//**************************************************************************************************************
void main(void){
setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_1 );
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
delay_ms(100); //start delay
//first stepper off
output_HIGH sleep;
//speed = 11058;
new_speed = 5529;
while(1){
//more code here //these values are measured with oscilloscope in practise
new_speed = 62771; //1 step 2 ms for stepper motor so one rev. is 400 ms also in practise
//new_speed = 27647; //this should be 20 ms step in theory but it is 27 ms in practise I
//do not know why ,,,??? if you know please tell me !
}
}
//**************************************************************************************************************
#INT_TIMER1
void step_isr(void)
{
output_toggle(PIN_B3);
speed = new_speed; //this must be here every time when interrupt occurs
set_timer1(speed);
}
//**************************************************************************************************************
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19496
|
|
Posted: Thu Aug 19, 2021 8:51 am |
|
|
So you have an 11.05920MHz crystal.
Get rid of INTRC. You are currently trying to select two clocks....
Your calculation is wrong.
11059200Hz/4 = 2764800Hz.
Clock period = 0.361689mSec
20mSec over this gives 55296 counts. Over 2 requires 27648 counts per
half cycle.
Timer therefore needs to be set to 65536 - 27648 = 37888
You are forgetting that the timer counts up from the set count to 65536. |
|
|
artohautala
Joined: 17 Nov 2011 Posts: 187
|
|
Posted: Fri Aug 20, 2021 3:39 am |
|
|
Ttelmah wrote: | So you have an 11.05920MHz crystal.
Get rid of INTRC. You are currently trying to select two clocks....
Your calculation is wrong.
11059200Hz/4 = 2764800Hz.
Clock period = 0.361689mSec
20mSec over this gives 55296 counts. Over 2 requires 27648 counts per
half cycle.
Timer therefore needs to be set to 65536 - 27648 = 37888
You are forgetting that the timer counts up from the set count to 65536. |
Thank you very much Now it works ! |
|
|
|
|
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
|