Translate

Tuesday, October 5, 2010

Launchpad experiment

In order to test the environment under Lucid Lynx for the MSP430, here a Launchpad board with a MSP430F2012, controlling a 5V stepper motor cannibalized from an old CD driver, using an Easydriver board with the A3967 chipset.
To facilitate the tests I built a breadboard extension for the MSP430, following the suggestion of this article.

 
( The MS1 and MS2 signals are not yet connected on the board)

Here a picture of the board :


In the photo the prototype already set up for field tests. There is only the power supply for the motor.
The Easydriver module is providing the 3.3V for the Launchpad.

Options


I removed from an old CD driver a small step motor.
The step motor is a 5V step motor (no specs, just deducted form some coil measurements).
I connected the small step motorinstead the big one and powered the entire board with a 5V 1Ausing a normal 5V router power supply.

It works perfectly.
So I already have two different step motors to experiment with.

In order to use a different step motor (compatible with the one bought with the driver) the only change is the power supply.

LaunchPad settings

Input



The input for the prototype will be two push-buttons.
One for direction.
The two push-buttons arc connected to the port 1.3 and port 1.4
  • P1.3 Left (INPUT)
  • P1.4 Right (INPUT)

Output



The main output for the interface will be two pins, one to select the direction on the driver, and one to drive the motor (STEP).
An additional I/O is used to enable/disable the motor (ENABLE pin EasyDriver)
  • P1.0 connected to EasyDriver STEP (OUTPUT) (red LED)
  • P1.6 connected to EasyDriver DIR (OUTPUT) (green LED)
  • P1.2 connected to EasyDriver SLEEP (OUTPUT)
  • P1.1 connected to Easydriver MS1 (OUTPUT)
  • P1.5 connected to Easydriver MS2 (OUTPUT)

Board settings


CAUTION !!

Some jumpers needs to be set on the LaunchPad board, depending the stage of development.
Development

In this stage, the LaunchPad is powered by the USB cable, so NO EXTERNAL power must be connected to the Launchpad board. A separate 12V powers the Easydriver and the motor.
All the jumpers are left in position.
Test on field

At this stage, the board will be powered by the Easydriver board.
So :
  1. remove on the Launchpad the jumpers :
    • Vcc
    • Reset
  2. Connect the 3.3 V out from the Easydriver to the VCC of the Launchpad (be sure to set the Easydriver to generate the 3.3 V and not the 5 V - default)


Here a brief movie showing the first prototype driving a small 5V stepper motor cannibalized from an old CD driver.


The code is "extremely" simple and unsofisticated.
It was edited using Code::Blocks as editor, compiled with MSPGCC 4.3, loaded and debugged with mspdebug via USB.

Here  what the software does :

And here the code :


/*
 *  Test stepmotor
 *  Copyright (c) 2010 - Stefano Bodini
 *
 *  This code is designed to drive a stepper motor using an EasyDriver board.
 *  The board is a LaunchPad board, using a MSP430F2012 and the code is compiled using MSPGCC 4.4.3
 *  using the -mmcu=msp430x2012  parameter
 */
#include <io.h>
#include <signal.h>

/*
 *  Defines for I/O
 *   P1.0  -> Easydriver STEP  (OUTPUT - red LED)
 *   P1.1  -> not used - input
 *   P1.2  -> Easydriver EN (OUTPUT)
 *   P1.3  -> Pushbutton (INPUT) Left
 *   P1.4  -> Pushbutton (INPUT) Right
 *   P1.5  -> not used - input
 *   P1.6  -> Easydriver DIR   (OUTPUT - green LED)
 *   P1.7  -> not used - input
 */

#define     EZDRV_SET_MASK        0x45  /* 0100 0101 */

#define     EZDRV_PORT            P1OUT
#define     EZDRV_STEP            BIT0  /* Easydriver STEP */
#define     EZDRV_DIR             BIT6  /* Easydriver DIR */
#define     EZDRV_EN              BIT2  /* Easydriver EN */
#define     EZDRV_MS1             BIT1  /* Easydriver MS1 */
#define     EZDRV_MS2             BIT5  /* Easydriver MS2 */

#define     EZDRV_STEP_ON         EZDRV_PORT |= EZDRV_STEP
#define     EZDRV_STEP_OFF        EZDRV_PORT &= ~EZDRV_STEP

#define     PB_MASK               0x18  /* 0001 1000 */
#define     PB_LEFT               0x10  /* 0001 0000 - PUSHBUTTON Left */
#define     PB_RIGHT              0x08  /* 0000 1000 - PUSHBUTTON Right */

#define     BUTTON_IE             P1IE
#define     BUTTON_IES            P1IES
#define     BUTTON_IFG            P1IFG
#define     BUTTON_REN            P1REN

#define     LED0                  BIT0    //Red LED
#define     LED1                  BIT6    //Green LED
#define     LED_DIR               P1DIR
#define     LED_OUT               P1OUT

#define     FALSE                 0
#define     TRUE                  1

#define     TMRVALUE              160    /* Timer will generate a interrupt every .01 ms */

#define     PWM1_MAXSTEP    100 /* Maximum step for the PWM 1 */
#define     PWMINITIALVALUE 50     /* Initial value duty cicle (generate 380 uSec) */

/*
 *  Global variables
 */
unsigned char StepRun;      /* The variable enable the output on STEP */

unsigned short Pwm1_dc;         /* PWM 1 output ducty cycle */
unsigned short Pwm1_cn;         /* PWM 1 counter */

int main(void)
{
   WDTCTL = WDTPW + WDTHOLD;      /* Stop WDT */
   /*
    *  Halt the watchdog timer
    *  According to the datasheet the watchdog timer
    *  starts automatically after powerup. It must be
    *  configured or halted at the beginning of code
    *  execution to avoid a system reset. Furthermore,
    *  the watchdog timer register (WDTCTL) is
    *  password protected, and requires the upper byte
    *  during write operations to be 0x5A, which is the
    *  value associated with WDTPW.
    */

   /*
    *  Set DCO
    */
   DCOCTL  = CALDCO_16MHZ;
   BCSCTL1 = CALBC1_16MHZ;       /* Set up 16 Mhz using internal calibration value */

   /*
    *  Set I/O port
    *  CAUTION ! Since are used the internal pull up resistors, remember
    *  to force the corresponded PxOUT bits, otherwise the internal resistor
    *  is not connected !!
    */
   P1SEL = 0;                   /* All I/O */
   P1DIR = EZDRV_SET_MASK;      /* Set up port 1 for input and output */
   P1OUT = PB_MASK;             /* Force output to zero and input pins to 1 (for pull-up resistors) */
   P1REN = PB_MASK;             /* Set up pull up resistor for buttons */

   StepRun   = FALSE;            /* By default no output */

   Pwm1_cn        = 0;                /* Reset virtual PWM 1 counter */
   Pwm1_dc        = PWMINITIALVALUE;  /* Set default PWM 1 value */

   /*
    *  Set Timer
    */
   TACTL = TASSEL_2 + MC_1;    /* Uses SMCLK, count in up mode */
   TACCTL0 = CCIE;             /* Use TACCR0 to generate interrupt */
   TACCR0 = TMRVALUE;          /* Approx .001 ms */

   /*  NORMAL MODE */
   TACCTL0 &= ~0x0080;         /* Disable Out0 */

   _BIS_SR(GIE);               /* Enable interrupt */
   eint();    //Enable global interrupts

   while(1)
   {
      switch(P1IN & PB_MASK)
      {
         default:
         case PB_MASK:
            /* both Pushbutton released ! */
            StepRun = FALSE;
            EZDRV_PORT &= ~EZDRV_STEP;    /* Set output to zero */
            EZDRV_PORT &= ~EZDRV_EN;       /* Disable motor */
            break;

         case PB_LEFT:
            /* Left Pushbutton pressed */
            EZDRV_PORT |= EZDRV_EN;       /* Enable motor */
            EZDRV_PORT |= EZDRV_DIR;
            StepRun = TRUE;
            break;

         case PB_RIGHT:
            /*  Pushbutton pressed */
            EZDRV_PORT |= EZDRV_EN;       /* Enable motor */
            EZDRV_PORT &= ~EZDRV_DIR;
            StepRun = TRUE;
            break;
      }
   }
}

interrupt(TIMERA0_VECTOR) TIMERA0_ISR(void)
{
   if(StepRun == TRUE)
   {
      /*
       *  PWM management
       *  This part of the code is handling the PWM 1 generation
       */
      if(Pwm1_cn < PWM1_MAXSTEP)
      {
         Pwm1_cn++;
         if(Pwm1_cn <= Pwm1_dc)
            EZDRV_STEP_ON;
         else
            EZDRV_STEP_OFF;
      }
      else
      {
         /*
          *  Expired counter
          *  Reload counters - force starting output
          */
         Pwm1_cn = 0;
         EZDRV_STEP_OFF;
      }
   }
}

No comments:

Post a Comment