summaryrefslogtreecommitdiff
path: root/robot
diff options
context:
space:
mode:
Diffstat (limited to 'robot')
-rw-r--r--robot/mode_grid.c462
-rw-r--r--robot/mode_grid.h82
2 files changed, 543 insertions, 1 deletions
diff --git a/robot/mode_grid.c b/robot/mode_grid.c
index 8526499..e36162e 100644
--- a/robot/mode_grid.c
+++ b/robot/mode_grid.c
@@ -1,3 +1,463 @@
#include "mode_grid.h"
-void w2_mode_grid() {}
+void w2_mode_grid() {
+
+ initialize(); //only keep this when using this module on its own
+
+ set_motors(0,0);
+
+ //int gridMode = 0; //robot is in the grid
+
+ //coordinates of the orders
+ orderOne();
+ orderTwo();
+ orderThree();
+ orderFour();
+
+ beginLocation();
+
+ for (int i = 0; i < 4; i++ ){
+
+ destination.x = order[i].x;
+ destination.y = order[i].y;
+
+ locationMessage();
+ delay(1000);
+
+ if (location.x != destination.x ){
+ while(location.x != destination.x ){
+ if (location.x > destination.x){
+ turn_West();
+ gridFollowLine();
+ grid_crossway_detection();
+ location.x--;
+ locationMessage();
+ if (location.x == destination.x){
+ arrivedMessage();
+ }
+ }
+
+ else if(location.x < destination.x){
+ turn_East();
+
+ gridFollowLine();
+ grid_crossway_detection();
+ location.x++;
+ locationMessage();
+ if (location.x == destination.x){
+ arrivedMessage();
+ }
+ }
+ }
+ }
+
+ if (location.y != destination.y ){
+ while(location.y != destination.y ){
+ if (location.y > destination.y){
+ turn_South();
+ gridFollowLine();
+ grid_crossway_detection();
+ location.y--;
+ locationMessage();
+ if (location.y == destination.y){
+ arrivedMessage();
+ }
+ }
+
+ else if(location.y < destination.y){
+ turn_North();
+ gridFollowLine();
+ grid_crossway_detection();
+ location.y++;
+ locationMessage();
+ if (location.y == destination.y){
+ arrivedMessage();
+ }
+ }
+ }
+ }
+ }
+}
+
+void full_rotation(){
+ delay_ms(500);
+ set_motors(60,-60);
+ delay_ms(540);
+ set_motors(0,0);
+ position = read_line(sensors,IR_EMITTERS_ON);
+ delay_ms(500);
+}
+
+void grid_rotation_left(){
+ delay_ms(500);
+ set_motors(-30,30);
+ delay_ms(600);
+ set_motors(0,0);
+ position = read_line(sensors,IR_EMITTERS_ON);
+ delay_ms(500);
+}
+
+void grid_rotation_right(){
+ delay_ms(500);
+ set_motors(30,-30);
+ delay_ms(600);
+ set_motors(0,0);
+ position = read_line(sensors,IR_EMITTERS_ON);
+ delay_ms(500);
+}
+
+void grid_crossway_detection(){
+ set_motors(0,0);
+ set_motors(50,50);
+ delay_ms(150); //150
+ set_motors(0,0);
+ position = read_line(sensors,IR_EMITTERS_ON);
+ delay_ms(500);
+}
+
+//variation on "void w2_mode_maze()"
+void gridFollowLine(){
+ unsigned int last_proportional=0;
+ long integral=0;
+
+ // This is the "main loop" - it will run forever.
+ while(1)
+ {
+ // Get the position of the line. Note that we *must* provide
+ // the "sensors" argument to read_line() here, even though we
+ // are not interested in the individual sensor readings.
+ position = read_line(sensors,IR_EMITTERS_ON);
+
+ // The "proportional" term should be 0 when we are on the line.
+ int proportional = ((int)position) - 2000;
+
+ // Compute the derivative (change) and integral (sum) of the
+ // position.
+ int derivative = proportional - last_proportional;
+ integral += proportional;
+
+ // Remember the last position.
+ last_proportional = proportional;
+
+ // Compute the difference between the two motor power settings,
+ // m1 - m2. If this is a positive number the robot will turn
+ // to the right. If it is a negative number, the robot will
+ // turn to the left, and the magnitude of the number determines
+ // the sharpness of the turn.
+ int power_difference = proportional/20 + integral/10000 + derivative*3/2;
+
+ // Compute the actual motor settings. We never set either motor
+ // to a negative value.
+ const int max = 60;
+ if(power_difference > max)
+ power_difference = max;
+ if(power_difference < -max)
+ power_difference = -max;
+
+ if(sensors[0] >= 500 && sensors[1] >= 250 && sensors[2] >= 500 && sensors[3] >= 250 &&sensors[4] >= 500){
+ break;
+ }
+ else if (sensors[0] >= 500 && sensors[1] >= 200 && sensors[4] < 100){
+ break;
+ }
+ else if(sensors[4] >= 500 && sensors[3] >= 200 && sensors[0] < 100){ //for the south and west borders of the grid
+ break;
+ }
+ else if(sensors[4] >= 500 && sensors[3] >= 200 && sensors[2] <100 && sensors[0] < 100){
+ break;
+ }
+
+ else{
+ if(power_difference < 0 && (sensors[2] > 100 || sensors[3] > 100 || sensors[1] > 100) ){
+ set_motors(max+power_difference, max);}
+ else if( power_difference > 0 && ( sensors[2] > 100 || sensors[3] > 100 || sensors[1] > 100)){
+ set_motors(max, max-power_difference);}
+ }
+ }
+}
+
+//coördinates of the orders
+void orderOne(){
+ order[0].x = 1; //1
+ order[0].y = 3; //0
+}
+
+void orderTwo(){
+ order[1].x = 3; //2
+ order[1].y = 2; //2
+}
+
+void orderThree(){
+ order[2].x = 1; //0
+ order[2].y = 4; //4
+}
+
+void orderFour(){
+ order[3].x = 0; //3
+ order[3].y = 0; //1
+}
+
+//setting coördinate and direction when entering the grid from the maze
+void beginLocation(){
+ location.x = 4;
+ location.y = 0;
+ direction = West;
+}
+
+void turn_North()
+{
+ clear();
+ print("North");
+
+ switch (direction)
+ {
+ case North:
+ break;
+
+ case East:
+ grid_rotation_left();
+ break;
+
+ case South:
+ full_rotation();
+ break;
+
+ case West:
+ grid_rotation_right();
+ break;
+ }
+ direction = North;
+}
+
+void turn_West()
+{
+ clear();
+ print("West");
+
+ switch (direction)
+ {
+ case West:
+ break;
+
+ case North:
+ grid_rotation_left();
+ break;
+
+ case East:
+ full_rotation();
+ break;
+
+ case South:
+ grid_rotation_right();;
+ break;
+ }
+ direction = West;
+}
+
+void turn_South()
+{
+ clear();
+ print("South");
+
+ switch (direction)
+ {
+ case South:
+ break;
+
+ case West:
+ grid_rotation_left();
+ break;
+
+ case North:
+ full_rotation();
+ break;
+
+ case East:
+ grid_rotation_right();;
+ break;
+ }
+ direction = South;
+}
+
+void turn_East()
+{
+ clear();
+ print("East");
+
+ switch (direction)
+ {
+ case East:
+ break;
+
+ case South:
+ grid_rotation_left();
+ break;
+
+ case West:
+ full_rotation();
+ break;
+
+ case North:
+ grid_rotation_right();;
+ break;
+ }
+ direction = East;
+}
+
+void locationMessage(){
+ clear();
+ print_long(location.x);
+ print(",");
+ print_long(location.y);
+ delay(200); //1000
+}
+
+void arrivedMessage(){
+ clear();
+ print("ARRIVED");
+}
+
+//!UNDER THIS CAN ALL BE TAKEN AWAY, THIS IS USED IN MODE_MAZE & Callibration!
+
+// Initializes the 3pi, displays a welcome message, calibrates, and
+// plays the initial music.
+// Initializes the 3pi, displays a welcome message, calibrates, and
+// plays the initial music.
+void initialize()
+{
+ unsigned int counter; // used as a simple timer
+
+ // This must be called at the beginning of 3pi code, to set up the
+ // sensors. We use a value of 2000 for the timeout, which
+ // corresponds to 2000*0.4 us = 0.8 ms on our 20 MHz processor.
+ pololu_3pi_init(2000);
+ load_custom_characters(); // load the custom characters
+
+ // Play welcome music and display a message
+ print_from_program_space(welcome_line1);
+ lcd_goto_xy(0,1);
+ print_from_program_space(welcome_line2);
+ play_from_program_space(welcome);
+ delay_ms(1000);
+
+ clear();
+ print_from_program_space(demo_name_line1);
+ lcd_goto_xy(0,1);
+ print_from_program_space(demo_name_line2);
+ delay_ms(1000);
+
+ // Display battery voltage and wait for button press
+ while(!button_is_pressed(BUTTON_B))
+ {
+ int bat = read_battery_millivolts();
+
+ clear();
+ print_long(bat);
+ print("mV");
+ lcd_goto_xy(0,1);
+ print("Press B");
+
+ delay_ms(100);
+ }
+
+ // Always wait for the button to be released so that 3pi doesn't
+ // start moving until your hand is away from it.
+ wait_for_button_release(BUTTON_B);
+ delay_ms(1000);
+
+ // Auto-calibration: turn right and left while calibrating the
+ // sensors.
+ for(counter=0;counter<80;counter++)
+ {
+ if(counter < 20 || counter >= 60)
+ set_motors(40,-40);
+ else
+ set_motors(-40,40);
+
+ // This function records a set of sensor readings and keeps
+ // track of the minimum and maximum values encountered. The
+ // IR_EMITTERS_ON argument means that the IR LEDs will be
+ // turned on during the reading, which is usually what you
+ // want.
+ calibrate_line_sensors(IR_EMITTERS_ON);
+
+ // Since our counter runs to 80, the total delay will be
+ // 80*20 = 1600 ms.
+ delay_ms(20);
+ }
+ set_motors(0,0);
+
+ // Display calibrated values as a bar graph.
+ while(!button_is_pressed(BUTTON_B))
+ {
+ // Read the sensor values and get the position measurement.
+ unsigned int position = read_line(sensors,IR_EMITTERS_ON);
+
+ // Display the position measurement, which will go from 0
+ // (when the leftmost sensor is over the line) to 4000 (when
+ // the rightmost sensor is over the line) on the 3pi, along
+ // with a bar graph of the sensor readings. This allows you
+ // to make sure the robot is ready to go.
+ clear();
+ print_long(position);
+ lcd_goto_xy(0,1);
+ display_readings(sensors);
+
+ delay_ms(100);
+ }
+ wait_for_button_release(BUTTON_B);
+
+ clear();
+
+ print("Go!");
+
+ // Play music and wait for it to finish before we start driving.
+ play_from_program_space(go);
+ while(is_playing());
+}
+
+// This function loads custom characters into the LCD. Up to 8
+// characters can be loaded; we use them for 7 levels of a bar graph.
+void load_custom_characters()
+{
+ lcd_load_custom_character(levels+0,0); // no offset, e.g. one bar
+ lcd_load_custom_character(levels+1,1); // two bars
+ lcd_load_custom_character(levels+2,2); // etc...
+ lcd_load_custom_character(levels+3,3);
+ lcd_load_custom_character(levels+4,4);
+ lcd_load_custom_character(levels+5,5);
+ lcd_load_custom_character(levels+6,6);
+ clear(); // the LCD must be cleared for the characters to take effect
+}
+
+// This function displays the sensor readings using a bar graph.
+void display_readings(const unsigned int *calibrated_values)
+{
+ unsigned char i;
+
+ for(i=0;i<5;i++) {
+ // Initialize the array of characters that we will use for the
+ // graph. Using the space, an extra copy of the one-bar
+ // character, and character 255 (a full black box), we get 10
+ // characters in the array.
+ const char display_characters[10] = {' ',0,0,1,2,3,4,5,6,255};
+
+ // The variable c will have values from 0 to 9, since
+ // calibrated values are in the range of 0 to 1000, and
+ // 1000/101 is 9 with integer math.
+ char c = display_characters[calibrated_values[i]/101];
+
+ // Display the bar graph character.
+ print_character(c);
+ }
+}
+
+void full_rotation(){
+ set_motors(0,0);
+ delay_ms(500);
+ set_motors(60,-60);
+ delay_ms(540);
+ set_motors(0,0);
+ position = read_line(sensors,IR_EMITTERS_ON);
+ delay_ms(500);
+}
diff --git a/robot/mode_grid.h b/robot/mode_grid.h
index 55093ad..42c2c80 100644
--- a/robot/mode_grid.h
+++ b/robot/mode_grid.h
@@ -7,4 +7,86 @@
*
* processes orders from the order buffer
*/
+
+enum orientation{
+ North,
+ East,
+ South,
+ West
+} direction;
+
+typedef struct {
+ int x;
+ int y;
+} coordinates;
+
+coordinates order[4];
+coordinates location;
+coordinates destination;
+
+char xLocation;
+char yLocation;
+
+//LINE 25-68 CAN BE TAKEN AWAY WHEN USED WITH MODE_MAZE
+
+// The 3pi include file must be at the beginning of any program that
+// uses the Pololu AVR library and 3pi.
+#include <pololu/3pi.h>
+
+// This include file allows data to be stored in program space. The
+// ATmega168 has 16k of program space compared to 1k of RAM, so large
+// pieces of static data should be stored in program space.
+#include <avr/pgmspace.h>
+
+unsigned int sensors[5]; // an array to hold sensor values
+unsigned int position;
+// Introductory messages. The "PROGMEM" identifier causes the data to
+// go into program space.
+const char welcome_line1[] PROGMEM = " Pololu";
+const char welcome_line2[] PROGMEM = "3\xf7 Robot";
+const char demo_name_line1[] PROGMEM = "PID Line";
+const char demo_name_line2[] PROGMEM = "follower";
+
+// A couple of simple tunes, stored in program space.
+const char welcome[] PROGMEM = ">g32>>c32";
+const char go[] PROGMEM = "L16 cdegreg4";
+
+// Data for generating the characters used in load_custom_characters
+// and display_readings. By reading levels[] starting at various
+// offsets, we can generate all of the 7 extra characters needed for a
+// bargraph. This is also stored in program space.
+const char levels[] PROGMEM = {
+ 0b00000,
+ 0b00000,
+ 0b00000,
+ 0b00000,
+ 0b00000,
+ 0b00000,
+ 0b00000,
+ 0b11111,
+ 0b11111,
+ 0b11111,
+ 0b11111,
+ 0b11111,
+ 0b11111,
+ 0b11111
+};
+
void w2_mode_grid();
+void full_rotation();
+void grid_rotation_left();
+void grid_rotation_right();
+void grid_crossway_detection();
+void gridFollowLine();
+void orderOne();
+void orderTwo();
+void orderThree()
+void orderFour()
+void beginLocation()
+void turn_North()
+void turn_West()
+void turn_South()
+void turn_East()
+void locationMessage()
+void arrivedMessage()
+