Day 6

So it turned out the code I wrote yesterday did not work as well with sharp corners, primarily because it only utilize the difference between the side readings and middle readings. So I turned it back to the old-days line avoiding algorithms –– that is, turn left when the left sensor senses a line and turn right when the right sensor senses a line.

const int MOTOR_LEFT_POS = 7;
const int MOTOR_LEFT_NEG = 8;
const int MOTOR_RIGHT_POS = 12;
const int MOTOR_RIGHT_NEG = 13;
const int MOTOR_LEFT_PWM = 10;
const int MOTOR_RIGHT_PWM = 11;

#include <Wire.h>
#define uchar unsigned char
uchar t;
uchar data[16];
//#define DEBUG
#define threshold 110
void setup() {
  pinMode(MOTOR_LEFT_POS, OUTPUT);
  pinMode(MOTOR_LEFT_NEG, OUTPUT);
  pinMode(MOTOR_RIGHT_POS, OUTPUT);
  pinMode(MOTOR_RIGHT_NEG, OUTPUT);
  Serial.begin(9600);
  Serial.println("Serial Connected");
  Wire.begin();        // join i2c bus (address optional for master)
  t = 0;
}

void drive(int left, int right) {
  if (left < 0) {
    digitalWrite(MOTOR_LEFT_POS, LOW);
    digitalWrite(MOTOR_LEFT_NEG, HIGH);
  } else {
    digitalWrite(MOTOR_LEFT_POS, HIGH);
    digitalWrite(MOTOR_LEFT_NEG, LOW);
  }

  if (right < 0) {
    digitalWrite(MOTOR_RIGHT_POS, HIGH);
    digitalWrite(MOTOR_RIGHT_NEG, LOW);
  } else {
    digitalWrite(MOTOR_RIGHT_POS, LOW);
    digitalWrite(MOTOR_RIGHT_NEG, HIGH);
  }

  analogWrite(MOTOR_LEFT_PWM, abs(left));
  analogWrite(MOTOR_RIGHT_PWM, abs(right));
}

I think the drive(int, int) function is very useful because it abstracts away the process of changing the motor direction and I can seamlessly control the motors as positive and negative numbers. A common practice for turning is to use only one wheel because it is rather tedious to change the motor direction. However, this means the robot is rotating about the other wheel when turning. By using negative motions (going backward) during turning, I was able to ensure the robot is rotating around its center, therefore being able to pass sharp-corners/discontinuous lines easily.

I also made it so that when the outer sensors sense the line, the robots turns faster. I’m not quite sure if this is necessary or making a significant difference as opposed to using uniformed turning, but it works pretty well.

With some tuning I was able to speed the robot up by quite a bit. Now it runs 2 laps in under 20 seconds.

void loop() {
Wire.requestFrom(9, 16);    // request 16 bytes from slave device #9
while (Wire.available())   // slave may send less than requested
{
data[t] = Wire.read(); // receive a byte as character
if (t < 15)
  t++;
else
  t = 0;
}

if (data[0] < threshold) {
drive(-255, 255);
return;
}

if (data[14] < threshold) {
drive(255, -255);
return;
}

if (data[12] < threshold) {
drive(255, -127);
return;
}

if (data[2] < threshold) {
drive(-127, 255);
return;
}

if (data[10] < threshold) {
drive(255, -63);
return;
}

if (data[4] < threshold) {
drive(-63, 255);
return;
}

drive(255, 255);

}