Tuesday, October 22, 2013

Movements with Encoders

Tasked to build a robot, using a Mega 2560 Arduino board, that went forwards, turned left, and turned right utilizing dc motors and encoders. I came up with the specimen in the videos below. A total of about 2 hours was spent wiring, coding, and debugging.







Wiring:



In this photo the connection to S1 and Ground of the motor controller (4 input side) can be seen.


In this photo the connections to the motors, switch, and battery can be seen.


In this photo the connections to the encoders are visible.


Code:


/* In this program the robot will demonstrate basic movement utilizing DC motors. This program is designed
   to make to robot move forwards, turn left, and turn right.
   
   Program written by Korbin Barker on 10/21/13
   
   Robotic Platform: Undetermined
   Microcontroller:  Arduino MEGA 2560
   Motors:           4 DC Motors
                     1 Sabertooth 2x12 Motor Controller
   Inputs:           1 Flip Switch
   Power Supply:     12 Volts DC
*/

#include <digitalWriteFast.h>

// It turns out that the regular digitalRead() calls are too slow and bring the arduino down when
// I use them in the interrupt routines while the motor runs at full speed creating more than
// 40000 encoder ticks per second per motor.

// Quadrature encoders
// Left encoder
#define c_LeftEncoderInterrupt 0  //This is the number of the interrupt NOT the pin
#define c_LeftEncoderPinA 2       //This is the PIN on the board and the one for the interrupt above
#define c_LeftEncoderPinB 4      // This is any other pin
#define LeftEncoderIsReversed
volatile bool _LeftEncoderBSet;
volatile long _LeftEncoderTicks = 0;

// Right encoder
#define c_RightEncoderInterrupt 1  // This is the number of the interrupt NOT the pin
#define c_RightEncoderPinA 3        // This is the PIN on the board and the one for the interrupt above
#define c_RightEncoderPinB 5        // This is any other pin
volatile bool _RightEncoderBSet;
volatile long _RightEncoderTicks = 0;

/* ================= FUNCTIONS I WROTE =================== */

/* moves robot forward */
void forward()
{

    Serial.print(_LeftEncoderTicks);
    Serial.print("       ");            //these three lines are used to print to the serial monitor for debugging purposes
    Serial.println(_RightEncoderTicks);
    
    if( _RightEncoderTicks == _LeftEncoderTicks)  //keeps robot moving straight
    {
      Serial1.write(127);//left motor full forward value
      Serial1.write(255);//right motor full forward value
      delay(100);
    }
    
    if( _RightEncoderTicks > _LeftEncoderTicks ) //veers robot to the right to account for leftward motion
    {
      Serial1.write(127); //left motor full forward value
      Serial1.write(230);  //right motor slow forward value
      delay(10);
    }
    
    if( _RightEncoderTicks < _LeftEncoderTicks ) //veers robot to the left to account for rightward motion
    {
      Serial1.write(255);  //right motor full forward value
      Serial1.write(102);  //left motor slow forward value
      delay(10);
    }
  
}

/* turns the robot approximately 90 degrees to the left */
void leftTurn()
{  
  while ( _RightEncoderTicks < 900 ) //is the right encoder tick value that the motors will turn to, used to execute the turn
  {
    Serial.print(_LeftEncoderTicks);
    Serial.print("       ");            //these three lines are used to print to the serial monitor
    Serial.println(_RightEncoderTicks);
  
    Serial1.write(255); //right motor full forward value
    Serial1.write(1);  //left motor full backward value
    delay(10);
  }
}

/* turns the robot approximately 90 degrees to the right */
void rightTurn()
{  
  while ( _LeftEncoderTicks < 800 )
  {
    Serial.print(_LeftEncoderTicks);
    Serial.print("       ");              //these three lines are used to print to the serial monitor
    Serial.println(_RightEncoderTicks);
    
    Serial1.write(128);  //right motor full backward value
    Serial1.write(127);  //left motor full forward value
    delay(10);
  }
}

void stopRobot()
{
  _RightEncoderTicks = 0;    // sets the right encoder tick value to 0 for resetting purposes
  _LeftEncoderTicks = 0;     // sets the left encoder tick value to 0 for resetting purposes
  Serial1.write(0);   //stops bot motors
  delay(1000);
}

void setup()
{
  
  Serial.begin(9600);
  Serial1.begin(9600);


  // Quadrature encoders
  // Left encoder
  pinMode(c_LeftEncoderPinA, INPUT);      // sets pin A as input
  digitalWrite(c_LeftEncoderPinA, LOW);  // turn on pullup resistors
  pinMode(c_LeftEncoderPinB, INPUT);      // sets pin B as input
  digitalWrite(c_LeftEncoderPinB, LOW);  // turn on pullup resistors
  attachInterrupt(c_LeftEncoderInterrupt, HandleLeftMotorInterruptA, RISING);

  // Right encoder
  pinMode(c_RightEncoderPinA, INPUT);      // sets pin A as input
  digitalWrite(c_RightEncoderPinA, LOW);  // turn on pullup resistors
  pinMode(c_RightEncoderPinB, INPUT);      // sets pin B as input
  digitalWrite(c_RightEncoderPinB, LOW);  // turn on pullup resistors
  attachInterrupt(c_RightEncoderInterrupt, HandleRightMotorInterruptA, RISING);
}

void loop()
{
  stopRobot();  //stops robot
  
   while ( _RightEncoderTicks < 4000 )  //used to drive the robot forward until 4000 encoder ticks
  { 
    forward();
  }
  
  stopRobot();  //stops robot
  
  leftTurn();  // turns robot left
  
  stopRobot();  //stops robot
  
  rightTurn();  // turns robot right
  
  
}

// Interrupt service routines for the left motor's quadrature encoder
void HandleLeftMotorInterruptA()
{
  // Test transition; since the interrupt will only fire on 'rising' we don't need to read pin A
  _LeftEncoderBSet = digitalReadFast(c_LeftEncoderPinB);   // read the input pin

  // and adjust counter + if A leads B
  #ifdef LeftEncoderIsReversed
    _LeftEncoderTicks -= _LeftEncoderBSet ? -1 : +1;
  #else
    _LeftEncoderTicks += _LeftEncoderBSet ? -1 : +1;
  #endif
}

// Interrupt service routines for the right motor's quadrature encoder
void HandleRightMotorInterruptA()
{
  // Test transition; since the interrupt will only fire on 'rising' we don't need to read pin A
  _RightEncoderBSet = digitalReadFast(c_RightEncoderPinB);   // read the input pin

  // and adjust counter + if A leads B
  #ifdef RightEncoderIsReversed
    _RightEncoderTicks -= _RightEncoderBSet ? -1 : +1;
  #else
    _RightEncoderTicks += _RightEncoderBSet ? -1 : +1;
  #endif
}





Issues:

No significant issues arose from this assignment that couldn't easily be remedied. The only real issue was that the robot was very jittery in the beginning, but this was remedied by increasing delays and rewriting the functions to better suit the needs of the program (I had used previous functions from other programs).

Tuesday, October 15, 2013

Simplified Serial

Tasked to build a robot, using a Mega 2560 Arduino board, that went forwards, backwards, turned left, turned right, and stopped utilizing dc motors. I came up with the specimen in the videos below. A total of about 1 hour was spent wiring, coding, and debugging.





In this video we can see the movements derived from the code.




In this video we can see the LCD Display as it reads the values associated with the motors.


Wiring:


In this photo the connection to S1 and Ground of the motor controller (4 input side) can be seen.


In this photo the connections to the motors, switch, and battery can be seen.


In this photo the connections to the arduino and breadboard can be seen.


Code:

/* In this program the robot will demonstrate basic movement utilizing DC motors. This program is designed
   to make to robot move forwards, backwards, turn left, turn right, veer left, veer right, and stop.
   
   Program written by Korbin Barker on 10/13/13
   
   Robotic Platform: Undetermined
   Microcontroller:  Arduino MEGA 2560
   Motors:           4 DC Motors
                     1 Sabertooth 2x12 Motor Controller
   Inputs:           1 Flip Switch
   Power Supply:     12 Volts DC
*/

/* ================ INCLUDE LIBRARY STEP =================*/

#include <SoftwareSerial.h>

/* ================= INITIALIZATION ===================== */

const int LCDDisplay = 14; //LCD Display is in TX 3 (port 14)

const int stopValue = 0; //neutral value
const int leftStop = 64;  //stops left motor
const int rightStop = 191;  //stops right motor
const int forwardLeft = 127; //full forward (left)
const int forwardRight = 255; //full forward (right)
const int forwardLeftSlow = 102; //slow forward (left)
const int forwardRightSlow = 230; //slow forward (right)
const int backwardLeft = 1;  //full backward (left)
const int backwardRight = 128;  //full backward (right)
const int backwardLeftSlow = 26; //full backward
const int backwardRightSlow =  153; //slow backward
const int time = 2000; //sets a time for delays

int leftValue = 0; //intializes left value for LCD Display
int rightValue = 0; //initializes right value for LCD Display

SoftwareSerial mySerial = SoftwareSerial(255, LCDDisplay);

/* =================== FUNCTION DECLARATION ==================== */

/* clears LCD Display */
void clearScreen()
{
  mySerial.write(12);  //clears screen
  mySerial.write(17);  //turns backlight on
  delay(5);
}

/* writes values to LCD */
void writeDisplay()
{
  clearScreen();
  mySerial.print("Left Value:");
  mySerial.print(leftValue);
  mySerial.write(13);
  mySerial.write(17);
  mySerial.print("Right Value:");
  mySerial.print(rightValue);
  delay(5);
}

/* stops robot's movement */
void stopRobot()
{
  rightValue = leftValue = stopValue; //sets values to be printed on LCD Display
  Serial1.write(stopValue); //writes pulse neutral (stopped) at 0
  delay(time);
}

/* moves robot forward */
void forward()
{
  leftValue = forwardLeft;  // sets value to be printed on LCD Display
  rightValue = forwardRight;   // sets value to be printed on LCD Display 
  Serial1.write(forwardLeft);  
  Serial1.write(forwardRight);
  writeDisplay();
  delay(time);
  stopRobot();
}

/* moves robot forward slowly */
void forwardSlow()
{
  leftValue = forwardLeftSlow;
  rightValue = forwardRightSlow;
  Serial1.write(forwardLeftSlow);
  Serial1.write(forwardRightSlow);
  writeDisplay();
  delay(time);
  stopRobot();
}

/* moves robot backward */
void backward()
{
  leftValue = backwardLeft;
  rightValue = backwardRight;
  Serial1.write(backwardLeft);
  Serial1.write(backwardRight);
  writeDisplay();
  delay(time);
  stopRobot();
}

/* moves robot backward slowly */
void backwardSlow()
{
  leftValue = backwardLeftSlow;
  rightValue = backwardRightSlow;
  Serial1.write(backwardLeftSlow);
  Serial1.write(backwardRightSlow);
  writeDisplay();
  delay(time);
  stopRobot();
}

/* turns robot to the left */
void leftTurn()
{
  leftValue = backwardLeft;
  rightValue = forwardRight;
  Serial1.write(backwardLeft);
  Serial1.write(forwardRight);
  writeDisplay();
  delay(time/2);
  stopRobot();
}

/* turns robot to the right */
void rightTurn()
{
  leftValue = forwardLeft;
  rightValue = backwardRight;
  Serial1.write(forwardLeft);
  Serial1.write(backwardRight);
  writeDisplay();
  delay(time/2);
  stopRobot();
}

/* veers robot to the left */
void leftVeer()
{
  leftValue = forwardLeftSlow;
  rightValue = forwardRight;
  Serial1.write(forwardLeftSlow);
  Serial1.write(forwardRight);
  writeDisplay();
  delay(time);
  stopRobot();
}

/* veers robot to the right */
void rightVeer()
{
  leftValue = forwardLeft;
  rightValue = forwardRightSlow;
  Serial1.write(forwardLeft);
  Serial1.write(forwardRightSlow);
  writeDisplay();
  delay(time);
  stopRobot();
}

/* ================= SETUP STEP ======================*/

void setup()
{
  pinMode(LCDDisplay, OUTPUT);
  digitalWrite(LCDDisplay, HIGH);
  mySerial.begin(9600);
  delay(100);
  Serial1.begin(9600);
  Serial.begin(9600);
}

/* ================ LOOP STEP =======================*/

void loop()
{
  /* see comments under the FUNCTION DECLARATION to see what each of the functions does */
  
  clearScreen();
  stopRobot();
  forward();
  forwardSlow();
  backward();
  backwardSlow();
  leftTurn();
  rightTurn();
  leftVeer();
  rightVeer();  
}


Issues:

No significant issues arose from this assignment that couldn't easily be remedied.




Tuesday, October 8, 2013

Basic Movements DC Motors (Sabertooth and Parallax motor controllers)

Tasked to build a robot, using a Mega 2560 Arduino board, that went forwards, backwards, turned left, turned right, and stopped utilizing dc motors. I came up with the specimen in the gifs below. A total of about 3 hours was spent wiring, coding, and debugging.



Parallax
Forwards, Forward Slow, Backwards, Backward Slow


Parallax
Left Turn, Right Turn, Left Veer, Right Veer


Sabertooth
Forwards, Forward Slow, Backwards, Backward Slow, Left Turn


Sabertooth
Backwards, Backward Slow, Left Turn, Right Turn, Left Veer, Right Veer


Parallax LCD Display
Shows writeMicroseconds values for each movement


Wiring:

For more information on the motor ports please see the previous blog entry.


Parallax
This photo shows the correct wiring scheme (that I found) that works with this setup.


Parallax
This photo shows the wiring scheme from the Parallax Motor Controllers to the breadboard and to the Arduino including the Parallax LCD Display (topmost set of connections)


Sabertooth
This photo shows the correct wiring scheme (that I found) for the Sabertooth motor controller to the Arduino and breadboard.


Sabertooth
This photo shows the correct wiring scheme (that I found) for the Sabertooth motor controller to the motors and power supply (12 Volt Battery).


Sabertooth
Here is another view of the breadboard and Arduino connections.

Code:

/* In this program the robot will demonstrate basic movement utilizing DC motors. This program is designed
   to make to robot move forwards, backwards, turn left, turn right, veer left, veer right, and stop.
   
   Program written by Korbin Barker on 9/27/13
   
   Robotic Platform: Undetermined
   Microcontroller:  Arduino MEGA 2560
   Motors:           4 DC Motors
                        2 Parallax Motor Controllers
                        1 Sabertooth Motor Controller
   Inputs:           1 Flip Switch
   Power Supply:     12 Volts DC
*/

#include <Servo.h>
#include <SoftwareSerial.h>

/* ================= INITIALIZATION ===================== */

/* initializes the servos */
Servo left;
Servo right;

/* initializes all necessary inputs for movement */
const int leftMotor = 2;  //left motor is in port 2
const int rightMotor = 7; // right motor is in port 7
const int LCDDisplay = 14; //LCD Display is in TX 3 (port 14)

const int stopValue = 1500; //neutral value
const int forwardValue = 2000; //full forward
const int forwardSlow = 1600; //slow forward
const int backwardValue = 1000; //full backward
const int backwardSlow =  1300; //slow backward
int leftValue = 0; //intializes left value for LCD Display
int rightValue = 0; //initializes right value for LCD Display

SoftwareSerial mySerial = SoftwareSerial(255, LCDDisplay);

/* =================== FUNCTION DECLARATION ==================== */

/* clears LCD Display */
void clearScreen()
{
  mySerial.write(12);  //clears screen
  mySerial.write(17);  //turns backlight on
  delay(5);
}

void writeDisplay()
{
  mySerial.print("Left Value:");
  mySerial.print(leftValue);
  mySerial.write(13);
  mySerial.write(17);
  mySerial.print("Right Value:");
  mySerial.print(rightValue);
  delay(5);
}

/* stops robot's movement */
void motorStop()
{
  rightValue = leftValue = stopValue; //sets values to be printed on LCD Display
  left.writeMicroseconds(stopValue);  //writes pulse (neutral / stopped) for 1.5 ms
  right.writeMicroseconds(stopValue); //writes pulse (neutral / stopped) for 1.5 ms
  writeDisplay();
  delay(2000);
}

/* moves robot forward */
void motorForward()
{
  rightValue = leftValue = forwardValue;
  left.writeMicroseconds(forwardValue);   //writes pulse (full positive rotation) for 2 ms
  right.writeMicroseconds(forwardValue);  //writes pulse (full positive rotation) for 2 ms
  writeDisplay();
  delay(2000);
  motorStop();
}

/* moves robot backward */
void motorBackward()
{
  rightValue = leftValue = backwardValue;
  left.writeMicroseconds(backwardValue);   //writes pulse (full negative rotation) for 1 ms
  right.writeMicroseconds(backwardValue);  //writes pulse (full negative rotation) for 1 ms
  writeDisplay();
  delay(2000);
  motorStop();
}

/* moves robot slow forward */
void slowForward()
{
  rightValue = leftValue = forwardSlow;
  left.writeMicroseconds(forwardSlow);
  right.writeMicroseconds(forwardSlow);
  writeDisplay();
  delay(2000);
  motorStop();
}

/* moves robot slow backward */
void slowBackward()
{
  rightValue = leftValue = backwardSlow;
  left.writeMicroseconds(backwardSlow);
  right.writeMicroseconds(backwardSlow);
  writeDisplay();
  delay(2000);
  motorStop();
}

/* turns robot left */
void rightTurn()
{
  leftValue = forwardValue;
  rightValue = backwardValue;
  left.writeMicroseconds(forwardValue);   //writes pulse (full positive rotation) for 2 ms
  right.writeMicroseconds(backwardValue);  //writes pulse (full negative rotation) for 1 ms
  writeDisplay();
  delay(1000);
  motorStop();
}

/* turns robot right */
void leftTurn()
{
  leftValue = backwardValue;
  rightValue = forwardValue;
  left.writeMicroseconds(backwardValue);   //writes pulse (full negative rotation) for 1 ms
  right.writeMicroseconds(forwardValue);  //writes pulse (full positive rotation) for 2 ms
  writeDisplay();
  delay(1000);
  motorStop();
}

/* veers robot left */
void leftVeer()
{
  leftValue = forwardSlow;
  rightValue = forwardValue;
  left.writeMicroseconds(forwardSlow);   //writes a very low positive pulse for 1.55 ms
  right.writeMicroseconds(forwardValue);  //writes pulse (full positive rotation) for 2 ms
  writeDisplay();
  delay(1000);
  motorStop();
}

/* veers robot right */
void rightVeer()
{
  leftValue = forwardValue;
  rightValue = forwardSlow;
  left.writeMicroseconds(forwardValue);   //writes pulse (full positive rotation) for 2 ms
  right.writeMicroseconds(forwardSlow);  //writes a very low positive pulse for 1.55 ms
  writeDisplay();
  delay(1000);
  motorStop();
}

/* ================= SETUP STEP ======================*/
void setup()
{
  left.attach(leftMotor);
  right.attach(rightMotor);
  pinMode(LCDDisplay, OUTPUT);
  digitalWrite(LCDDisplay, HIGH);
  mySerial.begin(9600);
  delay(100);
  Serial.begin(9600);  
}

/* ================ LOOP STEP =======================*/
void loop()
{
  /* see comments under the FUNCTION DECLARATION to see what each of the functions does */
  motorStop();
  motorForward();
  slowForward();
  motorBackward();
  slowBackward();
  leftTurn();
  rightTurn();
  leftVeer();
  rightVeer();  
}


Issues:
No significant issues arose from this assignment that couldn't easily be remedied. One of my original Parallax controllers didn't work so I borrowed one from a friend.