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.
Fork of PsiSwarmLibrary by
sensors.cpp
00001 /* University of York Robotics Laboratory PsiSwarm Library: Sensor Functions Source File 00002 * 00003 * File: sensors.cpp 00004 * 00005 * (C) Dept. Electronics & Computer Science, University of York 00006 * James Hilder, Alan Millard, Alexander Horsfield, Homero Elizondo, Jon Timmis 00007 * 00008 * PsiSwarm Library Version: 0.41 00009 * 00010 * March 2016 00011 * 00012 * 00013 */ 00014 00015 #include "psiswarm.h" 00016 00017 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00018 // Ultrasonic Sensor (SRF02) Functions 00019 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00020 00021 // The ultrasonic sensor needs a start command to be sent: this is done by calling update_ultrasonic_measure(). 00022 // It can be set to automatically refresh at 10Hz by called enable_ultrasonic_ticker and disable with disabled_ultrasonic_ticker 00023 00024 void enable_ultrasonic_ticker() 00025 { 00026 ultrasonic_ticker.attach_us(update_ultrasonic_measure,100000); 00027 } 00028 00029 void disable_ultrasonic_ticker() 00030 { 00031 ultrasonic_ticker.detach(); 00032 } 00033 00034 void update_ultrasonic_measure() 00035 { 00036 if(waiting_for_ultrasonic == 0) { 00037 waiting_for_ultrasonic = 1; 00038 if(has_ultrasonic_sensor) { 00039 char command[2]; 00040 command[0] = 0x00; // Set the command register 00041 command[1] = 0x51; // Get result is centimeters 00042 primary_i2c.write(ULTRASONIC_ADDRESS, command, 2); // Send the command to start a ranging burst 00043 } 00044 ultrasonic_timeout.attach_us(IF_read_ultrasonic_measure,70000); 00045 } else { 00046 debug("WARNING: Ultrasonic sensor called too frequently.\n"); 00047 } 00048 } 00049 00050 void IF_read_ultrasonic_measure() 00051 { 00052 if(has_ultrasonic_sensor) { 00053 char command[1]; 00054 char result[2]; 00055 command[0] = 0x02; // The start address of measure result 00056 primary_i2c.write(ULTRASONIC_ADDRESS, command, 1, 1); // Send address to read a measure 00057 primary_i2c.read(ULTRASONIC_ADDRESS, result, 2); // Read two byte of measure 00058 ultrasonic_distance = (result[0]<<8)+result[1]; 00059 } else ultrasonic_distance = 0; 00060 ultrasonic_distance_updated = 1; 00061 waiting_for_ultrasonic = 0; 00062 //debug("US:%d cm\n",ultrasonic_distance); 00063 } 00064 00065 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00066 // Additional Sensing Functions 00067 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00068 00069 float get_temperature() 00070 { 00071 if(has_temperature_sensor)return IF_read_from_temperature_sensor(); 00072 return 0; 00073 } 00074 00075 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00076 // Voltage Sensing Functions 00077 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00078 00079 float get_battery_voltage () 00080 { 00081 float raw_value = vin_battery.read(); 00082 return raw_value * 4.95; 00083 } 00084 00085 float get_current () 00086 { 00087 // Device uses a INA211 current sense monitor measuring voltage drop across a 2mOhm resistor 00088 // Device gain = 500 00089 float raw_value = vin_current.read(); 00090 return raw_value * 3.3; 00091 } 00092 00093 float get_dc_voltage () 00094 { 00095 float raw_value = vin_dc.read(); 00096 return raw_value * 6.6; 00097 } 00098 00099 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00100 // IR Sensor Functions 00101 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00102 00103 // Estimates the distance to an obstacle from one of the IR sensors, defined by index (range 0-7). 00104 // The value is converted to an approximate distance in millimetres, or 100.0 if no obstacle found. 00105 // NB This function is preserved for code-compatability and cases where only a single reading is needed 00106 // In many cases it is preferable to call store_reflected_ir_distances() to save all 8 values then read using get_reflected_ir_distance() 00107 float read_reflected_ir_distance ( char index ) 00108 { 00109 // Sanity check 00110 if(index>7) return 0.0; 00111 00112 //1. Read the ADC value without IR emitter on; store in the background_ir_values[] array 00113 background_ir_values [index] = IF_read_IR_adc_value(1, index ); 00114 00115 //2. Enable the relevant IR emitter by turning on its pulse output 00116 switch(index) { 00117 case 0: 00118 case 1: 00119 case 6: 00120 case 7: 00121 IF_set_IR_emitter_output(0, 1); 00122 break; 00123 case 2: 00124 case 3: 00125 case 4: 00126 case 5: 00127 IF_set_IR_emitter_output(1, 1); 00128 break; 00129 } 00130 wait_us(ir_pulse_delay); 00131 00132 //3. Read the ADC value now IR emitter is on; store in the illuminated_ir_values[] array 00133 illuminated_ir_values [index] = IF_read_IR_adc_value (1, index ); 00134 00135 //4. Turn off IR emitter 00136 switch(index) { 00137 case 0: 00138 case 1: 00139 case 6: 00140 case 7: 00141 IF_set_IR_emitter_output(0, 0); 00142 break; 00143 case 2: 00144 case 3: 00145 case 4: 00146 case 5: 00147 IF_set_IR_emitter_output(1, 0); 00148 break; 00149 } 00150 00151 //5. Estimate distance based on 2 values using calculate_reflected_distances(); store in reflected_ir_distances() 00152 reflected_ir_distances [index] = calculate_reflected_distance( background_ir_values [index], illuminated_ir_values [index]); 00153 ir_values_stored = 1; 00154 return reflected_ir_distances [index]; 00155 } 00156 00157 00158 // Returns the stored value of the reflected obstacle based on last call of either read_reflected_ir_distance or store_reflected_distances 00159 float get_reflected_ir_distance ( char index ) 00160 { 00161 // Sanity check: check range of index and that values have been stored 00162 if (index>7 || ir_values_stored == 0) return 0.0; 00163 return reflected_ir_distances[index]; 00164 } 00165 00166 // Returns the stored value of the non-illuminated sensor based on last call of store_background_raw_ir_values 00167 unsigned short get_background_raw_ir_value ( char index ) 00168 { 00169 // Sanity check: check range of index and that values have been stored 00170 if (index>7 || ir_values_stored == 0) return 0.0; 00171 return background_ir_values[index]; 00172 } 00173 00174 // Returns the stored value of the illuminated sensor based on last call of store_illuminated_raw_ir_values 00175 unsigned short get_illuminated_raw_ir_value ( char index ) 00176 { 00177 // Sanity check: check range of index and that values have been stored 00178 if (index>7 || ir_values_stored == 0) return 0.0; 00179 return illuminated_ir_values[index]; 00180 } 00181 00182 // Stores the reflected distances for all 8 IR sensors 00183 void store_reflected_ir_distances ( void ) 00184 { 00185 store_ir_values(); 00186 for(int i=0; i<8; i++) { 00187 reflected_ir_distances [i] = calculate_reflected_distance( background_ir_values [i], illuminated_ir_values [i]); 00188 } 00189 } 00190 00191 // Stores the rbackground and illuminated values for all 8 IR sensors 00192 void store_ir_values ( void ) 00193 { 00194 store_background_raw_ir_values(); 00195 store_illuminated_raw_ir_values(); 00196 } 00197 00198 // Stores the raw ADC values for all 8 IR sensors without enabling IR emitters 00199 void store_background_raw_ir_values ( void ) 00200 { 00201 ir_values_stored = 1; 00202 for(int i=0; i<8; i++) { 00203 background_ir_values [i] = IF_read_IR_adc_value(1,i); 00204 } 00205 } 00206 00207 // Stores the raw ADC values for all 8 IR sensors with a 500us emitter pulse 00208 void store_illuminated_raw_ir_values ( void ) 00209 { 00210 //1. Enable the front IR emitters and store the values 00211 IF_set_IR_emitter_output(0, 1); 00212 wait_us(ir_pulse_delay); 00213 illuminated_ir_values [0] = IF_read_IR_adc_value(1,0); 00214 illuminated_ir_values [1] = IF_read_IR_adc_value(1,1); 00215 illuminated_ir_values [6] = IF_read_IR_adc_value(1,6); 00216 illuminated_ir_values [7] = IF_read_IR_adc_value(1,7); 00217 IF_set_IR_emitter_output(0, 0); 00218 00219 //2. Enable the rear+side IR emitters and store the values 00220 IF_set_IR_emitter_output(1, 1); 00221 wait_us(ir_pulse_delay); 00222 illuminated_ir_values [2] = IF_read_IR_adc_value(1,2); 00223 illuminated_ir_values [3] = IF_read_IR_adc_value(1,3); 00224 illuminated_ir_values [4] = IF_read_IR_adc_value(1,4); 00225 illuminated_ir_values [5] = IF_read_IR_adc_value(1,5); 00226 IF_set_IR_emitter_output(1, 0); 00227 } 00228 00229 // Converts a background and illuminated value into a distance 00230 float calculate_reflected_distance ( unsigned short background_value, unsigned short illuminated_value ) 00231 { 00232 float approximate_distance = 4000 + background_value - illuminated_value; 00233 if(approximate_distance < 0) approximate_distance = 0; 00234 00235 // Very approximate: root value, divide by 2, approx distance in mm 00236 approximate_distance = sqrt (approximate_distance) / 2.0; 00237 00238 // Then add adjustment value if value >27 00239 if(approximate_distance > 27) { 00240 float shift = pow(approximate_distance - 27,3); 00241 approximate_distance += shift; 00242 } 00243 if(approximate_distance > 90) approximate_distance = 100.0; 00244 return approximate_distance; 00245 } 00246 00247 // Returns the illuminated raw sensor value for the IR sensor defined by index (range 0-7); turns on the emitters for a 500us pulse 00248 unsigned short read_illuminated_raw_ir_value ( char index ) 00249 { 00250 //This function reads the IR strength when illuminated - used for PC system debugging purposes 00251 //1. Enable the relevant IR emitter by turning on its pulse output 00252 switch(index) { 00253 case 0: 00254 case 1: 00255 case 6: 00256 case 7: 00257 IF_set_IR_emitter_output(0, 1); 00258 break; 00259 case 2: 00260 case 3: 00261 case 4: 00262 case 5: 00263 IF_set_IR_emitter_output(1, 1); 00264 break; 00265 } 00266 wait_us(ir_pulse_delay); 00267 //2. Read the ADC value now IR emitter is on 00268 unsigned short strong_value = IF_read_IR_adc_value( 1,index ); 00269 //3. Turn off IR emitter 00270 switch(index) { 00271 case 0: 00272 case 1: 00273 case 6: 00274 case 7: 00275 IF_set_IR_emitter_output(0, 0); 00276 break; 00277 case 2: 00278 case 3: 00279 case 4: 00280 case 5: 00281 IF_set_IR_emitter_output(1, 0); 00282 break; 00283 } 00284 return strong_value; 00285 } 00286 00287 // Base IR sensor functions 00288 00289 00290 // Returns the stored value of the non-illuminated sensor based on last call of store_background_base_ir_values 00291 unsigned short get_background_base_ir_value ( char index ) 00292 { 00293 // Sanity check: check range of index and that values have been stored 00294 if (index>4 || base_ir_values_stored == 0) return 0.0; 00295 return background_base_ir_values[index]; 00296 } 00297 00298 // Returns the stored value of the illuminated sensor based on last call of store_illuminated_base_ir_values 00299 unsigned short get_illuminated_base_ir_value ( char index ) 00300 { 00301 // Sanity check: check range of index and that values have been stored 00302 if (index>4 || base_ir_values_stored == 0) return 0.0; 00303 return illuminated_base_ir_values[index]; 00304 } 00305 00306 // Stores the reflected distances for all 5 base IR sensors 00307 void store_base_ir_values ( void ) 00308 { 00309 store_background_base_ir_values(); 00310 store_illuminated_base_ir_values(); 00311 //for(int i=0;i<5;i++){ 00312 // reflected_ir_distances [i] = calculate_reflected_distance( background_base_ir_values [i], illuminated_base_ir_values [i]); 00313 //} 00314 } 00315 00316 // Stores the raw ADC values for all 5 base IR sensors without enabling IR emitters 00317 void store_background_base_ir_values ( void ) 00318 { 00319 base_ir_values_stored = 1; 00320 for(int i=0; i<5; i++) { 00321 background_base_ir_values [i] = IF_read_IR_adc_value(2,i); 00322 } 00323 } 00324 00325 // Stores the raw ADC values for all 5 base IR sensors with a 500us emitter pulse 00326 void store_illuminated_base_ir_values ( void ) 00327 { 00328 //1. Enable the base IR emitters and store the values 00329 IF_set_IR_emitter_output(2, 1); 00330 wait_us(base_ir_pulse_delay); 00331 for(int i=0; i<5; i++) { 00332 illuminated_base_ir_values [i] = IF_read_IR_adc_value(2,i); 00333 } 00334 00335 IF_set_IR_emitter_output(2, 0); 00336 } 00337 00338 // Routine to store detected line position in a similar format to the used on 3Pi\m3Pi\PiSwarm 00339 void store_line_position ( ) 00340 { 00341 // Store background and reflected base IR values 00342 store_base_ir_values(); 00343 int h_value[5]; 00344 int line_threshold = 1000; 00345 int line_threshold_hi = 2000; 00346 char count = 0; 00347 line_found = 0; 00348 line_position = 0; 00349 for(int i=0; i<5; i++) { 00350 if(get_background_base_ir_value(i) > get_illuminated_base_ir_value(i)) h_value[i]=0; 00351 else h_value[i] = get_illuminated_base_ir_value(i) - get_background_base_ir_value(i); 00352 if(h_value[i] < line_threshold) count++; 00353 } 00354 if(count == 1) { 00355 line_found = 1; 00356 if(h_value[0] < line_threshold) { 00357 line_position = -1; 00358 if(h_value[1] < line_threshold_hi) line_position = -0.8; 00359 } 00360 00361 if (h_value[1] < line_threshold) { 00362 line_position = -0.5 + (0.00005 * h_value[0]) - (0.0001 * h_value[2]);; 00363 } 00364 if(h_value[2] < line_threshold) { 00365 line_position = (0.00005 * h_value[1]) - (0.0001 * h_value[3]); 00366 } 00367 if(h_value[3] < line_threshold) { 00368 line_position = 0.5 + (0.00005 * h_value[2]) - (0.0001 * h_value[4]);; 00369 } 00370 if(h_value[4] < line_threshold) { 00371 line_position = 1; 00372 if(h_value[3] < line_threshold_hi) line_position = 0.8; 00373 } 00374 } 00375 if(count == 2) { 00376 if(h_value[0] && h_value[1] < line_threshold) { 00377 line_found = 1; 00378 line_position = -0.6; 00379 } 00380 00381 if(h_value[1] && h_value[2] < line_threshold) { 00382 line_found = 1; 00383 line_position = -0.4; 00384 } 00385 00386 if(h_value[2] && h_value[3] < line_threshold) { 00387 line_found = 1; 00388 line_position = 0.4; 00389 } 00390 00391 if(h_value[3] && h_value[4] < line_threshold) { 00392 line_found = 1; 00393 line_position = 0.6; 00394 } 00395 } 00396 } 00397 00398 // Returns the subtraction of the background base IR value from the reflection based on last call of store_illuminated_base_ir_values 00399 unsigned short calculate_base_ir_value ( char index ){ 00400 // If the index is not in the correct range or the base IR values have not been stored, return zero 00401 if (index>4 || base_ir_values_stored == 0) return 0.0; 00402 // If the reflection value is greater than the background value, return the subtraction 00403 if(illuminated_base_ir_values[index] > background_base_ir_values[index]){ 00404 return illuminated_base_ir_values[index] - background_base_ir_values[index]; 00405 //Otherwise return zero 00406 } else { 00407 return 0.0; 00408 } 00409 } 00410 00411 // Returns the subtraction of the background side IR value from the reflection based on last call of store_illuminated_base_ir_values 00412 unsigned short calculate_side_ir_value ( char index ){ 00413 // If the index is not in the correct range or the base IR values have not been stored, return zero 00414 if (index>7 || ir_values_stored == 0) return 0.0; 00415 // If the reflection value is greater than the background value, return the subtraction 00416 if(illuminated_ir_values[index] > background_ir_values[index]){ 00417 return illuminated_ir_values[index] - background_ir_values[index]; 00418 //Otherwise return zero 00419 } else { 00420 return 0.0; 00421 } 00422 } 00423 00424 void calibrate_base_ir_sensors (void) 00425 { 00426 short white_background[5]; 00427 short white_active[5]; 00428 short black_background[5]; 00429 short black_active[5]; 00430 for(int k=0; k<5; k++) { 00431 white_background[k]=0; 00432 black_background[k]=0; 00433 white_active[k]=0; 00434 black_active[k]=0; 00435 } 00436 pc.printf("Base IR Calibration\n"); 00437 display.clear_display(); 00438 display.write_string("Calibrating base"); 00439 display.set_position(1,0); 00440 display.write_string("IR sensor"); 00441 wait(0.5); 00442 display.clear_display(); 00443 display.write_string("Place robot on"); 00444 display.set_position(1,0); 00445 display.write_string("white surface"); 00446 wait(3); 00447 display.clear_display(); 00448 display.write_string("Calibrating base"); 00449 display.set_position(1,0); 00450 display.write_string("IR sensor"); 00451 wait(0.5); 00452 pc.printf("\nWhite Background Results:\n"); 00453 00454 for(int i=0; i<5; i++) { 00455 wait(0.2); 00456 store_background_base_ir_values(); 00457 00458 display.set_position(1,9); 00459 display.write_string("."); 00460 wait(0.2); 00461 store_illuminated_base_ir_values(); 00462 for(int k=0; k<5; k++) { 00463 white_background[k]+= get_background_base_ir_value(k); 00464 white_active[k] += get_illuminated_base_ir_value(k); 00465 } 00466 pc.printf("Sample %d 1: %04d-%04d 2: %04d-%04d 3: %04d-%04d 4: %04d-%04d 5: %04d-%04d\n", (i+1), 00467 get_background_base_ir_value(0), get_illuminated_base_ir_value(0), 00468 get_background_base_ir_value(1), get_illuminated_base_ir_value(1), 00469 get_background_base_ir_value(2), get_illuminated_base_ir_value(2), 00470 get_background_base_ir_value(3), get_illuminated_base_ir_value(3), 00471 get_background_base_ir_value(4), get_illuminated_base_ir_value(4)); 00472 } 00473 for(int k=0; k<5; k++) { 00474 white_background[k]/=5; 00475 white_active[k]/=5; 00476 } 00477 pc.printf("Mean results 1: %04d-%04d 2: %04d-%04d 3: %04d-%04d 4: %04d-%04d 5: %04d-%04d\n", 00478 white_background[0], white_active[0], 00479 white_background[1], white_active[1], 00480 white_background[2], white_active[2], 00481 white_background[3], white_active[3], 00482 white_background[4], white_active[4]); 00483 00484 display.clear_display(); 00485 display.write_string("Place robot on"); 00486 display.set_position(1,0); 00487 display.write_string("black surface"); 00488 wait(3); 00489 00490 display.clear_display(); 00491 display.write_string("Calibrating base"); 00492 display.set_position(1,0); 00493 display.write_string("IR sensor"); 00494 wait(0.5); 00495 pc.printf("\nBlack Background Results:\n"); 00496 00497 for(int i=0; i<5; i++) { 00498 wait(0.2); 00499 00500 store_background_base_ir_values(); 00501 display.set_position(1,9); 00502 display.write_string("."); 00503 wait(0.2); 00504 store_illuminated_base_ir_values(); 00505 for(int k=0; k<5; k++) { 00506 black_background[k]+= get_background_base_ir_value(k); 00507 black_active[k] += get_illuminated_base_ir_value(k); 00508 } 00509 pc.printf("Sample %d 1: %04d-%04d 2: %04d-%04d 3: %04d-%04d 4: %04d-%04d 5: %04d-%04d\n", (i+1), 00510 get_background_base_ir_value(0), get_illuminated_base_ir_value(0), 00511 get_background_base_ir_value(1), get_illuminated_base_ir_value(1), 00512 get_background_base_ir_value(2), get_illuminated_base_ir_value(2), 00513 get_background_base_ir_value(3), get_illuminated_base_ir_value(3), 00514 get_background_base_ir_value(4), get_illuminated_base_ir_value(4)); 00515 } 00516 for(int k=0; k<5; k++) { 00517 black_background[k]/=5; 00518 black_active[k]/=5; 00519 } 00520 pc.printf("Mean results 1: %04d-%04d 2: %04d-%04d 3: %04d-%04d 4: %04d-%04d 5: %04d-%04d\n", 00521 black_background[0], black_active[0], 00522 black_background[1], black_active[1], 00523 black_background[2], black_active[2], 00524 black_background[3], black_active[3], 00525 black_background[4], black_active[4]); 00526 00527 } 00528 00529 00530 int get_bearing_from_ir_array (unsigned short * ir_sensor_readings) 00531 { 00532 //out("Getting bearing from array: [%d][%d][%d][%d][%d][%d][%d][%d]\n",ir_sensor_readings[0],ir_sensor_readings[1],ir_sensor_readings[2],ir_sensor_readings[3],ir_sensor_readings[4],ir_sensor_readings[5],ir_sensor_readings[6],ir_sensor_readings[7]); 00533 00534 float degrees_per_radian = 57.295779513; 00535 00536 // sin(IR sensor angle) and cos(IR sensor angle) LUT, for all 8 sensors 00537 float ir_sensor_sin[8] = {0.382683432, 0.923879533, 0.923879533, 0.382683432, -0.382683432, -0.923879533, -0.923879533, -0.382683432}; 00538 float ir_sensor_cos[8] = {0.923879533, 0.382683432, -0.382683432, -0.923879533, -0.923879533, -0.382683432, 0.382683432, 0.923879533}; 00539 00540 float sin_sum = 0; 00541 float cos_sum = 0; 00542 00543 for(int i = 0; i < 8; i++) { 00544 // Use IR sensor reading to weight bearing vector 00545 sin_sum += ir_sensor_sin[i] * ir_sensor_readings[i]; 00546 cos_sum += ir_sensor_cos[i] * ir_sensor_readings[i]; 00547 } 00548 00549 float bearing = atan2(sin_sum, cos_sum); // Calculate vector towards IR light source 00550 bearing *= degrees_per_radian; // Convert to degrees 00551 00552 //out("Sin sum:%f Cos sum:%f Bearing:%f\n",sin_sum,cos_sum,bearing); 00553 00554 return (int) bearing; 00555 } 00556
Generated on Sat Jul 16 2022 05:17:35 by
1.7.2
