diff --git a/include/bno055_imu_driver.h b/include/bno055_imu_driver.h index f69a302197e3e4ca7b5940e4f15d55b9b73686de..a68d95249b31fd6de6dc18f7e1a300b6275ea9ae 100644 --- a/include/bno055_imu_driver.h +++ b/include/bno055_imu_driver.h @@ -69,6 +69,9 @@ class CBNO055IMUDriver void detect_sensor(void); void get_sensor_units(void); void get_sensor_configs(void); + void send_read_cmd(unsigned char address,unsigned char length); + void send_write_cmd(unsigned char address,unsigned char length,unsigned char *data); + void get_answer(unsigned char length,unsigned char *data); public: CBNO055IMUDriver(const std::string &name); void open(const std::string &serial_dev); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 865a085bb606ed52b35bafda4eb0cedee6861a0a..85e9aa68b824758fdc1fbc3ef67b978a760db112 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,6 @@ # driver source files +add_compile_options(-std=c++11) + SET(sources bno055_imu_driver.cpp bno055_imu_exceptions.cpp) # application header files SET(headers ../include/bno055_imu_driver.h ../include/bno055_imu_exceptions.h ../include/bno055_common.h) diff --git a/src/bno055_imu_driver.cpp b/src/bno055_imu_driver.cpp index 1475131140bcb7d48a87096b894f785a3a223ba8..44117d231e810ef92a81146fac60c5f6ddc32cc8 100644 --- a/src/bno055_imu_driver.cpp +++ b/src/bno055_imu_driver.cpp @@ -212,27 +212,28 @@ void *CBNO055IMUDriver::data_thread(void *param) while(!end) { - if(imu->event_server->event_is_set(imu->finish_thread_event_id)) - end=true; - else + if(imu->op_mode!=config_mode) { - if(imu->op_mode!=config_mode) - { - try{ - imu->imu_access.enter(); - imu->change_register_page(0x00); - imu->read_registers(address,length,data); - imu->imu_access.exit(); - imu->process_data(data); - if(!imu->event_server->event_is_set(imu->new_data_event_id)) - imu->event_server->set_event(imu->new_data_event_id); - }catch(CException &e){ - imu->imu_access.exit(); - std::cout << e.what() << std::endl; - } + try{ + imu->imu_access.enter(); + imu->send_read_cmd(address,length); + imu->imu_access.exit(); + usleep((unsigned long int)(1000000.0/imu->data_rate_hz)-1000); + imu->imu_access.enter(); + imu->get_answer(length,data); + imu->imu_access.exit(); + imu->process_data(data); + if(!imu->event_server->event_is_set(imu->new_data_event_id)) + imu->event_server->set_event(imu->new_data_event_id); + }catch(CException &e){ + imu->imu_access.exit(); + std::cout << e.what() << std::endl; } } - usleep((unsigned long int)(1000000.0/imu->data_rate_hz)); + else + usleep((unsigned long int)(1000000.0/imu->data_rate_hz)); + if(imu->event_server->event_is_set(imu->finish_thread_event_id)) + end=true; } pthread_exit(NULL); @@ -240,50 +241,37 @@ void *CBNO055IMUDriver::data_thread(void *param) void CBNO055IMUDriver::write_registers(unsigned char address, unsigned char length,unsigned char *data) { - unsigned char *cmd,answer[2]; + unsigned char answer[2]; std::list<std::string> events; - unsigned int read_data=0,num,i,retries=0; + unsigned int read_data=0,num; if(this->imu_port==NULL) throw CBNO055IMUException(_HERE_,"Communications device not ready"); - cmd=new unsigned char[length+4]; - cmd[0]=0xAA; - cmd[1]=0x00; - cmd[2]=address; - cmd[3]=length; - for(i=0;i<length;i++) - cmd[4+i]=data[i]; + this->send_write_cmd(address,length,data); events.push_back(this->imu_port->get_rx_event_id()); - do{ - this->imu_port->write(cmd,length+4); - try{ - /* read the header */ - while(read_data<2) - { - if((num=this->imu_port->get_num_data())==0) - { - this->event_server->wait_all(events,500); - num=this->imu_port->get_num_data(); - } - if(num>(2-read_data)) - { - this->imu_port->read(&answer[read_data],2-read_data); - read_data+=(2-read_data); - } - else - { - this->imu_port->read(&answer[read_data],num); - read_data+=num; - } + try{ + /* read the header */ + while(read_data<2) + { + if((num=this->imu_port->get_num_data())==0) + { + this->event_server->wait_all(events,500); + num=this->imu_port->get_num_data(); + } + if(num>(2-read_data)) + { + this->imu_port->read(&answer[read_data],2-read_data); + read_data+=(2-read_data); + } + else + { + this->imu_port->read(&answer[read_data],num); + read_data+=num; } - }catch(CEventTimeoutException &e){ - delete[] cmd; - throw CBNO055IMUException(_HERE_,"Write acknowledge not received in the allowed time"); } - retries++; - read_data=0; - }while(answer[1]!=0x01 && retries<5); - delete[] cmd; + }catch(CEventTimeoutException &e){ + throw CBNO055IMUException(_HERE_,"Write acknowledge not received in the allowed time"); + } switch(answer[1]) { case 0x01: return; @@ -301,46 +289,39 @@ void CBNO055IMUDriver::write_registers(unsigned char address, unsigned char leng void CBNO055IMUDriver::read_registers(unsigned char address, unsigned char length,unsigned char *data) { - unsigned char cmd[4],answer[2]; + unsigned char answer[2]; std::list<std::string> events; - unsigned int read_data=0,num,retries=0; + unsigned int read_data=0,num; if(this->imu_port==NULL) throw CBNO055IMUException(_HERE_,"Communications device not ready"); - cmd[0]=0xAA; - cmd[1]=0x01; - cmd[2]=address; - cmd[3]=length; - events.push_back(this->imu_port->get_rx_event_id()); /* send the command */ - do{ - this->imu_port->write(cmd,4); - try{ - /* read the header */ - while(read_data<2) - { - if((num=this->imu_port->get_num_data())==0) - { - this->event_server->wait_all(events,500); - num=this->imu_port->get_num_data(); - } - if(num>(2-read_data)) - { - this->imu_port->read(&answer[read_data],2-read_data); - read_data+=(2-read_data); - } - else - { - this->imu_port->read(&answer[read_data],num); - read_data+=num; - } + this->send_read_cmd(address,length); + events.push_back(this->imu_port->get_rx_event_id()); + try{ + /* read the header */ + while(read_data<2) + { + if((num=this->imu_port->get_num_data())==0) + { + this->event_server->wait_all(events,500); + num=this->imu_port->get_num_data(); + } + if(num>(2-read_data)) + { + this->imu_port->read(&answer[read_data],2-read_data); + read_data+=(2-read_data); + } + else + { + this->imu_port->read(&answer[read_data],num); + read_data+=num; } - }catch(CEventTimeoutException &e){ - throw CBNO055IMUException(_HERE_,"Expected data not received in the allowed time"); } - retries++; - read_data=0; - }while(answer[0]!=0xBB && retries<5); + }catch(CEventTimeoutException &e){ + throw CBNO055IMUException(_HERE_,"Expected data not received in the allowed time"); + } + read_data=0; if(answer[0]==0xEE)/* there has been an error */ { switch(answer[1]) @@ -382,6 +363,124 @@ void CBNO055IMUDriver::read_registers(unsigned char address, unsigned char lengt } } +void CBNO055IMUDriver::send_read_cmd(unsigned char address,unsigned char length) +{ + unsigned char cmd; + + if(this->imu_port==NULL) + throw CBNO055IMUException(_HERE_,"Communications device not ready"); + cmd=0xAA; + this->imu_port->write(&cmd,1); + usleep(250); + cmd=0x01; + this->imu_port->write(&cmd,1); + usleep(250); + cmd=address; + this->imu_port->write(&cmd,1); + usleep(250); + cmd=length; + this->imu_port->write(&cmd,1); + usleep(250); +} + +void CBNO055IMUDriver::send_write_cmd(unsigned char address,unsigned char length,unsigned char *data) +{ + unsigned char cmd; + + if(this->imu_port==NULL) + throw CBNO055IMUException(_HERE_,"Communications device not ready"); + cmd=0xAA; + this->imu_port->write(&cmd,1); + usleep(250); + cmd=0x00; + this->imu_port->write(&cmd,1); + usleep(250); + cmd=address; + this->imu_port->write(&cmd,1); + usleep(250); + cmd=length; + this->imu_port->write(&cmd,1); + usleep(250); + for(unsigned int i=0;i<length;i++) + { + cmd=data[i]; + this->imu_port->write(&cmd,1); + usleep(250); + } +} + +void CBNO055IMUDriver::get_answer(unsigned char length,unsigned char *data) +{ + unsigned char answer[2]; + std::list<std::string> events; + unsigned int read_data=0,num; + + events.push_back(this->imu_port->get_rx_event_id()); + try{ + /* read the header */ + while(read_data<2) + { + if((num=this->imu_port->get_num_data())==0) + { + this->event_server->wait_all(events,500); + num=this->imu_port->get_num_data(); + } + if(num>(2-read_data)) + { + this->imu_port->read(&answer[read_data],2-read_data); + read_data+=(2-read_data); + } + else + { + this->imu_port->read(&answer[read_data],num); + read_data+=num; + } + } + }catch(CEventTimeoutException &e){ + throw CBNO055IMUException(_HERE_,"Expected data not received in the allowed time"); + } + read_data=0; + if(answer[0]==0xEE)/* there has been an error */ + { + switch(answer[1]) + { + case 0x02: throw CBNO055IMUException(_HERE_,"Impossible to execute the read operation"); + case 0x04: throw CBNO055IMUException(_HERE_,"Invalid address"); + case 0x05: throw CBNO055IMUException(_HERE_,"Write operation disabled"); + case 0x06: throw CBNO055IMUException(_HERE_,"Invalid start byte"); + case 0x07: throw CBNO055IMUException(_HERE_,"Serial overrun"); + case 0x08: throw CBNO055IMUException(_HERE_,"Maximum length exceeded"); + case 0x09: throw CBNO055IMUException(_HERE_,"Invalid command"); + case 0x0A: throw CBNO055IMUException(_HERE_,"Data timeout"); + } + } + try{ + /* read the received data */ + while(read_data<(int)answer[1]) + { + if((num=this->imu_port->get_num_data())==0) + { + this->event_server->wait_all(events,500); + num=this->imu_port->get_num_data(); + } + if(num>(length-read_data)) + { + this->imu_port->read(&data[read_data],length-read_data); + read_data+=(length-read_data); + } + else + { + this->imu_port->read(&data[read_data],num); + read_data+=num; + } + } + if(answer[1]!=length) + throw CBNO055IMUException(_HERE_,"Not all data has been received"); + }catch(CEventTimeoutException &e){ + throw CBNO055IMUException(_HERE_,"Expected data not received in the allowed time"); + } +} + void CBNO055IMUDriver::detect_sensor(void) { try{ @@ -681,7 +780,7 @@ void CBNO055IMUDriver::get_remap_axis(std::vector<char> &new_x,std::vector<char> void CBNO055IMUDriver::set_data_rate(double rate_hz) { - if(rate_hz>0.0 && rate_hz<=100.0) + if(rate_hz>0.0 && rate_hz<=1000.0) this->data_rate_hz=rate_hz; else throw CBNO055IMUException(_HERE_,"Invalid data rate"); diff --git a/src/examples/bno055_imu_driver_test.cpp b/src/examples/bno055_imu_driver_test.cpp index 55498fcd4009fffb7b9e394d201c9f0e561e43f2..bcfaf2315ff86e6965a2ce40777a64bdde4eaa11 100644 --- a/src/examples/bno055_imu_driver_test.cpp +++ b/src/examples/bno055_imu_driver_test.cpp @@ -2,6 +2,7 @@ #include "bno055_imu_exceptions.h" #include <unistd.h> #include <iostream> +#include <chrono> int main(int argc, char *argv[]) { @@ -13,25 +14,40 @@ int main(int argc, char *argv[]) std::vector<double> accel,mag,gyro; std::vector<double> quat,euler,linear_acc,gravity; unsigned int i; + unsigned char range,bandwidth,mode,rate,op_mode,power_mode; - imu.open("/tmp/darwin1_imu_uart"); + imu.open("/dev/ttyUSB2"); try{ imu.load_calibration("bno055.cal"); }catch(CException &e){ std::cout << e.what() << std::endl; } - imu.set_operation_mode(acc_mag_gyro_mode); - accel_cal=imu.is_accelerometer_calibrated(); - std::cout << "Accelerometer calibrated: " << accel_cal << std::endl; - mag_cal=imu.is_magnetometer_calibrated(); - std::cout << "Magnetometer calibrated: " << mag_cal << std::endl; - gyro_cal=imu.is_gyroscope_calibrated(); - std::cout << "Gyroscope calibrated: " << gyro_cal << std::endl; +// do{ +// accel_cal=imu.is_accelerometer_calibrated(); +// std::cout << "Accelerometer calibrated: " << accel_cal << std::endl; +// mag_cal=imu.is_magnetometer_calibrated(); +// std::cout << "Magnetometer calibrated: " << mag_cal << std::endl; +// gyro_cal=imu.is_gyroscope_calibrated(); +// std::cout << "Gyroscope calibrated: " << gyro_cal << std::endl; +// }while(!accel_cal || ! mag_cal || !gyro_cal); events.push_back(imu.get_new_data_event_id()); + imu.get_accel_config(&range,&bandwidth,&mode); + bandwidth=ACCEL_125_BW; + imu.set_accel_config(range,bandwidth,mode); + imu.get_mag_config(&rate,&op_mode,&power_mode); + rate=MAG_30_RATE; + imu.set_mag_config(rate,op_mode,power_mode); + imu.get_gyro_config(&range,&bandwidth,&mode); + bandwidth=GYRO_116_BW; + imu.set_gyro_config(range,bandwidth,mode); + imu.set_operation_mode(acc_mag_gyro_mode); + imu.set_data_rate(100); for(i=0;i<1000;i++) { + auto t1 = std::chrono::high_resolution_clock::now(); event_server->wait_all(events,1000); +/* quat=imu.get_orientation_quat(); std::cout << "Quaternion: X: " << quat[0] << ", Y: " << quat[1] << ", Z: " << quat[2] << ", W: " << quat[3] << std::endl; euler=imu.get_orientation_euler(); @@ -46,6 +62,11 @@ int main(int argc, char *argv[]) std::cout << "Magnetometer: X: " << mag[0] << ", Y: " << mag[1] << ", Z: " << mag[2] << std::endl; gyro=imu.get_raw_gyroscope(); std::cout << "Gyroscope: X: " << gyro[0] << ", Y: " << gyro[1] << ", Z: " << gyro[2] << std::endl; +*/ + auto t2 = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast<std::chrono::microseconds>( t2 - t1 ).count(); + std::cout << duration << std::endl; + std::cout << std::flush; } }catch(CException &e){