Arduino Motor Position Controller

image


An Arduino motor position controller can be built using an Arduino Uno and our Motion Mind 3 motor controller.  This example describes how to interface an Arduino Uno with a Motion Mind 3 to create a closed loop motor position controller.   This example and the associated code can be downloaded from our web site as Application Note 1008 (AN1008).

In this example you’ll be operating the Motion Mind 3 in mode 4 (serial control, closed loop). The SW1 DIP switch on the Motion Mind 3 should be set to mode 4, ASCII communication, with a baud rate of 9600BPS. See the image below for examples of appropriate settings.

clip_image001

The motor should be equipped with an incremental encoder for feedback as shown in the schematic below.

Pin 3 of the Arduino Uno is used to transmit serial data and pin 2 is used to receive serial data. These pins are not associated with a hardware UART so the program makes use of the serial software functions for the Arduino. This allows the program to use the serial monitor to read back/display data from the Motion Mind 3.

The program loads some of the PID settings and then loops continuously sending 2 position changes. In between position changes the Arduino reads encoder position and displays it via the serial monitor (ctrl-shift-m, set the monitor for 9600BPS).

clip_image002

/*
  Motion Mind 3 (MOTM3) ASCII Communication example

  This simple Arduino program used ASCII serial communication to program 
  basic PID register settings, and then sends back and forth position commands

  MOTM3 settings:
  SW1 DIP Switch settings set the device for serial closed loop control, 
  ASCII interface, 9600BPS.  An incremental encoder is used as for motor
  position feedback.

  1:  RUN - left
  2:  MOD2 - left = '1'
  3:  MOD1 - right = '0'
  4:  MOD0 - right = '0' MOD2-MOD2 -> operating mode 4
  5:  9.6K - right
  6:  ASC - left
  7: 4XEN - left, nothing special here just left the default switch setting
  8: NC - left

 The circuit: 
 * Arduino RX is digital pin 2 connects to J4 pin 14 DOUT of MOTM3
 * Arduino TX is digital pin 3 connects to J4 pin 13 DIN of MOTM3
 * VMOT should connect to motor power supply
 * GND should be common to Arduino and MOTM3

 */
#include <SoftwareSerial.h>

SoftwareSerial mySerial(2, 3); // Receive data on 2, send data on 3
byte SerialRXPointer;
char SerialRXBuffer[20];
char ch;
byte i;

void setup()  
{
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
  mySerial.begin(9600);

  mySerial.print("\r\n");           // send CR, LF to shake loose any partial comms
                                    // that might be caused by program changes during comm    
  delay(25);                        // we're not reading the response here, but allow time for it    
  mySerial.println("W01 04 6000");  // Write PTerm
  delay(25);                        // we're not reading the response here, but allow time for it
  mySerial.println("W01 05 250");   // Write ITerm
  delay(25);                        // we're not reading the response here, but allow time for it      
  mySerial.println("W01 06 0");     // Write DTerm
  delay(25);                        // we're not reading the response here, but allow time for it  
  mySerial.println("W01 08 14");    // Write Scaler
  delay(25);                       // we're not reading the response here, but allow time for it   
}

void loop() // run over and over
{
  mySerial.println("P01 10000");    // send move to position command
  delay(2000);                       // give motor some time to move 

  mySerial.flush();                  // clear serial softare receive buffer
  SerialRXPointer = 0;               // set pointer for my buffer to 0
  ch = '0';                          // load variable with non-linefeed character
  for(i=0;i<20;i++)
    SerialRXBuffer[i] = 0;            // clear my serial buffer of any previous data
  mySerial.println("R01 00");        // read position register at register index 0
  do{                                // do while reads serial data when available until linefeed occurs        
    if(mySerial.available())         // is data available 
      {
      ch = mySerial.read();          // read byte
      SerialRXBuffer[SerialRXPointer] = ch;   // copy to receive buffer
      SerialRXPointer++;             // point to next buffer location
      }
  }while(ch != 0x0a);                // if ch = linefeed then jump out
  Serial.print(SerialRXBuffer);    // send move to position command
  delay(25);                       // give motor some time to move 

  mySerial.println("P01 5000");     // now move somewhere else
  delay(2000);                       // give motor some time to move 

  mySerial.flush();                  // clear serial software receive buffer
  SerialRXPointer = 0;               // set pointer for my buffer to 0
  ch = '0';                          // load variable with non-linefeed character
  for(i=0;i<20;i++)
    SerialRXBuffer[i] = 0;            // clear my serial buffer of any previous data
  mySerial.println("R01 00");        // read position register at register index 0
  do{                                // do while reads serial data when available until linefeed occurs        
    if(mySerial.available())         // is data available 
      {
      ch = mySerial.read();          // read byte
      SerialRXBuffer[SerialRXPointer] = ch;   // copy to receive buffer
      SerialRXPointer++;             // point to next buffer location
      }
  }while(ch != 0x0a);                // if ch = linefeed then jump out
  Serial.print(SerialRXBuffer);    // send move to position command
  delay(25);                       // give motor some time to move 
}

The serial monitor should display something similar to the screen capture shown below if everything is connected correctly.

clip_image002[6]

Speak Your Mind

*