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.
m3pi.cpp
00001 #include "m3pi.h" 00002 00003 ////////////////////////// constructor/destructor ////////////////////////////// 00004 00005 00006 m3pi::m3pi() 00007 { 00008 _serial = new BufferedSerial(p9,p10); 00009 _reset = new DigitalOut(p8); 00010 _last_line_position = 0.0; 00011 00012 // initialise the arrays 00013 _bar_graph[0] = ' '; 00014 for (int i = 0; i < 6; i++) { 00015 _bar_graph[i+1] = i; 00016 } 00017 for (int i = 0; i < 5; i++) { 00018 _values[i]=0; 00019 } 00020 } 00021 00022 m3pi::~m3pi() 00023 { 00024 delete _serial; 00025 delete _reset; 00026 00027 } 00028 00029 /////////////////////////////// public methods ///////////////////////////////// 00030 00031 void m3pi::init() 00032 { 00033 _serial->set_baud(115200); 00034 reset(); // hard rest of 3pi 00035 stop(); // stop motors 00036 lcd_clear(); // clear LCD 00037 } 00038 00039 /////////////////////////////// serial slave commands //////////////////////////////// 00040 00041 void m3pi::scan() 00042 { 00043 get_calibrated_values(_values); 00044 } 00045 00046 void m3pi::get_signature(char *signature) 00047 { 00048 char buff[7]; 00049 //_serial->putc(0x81); 00050 buff[1]=0x81; 00051 _serial->write(buff,1); 00052 //_serial->gets(signature,7); 00053 _serial->read(buff,7); 00054 } 00055 00056 void m3pi::get_raw_values(unsigned int *values) 00057 { 00058 char buff[1]; // send command 00059 00060 while (_serial->readable() ) { // flush buffer 00061 //_serial->getc(); 00062 _serial->sync(); 00063 00064 } 00065 00066 char vals[10]; // array to receive 10 byte return message 00067 00068 //_serial->putc(0x86); 00069 buff[0]=0x86; 00070 _serial->write(buff,1); 00071 00072 for (int i=0; i < 10; i++) { 00073 //vals[i] = _serial->getc(); 00074 _serial->read(buff,1); 00075 vals[i] = buff[0]; 00076 } 00077 00078 for(int i=0; i<5; i++) { // construct the 2-byte values 00079 values[i] = (vals[2*i+1] << 8) | vals[2*i]; 00080 } 00081 } 00082 00083 void m3pi::get_calibrated_values(unsigned int *values) 00084 { 00085 char buff[1]; 00086 00087 while (_serial->readable() ) { // flush buffer 00088 //_serial->getc(); 00089 _serial->sync(); 00090 } 00091 00092 char vals[10]; // array to receive 10 byte return message 00093 //_serial->putc(0x87); // send command 00094 buff[0]=0x87; 00095 _serial->write(buff,1); 00096 00097 for (int i=0; i < 10; i++) { 00098 //vals[i] = _serial->getc(); 00099 _serial->read(buff,1); 00100 vals[i] = buff[0]; 00101 } 00102 00103 for(int i=0; i<5; i++) { // construct the 2-byte values 00104 values[i] = (vals[2*i+1] << 8) | vals[2*i]; 00105 } 00106 00107 } 00108 00109 float m3pi::get_trimpot_value() 00110 { 00111 char buff[1]; 00112 00113 //_serial->putc(0xB0); 00114 buff[0]=0xB0; 00115 _serial->write(buff,1); 00116 00117 char lsb;// = _serial->getc(); 00118 _serial->read(buff,1); 00119 lsb = buff[0]; 00120 char msb;// = _serial->getc(); 00121 _serial->read(buff,1); 00122 msb = buff[0]; 00123 // trimpot value in the range 0 - 1023 00124 float value = ( msb<<8 | lsb ) / 1023.0; 00125 return value; 00126 } 00127 00128 00129 float m3pi::get_battery_voltage() 00130 { 00131 char buff[1]; 00132 //_serial->putc(0xB1); 00133 buff[0]=0xB1; 00134 _serial->write(buff,1); 00135 char lsb;// = _serial->getc(); 00136 _serial->read(buff,1); 00137 lsb = buff[0]; 00138 char msb;// = _serial->getc(); 00139 _serial->read(buff,1); 00140 msb = buff[0]; 00141 // Battery in mV so convert to volts 00142 float voltage = ( msb<<8 | lsb ) / 1000.0; 00143 return voltage; 00144 } 00145 00146 void m3pi::play_music(const char notes[],int length) 00147 { 00148 char buff[1]; 00149 00150 length = length < 0 ? 0 : length; 00151 length = length > 100 ? 100 : length; 00152 00153 //_serial->putc(0xB3); 00154 buff[0]=0xB3; 00155 _serial->write(buff,1); 00156 00157 //_serial->putc(length); 00158 buff[0]=length; 00159 _serial->write(buff,1); 00160 00161 for (int i = 0 ; i < length ; i++) { 00162 //_serial->putc(notes[i]); 00163 buff[0]=notes[i]; 00164 _serial->write(buff,1); 00165 } 00166 } 00167 00168 void m3pi::calibrate() 00169 { 00170 char buff[1]; 00171 //_serial->putc(0xB4); 00172 buff[0]=0xB4; 00173 _serial->write(buff,1); 00174 } 00175 00176 void m3pi::reset_calibration() 00177 { 00178 char buff[1]; 00179 //_serial->putc(0xB5); 00180 buff[0]=0xB5; 00181 _serial->write(buff,1); 00182 } 00183 00184 float m3pi::get_line_position() 00185 { 00186 char buff[1]; 00187 //_serial->putc(0xB6); 00188 buff[0]=0xB6; 00189 _serial->write(buff,1); 00190 00191 char lsb;// = _serial->getc(); 00192 _serial->read(buff,1); 00193 lsb = buff[0]; 00194 char msb;// = _serial->getc(); 00195 _serial->read(buff,1); 00196 msb = buff[0]; 00197 int position = (msb<<8 | lsb); 00198 00199 return float(position - 2000)/2000.0; 00200 } 00201 00202 void m3pi::lcd_clear() 00203 { 00204 char buff[1]; 00205 //_serial->putc(0xB7); 00206 buff[0]=0xB7; 00207 _serial->write(buff,1); 00208 } 00209 00210 void m3pi::lcd_print(char text[],int length) 00211 { 00212 char buff[1]; 00213 00214 length = length < 0 ? 0 : length; 00215 length = length > 8 ? 8 : length; 00216 00217 //_serial->putc(0xB8); 00218 buff[0]=0xB8; 00219 _serial->write(buff,1); 00220 00221 //_serial->putc(length); 00222 buff[0]=length; 00223 _serial->write(buff,1); 00224 00225 for (int i = 0 ; i < length ; i++) { 00226 //_serial->putc(text[i]); 00227 buff[0]=text[i]; 00228 _serial->write(buff,1); 00229 } 00230 } 00231 00232 void m3pi::lcd_goto_xy(int x, int y) 00233 { 00234 char buff[1]; 00235 //_serial->putc(0xB9); 00236 buff[0]=0xB9; 00237 _serial->write(buff,1); 00238 //_serial->putc(x); 00239 buff[0]=x; 00240 _serial->write(buff,1); 00241 //_serial->putc(y); 00242 buff[0]=y; 00243 _serial->write(buff,1); 00244 } 00245 00246 void m3pi::auto_calibrate() 00247 { 00248 char buff[1]; 00249 //_serial->putc(0xBA); 00250 buff[0]=0xBA; 00251 _serial->write(buff,1); 00252 00253 while(1) { // wait for serial response 00254 if (_serial->readable()) { 00255 break; 00256 } 00257 } 00258 } 00259 00260 /////////////////////////////// motor methods //////////////////////////////// 00261 00262 void m3pi::left_motor(float speed) 00263 { 00264 char buff[1]; 00265 // check within bounds 00266 speed = speed > 1.0 ? 1.0 : speed; 00267 speed = speed < -1.0 ? -1.0 : speed; 00268 00269 if (speed > 0.0) { // forward 00270 //_serial->putc(0xC1); 00271 buff[0]=0xC1; 00272 _serial->write(buff,1); 00273 char s = char(127.0*speed); 00274 //_serial->putc(s); 00275 buff[0]=s; 00276 _serial->write(buff,1); 00277 } else { // backward - speed is negative 00278 //_serial->putc(0xC2); 00279 buff[0]=0xC2; 00280 _serial->write(buff,1); 00281 char s = char(-127.0*speed); 00282 //_serial->putc(s); 00283 buff[0]=s; 00284 _serial->write(buff,1); 00285 } 00286 00287 } 00288 00289 void m3pi::right_motor(float speed) 00290 { 00291 char buff[1]; 00292 // check within bounds 00293 speed = speed > 1.0 ? 1.0 : speed; 00294 speed = speed < -1.0 ? -1.0 : speed; 00295 00296 if (speed > 0.0) { // forward 00297 //_serial->putc(0xC5); 00298 buff[0]=0xC5; 00299 _serial->write(buff,1); 00300 char s = char(127.0*speed); 00301 //_serial->putc(s); 00302 buff[0]=s; 00303 _serial->write(buff,1); 00304 } else { // backward - speed is negative 00305 //_serial->putc(0xC6); 00306 buff[0]=0xC6; 00307 _serial->write(buff,1); 00308 char s = char(-127.0*speed); 00309 //_serial->putc(s); 00310 buff[0]=s; 00311 _serial->write(buff,1); 00312 } 00313 00314 } 00315 00316 // speeds from -1.0 to 1.0 (0 is stop) 00317 void m3pi::motors(float left_speed,float right_speed) 00318 { 00319 left_motor(left_speed); 00320 right_motor(right_speed); 00321 } 00322 00323 void m3pi::stop() 00324 { 00325 left_motor(0.0); 00326 right_motor(0.0); 00327 } 00328 00329 // speed in range 0.0 to 1.0 00330 void m3pi::forward(float speed) 00331 { 00332 speed = speed > 1.0 ? 1.0 : speed; 00333 speed = speed < 0.0 ? 0.0 : speed; 00334 00335 left_motor(speed); 00336 right_motor(speed); 00337 } 00338 00339 // speed in range 0 to 1.0 00340 void m3pi::reverse(float speed) 00341 { 00342 speed = speed > 1.0 ? 1.0 : speed; 00343 speed = speed < 0.0 ? 0.0 : speed; 00344 00345 left_motor(-speed); 00346 right_motor(-speed); 00347 } 00348 00349 void m3pi::spin_right(float speed) 00350 { 00351 speed = speed > 1.0 ? 1.0 : speed; 00352 speed = speed < 0.0 ? 0.0 : speed; 00353 00354 left_motor(speed); 00355 right_motor(-speed); 00356 } 00357 00358 void m3pi::spin_left(float speed) 00359 { 00360 speed = speed > 1.0 ? 1.0 : speed; 00361 speed = speed < 0.0 ? 0.0 : speed; 00362 00363 left_motor(-speed); 00364 right_motor(speed); 00365 } 00366 00367 //////////////////////////////////////////////////////////////////////////////// 00368 00369 void m3pi::display_battery_voltage(int x,int y) 00370 { 00371 float voltage = get_battery_voltage(); 00372 00373 char buffer[8]; 00374 sprintf(buffer,"%3.1f V",voltage); 00375 00376 lcd_goto_xy(x,y); 00377 lcd_print(buffer,5); 00378 } 00379 00380 void m3pi::display_signature(int x,int y) 00381 { 00382 char buffer[7]; // including NULL terminator 00383 00384 //_serial->putc(0x81); 00385 buffer[0]=0x81; 00386 _serial->write(buffer,1); 00387 00388 00389 //_serial->gets(buffer,7); 00390 _serial->read(buffer,7); 00391 00392 lcd_goto_xy(x,y); 00393 lcd_print(buffer,6); 00394 } 00395 00396 void m3pi::display_sensor_values(unsigned int values[],int y) 00397 { 00398 // initialise array to ASCII '0' 00399 lcd_goto_xy(1,y); 00400 00401 char sensor_values[5]; 00402 00403 // loop through sensor 00404 for (int sensor = 0 ; sensor < 5 ; sensor++) { 00405 // get the value and put it in the correct bin 00406 // (7 bins in the range 0 to 1000 00407 char value = char(values[sensor]/(1000.0/7.0)); 00408 // use the bin to select the bar graph icon to display 00409 sensor_values[sensor] = _bar_graph[value]; 00410 } 00411 00412 lcd_print(sensor_values,5); 00413 00414 } 00415 00416 void m3pi::display_data() 00417 { 00418 display_sensor_values(_values,1); 00419 00420 char buffer[8]= {0}; 00421 sprintf(buffer,"% .3f",_last_line_position); 00422 lcd_goto_xy(0,0); 00423 lcd_print(buffer,6); 00424 00425 } 00426 00427 unsigned int m3pi::get_sensor_array_value(unsigned int values[]) 00428 { 00429 unsigned int value = 0; 00430 00431 // loop through each bit, starting from PC4 00432 for (int i = 4; i >= 0; i--) { 00433 00434 unsigned int weight = pow(2.0,4-i); 00435 00436 // check if over threshold 00437 if (values[i] > 500) { 00438 // add equivalent binary weight to value 00439 value += weight; 00440 } 00441 00442 } 00443 00444 return value; 00445 } 00446 00447 float m3pi::calc_line_position(unsigned int values[]) 00448 { 00449 // calculate weighted average 00450 unsigned int value = 00451 (0*values[0]+1e3*values[1]+2e3*values[2]+3e3*values[3]+4e3*values[4])/ 00452 (values[0]+values[1]+values[2]+values[3]+values[4]); 00453 00454 // scale to between -1.0 and 1.0 00455 float position = (int(value) - 2000)/2000.0; 00456 00457 float is_on_line = false; 00458 00459 // loop through and check if any sensor reading is above the threshold 00460 for (int i = 0; i<5; i++) { 00461 if (values[i] > 500) { 00462 is_on_line = true; 00463 } 00464 } 00465 00466 // update last line position if over line 00467 if (is_on_line) { 00468 _last_line_position = position; 00469 } 00470 00471 // if not on line then the last line position will have the last value when over line 00472 return _last_line_position; 00473 } 00474 00475 float m3pi::read_line() 00476 { 00477 return calc_line_position(_values); 00478 } 00479 00480 00481 00482 /////////////////////////////// private methods //////////////////////////////// 00483 00484 void m3pi::reset() 00485 { 00486 // pulse the reset line (active-high) 00487 _reset->write(1); 00488 ThisThread::sleep_for(100ms); 00489 _reset->write(0); 00490 ThisThread::sleep_for(100ms); 00491 }
Generated on Mon Aug 1 2022 03:21:09 by
1.7.2