/* C code for the Main robot controller. This controller sends servo positions to the servo bank controllers. (C) 2004 justin_sane huntjas2@msu.edu Version 1.5 */ // This is the config register for the options that we need #pragma config |= 0x3FF0 /* pin definitions */ bit sel_switch @ PORTB.0; // attached to the mode controll switch //bit serial_in @ PORTB.1; // (in) serial data in from computer bit serial_out @ PORTB.2; // (out) serial out to computer bit ir_servo @ PORTB.3; // (out) outout for IR sensor // portb.4 is PGM, unusable in LVP mode bit led @ PORTB.5; // (out) led //bit data @ PORTB.7; // (in) data input form main computer //bit clock @ PORTB.6; // (in) clock input form main computer bit r_ready @ PORTA.0; // (in) right bank ready bit l_ready @ PORTA.1; // (in) left bank ready bit l_clock @ PORTA.2; // (out) left bank bit r_clock @ PORTA.3; // (out) clock out to right bank // porta.5 is MCLR, unusable in LVP mode bit data_out @ PORTA.4; // (out) data out is shared by both banks bit ir_enable @ PORTA.6; // (out) start control to ir bit ir_data @ PORTA.7; // (in) data back from the IR #define mode_forward 0 #define mode_turning 1 #define mode_backward 2 unsigned char r_servos[6]; // positions of the servos in the banks unsigned char l_servos[6]; unsigned char ir_servo_pos; // position of the gimble servo #define ir_servo_base 118 // base time offset for the gimgle servo int ir_dir; // current sweep direction for this servo unsigned char r_angle; // angle of right side unsigned char l_angle; // angle of left side int forward; // positive is forward movement int turn; // positive is left turn #include "sine.c" // sine functions #include "serial.c" // serial functions /* setup the system on boot */ void start_up(void) { TRISB = 0xC3; // bit 0, 1, 6, 7 input all others, output TRISA = 0x83; // Bits 2, 3, 4, 5, 6 are outputs CMCON = 0x07; // comparators off // init the ports PORTA = 0; PORTB = 0; serial_out = 1; // thid is the rest line state new_line(); send_string("ANT Version 1.5 2004 Jason Hunt"); new_line(); ir_servo_pos = 128; l_angle = 0; r_angle = 0; ir_dir = 1; } /* end of start_up */ /* move the ir servo */ void update_ir_servo(void) { ir_servo_pos += ir_dir; // swap directions if we are out range if ((ir_servo_pos == 128 - 64) || (ir_servo_pos == 128 + 64)) ir_dir = -ir_dir; unsigned char pos = ir_servo_pos; unsigned char base = ir_servo_base; ir_servo = 1; // turn on pwm control line if (base) while(--base); // delay for base position if (pos) while(--pos); // dealy for actual position ir_servo = 0; // line off } /* end of update ir servo */ /* sends all of the servo position to the banks */ // This can update both banks at the same time void update_servos(void) { // these work as flags and servo index counters int l_done = 0, r_done = 0, t; // wait until both servo banks have been updated while (!l_done || !r_done) { // if left side is ready, start transmittion if (l_ready && l_done == 0) { send_byte(l_bank, 0); // send "bank update" command for (t = 0; t < 6; t++) send_byte(l_bank, l_servos[t]); // send the next servo position l_done = 1; // inticate start of transmittion } // if left side is ready, start transmittion if (r_ready && r_done == 0) { send_byte(r_bank, 0); // send "bank update" command for (t = 0; t < 6; t++) send_byte(r_bank, r_servos[t]); // send the next servo position r_done = 1; // inticate start of transmittion } } } /* end of update servos */ /* calculate the new servo positions */ void calc_servo_pos(unsigned l_rake, unsigned r_rake, unsigned height) { // calculate trig values for the left side unsigned l_000_deg = sine(l_angle, height); unsigned l_180_deg = sine(l_angle + deg_180, height); unsigned l_090_deg = sine(l_angle + deg_90, l_rake); unsigned l_270_deg = sine(l_angle + deg_270, l_rake); // trig for right side unsigned r_000_deg = sine(r_angle, height); unsigned r_180_deg = sine(r_angle + deg_180, height); unsigned r_090_deg = sine(r_angle + deg_90, r_rake); unsigned r_270_deg = sine(r_angle + deg_270, r_rake); // lifting, right side (larger number, leg farther up) r_servos[0] = r_180_deg+30; r_servos[2] = r_000_deg; r_servos[4] = r_180_deg-30; // (-10) // raking, right side (larger number, more forward) r_servos[1] = r_090_deg - 30; // bring rear legs back farther r_servos[3] = r_270_deg - 30; r_servos[5] = r_090_deg - 30; // lifting, left side l_servos[0] = l_000_deg + 30; l_servos[2] = l_180_deg; l_servos[4] = l_000_deg - 30 ; // (-10) // raking, left side (larger number, more forward) l_servos[1] = l_270_deg - 30; l_servos[3] = l_090_deg - 30; l_servos[5] = l_270_deg - 30; } /* end of calc servo pos */ /* sends the direction data to the main computer */ void send_direction() { /* if (forward > 0) send_string("F"); if (forward < 0) send_string("B"); if (turn > 0) send_serial('L'); if (turn < 0) send_serial('R'); if (!forward && !turn) send_serial('S'); // stopped space();*/ } /* end of send_direction */ /* update the angular positions */ void update_movement(void) { unsigned l_rake = 3; // default rake amplitude divisor unsigned r_rake = 3; unsigned height = 4; // movement forward or backwards if (forward) { // move the cycle forward and sync legs r_angle += forward; l_angle = r_angle; // forward plus turn if (turn > 0) { l_rake = 5; r_rake = 2;} // left turn if (turn < 0) { l_rake = 2; r_rake = 5;} // right turn } // standing rotation (no movement forward or backwards) if (turn && !forward) { l_angle -= turn; // adjust the angle in the direction we are turning r_angle += turn; } // update the servo positions calc_servo_pos(l_rake, r_rake, height); } /* end of update movement */ /* get analog data from the ir ranger */ unsigned get_ir_dist(void) { ir_enable = 1; // start charging the compare cap unsigned long count = 0; while (!ir_data && count < 256) count++; // find out time until compare ir_enable = 0; // start discharging if (count > 255) count = 255; return(count); } /* main function */ void main( void) { // send the startup string start_up(); unsigned dist; unsigned led_count = 0; unsigned long count = 0; int mode = mode_forward; forward = 4; turn = 0; while (1) { // send_direction(); // send debugging info dist = get_ir_dist(); // send the scan data send_hex(ir_servo_pos); space(); send_hex(dist); new_line(); // switch in forward (run position) if (sel_switch) { update_movement(); // calculate all of the new pos data update_servos(); } update_ir_servo(); if (mode == mode_forward && dist > 40) { mode = mode_backward; forward = -4; turn = 0; count = 0; } if (mode == mode_backward && count > 50) { mode = mode_turning; turn = 4; forward = 0; count = 0; } if (mode == mode_turning && count > 75) { mode = mode_forward; forward = 4; turn = 0; count = 0; } count++; /* stuff to blink the led */ dist = 255 - dist; if (led_count > dist) { led = !led; led_count = 0; } if (dist == 0) led = 0; led_count += 20; } } /* end of main */