int main(){ if(initialize_cape()<0){ printf("Failed to initialize cape, exiting\n"); return -1; } printf("\n"); printf("This will sample the magnetometer for the next few seconds\n"); printf("Rotate the cape around in the air through as many orientations\n"); printf("as possible to collect sufficient data for calibration\n"); printf("Press ENTER to continue or anything else to quit\n"); if(continue_or_quit()<0){ cleanup_cape(); return -1; } if(calibrate_mag_routine()<0){ printf("Failed to complete magnetometer calibration\n"); cleanup_cape(); return -1; } printf("\nmagnetometer calibration file written\n"); printf("run test_imu to check performance\n"); cleanup_cape(); return 0; }
int main(){ initialize_cape(); printf("\nPress mode to change blink rate\n"); printf("hold pause to exit\n"); //Assign your own functions to be called when events occur set_pause_pressed_func(&on_pause_press); set_pause_unpressed_func(&on_pause_release); set_mode_pressed_func(&on_mode_press); set_mode_unpressed_func(&on_mode_release); // start in slow mode mode = 0; //toggle leds till the program state changes while(get_state() != EXITING){ usleep(500000 - (mode*200000)); if(!paused && toggle){ setGRN(LOW); setRED(HIGH); toggle = 0; } else if(!paused && !toggle){ setGRN(HIGH); setRED(LOW); toggle=1; } } cleanup_cape(); return 0; }
/*********************************************************************** * main() * start all the threads, and wait still something * triggers a shut down ***********************************************************************/ int main(){ // initialize cape hardware if(initialize_cape()<0){ blink_red(); return -1; } setRED(HIGH); setGRN(LOW); set_state(UNINITIALIZED); // set up button handlers first // so user can exit by holding pause set_pause_pressed_func(&on_pause_press); set_mode_unpressed_func(&on_mode_release); // load data from disk. if(load_config(&config)==-1){ printf("aborting, config file error\n"); return -1; } // start a thread to slowly sample battery pthread_t battery_thread; pthread_create(&battery_thread, NULL, battery_checker, (void*) NULL); // start printf_thread if running from a terminal // if it was started as a background process then don't bother if(isatty(fileno(stdout))){ pthread_t printf_thread; pthread_create(&printf_thread, NULL, printf_loop, (void*) NULL); } // start listening for RC control from dsm2 radio if(config.enable_dsm2){ if(initialize_dsm2()<0){ printf("failed to start DSM2\n"); } else{ pthread_t dsm2_thread; pthread_create(&dsm2_thread, NULL, dsm2_watcher, (void*) NULL); } } // this thread is in charge of arming and managing the core pthread_t drive_stack_thread; pthread_create(&drive_stack_thread, NULL, drive_stack, (void*) NULL); // all threads have started, off we go set_state(RUNNING); setRED(LOW); setGRN(HIGH); // chill until something exits the program while(get_state()!=EXITING){ usleep(100000); } cleanup_cape(); // always end with cleanup to shut down cleanly return 0; }
int main(int argc, char *argv[]){ initialize_cape(); int i; int ch = 0; int all = 0; // micros is in the middle of range int micros = (SERVO_MIN_US+SERVO_MAX_US)/2; // check if user gave command line argument for which servo to use if (argc==1){ // if not, drive all servos all = 1; } // set the single channel to use else{ ch = atoi(argv[1]); all = 0; if(ch>SERVO_CHANNELS || ch<1){ printf("choose a channel between 1 and %d\n", SERVO_CHANNELS); return -1; } } printf("\n"); printf("sending center pulses, width: %d microseconds\n", micros); printf("press ctrl-c to exit\n"); while(get_state()!=EXITING){ // if user gave no arguments, send single pulse to each servo if(all){ for(i=0; i<SERVO_CHANNELS; i++){ send_servo_pulse_us(i+1,micros); } } // or send to just the one requested servo else{ send_servo_pulse_us(ch,micros); } // Send pulses at roughly 50hz usleep(20000); } cleanup_cape(); return 0; }
int main(){ initialize_cape(); setGRN(HIGH); setRED(HIGH); printf("\n\nRaw data for encoders 1,2,3\n"); while(get_state() != EXITING){ printf("\r%3li %3li %3li ", get_encoder_pos(1),get_encoder_pos(2),get_encoder_pos(3)); fflush(stdout); usleep(50000); } cleanup_cape(); return 0; }
/************************************************************************ * int main() * initializes hardware and configuration struct. * starts the IMU interrupt routine * starts the orientation detection thread * prints out orientation to the screen ************************************************************************/ int main(){ initialize_cape(); // initialize the global conf struct with some values conf.sample_rate = 50; // Hz conf.det_time = 0.3; // seconds conf.det_poss_time = 0.1; // seconds conf.det_tolerance = 30; // degrees // initialize the IMU in flat orientation so that // flat is with the cape facing up signed char imu_orientation[9] = ORIENTATION_FLAT; initialize_imu(conf.sample_rate, imu_orientation); //start the interrupt handler set_imu_interrupt_func(&read_imu_data); // start the orientation detection thread in the background pthread_t orientation_thread; pthread_create(&orientation_thread, NULL, orientation_detector, (void*) NULL); // print a header printf("Move your BBB around and observe the changing orientation\n"); printf("\n\ncounter possible certain \n"); //now just wait, print_imu_data will run while (get_state() != EXITING) { printf("\r"); printf(" %3d ", cstate.counter); print_orientation(cstate.poss_orientation); printf(" "); print_orientation(cstate.orientation); printf(" "); // its important we flush the output to make sure // the next printf's print onto a clean line fflush(stdout); // sleep for 10ms usleep(10000); } cleanup_cape(); return 0; }
int main(){ initialize_cape(); if(initialize_dsm2()){ // if init returns -1 if there was a problem // most likely no calibration file found printf("run calibrate_dsm2 first\n"); return -1; } printf("framerate "); printf(" 1:Thr "); printf("2:Roll "); printf("3:Pitch "); printf("4:Yaw "); printf("5:Kill "); printf("6:Mode "); printf("7:Aux1 "); printf("8:Aux2 "); printf("9:Aux3"); printf("\n"); int i; while(get_state()!=EXITING){ if(is_new_dsm2_data()){ printf("\r");// keep printing on same line // print framerate printf(" %dms ", get_dsm2_frame_rate()); //print all channels for(i=0;i<RC_CHANNELS;i++){ printf("% 0.2f ", get_dsm2_ch_normalized(i+1)); } fflush(stdout); } else{ printf("\rNo New Radio Packets "); } fflush(stdout); usleep(25000); } cleanup_cape(); return 0; }
int main(){ initialize_cape(); set_esc(1,0); //this also sets the pwm period for servo/esc use printf("\nDISCONNECT PROPELLERS FROM MOTORS\n"); printf("DISCONNECT POWER FROM ESCS\n"); printf("press start to continue\n"); while(get_start_button() == LOW){ usleep(10000); } setGRN(HIGH); //set everything to full throttle to define upper bound for(i=1; i<=6; i++){ set_esc(i,1); } sleep(1); printf("\n"); printf("Now reapply power to the ESCs.\n"); printf("Press the start button after the ESCs chirp\n"); while(get_start_button() == LOW){ usleep(10000); } setGRN(LOW); //set everything to 0 throttle to define lower bound for(i=1; i<=6; i++){ set_esc(i,0); } sleep(2); printf("\nCalibration complete, closing.\n"); cleanup_cape(); return 0; }
int main(){ imu_data_t data; //struct to hold new data if(initialize_cape()){ printf("ERROR: failed to initialize_cape\n"); return -1; } // use defaults for now, except also enable magnetometer. imu_config_t conf = get_default_imu_config(); conf.enable_magnetometer=1; if(initialize_imu(&data, conf)){ printf("initialize_imu_failed\n"); return -1; } // print a header printf("\n"); printf(" Accel XYZ(m/s^2) |"); printf(" Gyro XYZ (deg/s) |"); printf(" Mag Field XYZ(uT) |"); printf(" Temp (C)"); printf("\n"); //now just wait, print_data will run while (get_state() != EXITING) { printf("\r"); if(read_accel_data(&data)<0) printf("read accel data failed\n"); else printf("%6.2f %6.2f %6.2f |", data.accel[0],\ data.accel[1],\ data.accel[2]); if(read_gyro_data(&data)<0) printf("read gyro data failed\n"); else printf("%6.1f %6.1f %6.1f |", data.gyro[0],\ data.gyro[1],\ data.gyro[2]); if(read_mag_data(&data)<0){ printf("read mag data failed\n"); } else printf("%6.1f %6.1f %6.1f |", data.mag[0],\ data.mag[1],\ data.mag[2]); if(read_imu_temp(&data)<0){ printf("read temp data failed\n"); } else printf(" %4.1f ", data.temp); fflush(stdout); usleep(100000); } power_off_imu(); cleanup_cape(); return 0; }
/*********************************************************************** * main() * initialize the IMU, start all the threads, and wait still something * triggers a shut down ***********************************************************************/ int main(int argc, char* argv[]){ // initialize cape hardware if(initialize_cape()<0){ blink_red(); return -1; } setRED(HIGH); setGRN(LOW); set_state(UNINITIALIZED); // set up button handlers first // so user can exit by holding pause set_pause_pressed_func(&on_pause_press); set_mode_unpressed_func(&on_mode_release); // load data from disk. if(load_config(&config)==-1){ printf("aborting, config file error\n"); return -1; } // start a thread to slowly sample battery pthread_t battery_thread; pthread_create(&battery_thread, NULL, battery_checker, (void*) NULL); // start listening for RC control from dsm2 radio if(config.enable_dsm2){ if(initialize_dsm2()<0){ printf("failed to start DSM2\n"); } else{ pthread_t dsm2_thread; pthread_create(&dsm2_thread, NULL, dsm2_watcher, (void*) NULL); } } // // start logging thread if enabled // if(config.enable_logging){ // if(start_log(SAMPLE_RATE_HZ, &cstate.time_us)<0){ // printf("failed to start log\n"); // } // else{ // // start new thread to write the file occationally // pthread_t logging_thread; // pthread_create(&logging_thread, NULL, log_writer, (void*) NULL); // } // } // // first check for user options // if(parse_arguments(argc, argv)<0){ // return -1; // } // // start logging thread if enabled // if(config.enable_logging){ // if(start_log(SAMPLE_RATE_HZ, &cstate.time_us)<0){ // printf("failed to start log\n"); // } // else{ // // start new thread to write the file occationally // pthread_t logging_thread; // pthread_create(&logging_thread, NULL, log_writer, (void*) NULL); // } // } // // Start Safety checking thread // pthread_create(&safety_thread, NULL, safety_thread_func, (void*) NULL); // Finally start the real-time interrupt driven control thread // start IMU with equilibrium set with upright orientation // for MiP with Ethernet pointing relatively up signed char orientation[9] = ORIENTATION_FLAT; if(initialize_imu(SAMPLE_RATE_HZ, orientation)){ // can't talk to IMU, all hope is lost // blink red until the user exits printf("IMU initialization failed, please reboot\n"); blink_red(); cleanup_cape(); return -1; } // assigning the interrupt function and stack // should be the last step in initialization // to make sure other setup functions don't interfere printf("starting core IMU interrupt\n"); cstate.core_start_time_us = microsSinceEpoch(); set_imu_interrupt_func(&flight_core); // start flight stack to control setpoints // this thread is in charge of arming and managing the core pthread_t flight_stack_thread; pthread_create(&flight_stack_thread, NULL, flight_stack, (void*) NULL); printf("\nReady for arming sequence\n"); set_state(RUNNING); // start printf_thread if running from a terminal // if it was started as a background process then don't bother if(isatty(fileno(stdout))){ pthread_t printf_thread; pthread_create(&printf_thread, NULL, printf_loop, (void*) NULL); } //chill until something exits the program while(get_state()!=EXITING){ usleep(100000); } // cleanup before closing //close(sock); // mavlink UDP socket cleanup_cape(); // de-initialize cape hardware return 0; }
// main() has a brief setup and starts one background thread. // then it enters one big while loop for testing multiple capes. int main(){ int ret; float volt; imu_data_t data; // not really used, just necessary to test imu // use defaults for now, except also enable magnetometer. imu_config_t conf = get_default_imu_config(); conf.enable_magnetometer=1; // counters for how many pass and fail num_passes = 0; num_fails = 0; // initialize_cape, this should never fail unless software is not set up // in which case a useful error message should be printed out. if(initialize_cape()<0){ printf("initialize_cape() failed, this is a software issue,\n"); printf("not a hardware issue. Try running install.sh and restart\n"); return -1; } // set up the button handlers once set_pause_pressed_func(&on_pause_pressed); set_pause_released_func(&on_pause_released); set_mode_pressed_func(&on_mode_pressed); set_mode_released_func(&on_mode_released); // start blinking thread for 6V test pthread_create(&blinking_thread, NULL, blinking_function, (void*) NULL); // print welcome clear_screen(); goto_line(0); printf("Welcome to the Robotics Cape tester!\n\n"); printf("this will walk you through testing multiple capes and keep\n"); printf("track of how many pass and fail.\n"); printf("Closing the program erases the pass/fail count.\n\n"); printf("Press enter to begin, anything else to quit.\n"); if(continue_or_quit()<1){ goto END; } /*************************************************************************** * Begin main while loop ***************************************************************************/ while(get_state()!=EXITING){ line = 0; // reset current printing line to top of terminal set_led(RED,OFF); set_led(GREEN,OFF); // clear screen and print pass/fail header clear_screen(); goto_line(line); printf("passes: %d fails: %d\n", num_passes, num_fails); line+=2; goto_line(INSTRUCTION_LINE-1); printf("*******************************************************************\n"); printf("Place a new cape in the test jig but don't connect anything else.\n"); printf("Press any key to start test.\n"); // wait to start test if(continue_or_quit()<0){ goto END; } /*********************************************************************** * begin list of tests ***********************************************************************/ // make sure 12V DC supply is disconnected CHECK_DC_DISCONNECT: volt = get_dc_jack_voltage(); if(volt>2.0){ clear_instruction_area(); printf("Voltage detected on the DC jack input. This is supposed to be\n"); printf("disconnected for this part of the test.\n"); printf("Disconnect and hit ENTER to continue\n"); printf("If the DC supply was disconnected, there may be a problem with resistors\n"); printf("R1 or R14, press any key other than ENTER to FAIL this test.\n"); ret = continue_or_quit(); if(ret==1) goto CHECK_DC_DISCONNECT; else if(ret<0) goto END; else{ goto_line(line); printf("FAILED DC JACK VOLTAGE TEST\n"); line++; fail_test(); continue; } } // test imu ret = initialize_imu(&data, conf); power_off_imu(); goto_line(line); line++; if(ret<0){ printf("FAILED MPU9250 IMU\n"); fail_test(); continue; // go to beginning to test next cape } printf("PASSED MPU9250 IMU\n"); // test barometer ret = initialize_barometer(BMP_OVERSAMPLE_16,BMP_FILTER_OFF); power_off_barometer(); goto_line(line); line++; if(ret<0){ printf("FAILED BMP280 BAROMETER\n"); fail_test(); continue; // go to beginning to test next cape } printf("PASSED BMP280 BAROMETER\n"); // test buttons/LEDS clear_instruction_area(); printf("Press the PAUSE button on cape, the RED led should light up.\n"); printf("Press the MODE button on cape, the GREEN led should light up.\n"); printf("Press ENTER to indicate the buttons/leds work\n"); printf("Press any other key to indicate a failure\n"); ret = continue_or_quit(); goto_line(line); line++; if(ret==0){ printf("FAILED BUTTON/LED\n"); fail_test(); continue; } else if(ret<0) goto END; printf("PASSED BUTTON/LED\n"); // DC power jack ADC check clear_instruction_area(); printf("Plug in the 12V power supply, GREEN CHG LED should turn on.\n"); printf("Press ENTER if the GREEN CHG LED turns on\n"); printf("Press any other key if not\n"); ret = continue_or_quit(); if(ret<0) goto END; goto_line(line); line++; if(ret==0){ printf("FAILED CHARGER\n"); printf("CHG_IC may be bad.\n"); fail_test(); continue; } printf("PASSED CHARGER\n"); volt = get_dc_jack_voltage(); if(volt<11.0 || volt>13.0){ printf("FAILED 12V DC VOLTAGE\n"); printf("measuring %0.2fV at DC jack, should be roughly 12V\n", volt); printf("Resistors R1 or R14 may be bad, shorted, or missing.\n"); fail_test(); continue; } line++; printf("PASSED 12V DC VOLTAGE\n"); // 5V regulator test clear_instruction_area(); printf("Plug in the 4-pin dongle to PWR socket\n"); printf("Press ENTER if the dongle LED lights up, any other key if not.\n"); ret = continue_or_quit(); goto_line(line); line++; if(ret==0){ printf("FAILED 5V REGULATOR\n"); printf("Diode D3 or IC 5VREG may be bad\n"); fail_test(); continue; } else if(ret<0) goto END; printf("PASSED 5V REGULATOR\n"); // battery ADC check clear_instruction_area(); printf("Plug in 2-cell battery and press any key to continue\n"); ret = continue_or_quit(); if(ret<0) goto END; volt = get_battery_voltage(); goto_line(line); line++; if(volt<5.0 || volt>9.0){ printf("FAILED BATTERY VOLTAGE\n"); printf("measuring %0.2fV at battery, should be between 6 and 8.4\n", volt); printf("Resistors R19 or R25 may be bad, shorted, or missing.\n"); fail_test(); continue; } printf("PASSED BATTERY VOLTAGE\n"); // battery discharge check clear_instruction_area(); printf("Disconnect the 12V DC power supply.\n"); printf("If 4-pin dongle LED is still lit, press ENTER\n"); printf("Otherwise press any other key.\n"); ret = continue_or_quit(); if(ret<0) goto END; goto_line(line); line++; if(ret==0){ printf("FAILED BATTERY DISCHARGE\n"); printf("Diode D2, or mosfet Q3 are bad.\n"); fail_test(); continue; } printf("PASSED BATTERY DISCHARGE\n"); // 6V regulator check clear_instruction_area(); printf("Plug in the 3-pin dongle into any of the 8 servo channels.\n"); printf("If the dongle LED is blinking press ENTER.\n"); printf("Otherwise press any other key.\n"); ret = continue_or_quit(); if(ret<0) goto END; goto_line(line); line++; if(ret==0){ printf("FAILED 6VREG\n"); printf("AOZ1284PI 6VREG or supporting components are bad.\n"); fail_test(); continue; } printf("PASSED 6VREG CHECK\n"); // END OF TESTING THIS CAPE, PASSED!!! num_passes++; printf("COMPLETE TEST PASSED\n"); goto_line(0); printf("passes: %d fails: %d\n", num_passes, num_fails); clear_instruction_area(); printf("Press any key to continue with next cape\n"); continue_or_quit(); if(ret<0) goto END; // now loop back to test next cape } // end while(get_state()!= EXITING) // if we got here there was a critical error or user hit ctrl+c END: pthread_join(blinking_thread, NULL); disable_servo_power_rail(); cleanup_cape(); clear_screen(); return 0; }
/****************************************************************** * main() * initialize the IMU, start all the threads, and wait still * something triggers a shut down *******************************************************************/ int main(){ initialize_cape(); set_led(RED,HIGH); set_led(GREEN,LOW); set_state(UNINITIALIZED); // set up button handlers first // so user can exit by holding pause set_pause_pressed_func(&on_pause_press); set_mode_unpressed_func(&on_mode_release); // load data from disk. if(load_config(&config)==-1){ printf("aborting, config file error\n"); return -1; } // start a thread to slowly sample battery pthread_t battery_thread; pthread_create(&battery_thread, NULL, battery_checker, (void*) NULL); // start printf_thread if running from a terminal // if it was started as a background process then don't bother if(isatty(fileno(stdout))){ pthread_t printf_thread; pthread_create(&printf_thread, NULL, printf_loop, (void*) NULL); } // start listening for RC control from dsm2 radio if(config.enable_dsm2){ initialize_dsm2(); pthread_t dsm2_thread; pthread_create(&dsm2_thread, NULL, dsm2_listener, (void*) NULL); } // start mavlink if enabled if(config.enable_mavlink_listening || config.enable_mavlink_listening){ char target_ip[16]; strcpy(target_ip, DEFAULT_MAV_ADDRESS); // open a udp port for mavlink // sock and gcAddr are global variables needed to send and receive gcAddr = initialize_mavlink_udp(target_ip, udp_sock); if(udp_sock != NULL){ printf("WARNING: continuing without mavlink enabled\n"); } else { if(config.enable_mavlink_listening){ // start a thread listening for incoming packets pthread_t mav_listen_thread; pthread_create(&mav_listen_thread, NULL, mavlink_listener, (void*) NULL); printf("Listening for Packets\n"); } if(config.enable_mavlink_transmitting){ // Start thread sending heartbeat and IMU attitude packets pthread_t mav_send_thread; pthread_create(&mav_send_thread, NULL, mavlink_sender, (void*) NULL); printf("Transmitting Heartbeat Packets\n"); } } } // start logging thread if enabled if(config.enable_logging){ if(start_log(SAMPLE_RATE_HZ, &cstate.time_us)<0){ printf("failed to start log\n"); } else{ // start new thread to write the file occationally pthread_t logging_thread; pthread_create(&logging_thread, NULL, log_writer, (void*) NULL); } } // Finally start the real-time interrupt driven control thread // start IMU with equilibrium set with upright orientation // for MiP with Ethernet pointing relatively up signed char orientation[9] = ORIENTATION_UPRIGHT; if(initialize_imu(SAMPLE_RATE_HZ, orientation)){ // can't talk to IMU, all hope is lost // blink red until the user exits blink_red(); return -1; } // this should be the last step in initialization // to make sure other setup functions don't interfere printf("starting core IMU interrupt\n"); core_start_time_us = microsSinceEpoch(); set_imu_interrupt_func(&balance_core); // start balance stack to control setpoints pthread_t balance_stack_thread; pthread_create(&balance_stack_thread, NULL, balance_stack, (void*) NULL); printf("\nHold your MIP upright to begin balancing\n"); set_state(RUNNING); // chill until something exits the program while(get_state()!=EXITING){ usleep(100000); } // close(*udp_sock); // close network socket cleanup_cape(); // always end with cleanup to shut down cleanly return 0; }
/******************************************************************************* * int main(int argc, char *argv[]) * * main() serves to parse user options, initialize the imu and interrupt handler, * and wait for the get_state()==EXITING condition before exiting cleanly. * The imu_interrupt function print_data() is what actually prints new imu data * to the screen after being set with set_imu_interrupt_func(). *******************************************************************************/ int main(int argc, char *argv[]){ int c, sample_rate, priority; int show_something = 0; // set to 1 when any show data option is given. // start with default config and modify based on options imu_config_t conf = get_default_imu_config(); // parse arguments opterr = 0; while ((c=getopt(argc, argv, "s:magrqtcp:hwo"))!=-1 && argc>1){ switch (c){ case 's': // sample rate option sample_rate = atoi(optarg); if(sample_rate>200 || sample_rate<4){ printf("sample_rate must be between 4 & 200"); return -1; } conf.dmp_sample_rate = sample_rate; break; case 'p': // priority option priority = atoi(optarg); const int max_pri = sched_get_priority_max(SCHED_FIFO); if(priority>max_pri || priority<0){ printf("priority must be between 0 & %d\n",max_pri); return -1; } conf.dmp_interrupt_priority = priority; break; case 'm': // magnetometer option show_something = 1; enable_mag = 1; conf.enable_magnetometer = 1; break; case 'c': // compass option show_something = 1; enable_mag = 1; show_compass = 1; conf.enable_magnetometer = 1; break; case 'a': // show accelerometer option show_something = 1; show_accel = 1; break; case 'g': // show gyro option show_something = 1; show_gyro = 1; break; case 'q': // show quaternion option show_something = 1; show_quat = 1; break; case 't': // show TaitBryan angle option show_something = 1; show_tb = 1; break; case 'T': // read thermometer option show_something = 1; show_temp = 1; break; case 'w': // print warnings conf.show_warnings=1; break; case 'o': // let user select imu orientation orientation_menu=1; break; case 'h': // show help option print_usage(); return -1; break; default: printf("opt: %c\n",c); printf("invalid argument\n"); print_usage(); return -1; break; } } // user didn't give an option to show anything. Print warning and return. if(show_something==0){ print_usage(); printf("please enable an option to print some data\n"); return -1; } // If the user gave the -o option to select an orientation then prompt them if(orientation_menu){ conf.orientation=orientation_prompt(); } // start by initializing cape as always if(initialize_cape()){ printf("ERROR: failed to initialize_cape\n"); return -1; } // now set up the imu for dmp interrupt operation if(initialize_imu_dmp(&data, conf)){ printf("initialize_imu_failed\n"); return -1; } // write labels for what data will be printed and associate the interrupt // function to print data immediately after the header. print_header(); set_imu_interrupt_func(&print_data); //now just wait, print_data() will be called by the interrupt while (get_state()!=EXITING) { usleep(10000); } // shut things down power_off_imu(); cleanup_cape(); return 0; }