Wireless Radio Hook

Since we only had several nRF24l01 Wireless Radios available and Logitech Dual Action Gamepad to control the copter, we implemented a new radio receiver hook into Aeroquad.  We found the Mirf library to be very helpful in this case, since it allowed us to create and send an simple C structure between the remote station and the quadcopter.  The structure of each radio packet is defined as follows:

struct radio_data {
	int receiverCommand[6];
	float p, i, d;
	uint8_t pidIndex;
	uint8_t flag;
};

typedef union radio_packet {
	byte data[RADIO_PAYLOAD];
	struct radio_data vars;
} radio_packet;

This structure not only allows controller commands to be sent, but also PID tuning data (explained in the PID tuning section).  The Mirf library only sends byte arrays between radios, so the union provided a way to easily convert the radio_data struct into a byte array.

To read controller commands, the radio hook for Aeroquad routinely checks the radio for new packets by calling the radioCheck() function, which updates the rcValue[] array with the latest controller commands.  The Aeroquad software can then poll the radio hook for the latest controller commands when required. This radio hook also allows for remote users to read and write PID values.  Code for the Aeroquad radio hook is shown below:

/*
  Author: Garrett Owen 
 */

#ifndef _AEROQUAD_RECEIVER_REMOTE_PC_H_
#define _AEROQUAD_RECEIVER_REMOTE_PC_H_

#include "Arduino.h"
#include "Receiver.h"
#include "Radio.h"
#include "../../AeroQuad/DataStorage.h"

// Array positions for rcValue[] and and recieverCommand[] 
// XAXIS 	0	Roll
// YAXIS 	1	Pitch
// ZAXIS 	2	Yaw
// THROTTLE     3	Throttle
// MODE 	4	Rate/Attitude mode selection
// AUX 		5

volatile uint16_t rcValue[6] = {1500,1500,1500,1000,1500,1500}; // interval [1000;2000]

void radioCheck() {
	radio_packet packet;
	int i;

	while (radio_check_recv(&packet)) {
		// Check for PID tuning or radio control
		if (packet.vars.flag == WRITE_PID
				&& packet.vars.pidIndex > -1
				&& packet.vars.pidIndex < 10 				&& motorArmed == OFF) { 			// Set PID Values 			struct PIDdata* pid = &PID[packet.vars.pidIndex]; 			pid->P = packet.vars.p;
			pid->I = packet.vars.i;
			pid->D = packet.vars.d;
			pid->lastPosition = 0;
			pid->integratedError = 0;
			zeroIntegralError();

		} else if (packet.vars.flag == READ_PID) {

			// Read and send PID Data
			struct PIDdata* pid = &PID[packet.vars.pidIndex];
			packet.vars.p = pid->P;
			packet.vars.i = pid->I;
			packet.vars.d = pid->D;
			radio_send_nowait(&packet, BASE_ADDR);

		} else if (packet.vars.flag == COMMIT_PID
				&& motorArmed == OFF) {

			writeEEPROM(); // defined in DataStorage.h
			zeroIntegralError();

		} else if (packet.vars.flag == CONTROL_DATA) {
			// Read controller values
			for (i = 0; i < 6; i++) {
				if (packet.vars.receiverCommand[i] < 1000 || packet.vars.receiverCommand[i] > 2000)
					continue;
				rcValue[i] = packet.vars.receiverCommand[i];
			}
		}
	}
}

void initializeReceiver(int nbChannel) {
	initializeReceiverParam(nbChannel);
	radio_init(COPTER_ADDR, RADIO_CHANNEL, RADIO_PAYLOAD);
}

int getRawChannelValue(byte channel) {
	return rcValue[channel];
}

void setChannelValue(byte channel,int value) {
	receiverCommand[channel] = value;
}

#endif

One thought on “Wireless Radio Hook

Comments are closed.