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

how to generate pulse train to A4988 stepper driver module

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



Joined: 17 Nov 2011
Posts: 187

View user's profile Send private message Send e-mail

how to generate pulse train to A4988 stepper driver module
PostPosted: Wed Aug 18, 2021 6:06 am     Reply with quote

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: 9232
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Aug 18, 2021 9:58 am     Reply with quote

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...... Smile

There may be CCS style code out on the Internet...

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19529

View user's profile Send private message

PostPosted: Wed Aug 18, 2021 10:06 am     Reply with quote

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

View user's profile Send private message Send e-mail

PostPosted: Wed Aug 18, 2021 10:51 am     Reply with quote

temtronic wrote:
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...... Smile

There may be CCS style code out on the Internet...

Jay

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

View user's profile Send private message Send e-mail

PostPosted: Wed Aug 18, 2021 10:54 am     Reply with quote

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: 1934
Location: Norman, OK

View user's profile Send private message

PostPosted: Wed Aug 18, 2021 12:03 pm     Reply with quote

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

View user's profile Send private message Send e-mail

PostPosted: Wed Aug 18, 2021 12:32 pm     Reply with quote

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: 19529

View user's profile Send private message

PostPosted: Thu Aug 19, 2021 3:10 am     Reply with 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).
artohautala



Joined: 17 Nov 2011
Posts: 187

View user's profile Send private message Send e-mail

PostPosted: Thu Aug 19, 2021 8:00 am     Reply with quote

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: 19529

View user's profile Send private message

PostPosted: Thu Aug 19, 2021 8:51 am     Reply with quote

So you have an 11.05920MHz crystal.
Get rid of INTRC. You are currently trying to select two clocks.... Sad

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

View user's profile Send private message Send e-mail

PostPosted: Fri Aug 20, 2021 3:39 am     Reply with quote

Ttelmah wrote:
So you have an 11.05920MHz crystal.
Get rid of INTRC. You are currently trying to select two clocks.... Sad

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 Smile Now it works !
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