/elec/quadcopter

To get this branch, use:
bzr branch http://bzr.ed.am/elec/quadcopter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//
// main.ino
//
// This software is intended to be run on a small Arduino (e.g., a Pro Mini),
// whose purpose is dedicated to talking to the RC system.  That is to say, it
// listens to the PPM signal from the RC receiver and produces a compatible
// single for the ESCs to control the motors.  It additionally talks to the main
// board via a trivial serial protocol.  In so doing, this software relieves the
// main board (and software running on it) of the task of interfacing with any
// of the RC system.
//
// Receiver
// --------
//
// The 8 channels (from the RC receiver) need to be combined and fed to two
// interrupts on the Arduino.  They need to be combined in such a way as to
// alternate pulses between the two interrupts (which are alternately used to
// read the pulses).  Like this:
//
//                  ch1  ch3  ch5  ch7  ch2  ch4  ch6  ch8
//                   |    |    |    |    |    |    |    |
//                   ▼    ▼    ▼    ▼    ▼    ▼    ▼    ▼
//                   ¯    ¯    ¯    ¯    ¯    ¯    ¯    ¯
//            ___    |    |    |    |    |    |    |    |     ___
//    GND ---|___|---+----+----+----+    +----+----+----+----|___|--- GND
//             R                    |    |                     R
//         ________________________ | __ | _____________________
//         ARDUINO                  |    |
//                           pin 2  o    o  pin 3
//                    (interrupt 0)        (interrupt 1)
//
// The two resistors in the circuit are pull-down resistors (so, say 100kΩ).
// Without them, the Arduino is unable to read the pulse wave at all.
//
// Note that your receiver may not send pulses sequentially, in "channel order".
// If this turns out to be the case, you will need to arrange for the pulses to
// wire up the channels in an order whereby the pulses arrive alternately
// between the two interrupts and adjust the channel order in config.h.
//
// Motor control
// -------------
//
// The four motor control outputs should be fed directly to the ESCs.
//
//                            ESC  ESC  ESC  ESC
//                             o    o    o    o
//                             |    |    |    |
//         ___________________ | __ | __ | __ | _____
//         ARDUINO             |    |    |    |
//                      pin 4  o    o    o    o  pin 7
//
// SERIAL INTERFACE
// ----------------
//
// The serial interface (pins 0 and 1) talk a very simple protocol.  When a
// complete set of 8 channel values have been read, it writes 0xffff followed by
// the 8, 16-bit unsigned channel values.  It expects to recieve 0xffff,
// followed by 4, 16-bit unsigned channel values.  All channel values are in the
// range specified in config.h.

#include "config.h"
#include "receiver.h"
#include "motors.h"
#include "comms.h"


void flash_led()
{
	static bool on = false;
	on = !on;
	digitalWrite( LED_PIN, on? HIGH : LOW );
}


void setup()
{
	// init subsystems
	Receiver::setup();
	Motors::setup();
	Comms::setup();

	// led
	pinMode( LED_PIN, OUTPUT );
	digitalWrite( LED_PIN, LOW );
}

void loop()
{
	int motor_values[ NUM_MOTORS ];
	int channel_values[ NUM_CHANNELS ];

	// reset the motor values
	for( int a = 0; a < NUM_MOTORS; a++ )
		motor_values[ a ] = 0;

	while( true )
	{
		// have we read a whole set of channel values?
		if( Receiver::read_channels( channel_values ) )
		{
			// yes, flash led!
			flash_led();

			// send channel values to main board
			Comms::write_channels( channel_values );
		}

		// update motors
		Motors::update();

		// read channel values from main board
		if( Comms::read_channels( motor_values ) )
		{
			// set motor speeds
			Motors::set_values( motor_values );
		}

		// update motors
		Motors::update();
	}
}