AR Drone 2/Motor driver

From PaparazziUAV
Jump to: navigation, search

The motor driver

Starting off with the project we first tried searching what had already been done for AR.Drone1 and we found a very good source: Perquin blog. This explained that, for the AR Drone 1, the motors where controlled by a device:

*/dev/ttyPA1

After initialization a PWM bit stream was sent to that device containing a 3 start bits, followed 9 bits for each motor and 1 stop bit. The data was send as a stream of five 8-bit unsigned integers. This means the data will look as follows:

001aaaaa aaaabbbb bbbbbccc ccccccdd ddddddd0

The start bit 001 seemed to be specific for controlling the motors as the device also controlled the motor LEDs. For that the start bit is 011, but more on that in another section. We soon noticed that the device name is different on the AR.Drone2. By using dmesg and trace functions we found that, for the motors, the device is as follows:

*/dev/ttyO0 : motor

After finding out what the correct device was, we could simply change the device name in the driver created by hugo: Perquin Program. This gave us a working motor driver.


Motor driver in Paparazzi

The next step was implementing that motor driver into Paparazzi. In order to make it work we have to implement 3 functions into the files actuators_pwm_arch.c and actuators_pwm_arch.h files.

But first I will explain a bit about how Paparazzi operates the motors. In the main file for rotorcraft a function is called periodicly:

SetActuatorsFromCommands(commands);

This function is defined in the airframe.h file that is generated for each aircraft and is based on the airframe.xml file. The commands parameter contains a array of values as set by the AHRS, INS or 'manually'. These values represent the Pitch, Yaw, Roll and Thrust. For Quadrotors this function then calls a function in motor mixing.

motor_mixing_run(autopilot_motors_on,FALSE,values);

Motor mixing is a file meant to realign the rotational direction and positioning of the rotorcraft's rotors in order to be able to translate the commands correctly into a thrust value for each motor. After this function has run, the actuator values have been calculated for each motor and can be set and translated into the correct structure for the specific motors, in our case a PWM signal.

Now the real work begins for in order to set the actuator values we have to implement the functions in the actuator_pwm_arch files as mentioned before. The functions are:

  • ActuatorPwmSet(_n,_v); where n is the number assigned to a motor and v is the associated value.
  • actuators_pwm_commit(); that is directly called from ActuatorsPwmCommit();.
  • actuators_pwm_arch_init();

ActuatorPwmSet(_n,_v); is a simple function that makes the calculated values available to actuators_pwm_commit();.

actuators_pwm_commit(); converts the received values into a pwm signal and sends this signal to the device. Our function looks like this:

void actuator_pwm_commit(void){
	uint8_t pwm_signal[5];

	pwm_signal[0] = 0x20 | ((actuators_pwm_values[0]&0x1ff)>>4);
	pwm_signal[1] = ((actuators_pwm_values[0]&0x1ff)<<4) | ((actuators_pwm_values[1]&0x1ff)>>5);
	pwm_signal[2] = ((actuators_pwm_values[1]&0x1ff)<<3) | ((actuators_pwm_values[2]&0x1ff)>>6);
	pwm_signal[3] = ((actuators_pwm_values[2]&0x1ff)<<2) | ((actuators_pwm_values[3]&0x1ff)>>7);
	pwm_signal[4] = ((actuators_pwm_values[3]&0x1ff)<<1)| 0x00;

	write(actuator_fd, pwm_signal, 5);
}

actuators_pwm_arch_init(); opens the device, configures the motors, activates the gpio ports, sets the reset bit to listening and opens a multicast in order to be able to commit data to all motors simultaneously.

Having implemented this we can now control the motors using Pararazzi.