Friday, November 29, 2013

Agile Robotics Final Project: Weeks 2 & 3

This was due a week or so ago but I haven't spent a significant amount of time on the robot as life has been preoccupying me.

Some updates:


  • Got the main "tracking rail" for the bed edge built and programmed to return
  • Began working on the actual following of the bed edge




Wiring:

In this photo, the connections between the servo and sensors are given. The push button and limit switch are connected to a "pull-up" resistor. The connections have been rearranged for organization in the past week.

Code: (uncommented)

#include <Servo.h>


 int val;
 int encoder0PinA = 12;
 int encoder0PinB = 13;
 int encoder0Pos = 0;
 int encoder0PinALast = LOW;
 int n = LOW;
 Servo finderServo;

 int stopButton = 4;
 int resetButton = 3;
 int stopButtonValue = 0;
 int resetButtonValue = 0;


 int encoderRead()
 {
    n = digitalRead(encoder0PinA);
   if ((encoder0PinALast == LOW) && (n == HIGH)) {
     if (digitalRead(encoder0PinB) == LOW) {
       encoder0Pos--;
     } else {
       encoder0Pos++;
     }
     Serial.println (encoder0Pos);
   }
   encoder0PinALast = n;
 }

 void armIn()
 {
   finderServo.write(0);
 }

 void armOut()
 {
   finderServo.write(180);
 }

 void armStop()
 {
   finderServo.write(90);
 }

 void armReturn()
 {
   while(stopButtonValue == 0)
   {
     stopButtonValue = digitalRead(stopButton);
     armIn();
   }
   armStop();
   Serial.print("StopButton Value =");
   Serial.println(stopButtonValue);
 }

 void setup() {
   pinMode (encoder0PinA,INPUT);
   pinMode (encoder0PinB,INPUT);
   Serial.begin (9600);
   finderServo.attach(9);
   pinMode (resetButton, INPUT);
   pinMode (stopButton, INPUT);
 }

 void loop()
 {
 
   while(resetButtonValue == 0)
   {
     resetButtonValue = digitalRead(resetButton);
     armStop();
     Serial.print("ResetButton Value = ");
     Serial.println(resetButtonValue);
     delay(50);
   }
 
   while (stopButtonValue == 0)
   {
     stopButtonValue == digitalRead(stopButton);
     armReturn();
     Serial.print("ResetButton Value = ");
     Serial.println(resetButtonValue);
     delay(50);
   }
 
   encoderRead();
 
   if(encoder0Pos < 150)
   {
    armOut();
   }
 
  if(encoder0Pos > 150)
   {
    armStop();
   }
 } 

Issues:
No significant issues have come about other than a minor encoder issue with getting it to read properly but this was resolved.

Tuesday, November 19, 2013

Agile Robotics Final Project: Week 1

I was lazy and didn't do any work from Tuesday, November 5 until Tuesday, November 12. On this day, however I began assembling the main parts of the robot. Information on this will be in  Agile Robotics Final Project: Week 2.

Tuesday, November 5, 2013

Own Programmed RC

The assignment given, really for the previous week but I couldn't get to work due to complexity, for this week was to integrate two more IOs to the Arduino, research them, and program to be able to use them. I chose two RF transceivers (pictured below) and a 2 axis joystick (also pictured below). Both of the integrated IOs used were developed by Parallax. About 6 hours were spent on the previous (failed) attempt and 4 spent on the most recent (successful) attempt at getting the robot to perform as desired.

The robot utilizes the 2 axis joystick to control its movements. The movement's are very rudimentary, only being able to move forwards, backwards, turn left, and turn right.








Wiring:


This photo shows the connections between the robotic platform and the RF transceiver. The dataline is directly connected to Rx1 on the Arduino board so that it can receive and interpret the data incoming to direct the robot's movements. The Tx/Rx select is pulled low as was specified in the datasheet associated with the transceiver, pulling it low makes it act as a receiver.



This photo shows the connections between the controller and the RF transceiver. The dataline is connected to Tx0 so that it can send values to be read by robotic platform. The Tx/Rx select is pulled high to make it act as a transmitter.


This photo shows the connections between the controller and the 2 axis joystick.  Power is applied to the L/R+ and the U/D+ and the datalines for L/R and U/D go to Analog ports A1 and A0 respectively.



Here is an overhead view of most of the controller circuit.

Code:
Transmitter (controller):
#include <SoftwareSerial.h>

int UD = 0;//initializes the up/down value to zero
int LR = 0;//initializes the left/right value to zero

void setup()
{
  Serial.begin(2400);
  /*set to 2400 baud, the corresponding receiving rate on the receiver so that the two 
    sets of programs can talk to each other over the RF transceivers*/
}

void loop()
{
  UD = analogRead(A0);//reads the up/down analog value of the joystick
  LR = analogRead(A1);//reads the left/right analog value of the joystick
  
  if (LR < 200)
  {
    Serial.println("L");//a value between 400 and 90 are considered to be leftward values so a large outlier was set at 200
  }
  
  if (LR > 700)
  {
    Serial.println("R");//a value between 600 and 900 are considered to be rightward values so a smaller outlier was set to 700
  }
  
  if (UD > 700)
  {
    Serial.println("U");//the same concept applies here as did to the Serial.println("R");
  }
  
  if (UD < 300)
  {
    Serial.println("D");//the same concept applies here as did to the Serial.println("L"); only using 300 as the large outlier
  }
  
  if (UD > 300 && UD < 700 && LR > 200 & LR < 700)
  {
    Serial.println("S");//a value that is below 700, above 300, above 200, and below 700 in the UD an LR will make the robot stop
  }
  
    delay(100);
}




Receiver (robot):
#include <SoftwareSerial.h>


const int stopValue = 0; //neutral value
const int forwardLeft = 127; //full forward (left)
const int forwardRight = 255; //full forward (right)
const int backwardLeft = 1;  //full backward (left)
const int backwardRight = 128;  //full backward (right)
char inByte;

/* stops robot's movement */
void stopRobot()
{
  Serial3.write(stopValue); //writes pulse neutral (stopped) at 0
  delay(50);
}

/* moves robot forward */
void forward()
{
  Serial3.write(127);  
  Serial3.write(255);
  delay(50);
}

/* moves robot backward */
void backward()
{
  Serial3.write(1);
  Serial3.write(128);
  delay(50);
}

/* turns robot to the left */
void leftTurn()
{
  Serial3.write(1);
  Serial3.write(255);
  delay(50);
}

/* turns robot to the right */
void rightTurn()
{
  Serial3.write(127);
  Serial3.write(128);
  delay(50);
}

void setup()
{
  Serial.begin(2400);
  Serial1.begin(2400);
  Serial3.begin(9600);
}

void loop()
{
  if (Serial1.available())
  {
    char inByte = Serial1.read();
    /*this couple of lines are the signal processing lines which take and
      use the value in the following case structure */
    Serial.print(inByte); 
  
   
   switch (inByte)
   {
     case 'U':
     forward();//if the value received is "U" the robot will go forward
     break;
     
     case 'D':
     backward();//if the value received is "D" the robot will go backward
     break;
     
     case 'L':
     leftTurn();//if the value received is "L" the robot will turn left
     break;
     
     case 'R':
     rightTurn();//if the value received is "R" the robot will turn right
     break;
     
     case 'S':
     stopRobot();//if the value received is "S" the robot will stop (this is the default action)
     break;
   }
  }
}

Issues:
The only issues that came about (in this final project) was getting the robot to act based on the incoming value. I had, at one point, used if statements instead of the case structure in the receiver program and it did not work. Next, I tried using a case structure and found that I was able to get the robot to go forward only. After examining the program, I found that I had done Serial3.begin(2400); which would not properly communicate with the Sabertooth motor controller. After fixing the error, making it Serial3.begin(9600); I got full functionality.


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.