Homero Silva / Mbed 2 deprecated PRGP_Pi_Swarm_ground_search_algorithm

Dependencies:   mbed

Fork of Pi_Swarm_Blank by James Hilder

Committer:
homero
Date:
Sun Aug 23 14:26:12 2015 +0000
Revision:
13:c18d82f62d38
Parent:
12:118f2b0ed8eb
Child:
14:fc406dfff94f
Pi-swarm controller 2. Improved functionality, ultrasonic sensor, individually calibrated IR sensors.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
re633 11:c5094a68283f 1 /*
re633 11:c5094a68283f 2 * Software License Agreement (BSD License)
re633 11:c5094a68283f 3 *
re633 11:c5094a68283f 4 * Copyright (c) 2015, University of York Robotics Laboratory (YRL).
re633 11:c5094a68283f 5 * All rights reserved.
re633 11:c5094a68283f 6 *
re633 11:c5094a68283f 7 * Redistribution and use in source and binary forms, with or without
re633 11:c5094a68283f 8 * modification, are permitted provided that the following conditions
re633 11:c5094a68283f 9 * are met:
re633 11:c5094a68283f 10 *
re633 11:c5094a68283f 11 * * Redistributions of source code must retain the above copyright
re633 11:c5094a68283f 12 * notice, this list of conditions and the following disclaimer.
re633 11:c5094a68283f 13 * * Redistributions in binary form must reproduce the above
re633 11:c5094a68283f 14 * copyright notice, this list of conditions and the following
re633 11:c5094a68283f 15 * disclaimer in the documentation and/or other materials provided
re633 11:c5094a68283f 16 * with the distribution.
re633 11:c5094a68283f 17 *
re633 11:c5094a68283f 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
re633 11:c5094a68283f 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
re633 11:c5094a68283f 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
re633 11:c5094a68283f 21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
re633 11:c5094a68283f 22 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
re633 11:c5094a68283f 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
re633 11:c5094a68283f 24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
re633 11:c5094a68283f 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
re633 11:c5094a68283f 26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
re633 11:c5094a68283f 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
re633 11:c5094a68283f 28 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
re633 11:c5094a68283f 29 * POSSIBILITY OF SUCH DAMAGE.
re633 11:c5094a68283f 30 */
re633 11:c5094a68283f 31 /**
re633 11:c5094a68283f 32 * @file main.cpp
re633 11:c5094a68283f 33 * @brief The Ticker fucntion for gaining sensor data and the main function for the PRGP Pi-Swarm Controllers.
re633 11:c5094a68283f 34 * @details In this file the main function for the Pi-Swarm Controller is defined.
re633 11:c5094a68283f 35 * @version 1.0
homero 13:c18d82f62d38 36 * @author Robert Evans
re633 11:c5094a68283f 37 * @date 24/07/15
homero 13:c18d82f62d38 38 * @version 2.0
homero 13:c18d82f62d38 39 * @author Homero Silva
homero 13:c18d82f62d38 40 * @date 16/08/15
homero 13:c18d82f62d38 41 * @ultrasonic sensor added
homero 13:c18d82f62d38 42 * @version 3.0
homero 13:c18d82f62d38 43 * @author Robert Evans
homero 13:c18d82f62d38 44 * @date 17/08/15
homero 13:c18d82f62d38 45 * @communication added
re633 11:c5094a68283f 46 */
jah128 3:1aa1de26966a 47 #include "main.h" // Certain parameters can be set by changing the defines in piswarm.h
re633 9:ef0907fda2f1 48 #include "PiSwarmControllerFunctions.h"
homero 13:c18d82f62d38 49 #include "hcsr04.h"
jah128 0:46cd1498a39a 50
jah128 1:37502eb3b70f 51 PiSwarm piswarm;
jah128 1:37502eb3b70f 52 Serial pc (USBTX,USBRX);
homero 13:c18d82f62d38 53 HCSR04 usensor(p30,p14);
jah128 0:46cd1498a39a 54
re633 9:ef0907fda2f1 55 //Tickers
re633 9:ef0907fda2f1 56 Ticker ticker_25ms;
homero 13:c18d82f62d38 57 Ticker ticker_ultrasonic50ms;
homero 13:c18d82f62d38 58
homero 13:c18d82f62d38 59 //Timeouts
homero 13:c18d82f62d38 60 Timeout tickChangeTimeout;
homero 13:c18d82f62d38 61 Timeout broadcastTimeout;
homero 13:c18d82f62d38 62
homero 13:c18d82f62d38 63 //Timers
re633 9:ef0907fda2f1 64 Timer timer;
re633 10:da62735d6df9 65 Timer timerLevy;
re633 9:ef0907fda2f1 66
re633 9:ef0907fda2f1 67 //Global Variables
re633 9:ef0907fda2f1 68 uint8_t const IR_READ_PER_BEAC = 20; //The number of IR readings between beacon flashes
re633 9:ef0907fda2f1 69 uint16_t volatile gv_IRVals[IR_READ_PER_BEAC][8] = {0}; //The passive IR values each are stored in this array every 25ms for the last 0.5 seconds
re633 9:ef0907fda2f1 70 int16_t volatile gv_IRValDiffs[IR_READ_PER_BEAC][8] = {0};
homero 13:c18d82f62d38 71 int16_t volatile gv_IRValDiffsTwo[IR_READ_PER_BEAC][8] = {0};
homero 13:c18d82f62d38 72
re633 9:ef0907fda2f1 73 uint8_t volatile beacon_detected[8] = {0};
re633 9:ef0907fda2f1 74 int8_t volatile gv_counter25ms = 0; //This counter is increased every 25ms and resets to zero after one second. (It is signed because 1 is subtracted from it in ReadIRs)
homero 13:c18d82f62d38 75 uint8_t const BEACON_SUSPECTED = 20; //Value by which consecutive IR sensor readings need to jump by for in order to cause beacon to be suspected.
homero 13:c18d82f62d38 76 uint16_t volatile AT_BEACON_THRESHOLD = 3800;
homero 13:c18d82f62d38 77 float volatile distance_ultrasonic_sensor = 1000;
homero 13:c18d82f62d38 78
homero 13:c18d82f62d38 79 float r_mot_scaler = 1;
homero 13:c18d82f62d38 80 float l_mot_scaler = 1;
homero 13:c18d82f62d38 81
re633 11:c5094a68283f 82 uint32_t levy_target_time_us = 0; //The amount of time in micro seconds by which the robot needs to move in order to reach the distance required in next section of the levy walk.
re633 9:ef0907fda2f1 83 uint8_t volatile gv_IRDistances[8]; //Using the custom distance function the active ir readings are converted to distances and stored here every 25ms.
homero 13:c18d82f62d38 84
homero 13:c18d82f62d38 85 //homero: ultrasonic reading
homero 13:c18d82f62d38 86
homero 13:c18d82f62d38 87 uint8_t volatile gv_state = States::READY_TO_START; //This is the current state of the finite state machine
re633 9:ef0907fda2f1 88 int16_t g_currentHeading = 0;
homero 13:c18d82f62d38 89 float BASE_SPEED = 0.6;
re633 9:ef0907fda2f1 90 int8_t g_beaconOn = 100;
re633 11:c5094a68283f 91 int8_t volatile tick_beacon_suspected = 100; //Is set to the tick value within the period between beacon flashes that the beacon flash is suspected to begin at
re633 11:c5094a68283f 92 int8_t tick_beacon_period_check = 100; //Is used to temporarily store the value of tick_beacon_suspected
homero 13:c18d82f62d38 93 uint8_t g_ultrasound_count = 0;
homero 13:c18d82f62d38 94 uint8_t broadcasted_count = 0;
homero 13:c18d82f62d38 95 uint8_t go_back_count = 0;
re633 9:ef0907fda2f1 96 //Flags
homero 13:c18d82f62d38 97 int8_t volatile start_flag = 1;
re633 12:118f2b0ed8eb 98 int8_t volatile back_flag = 0;
re633 12:118f2b0ed8eb 99 int8_t volatile return_flag = 0;
homero 13:c18d82f62d38 100 //int8_t volatile aligned_target_beacon = 0; //homero
re633 9:ef0907fda2f1 101 int8_t flagObstacle = 0;
homero 13:c18d82f62d38 102 uint8_t flagStationary = 1; //Used to determine if robot is currently stationary or moving.
re633 9:ef0907fda2f1 103 uint8_t flagBeaconSyncronised = 0; //Set to one when the robot is synchronised with the beacon
re633 9:ef0907fda2f1 104 uint8_t volatile flagBeaconIlluminated = 0; //Should be 1 when beacon is illuminated otherwise 0
re633 10:da62735d6df9 105 uint8_t flagSetNewLevyTime = 1; //Must start as 1
homero 13:c18d82f62d38 106 uint8_t broadcasted_flag = 1;
homero 13:c18d82f62d38 107 uint8_t robot_id;
homero 13:c18d82f62d38 108
re633 9:ef0907fda2f1 109 //Ticker Function*************************************************************************************
re633 9:ef0907fda2f1 110 //This function is called by a ticker every 25ms
re633 9:ef0907fda2f1 111 //The function firstly stores the background IRS values.
re633 9:ef0907fda2f1 112 //Secondly if beacon is off it uses illuminated IR sensors to estimate distances
re633 9:ef0907fda2f1 113 //Each second it will update when it believes beacon illumination time to be
re633 9:ef0907fda2f1 114 //It will work out which sensors spotted then beacon and will illuminate the Leds accordingly
re633 9:ef0907fda2f1 115 void readIRs(){
re633 9:ef0907fda2f1 116
re633 9:ef0907fda2f1 117 //Fistly update the beaconVisable flag if possible
re633 9:ef0907fda2f1 118 if(gv_counter25ms == mod8((g_beaconOn - 1), IR_READ_PER_BEAC)){
re633 9:ef0907fda2f1 119 flagBeaconIlluminated = 1;
re633 9:ef0907fda2f1 120 }
re633 9:ef0907fda2f1 121
re633 9:ef0907fda2f1 122 if(gv_counter25ms == mod8((g_beaconOn + 2), IR_READ_PER_BEAC)){
re633 9:ef0907fda2f1 123 flagBeaconIlluminated = 0;
re633 9:ef0907fda2f1 124 }
re633 9:ef0907fda2f1 125 //Firstly store background values
re633 9:ef0907fda2f1 126 //Also make a note of which point in the second did the values change most.
re633 9:ef0907fda2f1 127 //For which sensor specifically did the values change the most
re633 9:ef0907fda2f1 128 //That sensor will be used to estimate the beacon start time if a threshold value is met
re633 9:ef0907fda2f1 129 piswarm.store_background_raw_ir_values();
re633 9:ef0907fda2f1 130 int16_t IRchange = 0;
homero 13:c18d82f62d38 131 int16_t IRchange2 = 0;
re633 9:ef0907fda2f1 132 uint8_t loopCounter = 0;
re633 9:ef0907fda2f1 133 //In this loop the raw IR values are read.
re633 9:ef0907fda2f1 134 //If the points where the IR values have increased by the greatest amount are noted as this indicates a beacon illumination
re633 9:ef0907fda2f1 135 for(loopCounter = 0; loopCounter < 8; loopCounter++) {
re633 9:ef0907fda2f1 136 gv_IRVals[gv_counter25ms][loopCounter] = piswarm.get_background_raw_ir_value(loopCounter);
re633 9:ef0907fda2f1 137
homero 13:c18d82f62d38 138 IRchange = gv_IRVals[gv_counter25ms][loopCounter]-gv_IRVals[mod8((gv_counter25ms-1),IR_READ_PER_BEAC)][loopCounter];
homero 13:c18d82f62d38 139 IRchange2 = gv_IRVals[gv_counter25ms][loopCounter]-gv_IRVals[mod8((gv_counter25ms-2),IR_READ_PER_BEAC)][loopCounter];
re633 9:ef0907fda2f1 140 gv_IRValDiffs[gv_counter25ms][loopCounter] = IRchange;
homero 13:c18d82f62d38 141 gv_IRValDiffsTwo[gv_counter25ms][loopCounter] = IRchange2;
homero 13:c18d82f62d38 142
re633 9:ef0907fda2f1 143 //printf("change %d count %d\n",IRchange);
re633 9:ef0907fda2f1 144 //If difference is greater than a threshold value then the beacon is suspected. This will be confirmed depending on the robots state of movement.
re633 9:ef0907fda2f1 145 if (IRchange > BEACON_SUSPECTED){
re633 11:c5094a68283f 146 tick_beacon_suspected = gv_counter25ms;
re633 9:ef0907fda2f1 147 piswarm.cls();
re633 11:c5094a68283f 148 piswarm.printf("%d",tick_beacon_suspected);
re633 9:ef0907fda2f1 149 }
re633 9:ef0907fda2f1 150 }
homero 13:c18d82f62d38 151
re633 9:ef0907fda2f1 152 //Now store the illuminated values if the beacon is not illuminated-
re633 9:ef0907fda2f1 153 piswarm.store_illuminated_raw_ir_values();
homero 13:c18d82f62d38 154
re633 9:ef0907fda2f1 155 //In this loop convert each raw active IR reading into a distance estimate
re633 9:ef0907fda2f1 156 for(loopCounter = 0; loopCounter < 8; loopCounter++) {
re633 9:ef0907fda2f1 157
re633 9:ef0907fda2f1 158 //Specific sensor readings converted to distances
re633 9:ef0907fda2f1 159 float temp = piswarm.get_illuminated_raw_ir_value(loopCounter);
homero 13:c18d82f62d38 160 //if(gv_counter25ms == 1) pc.printf("sen %d :%f\n", loopCounter,temp);
homero 13:c18d82f62d38 161 if(gv_counter25ms == 0){
homero 13:c18d82f62d38 162 pc.printf("sen %d raw: %f",loopCounter,temp);
homero 13:c18d82f62d38 163 }
re633 9:ef0907fda2f1 164 if(temp>3500){
re633 9:ef0907fda2f1 165 temp = 3500;
re633 9:ef0907fda2f1 166 } else if (temp < 97){
re633 9:ef0907fda2f1 167 temp = 97;
re633 9:ef0907fda2f1 168 }
re633 9:ef0907fda2f1 169 //#put this into a function
re633 9:ef0907fda2f1 170 //Switch case for robot 5
homero 13:c18d82f62d38 171 switch(robot_id){
homero 13:c18d82f62d38 172 case 9:
homero 13:c18d82f62d38 173 switch(loopCounter){
homero 13:c18d82f62d38 174 case 0:
homero 13:c18d82f62d38 175 temp = 1643 * sqrt(1/(temp-190))-35;
homero 13:c18d82f62d38 176 break;
homero 13:c18d82f62d38 177 case 1:
homero 13:c18d82f62d38 178 temp = 1097 * sqrt(1/(temp-190))-24;
homero 13:c18d82f62d38 179 break;
homero 13:c18d82f62d38 180 case 2:
homero 13:c18d82f62d38 181 temp = 838 * sqrt(1/(temp-120))-17;
homero 13:c18d82f62d38 182 break;
homero 13:c18d82f62d38 183 case 3:
homero 13:c18d82f62d38 184 temp = 1017 * sqrt(1/(temp-175))-22;
homero 13:c18d82f62d38 185 break;
homero 13:c18d82f62d38 186 case 4:
homero 13:c18d82f62d38 187 temp = 777 * sqrt(1/(temp-130))-16;
homero 13:c18d82f62d38 188 break;
homero 13:c18d82f62d38 189 case 5:
homero 13:c18d82f62d38 190 temp = 765 * sqrt(1/(temp-115))-11;
homero 13:c18d82f62d38 191 break;
homero 13:c18d82f62d38 192 case 6:
homero 13:c18d82f62d38 193 temp = 1086 * sqrt(1/(temp-150))-17;
homero 13:c18d82f62d38 194 break;
homero 13:c18d82f62d38 195 case 7:
homero 13:c18d82f62d38 196 temp = 1578 * sqrt(1/(temp-220))-24;
homero 13:c18d82f62d38 197 break;
homero 13:c18d82f62d38 198 }
re633 9:ef0907fda2f1 199 break;
homero 13:c18d82f62d38 200 case 12:
homero 13:c18d82f62d38 201 switch(loopCounter){
homero 13:c18d82f62d38 202 case 0:
homero 13:c18d82f62d38 203 temp = 877 * sqrt(1/(temp-80))-13;
homero 13:c18d82f62d38 204 break;
homero 13:c18d82f62d38 205 case 1:
homero 13:c18d82f62d38 206 temp = 887 * sqrt(1/(temp-110))-13;
homero 13:c18d82f62d38 207 break;
homero 13:c18d82f62d38 208 case 2:
homero 13:c18d82f62d38 209 temp = 744 * sqrt(1/(temp-90))-8;
homero 13:c18d82f62d38 210 break;
homero 13:c18d82f62d38 211 case 3:
homero 13:c18d82f62d38 212 temp = 816 * sqrt(1/(temp-105))-17;
homero 13:c18d82f62d38 213 break;
homero 13:c18d82f62d38 214 case 4:
homero 13:c18d82f62d38 215 temp = 821 * sqrt(1/(temp-125))-7;
homero 13:c18d82f62d38 216 break;
homero 13:c18d82f62d38 217 case 5:
homero 13:c18d82f62d38 218 temp = 741 * sqrt(1/(temp-110))-7;
homero 13:c18d82f62d38 219 break;
homero 13:c18d82f62d38 220 case 6:
homero 13:c18d82f62d38 221 temp = 1000 * sqrt(1/(temp-95))-18;
homero 13:c18d82f62d38 222 break;
homero 13:c18d82f62d38 223 case 7:
homero 13:c18d82f62d38 224 temp = 924 * sqrt(1/(temp-115))-12;
homero 13:c18d82f62d38 225 break;
homero 13:c18d82f62d38 226 }
re633 9:ef0907fda2f1 227 break;
homero 13:c18d82f62d38 228 default:
homero 13:c18d82f62d38 229 temp = 662 * sqrt(1/(temp-152));
homero 13:c18d82f62d38 230
re633 9:ef0907fda2f1 231 }
homero 13:c18d82f62d38 232
homero 13:c18d82f62d38 233 if(gv_counter25ms == 0){
homero 13:c18d82f62d38 234 pc.printf("sen %d dist:%f\n",loopCounter,temp);
homero 13:c18d82f62d38 235 }
re633 9:ef0907fda2f1 236 if (temp > 130){
re633 9:ef0907fda2f1 237 temp = 130;
re633 9:ef0907fda2f1 238 }
re633 9:ef0907fda2f1 239 gv_IRDistances[loopCounter] = temp;
re633 9:ef0907fda2f1 240
homero 13:c18d82f62d38 241 }
homero 13:c18d82f62d38 242
re633 9:ef0907fda2f1 243 //reset counter after 1 second (beacon period)
re633 9:ef0907fda2f1 244 gv_counter25ms = mod8(gv_counter25ms + 1,IR_READ_PER_BEAC);
re633 9:ef0907fda2f1 245 }
re633 9:ef0907fda2f1 246
homero 13:c18d82f62d38 247 //Get the distance of the ultrsonic sensor in cm
homero 13:c18d82f62d38 248 void get_ultrasonic_readings(){
homero 13:c18d82f62d38 249 float old_dist = distance_ultrasonic_sensor;
homero 13:c18d82f62d38 250 int static count = 0;
homero 13:c18d82f62d38 251 distance_ultrasonic_sensor = usensor.get_dist_mm();
homero 13:c18d82f62d38 252 if(count <100){
homero 13:c18d82f62d38 253 pc.printf("US: %.1f, %d\n",distance_ultrasonic_sensor, count);
homero 13:c18d82f62d38 254 count ++;
homero 13:c18d82f62d38 255 }else{
homero 13:c18d82f62d38 256 count =0;
homero 13:c18d82f62d38 257 }
homero 13:c18d82f62d38 258
homero 13:c18d82f62d38 259 if(distance_ultrasonic_sensor <= 0 || distance_ultrasonic_sensor == 1000){
homero 13:c18d82f62d38 260 distance_ultrasonic_sensor = old_dist;
homero 13:c18d82f62d38 261 }
homero 13:c18d82f62d38 262 //piswarm.cls();
homero 13:c18d82f62d38 263
homero 13:c18d82f62d38 264 usensor.start();
homero 13:c18d82f62d38 265 }
homero 13:c18d82f62d38 266
homero 13:c18d82f62d38 267 //When called the readIRs ticker will be reattached after the specified time.
homero 13:c18d82f62d38 268 void atTimeout(){
homero 13:c18d82f62d38 269 ticker_25ms.attach_us(&readIRs,25000);
homero 13:c18d82f62d38 270 }
homero 13:c18d82f62d38 271
homero 13:c18d82f62d38 272 void atBroadcastTimeout(){
homero 13:c18d82f62d38 273 char function;
homero 13:c18d82f62d38 274 if(robot_id == 1|| robot_id == 12){
homero 13:c18d82f62d38 275 function = 2;
homero 13:c18d82f62d38 276 } else if(robot_id == 9){
homero 13:c18d82f62d38 277 function = 3;
homero 13:c18d82f62d38 278 }
homero 13:c18d82f62d38 279
homero 13:c18d82f62d38 280 char message[2];
homero 13:c18d82f62d38 281 message[0] = piswarm.get_id()+48;
homero 13:c18d82f62d38 282 broadcast_user_rf_command(function,message,1);
homero 13:c18d82f62d38 283 broadcasted_count++;
homero 13:c18d82f62d38 284 broadcasted_flag = 1;
homero 13:c18d82f62d38 285 }
homero 13:c18d82f62d38 286 //This is a wait function for one
homero 13:c18d82f62d38 287
re633 9:ef0907fda2f1 288 //*******************************************************************************************************
jah128 8:a789ef4fde52 289 //This is where the program code goes.
jah128 1:37502eb3b70f 290 int main() {
re633 9:ef0907fda2f1 291 init();
homero 13:c18d82f62d38 292 robot_id = piswarm.get_id();
re633 9:ef0907fda2f1 293 //starting point in state 11
homero 13:c18d82f62d38 294 //usensor.start(); // get first reading of the ultrasonic sensor required before ticker
homero 13:c18d82f62d38 295 //wait_ms(50);
re633 9:ef0907fda2f1 296
homero 13:c18d82f62d38 297
homero 13:c18d82f62d38 298 //wait(1); //Wait a second to allow IR array to be filled
jah128 8:a789ef4fde52 299
re633 9:ef0907fda2f1 300 //Controller is a finite state machine
re633 9:ef0907fda2f1 301 while(1){
re633 9:ef0907fda2f1 302
re633 9:ef0907fda2f1 303 //Waiting for signal to begin searching
homero 13:c18d82f62d38 304 if(gv_state == States::READY_TO_START){
homero 13:c18d82f62d38 305 //pc.printf("%d\n",start_flag);
re633 12:118f2b0ed8eb 306 if(start_flag == 1){
re633 12:118f2b0ed8eb 307 //Change state here after recieving a radio command
homero 13:c18d82f62d38 308 ticker_25ms.attach_us(&readIRs,25000);
homero 13:c18d82f62d38 309
homero 13:c18d82f62d38 310 if(robot_id == 1){
homero 13:c18d82f62d38 311 AT_BEACON_THRESHOLD = 3850;
homero 13:c18d82f62d38 312 }
homero 13:c18d82f62d38 313
homero 13:c18d82f62d38 314 else if (robot_id == 9){
homero 13:c18d82f62d38 315 AT_BEACON_THRESHOLD = 3950;
homero 13:c18d82f62d38 316 }
homero 13:c18d82f62d38 317
homero 13:c18d82f62d38 318 else if (robot_id == 12){
homero 13:c18d82f62d38 319 AT_BEACON_THRESHOLD = 3980;
homero 13:c18d82f62d38 320 r_mot_scaler = 1.02;
homero 13:c18d82f62d38 321 l_mot_scaler = 0.98;
homero 13:c18d82f62d38 322 }
homero 13:c18d82f62d38 323
homero 13:c18d82f62d38 324 else{
homero 13:c18d82f62d38 325 AT_BEACON_THRESHOLD = 3900;
homero 13:c18d82f62d38 326 }
homero 13:c18d82f62d38 327
homero 13:c18d82f62d38 328 usensor.start(); // get first reading of the ultrasonic sensor required before ticker
homero 13:c18d82f62d38 329 wait_ms(50);
homero 13:c18d82f62d38 330 ticker_ultrasonic50ms.attach_us(&get_ultrasonic_readings,50000);
homero 13:c18d82f62d38 331
homero 13:c18d82f62d38 332 timer.start();
homero 13:c18d82f62d38 333 timerLevy.start();
homero 13:c18d82f62d38 334 //pc.printf("why\n");
homero 13:c18d82f62d38 335 changeState(States::SEARCHING_FWD);
re633 10:da62735d6df9 336 }
homero 13:c18d82f62d38 337
re633 9:ef0907fda2f1 338 //Searching state
homero 13:c18d82f62d38 339 } else if (gv_state == States::SEARCHING_FWD || gv_state == States::SEARCHING_TURNING || gv_state == States::SEARCHING_REDUCED_SPEED){
re633 9:ef0907fda2f1 340
re633 12:118f2b0ed8eb 341 //Do something here on receipt of 'function 5' if necessary.
re633 12:118f2b0ed8eb 342 //As currently the home beacon will immediately switch on that is not necessary.
re633 12:118f2b0ed8eb 343
re633 12:118f2b0ed8eb 344 //Determine if suspected beacon is actually the beacon.
re633 9:ef0907fda2f1 345 //This is done by checking the period between flashes matches the beacon period
re633 11:c5094a68283f 346 if(tick_beacon_suspected != 100){
re633 9:ef0907fda2f1 347 //When the beacon flag is first raised store its value and reset it
re633 11:c5094a68283f 348 if(tick_beacon_period_check == 100){
re633 11:c5094a68283f 349 tick_beacon_period_check = tick_beacon_suspected;
re633 11:c5094a68283f 350 tick_beacon_suspected = 100;
re633 9:ef0907fda2f1 351 //Check the timing of the latest jump with the last one to see if period matches the Beacon.
re633 9:ef0907fda2f1 352 } else {
re633 9:ef0907fda2f1 353 piswarm.locate(0,1);
re633 11:c5094a68283f 354 piswarm.printf("%d %d",tick_beacon_period_check,tick_beacon_suspected);
re633 11:c5094a68283f 355 //printf("%d %d *********************************",tick_beacon_period_check,tick_beacon_suspected);
re633 9:ef0907fda2f1 356 //If the two numbers are similar then test will be low. For this to work the period of the ticker and beacon should be the same.
re633 11:c5094a68283f 357 int8_t test = (tick_beacon_period_check - tick_beacon_suspected);
re633 9:ef0907fda2f1 358
re633 9:ef0907fda2f1 359 test = test * test;
re633 9:ef0907fda2f1 360
re633 9:ef0907fda2f1 361 //if test is low then identify the beacon as the cause of the flags
re633 9:ef0907fda2f1 362 if(test < 2){
re633 9:ef0907fda2f1 363 //Beacon found change to state 2
re633 11:c5094a68283f 364 g_beaconOn = tick_beacon_period_check; //update the global variable that stores when beacon flashes occur
re633 9:ef0907fda2f1 365
homero 13:c18d82f62d38 366 //wait(2);
homero 13:c18d82f62d38 367 changeState(States::MOVING_TO_BEACON);
re633 9:ef0907fda2f1 368 } else {
re633 9:ef0907fda2f1 369 //Reset the flag to try again
re633 11:c5094a68283f 370 tick_beacon_period_check = 100;
re633 9:ef0907fda2f1 371 }
re633 9:ef0907fda2f1 372 }
re633 9:ef0907fda2f1 373 }
re633 9:ef0907fda2f1 374
homero 13:c18d82f62d38 375 if(gv_state == States::SEARCHING_FWD){
re633 9:ef0907fda2f1 376 //Secondly if obstacles are detected ahead then execute a random turn.
homero 13:c18d82f62d38 377
homero 13:c18d82f62d38 378 //pc.printf("Start\n");
homero 13:c18d82f62d38 379
homero 13:c18d82f62d38 380 //Homero: This is the obstacle avoidance part need to also turn if the ultrasound reading is high
homero 13:c18d82f62d38 381 //Avoid obstacle to the right
homero 13:c18d82f62d38 382 //if(distance_ultrasonic_sensor < 500 && distance_ultrasonic_sensor >= 100)
homero 13:c18d82f62d38 383 // {
homero 13:c18d82f62d38 384 // g_ultrasound_count++;
homero 13:c18d82f62d38 385 //
homero 13:c18d82f62d38 386 // } else {
homero 13:c18d82f62d38 387 // g_ultrasound_count = 0;
homero 13:c18d82f62d38 388 // }
homero 13:c18d82f62d38 389
homero 13:c18d82f62d38 390 //if (distance_ultrasonic_sensor < 500 && distance_ultrasonic_sensor >= 100 && g_ultrasound_count > 3){
homero 13:c18d82f62d38 391 // changeState(States::SEARCHING_REDUCED_SPEED);
homero 13:c18d82f62d38 392
re633 9:ef0907fda2f1 393 if(gv_IRDistances[0] < 100 || gv_IRDistances[1] < 100){
re633 9:ef0907fda2f1 394 piswarm.stop();
re633 10:da62735d6df9 395 piswarm.cls();
re633 10:da62735d6df9 396 piswarm.printf("ob R");
re633 10:da62735d6df9 397 piswarm.play_tune("CC",1);
homero 13:c18d82f62d38 398 //wait(0.1);
re633 9:ef0907fda2f1 399 flagObstacle = 1;
homero 13:c18d82f62d38 400 changeState(States::SEARCHING_TURNING);
homero 13:c18d82f62d38 401
homero 13:c18d82f62d38 402 //Avoid obstacle to the left
re633 9:ef0907fda2f1 403 } else if(gv_IRDistances[6] < 100 || gv_IRDistances[7] < 100){
re633 9:ef0907fda2f1 404 piswarm.stop();
re633 10:da62735d6df9 405 piswarm.cls();
re633 10:da62735d6df9 406 piswarm.printf("ob L");
re633 10:da62735d6df9 407 piswarm.play_tune("CC",1);
homero 13:c18d82f62d38 408 //wait(0.1);
re633 9:ef0907fda2f1 409 flagObstacle = 2;
homero 13:c18d82f62d38 410 changeState(States::SEARCHING_TURNING);
homero 13:c18d82f62d38 411
homero 13:c18d82f62d38 412 } else if(distance_ultrasonic_sensor < 50){
homero 13:c18d82f62d38 413 piswarm.stop();
homero 13:c18d82f62d38 414 piswarm.cls();
homero 13:c18d82f62d38 415 piswarm.printf("ob F");
homero 13:c18d82f62d38 416 //piswarm.printf("F: %f",distance_ultrasonic_sensor);
homero 13:c18d82f62d38 417 piswarm.play_tune("DD",1);
homero 13:c18d82f62d38 418 //wait(0.1);
homero 13:c18d82f62d38 419 flagObstacle = 3;
homero 13:c18d82f62d38 420 changeState(States::SEARCHING_TURNING);
homero 13:c18d82f62d38 421
homero 13:c18d82f62d38 422
homero 13:c18d82f62d38 423 } else if(distance_ultrasonic_sensor <= 80){
homero 13:c18d82f62d38 424 flagObstacle = 3;
homero 13:c18d82f62d38 425 changeState(States::SEARCHING_TURNING);
homero 13:c18d82f62d38 426
re633 11:c5094a68283f 427 } else if(timerLevy.read_us() > levy_target_time_us){
homero 13:c18d82f62d38 428 go_back_count++;
re633 10:da62735d6df9 429 flagSetNewLevyTime = 1;
re633 10:da62735d6df9 430 piswarm.play_tune("G",1);
homero 13:c18d82f62d38 431 piswarm.set_oled_colour(255,0,0);
homero 13:c18d82f62d38 432 changeState(States::SEARCHING_TURNING);
homero 13:c18d82f62d38 433 }else if(go_back_count >=10){
homero 13:c18d82f62d38 434 go_back_count = 0;
homero 13:c18d82f62d38 435 piswarm.stop();
homero 13:c18d82f62d38 436 wait_ms(200);
homero 13:c18d82f62d38 437 piswarm.left_motor(-0.4*l_mot_scaler);
homero 13:c18d82f62d38 438 piswarm.right_motor(-0.4*r_mot_scaler);
homero 13:c18d82f62d38 439 wait(0.5);
homero 13:c18d82f62d38 440 changeState(States::SEARCHING_TURNING);
homero 13:c18d82f62d38 441
homero 13:c18d82f62d38 442 } else if (distance_ultrasonic_sensor <= 800){
homero 13:c18d82f62d38 443 //decrease speed when PiSwarm is getting close to an obstacle
homero 13:c18d82f62d38 444 float velocity = 0.2;
homero 13:c18d82f62d38 445 if(distance_ultrasonic_sensor > 100){
homero 13:c18d82f62d38 446 velocity = (distance_ultrasonic_sensor*0.00057) + 0.142;
homero 13:c18d82f62d38 447 }
homero 13:c18d82f62d38 448 piswarm.left_motor(velocity*l_mot_scaler);
homero 13:c18d82f62d38 449 piswarm.right_motor(velocity*r_mot_scaler);
homero 13:c18d82f62d38 450 //wait_ms(0.2);
homero 13:c18d82f62d38 451
homero 13:c18d82f62d38 452
homero 13:c18d82f62d38 453 //Otherwise continue moving forward until distance determined by levy algorithm is calculated.
homero 13:c18d82f62d38 454
re633 9:ef0907fda2f1 455
homero 13:c18d82f62d38 456 } else {
homero 13:c18d82f62d38 457 piswarm.right_motor(BASE_SPEED*r_mot_scaler);
homero 13:c18d82f62d38 458 piswarm.left_motor(BASE_SPEED*l_mot_scaler);
homero 13:c18d82f62d38 459 //wait_ms(200);
homero 13:c18d82f62d38 460 //flagStationary = 0;
homero 13:c18d82f62d38 461 }
homero 13:c18d82f62d38 462 //wait to get new ultrasound reading
homero 13:c18d82f62d38 463 //wait_ms(50);
re633 9:ef0907fda2f1 464
homero 13:c18d82f62d38 465
homero 13:c18d82f62d38 466 } else if(gv_state == States::SEARCHING_TURNING){
re633 9:ef0907fda2f1 467 piswarm.stop();//Stop the robot.
re633 9:ef0907fda2f1 468 int16_t randomAngle;
re633 9:ef0907fda2f1 469 //If sent here beacuse of obstacle find angle between -180 to -90 and 90 to 180
re633 9:ef0907fda2f1 470 if(flagObstacle == 1){
re633 10:da62735d6df9 471 randomAngle = rand()%90 - 135;
re633 9:ef0907fda2f1 472
re633 9:ef0907fda2f1 473 } else if(flagObstacle == 2){
re633 10:da62735d6df9 474 randomAngle = rand()%90 + 45;
re633 10:da62735d6df9 475
homero 13:c18d82f62d38 476 } else if(flagObstacle == 3){
homero 13:c18d82f62d38 477 randomAngle = rand()%90 + 45;
homero 13:c18d82f62d38 478
re633 10:da62735d6df9 479 //Otherwise if here due to levy walk: turn to any random angle
re633 9:ef0907fda2f1 480 } else {
re633 10:da62735d6df9 481 randomAngle = rand()%360 - 180;
re633 9:ef0907fda2f1 482 }
re633 9:ef0907fda2f1 483 turnDegrees(randomAngle); //Make the turn
homero 13:c18d82f62d38 484 //wait(0.1);
re633 10:da62735d6df9 485 /* if(gv_IRDistances[0] < 70 || gv_IRDistances[1] < 70 || gv_IRDistances[6] < 70 || gv_IRDistances[7] < 70){
re633 10:da62735d6df9 486 //do nothing. Aim is that robot will keep turning the same way until clear of obstacle
re633 10:da62735d6df9 487 //could put a count in here to doemergency escape manouvre if necessary
re633 10:da62735d6df9 488 piswarm.play_tune("CC",1);
re633 10:da62735d6df9 489 } else { */
re633 10:da62735d6df9 490 flagObstacle = 0;
homero 13:c18d82f62d38 491 changeState(States::SEARCHING_FWD);//Move back into state 11
homero 13:c18d82f62d38 492
homero 13:c18d82f62d38 493 } else if (gv_state == States::SEARCHING_REDUCED_SPEED){
homero 13:c18d82f62d38 494
homero 13:c18d82f62d38 495
homero 13:c18d82f62d38 496
homero 13:c18d82f62d38 497 if(gv_IRDistances[0] < 100 || gv_IRDistances[1] < 100){
homero 13:c18d82f62d38 498 piswarm.stop();
homero 13:c18d82f62d38 499 piswarm.cls();
homero 13:c18d82f62d38 500 piswarm.printf("ob R");
homero 13:c18d82f62d38 501 piswarm.play_tune("CC",1);
homero 13:c18d82f62d38 502 flagObstacle = 1;
homero 13:c18d82f62d38 503 changeState(States::SEARCHING_TURNING);
homero 13:c18d82f62d38 504
homero 13:c18d82f62d38 505 //Avoid obstacle to the left
homero 13:c18d82f62d38 506 } else if(gv_IRDistances[6] < 100 || gv_IRDistances[7] < 100){
homero 13:c18d82f62d38 507 piswarm.stop();
homero 13:c18d82f62d38 508 piswarm.cls();
homero 13:c18d82f62d38 509 piswarm.printf("ob L");
homero 13:c18d82f62d38 510 piswarm.play_tune("CC",1);
homero 13:c18d82f62d38 511 flagObstacle = 2;
homero 13:c18d82f62d38 512 changeState(States::SEARCHING_TURNING);
re633 10:da62735d6df9 513
homero 13:c18d82f62d38 514 } else if(timerLevy.read_us() > levy_target_time_us){
homero 13:c18d82f62d38 515 flagSetNewLevyTime = 1;
homero 13:c18d82f62d38 516 piswarm.play_tune("G",1);
homero 13:c18d82f62d38 517 changeState(States::SEARCHING_TURNING);
homero 13:c18d82f62d38 518
homero 13:c18d82f62d38 519 } else if(distance_ultrasonic_sensor > 800 || distance_ultrasonic_sensor == 0){
homero 13:c18d82f62d38 520 changeState(States::SEARCHING_FWD);
homero 13:c18d82f62d38 521
homero 13:c18d82f62d38 522 } else if(distance_ultrasonic_sensor <= 50){
homero 13:c18d82f62d38 523 flagObstacle = 3;
homero 13:c18d82f62d38 524 changeState(States::SEARCHING_TURNING);
homero 13:c18d82f62d38 525 }else {
homero 13:c18d82f62d38 526 //decrease speed when PiSwarm is getting close to an obstacle
homero 13:c18d82f62d38 527 float velocity = 0.2;
homero 13:c18d82f62d38 528 if(distance_ultrasonic_sensor > 100){
homero 13:c18d82f62d38 529 velocity = (distance_ultrasonic_sensor*0.00043) + 0.157;
homero 13:c18d82f62d38 530 }
homero 13:c18d82f62d38 531 piswarm.left_motor(velocity);
homero 13:c18d82f62d38 532 piswarm.right_motor(velocity);
homero 13:c18d82f62d38 533 //wait_ms(0.2);
homero 13:c18d82f62d38 534 }
homero 13:c18d82f62d38 535
homero 13:c18d82f62d38 536 }
re633 9:ef0907fda2f1 537 //Beacon found state
homero 13:c18d82f62d38 538 } else if (gv_state == States::MOVING_TO_BEACON){
re633 12:118f2b0ed8eb 539
re633 12:118f2b0ed8eb 540 //Do something here on receipt of 'function 5' if necessary.
re633 12:118f2b0ed8eb 541 //As currently the home beacon will immediately switch on that is not necessary.
re633 12:118f2b0ed8eb 542
homero 13:c18d82f62d38 543 static int16_t valid_distances[8] = {0};
homero 13:c18d82f62d38 544
homero 13:c18d82f62d38 545
re633 9:ef0907fda2f1 546 int16_t maxValue[2] = {0,100}; //Value and sensor position
re633 9:ef0907fda2f1 547 //wait(1);
homero 13:c18d82f62d38 548 int8_t loopCounter = 0;
homero 13:c18d82f62d38 549
homero 13:c18d82f62d38 550 if(flagBeaconIlluminated == 0){
homero 13:c18d82f62d38 551 for(loopCounter = 0; loopCounter < 8; loopCounter++){
homero 13:c18d82f62d38 552 valid_distances[loopCounter] = gv_IRDistances[loopCounter];
homero 13:c18d82f62d38 553 }
homero 13:c18d82f62d38 554 }
re633 9:ef0907fda2f1 555
re633 9:ef0907fda2f1 556 //If beacon visible
re633 9:ef0907fda2f1 557 if(flagBeaconSyncronised == 1){
re633 9:ef0907fda2f1 558
re633 9:ef0907fda2f1 559 //Firstly check beacon is still visible
re633 9:ef0907fda2f1 560 flagBeaconSyncronised = 0;
re633 9:ef0907fda2f1 561 //Update array concerning which IRs can see the beacon
re633 9:ef0907fda2f1 562 for(loopCounter = 0; loopCounter<8; loopCounter++) {
re633 9:ef0907fda2f1 563
re633 9:ef0907fda2f1 564 //Find which sensor has the highest reading
re633 9:ef0907fda2f1 565 if( gv_IRValDiffs[g_beaconOn][loopCounter] > BEACON_SUSPECTED) {
homero 13:c18d82f62d38 566 if( valid_distances[loopCounter] > 100 && valid_distances[mod8((loopCounter + 1),8)]>100 && valid_distances[mod8((loopCounter - 1),8)]>100){
homero 13:c18d82f62d38 567 if(gv_IRVals[g_beaconOn][loopCounter] > maxValue[0]){
homero 13:c18d82f62d38 568 maxValue[0] = gv_IRVals[g_beaconOn][loopCounter];
homero 13:c18d82f62d38 569 maxValue[1] = loopCounter;
homero 13:c18d82f62d38 570 flagBeaconSyncronised = 1; //This will remain as one so long as at least on sensor can see beacon
homero 13:c18d82f62d38 571 }
re633 9:ef0907fda2f1 572 }
re633 9:ef0907fda2f1 573 }
re633 9:ef0907fda2f1 574 }
re633 9:ef0907fda2f1 575
re633 9:ef0907fda2f1 576 //Only do this if beacon still visible
re633 9:ef0907fda2f1 577 if(flagBeaconSyncronised == 1){
re633 9:ef0907fda2f1 578
re633 9:ef0907fda2f1 579 //If the adjacent two sensors are above the threshold too then they can also be marked as illuminated
re633 9:ef0907fda2f1 580 for(loopCounter = 0; loopCounter<8; loopCounter++){
re633 9:ef0907fda2f1 581
re633 9:ef0907fda2f1 582 //reset all beacon detected values
re633 9:ef0907fda2f1 583 beacon_detected[loopCounter] = 0;
re633 9:ef0907fda2f1 584
re633 9:ef0907fda2f1 585 if(abs(maxValue[1] - loopCounter)< 3 || abs(maxValue[1] + 8 - loopCounter)< 3 || abs(maxValue[1] - 8 - loopCounter)< 3) {
re633 9:ef0907fda2f1 586 if(gv_IRValDiffs[g_beaconOn][loopCounter] > BEACON_SUSPECTED){
re633 9:ef0907fda2f1 587 beacon_detected[loopCounter] = 1;
re633 9:ef0907fda2f1 588 }
re633 9:ef0907fda2f1 589 }
re633 9:ef0907fda2f1 590 }
re633 9:ef0907fda2f1 591
re633 9:ef0907fda2f1 592
re633 9:ef0907fda2f1 593 //Update the piswarm LEDS so the ones that can see the beacon are on.
re633 9:ef0907fda2f1 594 piswarm.set_oleds(beacon_detected[0]||beacon_detected[1],
re633 9:ef0907fda2f1 595 beacon_detected[1]||beacon_detected[2],
re633 9:ef0907fda2f1 596 beacon_detected[2],
re633 9:ef0907fda2f1 597 beacon_detected[3],
re633 9:ef0907fda2f1 598 0,
re633 9:ef0907fda2f1 599 beacon_detected[4],
re633 9:ef0907fda2f1 600 beacon_detected[5],
re633 9:ef0907fda2f1 601 beacon_detected[5]||beacon_detected[6],
re633 9:ef0907fda2f1 602 beacon_detected[6]||beacon_detected[7],
re633 9:ef0907fda2f1 603 beacon_detected[7]||beacon_detected[0]);
re633 9:ef0907fda2f1 604
re633 9:ef0907fda2f1 605 //If the max IR value is below a threshold then move toward beacon. Else change state
re633 9:ef0907fda2f1 606 if(maxValue[0] < AT_BEACON_THRESHOLD){
re633 9:ef0907fda2f1 607
re633 9:ef0907fda2f1 608 //Calculate the heading of Pi-Swarm Relative to beacon
re633 9:ef0907fda2f1 609 //printf("%d ",g_currentHeading);
re633 9:ef0907fda2f1 610 calculateNewHeading();
homero 13:c18d82f62d38 611 //printf("%d ",g_currentHeading);
homero 13:c18d82f62d38 612 if(g_currentHeading > 5 || g_currentHeading < -5){
re633 9:ef0907fda2f1 613 turnDegrees(-g_currentHeading);
re633 9:ef0907fda2f1 614 }
re633 9:ef0907fda2f1 615
re633 9:ef0907fda2f1 616 //If the beacon is not currently on but obstacle detected then do obstacle avoidance
homero 13:c18d82f62d38 617 int16_t randomAngle;
re633 9:ef0907fda2f1 618 if(flagBeaconIlluminated == 0){
re633 9:ef0907fda2f1 619 if(gv_IRDistances[0] < 100 || gv_IRDistances[1] < 100){
homero 13:c18d82f62d38 620 randomAngle = rand()%90 - 135;
homero 13:c18d82f62d38 621 piswarm.stop();
homero 13:c18d82f62d38 622 wait_ms(100);
homero 13:c18d82f62d38 623 piswarm.backward(0.3);
homero 13:c18d82f62d38 624 wait_ms(200);
homero 13:c18d82f62d38 625 turnDegrees(randomAngle);
homero 13:c18d82f62d38 626 //piswarm.forward(0.2);
homero 13:c18d82f62d38 627 // wait_ms(500);
re633 9:ef0907fda2f1 628 } else if (gv_IRDistances[6] < 100 || gv_IRDistances[7] < 100){
homero 13:c18d82f62d38 629 randomAngle = rand()%90 + 45;
homero 13:c18d82f62d38 630 piswarm.stop();
homero 13:c18d82f62d38 631 wait_ms(100);
homero 13:c18d82f62d38 632 piswarm.backward(0.3);
homero 13:c18d82f62d38 633 wait_ms(200);
homero 13:c18d82f62d38 634 turnDegrees(randomAngle);
homero 13:c18d82f62d38 635 // piswarm.forward(0.2);
homero 13:c18d82f62d38 636 // wait_ms(500);
homero 13:c18d82f62d38 637 } else if ( distance_ultrasonic_sensor < 100){
homero 13:c18d82f62d38 638 randomAngle = rand()%60 - 30;
homero 13:c18d82f62d38 639 piswarm.stop();
homero 13:c18d82f62d38 640 wait_ms(100);
homero 13:c18d82f62d38 641 piswarm.backward(0.3);
homero 13:c18d82f62d38 642 wait_ms(200);
homero 13:c18d82f62d38 643 turnDegrees(randomAngle);
homero 13:c18d82f62d38 644 //piswarm.forward(0.2);
homero 13:c18d82f62d38 645 // wait_ms(500);
re633 9:ef0907fda2f1 646 }
re633 9:ef0907fda2f1 647 }
homero 13:c18d82f62d38 648 piswarm.right_motor(0.3*r_mot_scaler*r_mot_scaler);
homero 13:c18d82f62d38 649 piswarm.left_motor(0.3*l_mot_scaler*l_mot_scaler);
homero 13:c18d82f62d38 650 wait_ms(500);
re633 9:ef0907fda2f1 651 //Should be at beacon
re633 9:ef0907fda2f1 652 } else {
re633 9:ef0907fda2f1 653 piswarm.stop();
homero 13:c18d82f62d38 654 calculateNewHeading();
homero 13:c18d82f62d38 655 //printf("%d ",g_currentHeading);
homero 13:c18d82f62d38 656 if(g_currentHeading > 5 || g_currentHeading < -5){
homero 13:c18d82f62d38 657 turnDegrees(-g_currentHeading);
homero 13:c18d82f62d38 658 }
re633 9:ef0907fda2f1 659
re633 12:118f2b0ed8eb 660 //If either of these flags is one then the beacon should be the home beacon so change to state 4.
re633 12:118f2b0ed8eb 661 if(return_flag == 1 || back_flag == 1){
homero 13:c18d82f62d38 662 changeState(States::AT_HOME_BEACON);
re633 12:118f2b0ed8eb 663 } else {
homero 13:c18d82f62d38 664 changeState(States::AT_TARGET_BEACON);
re633 12:118f2b0ed8eb 665 }
re633 9:ef0907fda2f1 666 }
re633 9:ef0907fda2f1 667 }
re633 9:ef0907fda2f1 668 //Else need to syncronise with beacon
re633 9:ef0907fda2f1 669 } else {
re633 9:ef0907fda2f1 670
re633 9:ef0907fda2f1 671 while(flagBeaconSyncronised == 0){
re633 9:ef0907fda2f1 672 //Sychronise the ticker with the beacon
re633 9:ef0907fda2f1 673
re633 9:ef0907fda2f1 674 uint8_t testBefore = 0;
re633 9:ef0907fda2f1 675 uint8_t testDuring = 0;
re633 9:ef0907fda2f1 676 uint8_t testAfter = 0;
re633 9:ef0907fda2f1 677 for(loopCounter = 0; loopCounter < 8; loopCounter++){
re633 9:ef0907fda2f1 678 if (gv_IRValDiffs[mod8((g_beaconOn - 1),IR_READ_PER_BEAC)][loopCounter] > BEACON_SUSPECTED){
re633 9:ef0907fda2f1 679 testBefore = 1;
re633 9:ef0907fda2f1 680 }
re633 9:ef0907fda2f1 681 if (gv_IRValDiffs[g_beaconOn][loopCounter] > BEACON_SUSPECTED){
re633 9:ef0907fda2f1 682 testDuring = 1;
re633 9:ef0907fda2f1 683 }
homero 13:c18d82f62d38 684 if (gv_IRValDiffsTwo[mod8((g_beaconOn + 2),IR_READ_PER_BEAC)][loopCounter] > BEACON_SUSPECTED){
re633 9:ef0907fda2f1 685 testAfter = 1;
re633 9:ef0907fda2f1 686 }
homero 13:c18d82f62d38 687 if (gv_IRValDiffsTwo[mod8((g_beaconOn + 2),IR_READ_PER_BEAC)][loopCounter] < -BEACON_SUSPECTED){
re633 9:ef0907fda2f1 688 testAfter = 2;
re633 9:ef0907fda2f1 689 }
re633 9:ef0907fda2f1 690 }
re633 9:ef0907fda2f1 691 //Firstly if the beacon is not detected by any of the sensors then change state back to search
re633 9:ef0907fda2f1 692 if(testBefore == 0 && testDuring == 0 && testAfter == 0){
homero 13:c18d82f62d38 693 changeState(States::SEARCHING_FWD);
re633 9:ef0907fda2f1 694 flagBeaconSyncronised = 1;//to exit while loop
re633 9:ef0907fda2f1 695
re633 9:ef0907fda2f1 696 //If the tick before g_beaconOn is detecting the change caused by the flash change the value of g_beaconOn
re633 9:ef0907fda2f1 697 } else if(testBefore == 1){
re633 9:ef0907fda2f1 698 g_beaconOn = g_beaconOn - 1;
re633 9:ef0907fda2f1 699
homero 13:c18d82f62d38 700 //If the After Tick does not show a drop in value then it is also occuring within the beacon flash so delay the ticker by 10ms
re633 9:ef0907fda2f1 701 } else if(testBefore == 0 && testDuring == 1 && testAfter == 1){
re633 9:ef0907fda2f1 702 ticker_25ms.detach();
homero 13:c18d82f62d38 703 //This was 100000? I think it should be 10000
homero 13:c18d82f62d38 704 tickChangeTimeout.attach_us(&atTimeout,10000);
homero 13:c18d82f62d38 705 wait(1);//Do not delete this wait
re633 9:ef0907fda2f1 706
re633 9:ef0907fda2f1 707 //If successful the set flag
re633 9:ef0907fda2f1 708 } else if (testBefore == 0 && testDuring == 1 && testAfter == 2){
re633 9:ef0907fda2f1 709 flagBeaconSyncronised = 1;
re633 9:ef0907fda2f1 710
re633 9:ef0907fda2f1 711 //Error handle. If this happens stop the piswarm
re633 9:ef0907fda2f1 712 } else {
re633 9:ef0907fda2f1 713 piswarm.set_oled_colour(255,255,255);
re633 9:ef0907fda2f1 714 piswarm.set_oleds(1,1,1,1,1,1,1,1,1,1);
re633 9:ef0907fda2f1 715 piswarm.cls();
re633 9:ef0907fda2f1 716 piswarm.printf("%d %d %d",testBefore, testDuring,testAfter);
re633 9:ef0907fda2f1 717 piswarm.stop();
homero 13:c18d82f62d38 718 ticker_25ms.detach();
homero 13:c18d82f62d38 719 tickChangeTimeout.attach_us(&atTimeout,10000);
homero 13:c18d82f62d38 720 wait_ms(500);
homero 13:c18d82f62d38 721 flagBeaconSyncronised = 1;
homero 13:c18d82f62d38 722 changeState(States::SEARCHING_FWD);
re633 9:ef0907fda2f1 723 }
re633 9:ef0907fda2f1 724 }
re633 12:118f2b0ed8eb 725 }
re633 12:118f2b0ed8eb 726 //At target Beacon.
re633 12:118f2b0ed8eb 727 //Broadcast target beacon found and wait.
homero 13:c18d82f62d38 728 } else if (gv_state == States::AT_TARGET_BEACON){
re633 12:118f2b0ed8eb 729
re633 12:118f2b0ed8eb 730 piswarm.stop();
re633 12:118f2b0ed8eb 731 piswarm.set_oled_colour(150,255,0);
re633 12:118f2b0ed8eb 732 piswarm.set_oleds(1,1,1,1,1,1,1,1,1,1);
re633 12:118f2b0ed8eb 733
homero 13:c18d82f62d38 734 //Detach tickers before broadcasting and waiting for reply
homero 13:c18d82f62d38 735 ticker_25ms.detach();
homero 13:c18d82f62d38 736 ticker_ultrasonic50ms.detach();
homero 13:c18d82f62d38 737
homero 13:c18d82f62d38 738 uint8_t const num_to_broadcast = 10;
homero 13:c18d82f62d38 739
homero 13:c18d82f62d38 740 /* while(aligned_target_beacon ==0){
homero 13:c18d82f62d38 741 if(gv_IRVals[gv_counter25ms][7] < AT_BEACON_THRESHOLD && gv_IRVals[gv_counter25ms][0] < AT_BEACON_THRESHOLD ){
homero 13:c18d82f62d38 742 calculateNewHeading();
homero 13:c18d82f62d38 743 wait(0.025);
homero 13:c18d82f62d38 744 turnDegrees(-g_currentHeading);
homero 13:c18d82f62d38 745
homero 13:c18d82f62d38 746 }
homero 13:c18d82f62d38 747 else if (gv_IRVals[gv_counter25ms][7] > AT_BEACON_THRESHOLD && gv_IRVals[gv_counter25ms][0] > AT_BEACON_THRESHOLD) {
homero 13:c18d82f62d38 748 aligned_target_beacon = 1;
homero 13:c18d82f62d38 749 }
homero 13:c18d82f62d38 750
homero 13:c18d82f62d38 751 else{
homero 13:c18d82f62d38 752 piswarm.printf("stuck");
homero 13:c18d82f62d38 753 }
homero 13:c18d82f62d38 754 }*/
homero 13:c18d82f62d38 755
re633 12:118f2b0ed8eb 756
re633 12:118f2b0ed8eb 757 while(back_flag == 0){
homero 13:c18d82f62d38 758 if(broadcasted_flag == 1 && broadcasted_count < num_to_broadcast){
homero 13:c18d82f62d38 759 broadcastTimeout.attach_us(&atBroadcastTimeout,100000);
homero 13:c18d82f62d38 760 broadcasted_flag = 0;
homero 13:c18d82f62d38 761 }
re633 12:118f2b0ed8eb 762 //Wait for the back flag to change
homero 13:c18d82f62d38 763 //wait_us(1000);
re633 12:118f2b0ed8eb 764 }
homero 13:c18d82f62d38 765
homero 13:c18d82f62d38 766 ticker_25ms.attach_us(&readIRs,25000);
homero 13:c18d82f62d38 767 ticker_ultrasonic50ms.attach_us(&get_ultrasonic_readings,50000);
re633 12:118f2b0ed8eb 768
re633 12:118f2b0ed8eb 769 //Return to beacon search state but now robot is lookling for the home beacon.
homero 13:c18d82f62d38 770 changeState(States::SEARCHING_FWD);
re633 12:118f2b0ed8eb 771
re633 12:118f2b0ed8eb 772 //Back at home area. Stop and wait.
homero 13:c18d82f62d38 773 } else if (gv_state == States::AT_HOME_BEACON){
re633 12:118f2b0ed8eb 774 piswarm.stop();
re633 12:118f2b0ed8eb 775 piswarm.set_oleds(1,1,1,1,1,1,1,1,1,1);
homero 13:c18d82f62d38 776 piswarm.play_tune( "T180L8O5EERERCL4EGR<GR",22 );
re633 12:118f2b0ed8eb 777 while(1){
re633 12:118f2b0ed8eb 778 piswarm.set_oled_colour(0,150,0);
homero 13:c18d82f62d38 779 wait_ms(200);
re633 12:118f2b0ed8eb 780 piswarm.set_oled_colour(150,0,0);
homero 13:c18d82f62d38 781 wait_ms(200);
re633 12:118f2b0ed8eb 782 piswarm.set_oled_colour(0,0,150);
homero 13:c18d82f62d38 783 wait_ms(200);
re633 12:118f2b0ed8eb 784 }
re633 9:ef0907fda2f1 785 }
re633 9:ef0907fda2f1 786 }
jah128 7:d03e54d9eb1c 787 }
jah128 7:d03e54d9eb1c 788
jah128 2:e806b595f9ce 789 /***************************************************************************************************************************************
jah128 2:e806b595f9ce 790 *
jah128 4:823174be9a6b 791 * Beyond this point, empty code blocks for optional functions is given
jah128 2:e806b595f9ce 792 *
jah128 4:823174be9a6b 793 * These may be left blank if not used, but should not be deleted
jah128 2:e806b595f9ce 794 *
jah128 2:e806b595f9ce 795 **************************************************************************************************************************************/
jah128 2:e806b595f9ce 796
jah128 1:37502eb3b70f 797 // Communications
jah128 1:37502eb3b70f 798
jah128 1:37502eb3b70f 799 // If using the communication stack (USE_COMMUNICATION_STACK = 1), functionality for handling user RF responses should be added to the following functions
jah128 1:37502eb3b70f 800 // If the communication stack is not being used, all radio data is sent to processRawRFData() instead
jah128 1:37502eb3b70f 801
jah128 1:37502eb3b70f 802 void handleUserRFCommand(char sender, char broadcast_message, char request_response, char id, char is_command, char function, char * data, char length){
jah128 1:37502eb3b70f 803 // A 'user' RF Command has been received: write the code here to process it
jah128 1:37502eb3b70f 804 // sender = ID of the sender, range 0 to 31
jah128 1:37502eb3b70f 805 // broadcast_message = 1 is message sent to all robots, 0 otherwise
jah128 1:37502eb3b70f 806 // request_response = 1 if a response is expected, 0 otherwise
jah128 1:37502eb3b70f 807 // id = Message ID, range 0 to 255
jah128 1:37502eb3b70f 808 // is_command = 1 is message is a command, 0 if it is a request. If RF_ALLOW_COMMANDS is not selected, only requests will be sent to this block
jah128 1:37502eb3b70f 809 // function = The function identifier. Range 0 to 15
jah128 1:37502eb3b70f 810 // * data = Array containing extra data bytes
jah128 1:37502eb3b70f 811 // length = Length of extra data bytes held (range 0 to 57)
jah128 8:a789ef4fde52 812
jah128 7:d03e54d9eb1c 813
jah128 4:823174be9a6b 814 //Do something...
re633 12:118f2b0ed8eb 815 piswarm.cls();
re633 12:118f2b0ed8eb 816 piswarm.locate(0,0);
re633 12:118f2b0ed8eb 817 piswarm.printf("URF:%d",function);
re633 12:118f2b0ed8eb 818 if(length > 0) {
re633 12:118f2b0ed8eb 819 piswarm.locate(0,1);
re633 12:118f2b0ed8eb 820 piswarm.printf("%s",data);
re633 12:118f2b0ed8eb 821 }
re633 12:118f2b0ed8eb 822
re633 12:118f2b0ed8eb 823 if(function == 1){
re633 12:118f2b0ed8eb 824 start_flag = 1;
re633 12:118f2b0ed8eb 825 }
re633 12:118f2b0ed8eb 826
re633 12:118f2b0ed8eb 827 if(function == 5){
re633 12:118f2b0ed8eb 828 return_flag = 1;
re633 12:118f2b0ed8eb 829 }
re633 12:118f2b0ed8eb 830 if(function == 6){
re633 12:118f2b0ed8eb 831 back_flag = 1;
re633 10:da62735d6df9 832 }
jah128 1:37502eb3b70f 833 }
jah128 1:37502eb3b70f 834
re633 12:118f2b0ed8eb 835 // This function is used to send the RF message:
re633 12:118f2b0ed8eb 836 void broadcast_user_rf_command(int function, char * message, int length)
re633 12:118f2b0ed8eb 837 {
re633 12:118f2b0ed8eb 838 //This function augments the communications stack
re633 12:118f2b0ed8eb 839 //It sends a 'user' RF command to all members (ie target_id = 0)
re633 12:118f2b0ed8eb 840 //It sends a 'request', not a 'command', meaning it will still be handled if commands are disabled (RF_ALLOW_COMMANDS set to 0, recommended)
re633 12:118f2b0ed8eb 841 //It takes three inputs:
re633 12:118f2b0ed8eb 842 // * function (an integer from 0 to 15)
re633 12:118f2b0ed8eb 843 // * message (a char array)
re633 12:118f2b0ed8eb 844 // * length (length of message in bytes)
re633 12:118f2b0ed8eb 845 send_rf_message(0,48+(function % 16),message,length);
re633 12:118f2b0ed8eb 846 }
re633 12:118f2b0ed8eb 847
jah128 1:37502eb3b70f 848 void handleUserRFResponse(char sender, char broadcast_message, char success, char id, char is_command, char function, char * data, char length){
jah128 1:37502eb3b70f 849 // A 'user' RF Response has been received: write the code here to process it
jah128 1:37502eb3b70f 850 // sender = ID of the sender, range 0 to 31
jah128 1:37502eb3b70f 851 // broadcast_message = 1 is message sent to all robots, 0 otherwise
jah128 1:37502eb3b70f 852 // success = 1 if operation successful, 0 otherwise
jah128 1:37502eb3b70f 853 // id = Message ID, range 0 to 255
jah128 1:37502eb3b70f 854 // is_command = 1 is message is a command, 0 if it is a request. If RF_ALLOW_COMMANDS is not selected, only requests will be sent to this block
jah128 1:37502eb3b70f 855 // function = The function identifier. Range 0 to 15
jah128 1:37502eb3b70f 856 // * data = Array containing extra data bytes
jah128 1:37502eb3b70f 857 // length = Length of extra data bytes held (range 0 to 57)
jah128 4:823174be9a6b 858
jah128 4:823174be9a6b 859 //Do something...
jah128 1:37502eb3b70f 860 }
jah128 1:37502eb3b70f 861
jah128 1:37502eb3b70f 862 void processRawRFData(char * rstring, char cCount){
jah128 1:37502eb3b70f 863 // A raw RF packet has been received: write the code here to process it
jah128 1:37502eb3b70f 864 // rstring = The received packet
jah128 1:37502eb3b70f 865 // cCount = Packet length
jah128 4:823174be9a6b 866
jah128 4:823174be9a6b 867 //Do something...
jah128 0:46cd1498a39a 868 }
jah128 0:46cd1498a39a 869
jah128 1:37502eb3b70f 870 void switch_pressed() {
jah128 1:37502eb3b70f 871 //Switch(es) pressed {1 = Center 2 = Right 4 = Left 8 = Down 16 = Up}
jah128 1:37502eb3b70f 872 char switches = piswarm.get_switches();
jah128 1:37502eb3b70f 873
jah128 1:37502eb3b70f 874 //Do something...
homero 13:c18d82f62d38 875 }