Final version of the m3pi software
Dependencies: mbed m3pi FreeRTOS_V8_2_1_LPC1768
main.cpp
- Committer:
- JoaoJardim
- Date:
- 2018-12-21
- Revision:
- 8:167680431cf4
- Parent:
- 6:00f820418d01
File content as of revision 8:167680431cf4:
//******************************************************************************************************************* // Includes //******************************************************************************************************************* #include "mbed.h" #include "FreeRTOS.h" #include "task.h" #include "m3pi.h" #include "queue.h" //******************************************************************************************************************* // Definitions & Initializations //******************************************************************************************************************* // Task Priorities #define PRIORITY_MAX 4 #define PRIORITY_HIGH 3 #define PRIORITY_NORMAL 2 #define PRIORITY_LOW 1 #define PRIORITY_IDLE 0 #define FORWARD 2 #define BACKWARD 3 #define LEFT 4 #define RIGHT 5 #define STOP 6 m3pi m3pi; DigitalOut led1(LED1); DigitalOut led2(LED2); DigitalOut led3(LED3); DigitalOut led4(LED4); DigitalOut nRST(p26); const portTickType xDelay = 100 / portTICK_RATE_MS; const portTickType xDelayMZ = 100 / portTICK_RATE_MS; const portTickType xDelayRst = 2000 / portTICK_RATE_MS; const portTickType xDelayLF = 1000 / portTICK_RATE_MS; const float fVref = 4.0; QueueHandle_t xQueue1; //******************************************************************************************************************* // Task Free //******************************************************************************************************************* void TaskFree (void* pvParameters) { (void) pvParameters; // Just to stop compiler warnings. void *pvQBuf = malloc(sizeof(int)); for( ;; ) { if ( xQueueReceive(xQueue1, pvQBuf, 0) ) { taskENTER_CRITICAL(); // Critical section so that the Scheduler won't interrupt the m3pi commands switch(*((int*)pvQBuf)) { case FORWARD: m3pi.forward(0.2); break; case BACKWARD: m3pi.backward(0.2); break; case LEFT: m3pi.left(0.2); break; case RIGHT: m3pi.right(0.2); break; case STOP: m3pi.stop(); break; } taskEXIT_CRITICAL(); } } } //******************************************************************************************************************* // Task Maze //******************************************************************************************************************* void TaskMZ (void* pvParameters){ (void) pvParameters; // Just to stop compiler warnings. led1 = 0; m3pi.reset(); vTaskDelay(xDelayRst); float speed = 0.125; float correction = 0.125; float threshold = 0.5; float u_turn_t = 0.2; // float u_turn_t = 1.4; float u_turn_thresh = 50; // These variables record whether the robot has seen a line to the // left, straight ahead, and right, while examining the current intersection. int sensors[5]; int foundjunction=0; int threshold_sns = 500; m3pi.locate(0,1); m3pi.printf("Maze slv"); m3pi.sensor_auto_calibrate(); for( ;; ){ led1 = !led1; // Line Follower **************************************************************************** // -1.0 is far left, 1.0 is far right, 0.0 in the middle float position_of_line = m3pi.line_position(); // Line is more than the threshold to the right, slow the left motor if (position_of_line > threshold) { m3pi.right_motor(speed); m3pi.left_motor(speed-(position_of_line*correction)); } // Line is more than 50% to the left, slow the right motor else if (position_of_line < -threshold) { m3pi.left_motor(speed); m3pi.right_motor(speed+(position_of_line*correction)); } // Line is in the middle else { m3pi.forward(speed); } // Detect junctions ************************************************************************* m3pi.readsensor(sensors); // Read the sensors if ( (sensors[1]<threshold_sns) && (sensors[2]<threshold_sns) && (sensors[3]<threshold_sns) ){ // Detects the a dead end and resolves it by "u turning" float a = sensors[1] - sensors[3]; while ( (a < u_turn_thresh) && ((-1*a) < u_turn_thresh) ) { led3 = !led3; m3pi.left_motor(-1*speed); // UTURN m3pi.right_motor(speed); wait(u_turn_t); m3pi.readsensor(sensors); // Read the sensors a = sensors[1] - sensors[3]; } } else { // Detect "dead end" if(sensors[0] > threshold_sns || sensors[4] > threshold_sns) { foundjunction = 1; // Found an intersection } // Solve junctions ******************************************************** // The order of the statements in this "if" is sufficient // to implement a follow left-hand wall algorithm if (foundjunction==1) { led2 = !led2; taskENTER_CRITICAL(); // We dont want the maze solver to be stopped during a turn m3pi.forward(0.1); // Move forward a bit in case it meet wait(0.05); // the intersection sideways m3pi.stop(); m3pi.readsensor(sensors); // Read the sensors again if(sensors[0] > threshold_sns) { m3pi.forward(0.1); wait(0.67); m3pi.left_motor(speed); // LEFT m3pi.right_motor(-1*speed); wait(0.67); // Was tuned for a 90 deg turn } else { m3pi.forward(0.1); // Move forward a bit to discover wait(0.3); // if its a R or FR junction m3pi.stop(); m3pi.readsensor(sensors); // Read the sensors again if ( (sensors[1]<threshold_sns) && (sensors[2]<threshold_sns) && (sensors[3]<threshold_sns) ) { // if the center sensors are white, its a R junction m3pi.forward(0.1); wait(0.30); m3pi.left_motor(-1*speed); // RIGHT m3pi.right_motor(speed); wait(0.57); // Was tuned for a 90 deg turn } else { m3pi.forward(speed); // FRONT wait(0.3); } } foundjunction = 0; // Resets foundjunction flag taskEXIT_CRITICAL(); } } vTaskDelay(xDelayMZ); } } //******************************************************************************************************************* // Task Follow //******************************************************************************************************************* void TaskLF (void* pvParameters){ (void) pvParameters; // Just to stop compiler warnings. m3pi.reset(); vTaskDelay(xDelayRst); float speed = 0.3; float correction = 0.2; float threshold = 0.5; m3pi.locate(0,1); m3pi.printf("Line Flw"); vTaskDelay(xDelayLF); m3pi.sensor_auto_calibrate(); for( ;; ){ led1 = !led1; taskENTER_CRITICAL(); // Critical section so that the Scheduler won't interrupt the m3pi commands // -1.0 is far left, 1.0 is far right, 0.0 in the middle float position_of_line = m3pi.line_position(); // Line is more than the threshold to the right, slow the left motor if (position_of_line > threshold) { m3pi.right_motor(speed); m3pi.left_motor(speed-correction); } // Line is more than 50% to the left, slow the right motor else if (position_of_line < -threshold) { m3pi.left_motor(speed); m3pi.right_motor(speed-correction); } // Line is in the middle else { m3pi.forward(speed); } taskEXIT_CRITICAL(); vTaskDelay(xDelay); } } //******************************************************************************************************************* // Task Bluetooth //******************************************************************************************************************* void TaskBluetooth (void* pvParameters) { (void) pvParameters; // Just to stop compiler warnings. TaskHandle_t xRunngTask = NULL; void *pvQSnd = malloc(sizeof(int)); // char cMsg[8]=""; // Used for writing to the LCD // Resets the Wireless module nRST = 0; vTaskDelay(xDelay); nRST = 1; Serial rn41(p28,p27); // Serial rn41(p9,p10); rn41.baud(115200); led1 = 0; led2 = 0; led3 = 0; led4 = 0; m3pi.cls(); // Clears the LCD xTaskCreate( TaskFree, ( const char * ) "TaskFree", configMINIMAL_STACK_SIZE, NULL, PRIORITY_LOW, &xRunngTask ); for (;;) { if(m3pi.battery() < fVref) { m3pi.locate(0,0); m3pi.print("Low Pwr!", 8); } else{ m3pi.locate(0,0); m3pi.print("BT Task", 8); } if (rn41.readable()) { // When BT is readable *((int*)pvQSnd) = rn41.getc(); // Reads Bluetooth //led2 = *((int*)pvQSnd); // The received[0 / 1] turns [off / on] LED2 /* sprintf(&cMsg[0], "%d", *((int*)pvQSnd)); // m3pi.locate(0,1); m3pi.print(cMsg, 8); */ if(rn41.writeable()) { rn41.putc(led2); // Send LED2 state to the BT terminal } if (*((int*)pvQSnd) == 7) { vTaskDelete(xRunngTask); // Deletes the task that controls the currently running mode m3pi.stop(); // Prevents the m3pi from running wild while the system prepares the new mode xTaskCreate( TaskFree, ( const char * ) "TaskFree", configMINIMAL_STACK_SIZE, NULL, PRIORITY_LOW, &xRunngTask ); } else if (*((int*)pvQSnd) == 8) { vTaskDelete(xRunngTask); // Deletes the task that controls the currently running mode m3pi.stop(); // Prevents the m3pi from running wild while the system prepares the new mode xTaskCreate( TaskMZ, ( const char * ) "TaskMZ", configMINIMAL_STACK_SIZE, NULL, PRIORITY_LOW, &xRunngTask ); } else if (*((int*)pvQSnd) == 9) { vTaskDelete(xRunngTask); // Deletes the task that controls the currently running mode m3pi.stop(); // Prevents the m3pi from running wild while the system prepares the new mode xTaskCreate( TaskLF, ( const char * ) "TaskLF", configMINIMAL_STACK_SIZE, NULL, PRIORITY_LOW, &xRunngTask ); } else xQueueSend(xQueue1, pvQSnd, 0); } led1 = !led1; vTaskDelay(xDelay); } } //******************************************************************************************************************* // Main //******************************************************************************************************************* int main (void) { xQueue1 = xQueueCreate( 1, sizeof( int ) ); if(xQueue1 == NULL) led4=1; xTaskCreate( TaskBluetooth, ( const char * ) "TaskBluetooth", configMINIMAL_STACK_SIZE, NULL, PRIORITY_LOW, ( xTaskHandle * ) NULL ); vTaskStartScheduler(); //should never get here printf("ERORR: vTaskStartScheduler returned!"); for (;;); }