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