Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
main.c
- Committer:
- alecguertin
- Date:
- 2014-12-18
- Revision:
- 42:727612987d77
- Parent:
- 41:1b6d8664d7a7
- Child:
- 43:a0c9549a6f8a
File content as of revision 42:727612987d77:
/**
* @file driver.c
* @brief Primary control logic for robot.
*
* @author John Wilkey
* @author Alec Guertin
* @author Chester Chu
*/
#include "main.h"
m3pi pi; /**< m3pi Object for all control operations. */
Timer timer; /**< Timer used to wait in timerWait. */
DigitalIn start_button(p21); /**< Pi start button input on mBed pin 32 */
int draw; /**< Boolean for drawing/moving. */
/* 4 mBed onboard LEDs */
DigitalOut oled_1(LED1), oled_2(LED2), oled_3(LED3), oled_4(LED4);
/* 8 LEDs driven from mBed digital outs. */
DigitalOut pin13(p13), pin14(p14), pin15(p15), pin16(p16),
pin17(p17), pin18(p18), pin19(p19), pin20(p20);
/* Local File System */
LocalFileSystem local("local");
enum RobotState {
ERROR,
PARSE,
TURN,
MOVE,
DRAW,
FINISHED,
};
/** @brief Entry point. Main loop. */
int main()
{
Timer caltimer;
FILE *ps_file;
RobotState state, last_state;
double dist;
float delta_a, angle, cal_time;
size_t bytes_read;
int corner, err, init, x, y, last_x, last_y, dim_x, dim_y, offset;
char instbuf[INST_BUF_SIZE];
char *cur, *next;
angle = 0;
x = 0;
y = 0;
last_x = 0;
last_y = 0;
bytes_read = 0;
offset = 0;
init = 0;
caltimer = Timer();
/* First calibrate robot and figure out space dimensions. */
robot_printf(0, "%f mV", pi.battery());
/* Calibrate robot reflective sensors to line. */
pi.sensor_auto_calibrate();
timerWait(0.2);
/* Find left bottom right corner of frame. */
corner = find_corner(1);
if (!corner) {
robot_printf(0, "no left\n");
while (1);
}
left(HALF_TURN);
/*
* Find bottom left corner of frame and
* and measure length of frame side.
*/
caltimer.start();
corner = find_corner(0);
if (!corner) {
robot_printf(0, "no right\n");
while (1);
}
caltimer.stop();
cal_time = caltimer.read_ms();
/* Back up into corner (coordinate x=0,y=0). */
right(HALF_TURN);
timerWait(0.2);
backward(400);
/* Open instruction file. */
ps_file = fopen("/local/test.ps", "r");
if (ps_file == NULL) {
return 1;
}
/* Read beginning of file into buffer. */
memset(instbuf, 0, INST_BUF_SIZE);
bytes_read = fread(instbuf, sizeof(char), INST_BUF_SIZE-1, ps_file);
if (bytes_read == 0) {
return 1;
}
/* Read first line of file - the dimensions of the frame. */
err = sscanf(instbuf, "%d/%d", &dim_x, &dim_y);
if (err != 2) {
robot_printf(0, "sscanf1");
while(1);
}
cur = strchr(instbuf, '\n');
cur++;
offset = instbuf+INST_BUF_SIZE-cur-1;
memcpy(instbuf, cur, offset);
/*
* File open and buffer setup. Begin reading instructions and
* moving robot. Refill buffer after each instruction.
*/
state = PARSE;
last_state = PARSE;
while (1) {
switch (state) {
case PARSE:
if (init) {
next = strchr(cur, '\n');
if (next == NULL) {
last_state = state;
state = ERROR;
break;
}
cur = next+1;
offset = instbuf+INST_BUF_SIZE-cur-1;
memcpy(instbuf, cur, offset);
}
init = 1;
memset(instbuf+offset, 0, INST_BUF_SIZE-offset);
bytes_read = fread(instbuf+offset, sizeof(char), INST_BUF_SIZE-1-offset, ps_file);
if (instbuf[0] == '\0') {
pen_up();
last_state = state;
state = FINISHED;
break;
}
last_x = x;
last_y = y;
cur = instbuf;
err = retrieve_inst(instbuf, &x, &y, &draw);
if (err == 0) {
last_state = state;
state = ERROR;
break;
} else {
last_state = state;
state = TURN;
break;
}
case TURN:
delta_a = compute_turn_angle(last_x, last_y, x, y, angle);
angle += delta_a;
if (angle >= FULL_TURN) {
angle -= FULL_TURN;
}
left(delta_a);
if (draw) {
last_state = state;
state = DRAW;
break;
} else {
last_state = state;
state = MOVE;
break;
}
case DRAW:
dist = fabs(distance(last_x, last_y, x, y));
pen_down();
forward(CAL_FACTOR*cal_time*(dist/(double)dim_x));
pen_up();
last_state = state;
state = PARSE;
break;
case MOVE:
dist = fabs(distance(last_x, last_y, x, y));
forward(CAL_FACTOR*cal_time*(dist/(double)dim_x));
last_state = state;
state = PARSE;
break;
case FINISHED:
robot_printf(0, "done\n");
while(1);
case ERROR:
robot_printf(0, "E:%d\n", last_state);
while(1);
default:
last_state = state;
state = ERROR;
break;
}
}
/*
while (1) {
memset(instbuf+offset, 0, INST_BUF_SIZE-offset);
bytes_read = fread(instbuf+offset, sizeof(char), INST_BUF_SIZE-1-offset, ps_file);
if (instbuf[0] == '\0') {
robot_printf(0, "%s", instbuf+1);
pen_up();
while(1);
}
cur = instbuf;
err = retrieve_inst(instbuf, &x, &y, &draw);
if (err == 0) {
robot_printf(0, "noinst");
return 1;
}
if (0 && !draw && init) {
float pos;
right(angle+QUARTER_TURN);
find_line();
forward(100);
pi.left(CAL_SPEED);
pos = pi.line_position();
while (pos > CORRECTION_THRESHOLD || pos < 0) {
pos = pi.line_position();
}
pi.stop();
find_corner(1);
left(180);
find_corner(0);
right(HALF_TURN);
timerWait(0.5);
backward(400);
angle = 0;
last_x = 0;
last_y = 0;
}
init = 1;
delta_a = compute_turn_angle(last_x, last_y, x, y, angle);
angle += delta_a;
if (angle >= FULL_TURN) {
angle -= FULL_TURN;
}
robot_printf(0, "a:%f", delta_a);
left(delta_a);
dist = fabs(distance(last_x, last_y, x, y));
robot_printf(0, "d:%f", CAL_FACTOR*cal_time*(dist/(double)dim_x));
if (draw) {
pen_down();
} else {
pen_up();
}
forward(CAL_FACTOR*cal_time*(dist/(double)dim_x));
pen_up();
last_x = x;
last_y = y;
next = strchr(cur, '\n');
if (next == NULL) {
robot_printf(0, "nonext");
break;
}
cur = next+1;
offset = instbuf+INST_BUF_SIZE-cur-1;
memcpy(instbuf, cur, offset);
}
*/
robot_printf(0, "Done");
pi.stop();
pen_up();
while (1);
}
float compute_turn_angle(int last_x, int last_y, int x, int y, float angle)
{
int delta_x, delta_y;
float theta, delta_a;
delta_x = x-last_x;
delta_y = y-last_y;
if (delta_y == 0) {
if (delta_x < 0) {
theta = HALF_TURN;
} else {
theta = 0;
}
} else if (delta_x == 0) {
if (delta_y < 0) {
theta = -QUARTER_TURN;
} else {
theta = QUARTER_TURN;
}
} else {
theta = atan(((double) delta_y)/((double) delta_x));
theta *= RAD_TO_DEG;
}
if (delta_x < 0 && delta_y > 0) {
theta += HALF_TURN;
}
delta_a = theta-angle;
if (delta_x < 0 && delta_y < 0) {
delta_a += HALF_TURN;
}
if (delta_a > HALF_TURN) {
delta_a -= FULL_TURN;
} else if (delta_a < -HALF_TURN) {
delta_a = FULL_TURN + delta_a;
}
return delta_a;
}
void robot_printf(int line, const char *format, ...)
{
char buf[18];
va_list args;
pi.cls();
pi.locate(0,line);
va_start(args, format);
vsprintf(buf, format, args);
pi.printf("%s", buf);
va_end(args);
}
float distance(int x1, int y1, int x2, int y2)
{
return sqrt(pow((double) (x2-x1),2) + pow((double) (y2-y1), 2));
}
void find_line()
{
float pos, pos1;
pi.forward(DRIVE_SPEED);
pos1 = pi.line_position();
pos = pos1;
while (fabs(pos1-pos) < 0.1 || pos == -1) {
pos = pi.line_position();
robot_printf(0, "%f\n", pos);
}
robot_printf(0, "f:%f\n", pos);
pi.stop();
}
int find_corner(int left)
{
float pos;
float threshold = CORNER_THRESHOLD;
if (left) {
threshold *= -1;
}
do {
pos = pi.line_position();
if(pos > CORRECTION_THRESHOLD) {
pi.right_motor(CAL_SPEED);
pi.left_motor(CAL_SPEED-CORRECTION_SPEED);
} else if(pos < -CORRECTION_THRESHOLD) {
pi.left_motor(CAL_SPEED);
pi.right_motor(CAL_SPEED-CORRECTION_SPEED);
} else {
pi.right_motor(CAL_SPEED);
pi.left_motor(CAL_SPEED);
}
robot_printf(0, "Pos: %f", pos);
} while(pos != -1 && ((left && pos > threshold) || (!left && pos < threshold)));
pi.stop();
if(pos == -1) {
oled_1 = 1;
return 0;
}
return 1;
}
int retrieve_inst(char *buf, int *x, int *y, int *draw)
{
int matches;
char *srch;
matches = sscanf(buf, "%d %d", x, y);
if (matches != 2) {
robot_printf(0, "nomatch");
return 0;
}
srch = strchr(buf, ' ');
srch++;
srch = strchr(srch, ' ');
srch++;
if (srch[0] == 'm') {
*draw = 0;
} else if (srch[0] == 'l') {
*draw = 1;
} else {
robot_printf(0, "%.8s", srch);
return 0;
}
return 1;
}
void forward(int amt)
{
Timer t;
float ms = 0;
float last_ms = 0;
robot_printf(0, "Fwd %d", amt);
t.start();
pi.left_motor(DRIVE_SPEED+.002);
pi.right_motor(DRIVE_SPEED);
ms = t.read_ms();
while(ms < amt) {
if (ms-last_ms > 500) {
t.stop();
right(1.5);
last_ms = ms;
t.start();
pi.left_motor(DRIVE_SPEED+.002);
pi.right_motor(DRIVE_SPEED);
}
ms = t.read_ms();
}
pi.stop();
}
void backward(int amt)
{
Timer t;
t.start();
pi.backward(.5*DRIVE_SPEED);
while(t.read_ms() < amt);
pi.stop();
}
void left(float deg)
{
Timer t;
deg += DEGREE_CORRECTION;
if(deg < 0) {
return right(-1*deg);
}
float amt = (((float)deg)/FULL_TURN)*TIME_FACT*1000;
pi.left(TURN_SPEED);
t.start();
while(t.read_us() < amt);
pi.stop();
}
void right(float deg)
{
Timer t;
deg += DEGREE_CORRECTION;
if(deg < 0) {
return left(-1*deg);
}
float amt = ((((float)deg)/FULL_TURN)*TIME_FACT*1000);
t.start();
pi.right(TURN_SPEED);
while(t.read_us() < amt);
pi.stop();
}
void timerWait(float seconds)
{
Timer t;
t.start();
while(t.read_us() < 1000000*seconds);
}
void pen_down()
{
oled_3 = 1;
}
void pen_up()
{
oled_3 = 0;
}