int ardrone_interface_thread_main(int argc, char *argv[]) { thread_running = true; char *device = "/dev/ttyS1"; /* welcome user */ printf("[ardrone_interface] Control started, taking over motors\n"); /* File descriptors */ int gpios; char *commandline_usage = "\tusage: ardrone_interface start|status|stop [-t for motor test (10%% thrust)]\n"; bool motor_test_mode = false; int test_motor = -1; /* read commandline arguments */ for (int i = 0; i < argc && argv[i]; i++) { if (strcmp(argv[i], "-t") == 0 || strcmp(argv[i], "--test") == 0) { motor_test_mode = true; } if (strcmp(argv[i], "-m") == 0 || strcmp(argv[i], "--motor") == 0) { if (i+1 < argc) { int motor = atoi(argv[i+1]); if (motor > 0 && motor < 5) { test_motor = motor; } else { thread_running = false; errx(1, "supply a motor # between 1 and 4. Example: -m 1\n %s", commandline_usage); } } else { thread_running = false; errx(1, "missing parameter to -m 1..4\n %s", commandline_usage); } } if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--device") == 0) { //device set if (argc > i + 1) { device = argv[i + 1]; } else { thread_running = false; errx(1, "missing parameter to -m 1..4\n %s", commandline_usage); } } } struct termios uart_config_original; if (motor_test_mode) { printf("[ardrone_interface] Motor test mode enabled, setting 10 %% thrust.\n"); } /* Led animation */ int counter = 0; int led_counter = 0; /* declare and safely initialize all structs */ struct vehicle_status_s state; memset(&state, 0, sizeof(state)); struct actuator_controls_s actuator_controls; memset(&actuator_controls, 0, sizeof(actuator_controls)); struct actuator_armed_s armed; armed.armed = false; /* subscribe to attitude, motor setpoints and system state */ int actuator_controls_sub = orb_subscribe(ORB_ID_VEHICLE_ATTITUDE_CONTROLS); int state_sub = orb_subscribe(ORB_ID(vehicle_status)); int armed_sub = orb_subscribe(ORB_ID(actuator_armed)); printf("[ardrone_interface] Motors initialized - ready.\n"); fflush(stdout); /* enable UART, writes potentially an empty buffer, but multiplexing is disabled */ ardrone_write = ardrone_open_uart(device, &uart_config_original); /* initialize multiplexing, deactivate all outputs - must happen after UART open to claim GPIOs on PX4FMU */ gpios = ar_multiplexing_init(); if (ardrone_write < 0) { fprintf(stderr, "[ardrone_interface] Failed opening AR.Drone UART, exiting.\n"); thread_running = false; exit(ERROR); } /* initialize motors */ if (OK != ar_init_motors(ardrone_write, gpios)) { close(ardrone_write); fprintf(stderr, "[ardrone_interface] Failed initializing AR.Drone motors, exiting.\n"); thread_running = false; exit(ERROR); } ardrone_write_motor_commands(ardrone_write, 0, 0, 0, 0); // XXX Re-done initialization to make sure it is accepted by the motors // XXX should be removed after more testing, but no harm /* close uarts */ close(ardrone_write); /* enable UART, writes potentially an empty buffer, but multiplexing is disabled */ ardrone_write = ardrone_open_uart(device, &uart_config_original); /* initialize multiplexing, deactivate all outputs - must happen after UART open to claim GPIOs on PX4FMU */ gpios = ar_multiplexing_init(); if (ardrone_write < 0) { fprintf(stderr, "[ardrone_interface] Failed opening AR.Drone UART, exiting.\n"); thread_running = false; exit(ERROR); } /* initialize motors */ if (OK != ar_init_motors(ardrone_write, gpios)) { close(ardrone_write); fprintf(stderr, "[ardrone_interface] Failed initializing AR.Drone motors, exiting.\n"); thread_running = false; exit(ERROR); } while (!thread_should_exit) { if (motor_test_mode) { /* set motors to idle speed */ if (test_motor > 0 && test_motor < 5) { int motors[4] = {0, 0, 0, 0}; motors[test_motor - 1] = 10; ardrone_write_motor_commands(ardrone_write, motors[0], motors[1], motors[2], motors[3]); } else { ardrone_write_motor_commands(ardrone_write, 10, 10, 10, 10); } } else { /* MAIN OPERATION MODE */ /* get a local copy of the vehicle state */ orb_copy(ORB_ID(vehicle_status), state_sub, &state); /* get a local copy of the actuator controls */ orb_copy(ORB_ID_VEHICLE_ATTITUDE_CONTROLS, actuator_controls_sub, &actuator_controls); orb_copy(ORB_ID(actuator_armed), armed_sub, &armed); /* for now only spin if armed and immediately shut down * if in failsafe */ if (armed.armed && !armed.lockdown) { ardrone_mixing_and_output(ardrone_write, &actuator_controls); } else { /* Silently lock down motor speeds to zero */ ardrone_write_motor_commands(ardrone_write, 0, 0, 0, 0); } } if (counter % 24 == 0) { if (led_counter == 0) ar_set_leds(ardrone_write, 0, 1, 0, 0, 0, 0, 0 , 0); if (led_counter == 1) ar_set_leds(ardrone_write, 1, 1, 0, 0, 0, 0, 0 , 0); if (led_counter == 2) ar_set_leds(ardrone_write, 1, 0, 0, 0, 0, 0, 0 , 0); if (led_counter == 3) ar_set_leds(ardrone_write, 0, 0, 0, 1, 0, 0, 0 , 0); if (led_counter == 4) ar_set_leds(ardrone_write, 0, 0, 1, 1, 0, 0, 0 , 0); if (led_counter == 5) ar_set_leds(ardrone_write, 0, 0, 1, 0, 0, 0, 0 , 0); if (led_counter == 6) ar_set_leds(ardrone_write, 0, 0, 0, 0, 0, 1, 0 , 0); if (led_counter == 7) ar_set_leds(ardrone_write, 0, 0, 0, 0, 1, 1, 0 , 0); if (led_counter == 8) ar_set_leds(ardrone_write, 0, 0, 0, 0, 1, 0, 0 , 0); if (led_counter == 9) ar_set_leds(ardrone_write, 0, 0, 0, 0, 0, 0, 0 , 1); if (led_counter == 10) ar_set_leds(ardrone_write, 0, 0, 0, 0, 0, 0, 1 , 1); if (led_counter == 11) ar_set_leds(ardrone_write, 0, 0, 0, 0, 0, 0, 1 , 0); led_counter++; if (led_counter == 12) led_counter = 0; } /* run at approximately 200 Hz */ usleep(4500); counter++; } /* restore old UART config */ int termios_state; if ((termios_state = tcsetattr(ardrone_write, TCSANOW, &uart_config_original)) < 0) { fprintf(stderr, "[ardrone_interface] ERROR setting baudrate / termios config for (tcsetattr)\n"); } printf("[ardrone_interface] Restored original UART config, exiting..\n"); /* close uarts */ close(ardrone_write); ar_multiplexing_deinit(gpios); fflush(stdout); thread_running = false; return OK; }
void ar_init_motors(int ardrone_uart, int *gpios_pin) { /* Initialize multiplexing */ *gpios_pin = ar_multiplexing_init(); /* Write ARDrone commands on UART2 */ uint8_t initbuf[] = {0xE0, 0x91, 0xA1, 0x00, 0x40}; uint8_t multicastbuf[] = {0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0}; /* initialize all motors * - select one motor at a time * - configure motor */ int i; int errcounter = 0; for (i = 1; i < 5; ++i) { /* Initialize motors 1-4 */ initbuf[3] = i; errcounter += ar_select_motor(*gpios_pin, i); write(ardrone_uart, initbuf + 0, 1); /* sleep 400 ms */ usleep(200000); usleep(200000); write(ardrone_uart, initbuf + 1, 1); /* wait 50 ms */ usleep(50000); write(ardrone_uart, initbuf + 2, 1); /* wait 50 ms */ usleep(50000); write(ardrone_uart, initbuf + 3, 1); /* wait 50 ms */ usleep(50000); write(ardrone_uart, initbuf + 4, 1); /* wait 50 ms */ usleep(50000); /* enable multicast */ write(ardrone_uart, multicastbuf + 0, 1); /* wait 1 ms */ usleep(1000); write(ardrone_uart, multicastbuf + 1, 1); /* wait 1 ms */ usleep(1000); write(ardrone_uart, multicastbuf + 2, 1); /* wait 1 ms */ usleep(1000); write(ardrone_uart, multicastbuf + 3, 1); /* wait 1 ms */ usleep(1000); write(ardrone_uart, multicastbuf + 4, 1); /* wait 1 ms */ usleep(1000); write(ardrone_uart, multicastbuf + 5, 1); /* wait 5 ms */ usleep(50000); } /* start the multicast part */ errcounter += ar_select_motor(*gpios_pin, 0); if (errcounter != 0) { printf("AR: init sequence incomplete, failed %d times", -errcounter); fflush(stdout); } }