RC Car Schematic |
Adafruit Motorshield. This code is free for anybody to use or modify
*/
#include <Wire.h> //needed for motors and motor shield
#include <Adafruit_MotorShield.h> //needed for motors and motor shield
#include "utility/Adafruit_PWMServoDriver.h" //needed for motors and motor shield
#include <ctype.h>
int con = 0; //global variable to track connection status
// Create the motor shield object with the default I2C address
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
// create an object for each motor and assign it to a port on the shield
Adafruit_DCMotor *M1 = AFMS.getMotor(1);
Adafruit_DCMotor *M2 = AFMS.getMotor(2);
Adafruit_DCMotor *M3 = AFMS.getMotor(3);
Adafruit_DCMotor *M4 = AFMS.getMotor(4);
int count = 0; //counts how long its been since comms from joystick
String uDSpeed = "500"; //create global variables to hold speed and direction info
String lRSpeed = "500"; //defulat is 500 because that is stop condition
//setup code only executed once
void setup() {
Serial.begin(115200); //start serial commm
//This loop runs until a connection from another RN42 is complete and a "#" is recieved from the car
//The joystick RN42 is the slave
while(!con) {
if((char)Serial.read() == '#') { con = 1; }//once connected change "con" to true
delay(5);
}
AFMS.begin(); //Start motor shield object, create with the default frequency 1.6KHz
}
void loop() {
//check if a full speed / direction frame is ready to be read
if(Serial.available() >= 6) {
String temp; //temperary string to hold incoming data
char c = (char)Serial.read();
if(c == 'u') { //If a 'u' was read this is start of an up / down data frame
for(int i=0; i<5; i++) { //loop to read 5 other bytes of frame
if(i < 4) { //reads the speed portion of frame into string
temp += (char)Serial.read();
}
else { //look for end of frame 'd' character, if it is there save this reading as new speed
if((char)Serial.read() == 'd') {
uDSpeed = temp;
count = 0; //just got speed so reset count
}
}
}
}
else if(c == 'l') { //If a 'l' was read this is start of an left / right data frame
for(int i=0; i<5; i++) { //following code is the same as above except for direction frame
if(i < 4) {
temp += (char)Serial.read();
}
else {
if((char)Serial.read() == 'r') {
lRSpeed = temp;
count = 0; //just got speed so reset count
}
}
}
}
}
delay(1);
//the following code will stop the car if no comms with joystick for 150ms
count++;
if(count > 20) {
setMotorSpeed(500,500);
}
//function call to set motor speeds
setMotorSpeed(uDSpeed.toInt(),lRSpeed.toInt());
}
//This function clears all bytes out of arduino serial read buffer
void clearSerialBuf() {
while(Serial.available()) { Serial.read(); }
}
//This function uses the ADC values from the joystick and turns them into motor speeds for going
//forware, right, left, and reverse. Inputs are the left/right and up/down joystick axis
void setMotorSpeed(int upDown, int leftRight) {
int lR = 0;
int bF = 0;
//If left/right is 500 no turn
if(leftRight == 500) {
lR = 0;
}
else if(leftRight > 500) { //If greater than 500 this is a right turn
lR = 1;
leftRight = leftRight - 500;
}
else { //less than 500 this is a left turn
lR = 2;
leftRight = 500 - leftRight;
}
if(upDown == 500) { //500 no up/down direction
bF = 0;
}
else if(upDown > 500) {//more than 500 go forward
bF = 1;
upDown = upDown - 500;
}
else { //less than 500 go backward
bF = 2;
upDown = 500 - upDown;
}
//If direction variables are both 0 the car is stopped
if(lR == 0 && bF == 0) {
motorStop();
}
else if (bF==1) { //if forward variable is true
if(lR == 0) { //no turn so go straight forward
goForward(scaleSpeed(upDown));
}
else if(lR == 1) { //go forward and right
goTurn(scaleSpeed(scaleTurn(upDown,leftRight)), scaleSpeed(upDown), 1);
}
else { //go forward and left
goTurn(scaleSpeed(upDown),scaleSpeed(scaleTurn(upDown,leftRight)), 1);
}
}
else if (bF==2) { //if backwards variable is true
if(lR == 0) { //go straight backwards
goBackward(scaleSpeed(upDown));
}
else if(lR == 1) { //go backward and right
goTurn(scaleSpeed(scaleTurn(upDown,leftRight)), scaleSpeed(upDown), 0);
}
else { //go backward and left
goTurn(scaleSpeed(upDown),scaleSpeed(scaleTurn(upDown,leftRight)), 0);
}
}
else { //if no forward or back then just turn
if(lR==1) { //Right turn, left wheels forward and right wheels backwards
goRight(scaleSpeed(leftRight));
}
else { //left turn, right wheels forward and left wheels backwards
goLeft(scaleSpeed(leftRight));
}
}
}
//function to stop the motors
void motorStop() {
M2->run(RELEASE);
M4->run(RELEASE);
M1->run(RELEASE);
M3->run(RELEASE);
}
//function to tell motors to go forward, input is speed
void goForward(int mSpeed) {
M1->setSpeed(mSpeed);
M2->setSpeed(mSpeed);
M3->setSpeed(mSpeed);
M4->setSpeed(mSpeed);
M2->run(FORWARD);
M4->run(FORWARD);
M1->run(FORWARD);
M3->run(FORWARD);
}
//function to tell motors to go backward, input is speed
void goBackward(int mSpeed) {
M1->setSpeed(mSpeed);
M2->setSpeed(mSpeed);
M3->setSpeed(mSpeed);
M4->setSpeed(mSpeed);
M2->run(BACKWARD);
M4->run(BACKWARD);
M1->run(BACKWARD);
M3->run(BACKWARD);
}
//function for left or right turn. inputs are speed for left tires and speed for right tires
//and whether we are going forward or backwards
void goTurn(int rTire, int lTire, int forward) {
M1->setSpeed(rTire);
M2->setSpeed(lTire);
M3->setSpeed(rTire);
M4->setSpeed(lTire);
//code to turn Right
if(forward) {
M2->run(FORWARD); //M2 and M4 are left tires
M4->run(FORWARD);
M1->run(FORWARD); //M1 and M3 are right tires
M3->run(FORWARD);
}
else {
M2->run(BACKWARD);
M4->run(BACKWARD);
M1->run(BACKWARD);
M3->run(BACKWARD);
}
}
//right turn function, no forward or backwards motion
void goRight(int tSpeed) {
tSpeed = tSpeed - (tSpeed*.2); //reduce speed by 20%
M1->setSpeed(tSpeed);
M2->setSpeed(tSpeed);
M3->setSpeed(tSpeed);
M4->setSpeed(tSpeed);
//code to turn Right
M2->run(FORWARD); //left tires
M4->run(FORWARD);
M1->run(BACKWARD); //right tires
M3->run(BACKWARD);
}
//left turn function, no forward or backwards motion
void goLeft(int tSpeed) {
tSpeed = tSpeed - (tSpeed*.2); //reduce speed by 20%
M1->setSpeed(tSpeed);
M2->setSpeed(tSpeed);
M3->setSpeed(tSpeed);
M4->setSpeed(tSpeed);
//code to turn Right
M2->run(BACKWARD); //left tires
M4->run(BACKWARD);
M1->run(FORWARD); //right tires
M3->run(FORWARD);
}
//This function scales the speed values from the joystick ADCs to the speed values of the motors
int scaleSpeed(int scale) {
float r = ((float)scale/500)*250;
return int(r);
}
//This scales the turns based on the forward / backward speeds
int scaleTurn(int fBSp, int lRSp) {
float r =(float)fBSp*(1 - (float)lRSp/500);
return int(r);
}