flying_robot 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,14 @@
1
+ == 0.0.1 2009-04-03
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
5
+
6
+ == 0.0.2 2009-07-08
7
+
8
+ * 1 major enhancement:
9
+ * Plugin support for all hardware included with Blimpduino, including L293D and Maxsonar Ultrasonic range finder
10
+
11
+ == 0.0.3 2009-11-14
12
+
13
+ * 1 major enhancement:
14
+ * Update parser for aileron command support
@@ -0,0 +1,29 @@
1
+ History.txt
2
+ Manifest.txt
3
+ PostInstall.txt
4
+ README.rdoc
5
+ README.txt
6
+ Rakefile
7
+ app_generators/flying_robot/USAGE
8
+ app_generators/flying_robot/flying_robot_generator.rb
9
+ app_generators/flying_robot/templates/plugins/Hmc6352_compass.rb
10
+ app_generators/flying_robot/templates/plugins/battery.rb
11
+ app_generators/flying_robot/templates/plugins/flying_robot.rb
12
+ app_generators/flying_robot/templates/plugins/pololu_ir_receiver.rb
13
+ app_generators/flying_robot/templates/plugins/pololu_micro_serial_controller.rb
14
+ app_generators/flying_robot/templates/plugins/pololu_qik_dual_serial_motor_controller.rb
15
+ app_generators/flying_robot/templates/plugins/L293d.rb
16
+ app_generators/flying_robot/templates/plugins/maxsonar.rb
17
+ app_generators/flying_robot/templates/sketch.rb.erb
18
+ bin/flying_robot
19
+ flying_robot.gemspec
20
+ lib/flying_robot.rb
21
+ script/console
22
+ script/destroy
23
+ script/generate
24
+ spec/flying_robot_spec.rb
25
+ spec/spec.opts
26
+ spec/spec_helper.rb
27
+ tasks/rspec.rake
28
+ test/test_flying_robot_generator.rb
29
+ test/test_generator_helper.rb
@@ -0,0 +1,3 @@
1
+
2
+ For more information on flying_robot, see http://flyingrobo.com
3
+
@@ -0,0 +1,58 @@
1
+ = flying_robot
2
+
3
+ http://github.com/deadprogrammer/flying_robot
4
+
5
+ == DESCRIPTION:
6
+
7
+ flying_robot takes a standard Ruby Arduino Development (RAD) project, and turns it into a Unmanned Aerial Vehicle (UAV)
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * Plugins for RAD for cool UAV-related hardware, like Pololu motor controllers and Honeywell digital compass
12
+ * Complete support for Blimpduino hardware
13
+ * More plugins coming soon to support other available Arduino-based systems like ArduPilot
14
+
15
+ == SYNOPSIS:
16
+
17
+ flying_robot takes a standard Ruby Arduino Development (RAD) project, and turns it into a Unmanned Aerial Vehicle (UAV). It includes plugin support for the following hardware:
18
+
19
+ * LiPo Battery Voltage
20
+ * Honeywell HMC6352 Digital Compass
21
+ * L293D Motor Driver
22
+ * Maxbotix Maxsonar Ultrasonic Range Finder
23
+ * Pololu Infrared Detector Array
24
+ * Pololu Micro Serial Motor Controller
25
+ * Pololu QIK Dual Serial Motor Controller
26
+
27
+ == REQUIREMENTS:
28
+
29
+ * sudo gem install rad
30
+
31
+ == INSTALL:
32
+
33
+ * sudo gem install deadprogrammer-flying_robot
34
+
35
+ == LICENSE:
36
+
37
+ (The MIT License)
38
+
39
+ Copyright (c) 2009 Ron Evans
40
+
41
+ Permission is hereby granted, free of charge, to any person obtaining
42
+ a copy of this software and associated documentation files (the
43
+ 'Software'), to deal in the Software without restriction, including
44
+ without limitation the rights to use, copy, modify, merge, publish,
45
+ distribute, sublicense, and/or sell copies of the Software, and to
46
+ permit persons to whom the Software is furnished to do so, subject to
47
+ the following conditions:
48
+
49
+ The above copyright notice and this permission notice shall be
50
+ included in all copies or substantial portions of the Software.
51
+
52
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
53
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
54
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
55
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
56
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
57
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
58
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,58 @@
1
+ = flying_robot
2
+
3
+ http://github.com/deadprogrammer/flying_robot
4
+
5
+ == DESCRIPTION:
6
+
7
+ flying_robot takes a standard Ruby Arduino Development (RAD) project, and turns it into a Unmanned Aerial Vehicle (UAV)
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * Plugins for RAD for cool UAV-related hardware, like Pololu motor controllers and Honeywell digital compass
12
+ * Complete support for Blimpduino hardware
13
+ * More plugins coming soon to support other available Arduino-based systems like ArduPilot
14
+
15
+ == SYNOPSIS:
16
+
17
+ flying_robot takes a standard Ruby Arduino Development (RAD) project, and turns it into a Unmanned Aerial Vehicle (UAV). It includes plugin support for the following hardware:
18
+
19
+ * LiPo Battery Voltage
20
+ * Honeywell HMC6352 Digital Compass
21
+ * L293D Motor Driver
22
+ * Maxbotix Maxsonar Ultrasonic Range Finder
23
+ * Pololu Infrared Detector Array
24
+ * Pololu Micro Serial Motor Controller
25
+ * Pololu QIK Dual Serial Motor Controller
26
+
27
+ == REQUIREMENTS:
28
+
29
+ * sudo gem install rad
30
+
31
+ == INSTALL:
32
+
33
+ * sudo gem install deadprogrammer-flying_robot
34
+
35
+ == LICENSE:
36
+
37
+ (The MIT License)
38
+
39
+ Copyright (c) 2009 Ron Evans
40
+
41
+ Permission is hereby granted, free of charge, to any person obtaining
42
+ a copy of this software and associated documentation files (the
43
+ 'Software'), to deal in the Software without restriction, including
44
+ without limitation the rights to use, copy, modify, merge, publish,
45
+ distribute, sublicense, and/or sell copies of the Software, and to
46
+ permit persons to whom the Software is furnished to do so, subject to
47
+ the following conditions:
48
+
49
+ The above copyright notice and this permission notice shall be
50
+ included in all copies or substantial portions of the Software.
51
+
52
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
53
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
54
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
55
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
56
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
57
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
58
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'hoe'
3
+
4
+ Hoe.spec 'flying_robot' do
5
+ developer('Ron Evans', 'ron dot evans at gmail dot com')
6
+
7
+ self.rubyforge_name = 'deadprogrammer'
8
+ end
9
+
10
+ task :cultivate do
11
+ system "touch Manifest.txt; rake check_manifest | grep -v \"(in \" | patch"
12
+ system "rake debug_gem | grep -v \"(in \" > `basename \\`pwd\\``.gemspec"
13
+ end
@@ -0,0 +1,7 @@
1
+ Description:
2
+
3
+ flying_robot takes a standard Ruby Arduino Development (RAD) project, and turns it into a Unmanned Aerial Vehicle (UAV)
4
+
5
+ Usage:
6
+
7
+ flying_robot [appname]
@@ -0,0 +1,75 @@
1
+ class FlyingRobotGenerator < RubiGen::Base
2
+
3
+ DEFAULT_SHEBANG = File.join(Config::CONFIG['bindir'],
4
+ Config::CONFIG['ruby_install_name'])
5
+
6
+ default_options :author => nil
7
+
8
+ attr_reader :name
9
+
10
+ def initialize(runtime_args, runtime_options = {})
11
+ super
12
+ usage if args.empty?
13
+ @destination_root = File.expand_path(args.shift)
14
+ @name = base_name
15
+ extract_options
16
+ end
17
+
18
+ def manifest
19
+ record do |m|
20
+ # Ensure appropriate folder(s) exists
21
+ m.directory ''
22
+ BASEDIRS.each { |path| m.directory path }
23
+
24
+ # create stub
25
+ m.template 'sketch.rb.erb' , "#{base_name}.rb"
26
+
27
+ # copy plugins
28
+ m.file "plugins/battery.rb", "vendor/plugins/battery.rb"
29
+ m.file "plugins/flying_robot.rb", "vendor/plugins/flying_robot.rb"
30
+ m.file "plugins/Hmc6352_compass.rb", "vendor/plugins/Hmc6352_compass.rb"
31
+ m.file "plugins/pololu_ir_receiver.rb", "vendor/plugins/pololu_ir_receiver.rb"
32
+ m.file "plugins/pololu_micro_serial_controller.rb", "vendor/plugins/pololu_micro_serial_controller.rb"
33
+ m.file "plugins/pololu_qik_dual_serial_motor_controller.rb", "vendor/plugins/pololu_qik_dual_serial_motor_controller.rb"
34
+ m.file "plugins/L293d.rb", "vendor/plugins/L293d.rb"
35
+ m.file "plugins/maxsonar.rb", "vendor/plugins/maxsonar.rb"
36
+
37
+ m.dependency "install_rubigen_scripts", [destination_root, 'flying_robot'],
38
+ :shebang => options[:shebang], :collision => :force
39
+ end
40
+ end
41
+
42
+ protected
43
+ def banner
44
+ <<-EOS
45
+ Creates a ...
46
+
47
+ USAGE: #{spec.name} name
48
+ EOS
49
+ end
50
+
51
+ def add_options!(opts)
52
+ opts.separator ''
53
+ opts.separator 'Options:'
54
+ # For each option below, place the default
55
+ # at the top of the file next to "default_options"
56
+ # opts.on("-a", "--author=\"Your Name\"", String,
57
+ # "Some comment about this option",
58
+ # "Default: none") { |o| options[:author] = o }
59
+ opts.on("-v", "--version", "Show the #{File.basename($0)} version number and quit.")
60
+ end
61
+
62
+ def extract_options
63
+ # for each option, extract it into a local variable (and create an "attr_reader :author" at the top)
64
+ # Templates can access these value via the attr_reader-generated methods, but not the
65
+ # raw instance variable value.
66
+ # @author = options[:author]
67
+ end
68
+
69
+ # Installation skeleton. Intermediate directories are automatically
70
+ # created so don't sweat their absence here.
71
+ BASEDIRS = %w(
72
+ vendor/plugins
73
+ examples
74
+ )
75
+ end
@@ -0,0 +1,56 @@
1
+ # Plugin for Ruby Arduino Development that allows use of the HMC6352 Compass module
2
+ # Written by Ron Evans (http://deadprogrammersociety.com) for the flying_robot project
3
+ #
4
+ # Based on code taken from the SparkFun forums: http://forum.sparkfun.com/viewtopic.php?t=6236
5
+ class Hmc6352Compass < ArduinoPlugin
6
+ include_wire
7
+
8
+ external_variables "int HMC6352Address = 0x42"
9
+ external_variables "byte headingData[2]"
10
+ external_variables "int headingValue = 0"
11
+
12
+ # Shift the device's documented slave address (0x42) 1 bit right
13
+ # This compensates for how the TWI library only wants the
14
+ # 7 most significant bits (with the high bit padded with 0)
15
+ # This results in 0x21 as the address to pass to TWI
16
+ external_variables "int slaveAddress = HMC6352Address >> 1"
17
+
18
+ void prepare_compass() {
19
+ // hack to reference plugin, copied this trick from twitter plugin
20
+ }
21
+
22
+ // The whole number part of the heading
23
+ int heading()
24
+ {
25
+ return int (headingValue / 10) ;
26
+ }
27
+
28
+ // The fractional part of the heading
29
+ int heading_fractional()
30
+ {
31
+ return int (headingValue % 10) ;
32
+ }
33
+
34
+ void read_compass()
35
+ {
36
+ // Send a "A" command to the HMC6352
37
+ // This requests the current heading data
38
+ Wire.beginTransmission(slaveAddress);
39
+ Wire.send("A"); // The "Get Data" command
40
+ Wire.endTransmission();
41
+ delay(10); // The HMC6352 needs at least a 70us (microsecond) delay
42
+ // after this command. Using 10ms just makes it safe
43
+ // Read the 2 heading bytes, MSB first
44
+ // The resulting 16bit word is the compass heading in 10ths of a degree
45
+ // For example: a heading of 1345 would be 134.5 degrees
46
+ Wire.requestFrom(slaveAddress, 2); // Request the 2 byte heading (MSB comes first)
47
+ int i = 0;
48
+ while(Wire.available() && i < 2)
49
+ {
50
+ headingData[i] = Wire.receive();
51
+ i++;
52
+ }
53
+ headingValue = headingData[0]*256 + headingData[1]; // Put the MSB and LSB together
54
+ }
55
+
56
+ end
@@ -0,0 +1,27 @@
1
+ # Plugin for Ruby Arduino Development that allows use of the L293D motor controller
2
+ # Written by Ron Evans (http://deadprogrammersociety.com) for the flying_robot project
3
+ #
4
+ #
5
+ # Adapted from code written by Jordi Muñoz for the Blimpduino project
6
+ # http://blimpduino.googlecode.com/svn/trunk/Motors.pde
7
+ #
8
+ class L293d < ArduinoPlugin
9
+ plugin_directives "#define FORWARD 1"
10
+ plugin_directives "#define REVERSE 0"
11
+
12
+ void L293_send_command(int directionPin, int speedPin, byte direction, byte speed)
13
+ {
14
+ direction = constrain(direction, 0, 1);
15
+ speed = constrain(speed, 0, 127);
16
+
17
+ if (direction == FORWARD) {
18
+ digitalWrite(directionPin, LOW);
19
+ analogWrite(speedPin, speed);
20
+ } else {
21
+ speed = 255 - speed ;
22
+ digitalWrite(directionPin, HIGH);
23
+ analogWrite(speedPin, speed);
24
+ }
25
+ }
26
+
27
+ end
@@ -0,0 +1,41 @@
1
+ # Plugin for Ruby Arduino Development that reads a battery voltage from a power source that has been connected
2
+ # to one of the Arduino's analog pins. Note that you probably need to reduce the voltage considerably with a resistor (10K value?)
3
+ # before feeding it to the analog pin. You should also add another 10K resistor as a pull-down from the pin to ground.
4
+ #
5
+ # Written by Ron Evans (http://deadprogrammersociety.com) for the flying_robot project
6
+ # http://github.com/deadprogrammer/flying_robot
7
+ #
8
+ # Adapted from code written by Jordi Muñoz for the Blimpduino project
9
+ # http://code.google.com/p/blimpduino/source/browse/trunk/BlimpDuino_v4.pde)
10
+ #
11
+ class Battery < ArduinoPlugin
12
+ external_variables "float average_battery = 0.0"
13
+ external_variables "bool battery_init_completed"
14
+
15
+ add_to_setup "battery_init_completed = false;"
16
+
17
+ # bogus function here to make RAD happy
18
+ void battery_test() {
19
+ }
20
+
21
+ // initialize the battery reading
22
+ void init_battery(int pin) {
23
+ average_battery = analogRead(pin);
24
+ }
25
+
26
+ // get the current voltage
27
+ // TODO: allow user to set constants for different expected battery voltages
28
+ float voltage(int pin)
29
+ {
30
+ if (! battery_init_completed) {
31
+ init_battery(pin);
32
+ }
33
+
34
+ average_battery=(((float) average_battery * 0.99) + (float)((float) analogRead(pin) * 0.01)); // Jordi called it dynamic average
35
+
36
+ float battery_voltage=(float)((float) average_battery * (float)4.887586) * (float)2; // converting values to millivolts..,
37
+
38
+ return battery_voltage ;
39
+ }
40
+
41
+ end
@@ -0,0 +1,282 @@
1
+ # Plugin for Ruby Arduino Development that parses the flying_robot command set from any source of input to the serial port
2
+ # Written by Ron Evans (http://deadprogrammersociety.com) for the flying_robot project
3
+ #
4
+ # In order to implement a sketch that uses the flying_robot parser, you need to implement the methods that make up its interface
5
+ # so that it will respond to the standard command set.
6
+ #
7
+ # The following commands are supported:
8
+ # (h)ail - See if the UAV can still respond. Should send "Roger" back.
9
+ # (s)tatus - Grab a snapshot of all instrument readings plus any other status info that the UAV can support
10
+ # (e)levators - Set the elevators. The command supports two parameters:
11
+ # direction - enter 'u' for up, 'c' for centered, or 'd' for down
12
+ # deflection - enter an angle between 0 and 90 degrees
13
+ # (r)udder - Set the rudder. This command supports two parameters:
14
+ # direction - enter 'l' for left, 'c' for centered, or 'r' for right
15
+ # deflection - enter an angle between 0 and 90 degrees
16
+ # (a)ilerons - Set the ailerons. This command supports two parameters:
17
+ # direction - enter 'l' for left, 'c' for centered, or 'r' for right
18
+ # deflection - enter an angle between 0 and 90 degrees
19
+ # (t)hrottle - Set the throttle. This command supports two parameters:
20
+ # direction - enter 'f' for forward, or 'r' for reverse
21
+ # speed - enter a percentage from 0 to 100
22
+ # (i)nstruments - Read the current data for one of the installed instruments on the UAV. This command supports one parameter:
23
+ # id - enter an integer for which instrment readings should be returned from. If there is not an instrument installed
24
+ # for that id 'Invalid instrument' will be returned
25
+ # (p)rogram - Engage whatever autopilot program is available, if any. This command supports one parameter:
26
+ # id - enter an integer for which autopilot routine should be used. Enter 0 to cancel autopilot
27
+ #
28
+ class FlyingRobot < ArduinoPlugin
29
+ # used for parsing input commands
30
+ external_variables "bool current_command_received_complete"
31
+ external_variables "int current_command_length"
32
+ external_variables "char command_buffer[120]"
33
+
34
+ # the parsed command
35
+ external_variables "char command_code[1]"
36
+ external_variables "char direction_code[1]"
37
+ external_variables "char instrument_code[1]"
38
+ external_variables "char autopilot_code[1]"
39
+ external_variables "int command_value"
40
+
41
+ # current elevator values
42
+ external_variables "char elevator_direction[1]"
43
+ external_variables "int elevator_deflection = 0"
44
+
45
+ # current rudder values
46
+ external_variables "char rudder_direction[1]"
47
+ external_variables "int rudder_deflection = 0"
48
+
49
+ # current aileron values
50
+ external_variables "char aileron_direction[1]"
51
+ external_variables "int aileron_deflection = 0"
52
+
53
+ # current throttle values
54
+ external_variables "char throttle_direction[1]"
55
+ external_variables "int throttle_speed = 0"
56
+
57
+ # autopilot
58
+ external_variables "bool autopilot_engaged"
59
+
60
+ # initialize parser vars
61
+ add_to_setup "current_command_received_complete = false; elevator_direction[0] = 'c'; rudder_direction[0] = 'c'; throttle_direction[0] = 'f'; autopilot_engaged = false;"
62
+
63
+ # this is a hack to get the plugin included, that I got from the twitter_connect example
64
+ void be_flying_robot(){}
65
+
66
+ boolean current_command_received_is_complete() {
67
+ return current_command_received_complete == true ;
68
+ }
69
+
70
+ char current_command() {
71
+ return command_code[0];
72
+ }
73
+
74
+ char current_command_direction() {
75
+ return direction_code[0];
76
+ }
77
+
78
+ char current_command_instrument() {
79
+ return instrument_code[0];
80
+ }
81
+
82
+ char current_command_autopilot() {
83
+ return autopilot_code[0];
84
+ }
85
+
86
+ int current_command_value() {
87
+ return command_value ;
88
+ }
89
+
90
+ char current_elevator_direction() {
91
+ return elevator_direction[0];
92
+ }
93
+
94
+ int current_elevator_deflection() {
95
+ return elevator_deflection ;
96
+ }
97
+
98
+ char current_aileron_direction() {
99
+ return aileron_direction[0];
100
+ }
101
+
102
+ int current_aileron_deflection() {
103
+ return aileron_deflection ;
104
+ }
105
+
106
+ char current_rudder_direction() {
107
+ return rudder_direction[0];
108
+ }
109
+
110
+ int current_rudder_deflection() {
111
+ return rudder_deflection ;
112
+ }
113
+
114
+ char current_throttle_direction() {
115
+ return throttle_direction[0];
116
+ }
117
+
118
+ int current_throttle_speed() {
119
+ return throttle_speed ;
120
+ }
121
+
122
+ boolean is_autopilot_on() {
123
+ return autopilot_engaged == true ;
124
+ }
125
+
126
+ void autopilot_on() {
127
+ autopilot_engaged = true;
128
+ }
129
+
130
+ void autopilot_off() {
131
+ autopilot_engaged = false;
132
+ }
133
+
134
+ void clear_command_buffer() {
135
+ for(int i=0; i<120; i++){
136
+ command_buffer[i] = 0 ;
137
+ }
138
+
139
+ command_code[0] = 0 ;
140
+ direction_code[0] = 0 ;
141
+ instrument_code[0] = 0 ;
142
+ current_command_length = 0 ;
143
+ current_command_received_complete = false ;
144
+ }
145
+
146
+ void parse_command_code() {
147
+ if(current_command_length == 0) {
148
+ command_code[0] = 0;
149
+ } else {
150
+ command_code[0] = command_buffer[0];
151
+ }
152
+ }
153
+
154
+ void parse_direction_code() {
155
+ if(current_command_length >= 3) {
156
+ direction_code[0] = command_buffer[2];
157
+ } else {
158
+ direction_code[0] = 0;
159
+ }
160
+ }
161
+
162
+ void parse_instrument_code() {
163
+ if(current_command_length >= 3) {
164
+ instrument_code[0] = command_buffer[2];
165
+ } else {
166
+ instrument_code[0] = 0;
167
+ }
168
+ }
169
+
170
+ void parse_autopilot_code() {
171
+ if(current_command_length >= 3) {
172
+ autopilot_code[0] = command_buffer[2];
173
+ } else {
174
+ autopilot_code[0] = 0;
175
+ }
176
+ }
177
+
178
+ void parse_command_value(int start) {
179
+ if(current_command_length >= start + 1) {
180
+ command_value = atoi(command_buffer + start);
181
+ } else {
182
+ command_value = 0 ;
183
+ }
184
+ }
185
+
186
+ void get_command() {
187
+ if(current_command_received_complete) {
188
+ clear_command_buffer();
189
+ }
190
+
191
+ while(Serial.available() > 0) {
192
+ command_buffer[current_command_length] = Serial.read();
193
+ if(command_buffer[current_command_length] == '\r') {
194
+ current_command_received_complete = true ;
195
+ parse_command_code();
196
+ return;
197
+ } else {
198
+ current_command_length++ ;
199
+ }
200
+ }
201
+ }
202
+
203
+ // used to echo the commands being received via serial
204
+ void print_current_command(const char* cmd, int val) {
205
+ Serial.print(cmd);
206
+ Serial.print(" command - direction:");
207
+ Serial.print(current_command_direction());
208
+ Serial.print(" value:");
209
+ Serial.println(val);
210
+ }
211
+
212
+ void dispatch_command() {
213
+ if(!current_command_received_is_complete()) {
214
+ return;
215
+ }
216
+
217
+ char cmd = current_command();
218
+
219
+ if (cmd == 'h') {
220
+ hail();
221
+ } else if (cmd == 's') {
222
+ status();
223
+ } else if (cmd == 'e') {
224
+ parse_direction_code();
225
+ parse_command_value(4);
226
+ elevator_direction[0] = current_command_direction();
227
+ elevator_deflection = current_command_value();
228
+ if (elevator_deflection > 90) {
229
+ elevator_deflection = 90 ;
230
+ }
231
+
232
+ elevators();
233
+ } else if (cmd == 'r') {
234
+ parse_direction_code();
235
+ parse_command_value(4);
236
+ rudder_direction[0] = current_command_direction();
237
+ rudder_deflection = current_command_value();
238
+ if (rudder_deflection > 90) {
239
+ rudder_deflection = 90 ;
240
+ }
241
+
242
+ rudder();
243
+ } else if (cmd == 'a') {
244
+ parse_direction_code();
245
+ parse_command_value(4);
246
+ aileron_direction[0] = current_command_direction();
247
+ aileron_deflection = current_command_value();
248
+ if (aileron_deflection > 90) {
249
+ aileron_deflection = 90 ;
250
+ }
251
+
252
+ ailerons();
253
+ } else if (cmd == 't') {
254
+ parse_direction_code();
255
+ parse_command_value(4);
256
+ throttle_direction[0] = current_command_direction();
257
+ throttle_speed = current_command_value();
258
+ if (throttle_speed > 100) {
259
+ throttle_speed = 100 ;
260
+ }
261
+
262
+ throttle();
263
+ } else if (cmd == 'i') {
264
+ parse_instrument_code();
265
+ instruments();
266
+ } else if (cmd == 'p') {
267
+ parse_autopilot_code();
268
+ if (autopilot_code[0] == '0') {
269
+ autopilot_off();
270
+ }
271
+
272
+ autopilot();
273
+ } else {
274
+ Serial.println("Invalid command");
275
+ }
276
+ }
277
+
278
+ void process_command() {
279
+ get_command();
280
+ dispatch_command();
281
+ }
282
+ end