Freescale MC9S12DP256B - Closed-loop Stepper Motor Control System Using MC9S12DP256B

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Freescale MC9S12DP256B - Closed-loop Stepper Motor Control System Using MC9S12DP256B

6,064 Views
admin
Specialist II
Hello,

I'm a student doing my project where I'm going to use this microcontroller (MC9S12DP256B) to control a hybrid stepper motor in a closed-loop system. I'm still new in learning this microcontroller. Therefore, I have few questions stated below :

1. Can anyone provide me an example of C program to control a hybrid stepper motor in closed-loop
    system using PWM?
2. Incremental encoder will be used to feedback the position of the motor. As I know, decoder and
    counter will be needed to change the quadrature signal to digital position of the motor.
    Is MC9S12DP256B provides such capabilities? So that external decoder and counter can be
    eliminated.
3. To use it in motor control system, what else should I read from its datasheet?

I would be grateful for any reply. Thanks you.

best regards,
yj




Message Edited by yj on 2007-10-01 04:27 PM

Message Edited by yj on 2007-10-01 04:28 PM
Labels (1)
0 Kudos
36 Replies

1,295 Views
admin
Specialist II
Hi,

I got what you mean on setting and clearing a specific bit in a register. How about if I want to evaluate the specific bit using relational operators?

Thanks.

Regards,
yj
0 Kudos

1,295 Views
JimDon
Senior Contributor III
Code:
if( PIFP & 0x80 ) // check if a bit is set.{  ...}if( !(PIFP & 0x80) ) // check if a bit is clear.{  ...}

 
0 Kudos

1,295 Views
admin
Specialist II
Hi,

I'm using ImageCraft Compiler, ICCV7.

What do you mean by this:
On exception is the TFLG1  register, as it says that writing a 1 only affects that channel and you should not use the "or" '|'  operator. But in configuration registers, you should so you don't change other setups.

Thanks in advance.

Regards,
yj

0 Kudos

1,295 Views
JimDon
Senior Contributor III
Ok, lets say you want to set a single bit in an I/O register without affecting any other bits.

You would write:

PWME |= 0x80;    // OR 0x80 setting the bit.
PWME &= ~0x80 // AND the inverse to clear only that bit.

Because PWME = 0x80; would set that bit, but clear all the others.

The TFLG1 register is "special", because writing TFLG1 = 0x80 ONLY affects the bit that was set because that register has special logic so only the bit that was set has any meaning. Other register aren't like this.

The reason you can't use PIFP_PIFP7 is because this is only found in the CodeWarrior headers and is not supported by  image craft.

Do you have NOICE ?
0 Kudos

1,295 Views
admin
Specialist II
Hi,

Yes, you are correct. What I can do is to change the period or duty cycle only in order to step the motor faster or slower. Is there any algorithm to change the period/duty cycle to accelerate the motor until it reaches constant speed? Or I just have to change the TC7 value (Output Compare) or period (PWM) randomly in descending order? Sorry for the newbie questions.

I have tried Output Compare, Input Capture and the PWM as well. They function accordingly.

1.    I have came across a situation where I pass the step pulses generated by Output Compare (IOC7) to the Input Capture (IO6) as stated below:

Code:
#pragma interrupt_handler TOC7_ISR  //Generate pulses
void TOC7_ISR(void)
{
 TC7 += 31250;
 TFLG1 = 0x80;
}

#pragma interrupt_handler TOC6_ISR  //Detect edge
void TOC6_ISR(void)
{
 count++;
 TFLG1 = 0x40;
}

 The count did not increment at all. Is it because of both interrupts happened at the same time and TOC7_ISR had the most priority ?

2.    How to assigned value like 0 and 1 into specific bit in a register? For example, if I want to set high PWME7 bit in register PWME, what I will do is PWME=0x80. I tried your example PWME_PWME7=1, but it returns undeclared identifier 'PWME_PWME7'. I just want to learn more.

Thank you and Merry Christmas.

Best Regards,
yj



Message Edited by yj on 2007-12-21 05:22 PM
0 Kudos

1,295 Views
JimDon
Senior Contributor III
First if you sy:
PWME |= 0x80;
It will just set the bit without affecting other bits.
If you say :
PWME &= ~0x80;
It will clear just that bit.

Are you using code warrior? If so what version ?
(Click Help/About then click "Installed Products" - the IDE Version given on the about screen is NOT the version of Code Warrior) PWME_PWME7 is defined in the Code Warrior includes. But you can do it as shown above.

On exception is the TFLG1  register, as it says that writing a 1 only affects that channel and you should not use the "or" '|'  operator. But in configuration registers, you should so you don't change other setups.

You will have show me the reset of the timer code - like the set up.
You should get an interrupt on both timer 6 and timer 7.





0 Kudos

1,295 Views
admin
Specialist II
Hi,

I got what you mean. Thanks.

I have read some information about the algorithm for stepper-motor acceleration from this link but I still cant get how to configure my PWM or ECT module to accelerate my stepper motor in 0.5 seconds. Is there any simple guidelines or algorithms that are suitable in my case?

Once again, thanks.

Best Regards,
yj
0 Kudos

1,295 Views
JimDon
Senior Contributor III
First of all you said:

2.    MCU will drive the stepper motor according to the input via a driver. The driver needs three input namely STEP, DIRECTION and ENABLE. Motor will step on rising edge of STEP input.

Which means all you can do is change the period of the PWM to step the motor faster.
You don't have any control over the phases or how the stepper controller drives the motor.
All you can do is pulse the controller board faster. There is some maximum rate for that board that you can pulse it, and that is all you can do.

The lower the period of the PWM, the faster the motor will step.

Do you have the specifications for the motor driver board?
Have you tried stepping the motor yet?

I recommend you get the encoder working and get entire system working before you start to worry about the fine points. You don't even know if it will not correct fast enough yet.
0 Kudos

1,295 Views
admin
Specialist II
Hi,

1.  What do you mean by this:

" Also remember to write to the 16 bit registers for PWM, or your value will not be set right in the period and duty cycle registers.

If lower the period (and duty cycle, so you maintain the duty cycle) it will step faster or slower. "


2.  Can I know whether this Adapt9S12DP256 board produces 5V CMOS or TTL logic signals by the digital I/O port?
I cant get any information on this. Hope you can help.

Thank you.

Best Regards,
yj

0 Kudos

1,295 Views
JimDon
Senior Contributor III
" Also remember to write to the 16 bit registers for PWM, or your value will not be set right in the period and duty cycle registers."

In your code, you were using PWMPER7  PWMDTY7 which are 8 bit registers. Since you are using 16 concat mode, you should use PWMPER67 PWMDTY67 which are the concat registers for channel 6 & 7.

"If you lower the period (and duty cycle, so you maintain the duty cycle) it will step faster or slower"

What I mean is that if you lower the period, there will be a higher rate of step pulse, so the motor will step faster. You also want to lower the counts in the duty cycle register, as the duty cycle is the ratio of the period to the duty cycle registers.

Code:
      PWMPER67 = 62500;   // 50% Duty cycle      PWMDTY67 = 31250;      // Same duty cycle, but steps twice as fast.      PWMPER67 = 31250;   // 50% Duty cycle      PWMDTY67 = 15625;

 
The HCS12 runs on 5V and the outputs can drive TTL or HC logic.

Here is a link to the board.     If you email TechArts, they may send you a schematic. I don't know any more about this board than what is at this link.



0 Kudos

1,295 Views
admin
Specialist II
Hi,

I think I left the concatenation part. If I am using the PWM module, in order to count the pulses, can I mask the PWM output from the Port P? I'll mask low level from the Port P and increment the count. Is this possible? I'll try it first.

How am I going to accelerate and decelerate the motor? Is it by changing the time interval between step pulses?

Thanks for your replies.

Best Regards,
yj
0 Kudos

1,295 Views
JimDon
Senior Contributor III
Also remember to write to the 16 bit registers for PWM, or your value will not be set right in the period and duty cycle registers.

If lower the period (and duty cycle, so you maintain the duty cycle) it will step faster or slower.



Yes, you can get an edge interrupt from Port P and you could count them that way.


You could also try counting the encoder pulses and stop when you have enough. This might work better, as the encoder pulses may not map 1:1 with step pulses. After all, thats what closed loop is all about.

Code:
...// Init code.
      PPSP = 0;            // set falling edge.      PIFP = 0xff;         // Reset all int flags.      PIEP_PIEP7 = 1;      // Enable chn 7 for edge interrupt.... // Interupt handlerword PortPcounter=0;__interrupt void PortPEdge(void){        if(1 == PIFP_PIFP7)  // test if this channel    {      PIFP_PIFP7 = 1;   // Yes reset the flag      ++PortPcounter;   // Increment the counter    }}// Don't forget to set the vector.const tIsrFunc _vectab2[] @0xFF8E ={  (tIsrFunc)PortPEdge,                          /* Timer 7 0xFFE0                */};

 


0 Kudos

1,295 Views
admin
Specialist II
Hi,

What are the differences between ECT module and PWM module in generating step pulses? In my system, which one will be the best in driving the motor driver?

I have tried to use PWM to generate step at Port P7 as well. Below is the addition to my previous code.

Code:
void PWM_Init(void){    PWMPOL=0x80;    // PPOL7=1, Step begin at high level PWM Channel 7    PWMCLK=0x00;    // PCLK7=0, clock B as clock source for PWM Channel 7    PWMPRCLK=0x70;  // clock B = bus clock / 128 = 8MHz / 128 = 62500Hz    PWMPER7=62500;  // 62500 / 62500Hz = 1 second    PWMDTY7=31250;  // Duty cycle = 50 %,  62500 / 31250 = 0.5    PWME=0x80;      // PWME7 enable}

But the LED Port P7 turn on and didn't blink at all. Am I missing something? Should I declare anything like interrupt? I thought when PWM is enabled (PWME=0x80), the step pulses will be generated.

Once again, thank you. Really appreciate your help.

Best Regards,
yj
0 Kudos

1,295 Views
JimDon
Senior Contributor III
From what I understood of your application, you need to send and exact number of pulses.
So the timer interrupt let you count each pulse.
How would you do that with PWM?
0 Kudos

1,295 Views
JimDon
Senior Contributor III
As for your set up code, you never set the  PWMCTL register.
It appears you wish to concatenate channels 6&7, so you need to set 0x80 (CON67).
Also you need to write to the 16 bit registers as shown below.

CON67 — Concatenate channels 6 and 7
1 = Channels 6 and 7 are concatenated to create one 16-bit PWM channel. Channel 6 becomes the
high order byte and channel 7 becomes the low order byte. Channel 7 output pin is used as the
output for this 16-bit PWM (bit 7 of port PWMP). Channel 7 clock select control-bit
determines the clock source, channel 7 polarity bit determines the polarity, channel 7 enable
bit enables the output and channel 7 center aligned enable bit determines the output mode.
0 = Channels 6 and 7 are separate 8-bit PWMs.

Code:
void InitPWM7(void ){      // Set up channels 6 & 7 for 16 bit operation.      PWMCLK_PCLK7 = 0;   // Set channel 7 for clk b.      PWMPOL_PPOL7  = 1;  // Start with a high.      PWMCTL_CON67  = 1;  // concat 6&7      PWMPRCLK_PCKB  =0;  // Set clk b divider to 0      PWMCAE_CAE7   = 0;  // set left algn mode.      PWMPER67 = 62500;   // 50% Duty cycle      PWMDTY67 = 31250;      PWME_PWME7 = 1;     // enable the channel.           }

 
Please note how I have done things here, so as not to change settings on other channels.
After you insert this code and build it, you can use "Got to macro declaration" on the right click menu to see how these work. While it seems unimportant now, later when you have much code it will reduce the possibility of bugs.






Message Edited by JimDon on 2007-12-11 11:48 AM
0 Kudos

1,304 Views
admin
Specialist II
Hi,


1.    If the crystal freq is 16MHz and I don't use PLL code, then my default bus clock into ECT module is equal to 8Mhz.
Am I correct?

2.    The previous code for interrupt succeeded. The LED blink according to the duration I want.

3.    If I want to execute the ISR routine for a specific amount, let say I want to produce 2 step pulses (LED will blink 2 times), then the ISR routine must be executed 4 times. After 4 times the routine being serviced, I disable the timer interrupt. Below is the simple code for this case. This will be used in my system when I want to drive the stepper motor to a desired position, then I will service this routine for the desired amount. (Please correct me if I wrong)

Code:
int i=1;void TOC7_ISR(void){         PTP ^= 0x80;     if (i<4)       i++;    else    {       TIE=0x00;     // Timer interrupt disable, C7I=0       TSCR1=0x10;   // Timer disable TEN=0, fast flag clear TFFCA=1     }}    

 
But the LED blink continuously and didn't stop. Am I miss something in disabling the interrupt?
Hope you can help me on this.
   
Thank you.

Best Regards,
yj


Message Edited by yj on 2007-12-09 06:29 AM
0 Kudos

1,295 Views
admin
Specialist II
Hi,

Finally, I have figured it out. Actually I miss a line to declare the interrupt routine. The fast flag clear doesn't work and I'm not sure why. But I'm using TFLG1=0x80; and it works nice. Regarding the counter, I have enabled the counter reset, so I don't have to write TC7 += 62500. Here is my simple code to blink LED two times in 2 seconds:

Code:
#include <mc9s12dp256.h>
#include "vectors_dp256.c"
 
void TOC7_Init(void);
void TOC7_ISR(void);

int k=1;

void TOC7_Init(void)
{
    asm(" sei");

    TIOS=0x80;    // IOS7 = 1, channel 7 is output compare
    TCTL1=0x40;   // OM7 = 0, OL7 = 1, Toggle output on PTT7/IOC7
    TSCR2=0x0F;   // TCRE = 1, counter reset enable
    // Prescaler = 128 (Timer clock freq = 8MHz/128 = 62500Hz)

    TC7=31250;    // LED on/off duration = 31250/62500Hz = 0.5s
    TIE=0x80;     // Timer interrupt enable, C7I=1
    TSCR1=0x80;   // Timer enable TEN=1
   
    asm(" cli");
}

void main()
{

    DDRP=0xFF;    // Port P as output
    TOC7_Init();
  
 while(1)
 {
 
 }

}


#pragma interrupt_handler TOC7_ISR   // This is the line I missed.
void TOC7_ISR(void)
{

 if (k<=4)
 {    
  PTP ^= 0x80;
  k++;
  TFLG1 = 0x80;
 }
 else
 {
    TFLG1 = 0x80;
  TSCR1=0x00;
 }
      
}


If the crystal freq is 16MHz and I don't use PLL code, then my default bus clock into ECT module is equal to 8Mhz.
Am I correct?

Thank you.

Best Regards,
yj

0 Kudos

1,295 Views
JimDon
Senior Contributor III
Great!!!

Yes, if the ocillator is 16MHz, then the bus clock is 8 MHz.

0 Kudos

1,304 Views
admin
Specialist II
Hi,

I have try many simple codes in the interrupt routine.

Code:
int k;

void main()
{
  k=1;
  .... initialize the interrupt
  while(1)
  {
    }
}

void TOC7_ISR(void){         k=k+1;       if (k==4)        { PTP ^= 0x80;          PTS ^= 0x80;          blink_delay();          PTS ^= 0x80;          TFLG1 = 0x80;        }       else       {           TFLG1 = 0x80;            }}

 
The if part not evaluated as true. It seems like any variable not increasing in the routine. This happens in previous code as well. I really don't understand what happen. I need your help.

Thank you.

Best Regards,
yj
0 Kudos

1,304 Views
JimDon
Senior Contributor III
Questions:

How do you declare TOC7_ISR as being an interrupt handler? You should really use the __interrupt keyword on the function, otherwise it is hard for someone reading your code to know that.

How are you debugging this ? Do you have a BDM? What make you think that the variable is not working?

Because variables in a proper interrupt handler work fine. Your code does not look wrong as far as the variable is concerned.

Please post the init code too. At one point you seemed to follow my advice using the fast clear mode and TC7 += 62500; but now you stopped using that so I can't say if the interrupt is running correctly or not.
(BTW TFLG1 = 0x80 should work, I just have never done it that way)





Message Edited by JimDon on 2007-12-10 01:32 PM
0 Kudos