00001 // RCRx.h 00002 // 00003 // Remote Control Receiver module for RCOIP protocol 00004 /// 00005 /// \mainpage RCKit library for Arduino 00006 /// 00007 /// This is the Arduino RCKit 1.2 library. 00008 /// 00009 /// RCKit provides a kit of software objects that make it easy to build an 00010 /// RCOIP (Remote Control Over IP) receiver on Arduino. RCOIP protocol is used to 00011 /// carry remote control commands from a transmitter to a receiver over an IP 00012 /// transport such as Ethernet or Wi-Fi. 00013 /// 00014 /// As such it can be used to build Remote Controlled (RC) vehicles and devices of various kinds, along with 00015 /// matching transmitters. Large numbers of channels can be supported, along with a back-channel 00016 /// which sends data from the Receiver to the Transmitter. 00017 /// A compatible iPhone transmitter app is also available. 00018 /// 00019 /// The transmitter could be a handheld Wi-Fi enabled device such as an iPhone, iPad or Arduino based device. 00020 /// Or it could be an interactive program running on a desktop computer. The RCTx iPhone transmitter app is 00021 /// available on the Apple App Store. It provides a simple RCOIP transmitter equipped with 2 joysticks and 00022 /// a number of switches. 00023 /// 00024 /// The receiver (using this RCKit software) could be a remote controlled car, 00025 /// plane, helicopter or some other device. 00026 /// 00027 /// The RCOIP protocol is a 2-way protocol that defines UDP messages between 00028 /// the RCOIP transmitter and receiver. 00029 /// This effectively makes the transmitter a UDP client and the receiver a UDP server. 00030 /// Messages sent from the transmitter to the receiver include setting analog outputs, 00031 /// and messages from the receiver to the transmitter include receiver status messages. 00032 /// 00033 /// RCTx, RCKit and the RCOIP protocol offer the following advantages over conventional Remote Control: 00034 /// \li Large numbers of channels (> 100) not just 5 or 6, including analog, digital, text, data etc. 00035 /// \li Back channel for telemetry (voltages, signal strengths, GPS position etc) 00036 /// \li Failsafe modes 00037 /// \li Programmable, configurable and extensible 00038 /// \li Works with a variety of types of vehicle and remote devices 00039 /// \li Hackable 00040 /// \li Opportunity to tightly integrate remote control and autonomous vehicle software control 00041 /// \li Works with a variety of IP transports Wi-Fi (ad-hoc or infrastructure), Wired etc. 00042 /// 00043 /// Videos explaining how it works and what you can do with it can be found at: 00044 /// \li http://www.youtube.com/watch?v=SKwY-CcotRY 00045 /// \li http://www.youtube.com/watch?v=i0ZogFmytPI 00046 /// 00047 /// There is also a video showing how RCKit can be used with the IRrc library at 00048 /// http://www.open.com.au/mikem/arduino/IRrc to control a 3 channel infra-red model helicopter at: 00049 /// \li http://www.youtube.com/watch?v=lzRpyqnD6_M 00050 /// 00051 /// The version of the package that this documentation refers to can be downloaded 00052 /// from http://www.open.com.au/mikem/arduino/RCKit/RCKit-1.2.zip 00053 /// You can find the latest version at http://www.open.com.au/mikem/arduino/RCKit 00054 /// 00055 /// Tested on Arduino Duemilanove, Diecimila, Mega and Asynclabs Yellowjacket 00056 /// with arduino-0018 on OpenSuSE 11.1 00057 /// and avr-libc-1.6.2-5.11, 00058 /// cross-avr-binutils-2.19-9.1 and cross-avr-gcc43-4.3.3_20081022-9.3 00059 /// 00060 /// \par Setters 00061 /// 00062 /// Setter are object that receive a value, maybe transform it and then do something with it. Typically 00063 /// they set an output pin according to the received input value, but almost any other transformation, 00064 /// output or communication can be imagined. 00065 /// 00066 /// The following output Setter objects are provided with RCKit. They can be used to translate 00067 /// receiver channel values into physical outputs: 00068 /// \li AnalogSetter 00069 /// \li DigitalSetter 00070 /// \li ServoSetter 00071 /// \li AccelStepperPositionSetter 00072 /// \li AccelStepperSpeedSetter 00073 /// \li HBridgeSetter 00074 /// \li DifferentialSetter 00075 /// 00076 /// The following transformation Setter objects are provided with RCKit. They can be used to 00077 /// transform receiver channel values before being given to one of the output Setter classes above: 00078 /// \li Inverter 00079 /// \li Limiter 00080 /// \li Linear 00081 /// 00082 /// \par RCRx 00083 /// 00084 /// RCRx class is a Wi-Fi RCOIP receiver. It works with Arduino and WiShield and any 00085 /// RCOIP compliant Wi-Fi Transmitter (such as the RCTx iPhone app available on the Apple App Store). 00086 /// 00087 /// By default, RCRx is configured as an Ad-Hoc Wi-Fi network with SSID of 'RCArduino' 00088 /// By default, the network is Open (ie no encryption) and 00089 /// It is configured with a static IP address of 169.254.1.100. 00090 /// These setting can be changed by editing RCRx.cpp in the RCKit distribution. 00091 /// 00092 /// When the RCRx object is constructed, it must be given an array of Setter objects. 00093 /// When a RCOIPv1CmdSetAnalogChannels is received by RCRx, The Setter corresponding to each 00094 /// Channel value in the RCOIPv1CmdSetAnalogChannels command will be passed to the 00095 /// respective Setter in the analogOutputs array. 00096 /// The Arduino software is expected to be configured so that each analogOutput is connected to a Setter that 00097 /// will implement the received value, perhaps by setting an analog or digital output on an Arduino pin. 00098 /// Setter objects are provided to achieve this. 00099 /// 00100 /// RCRx will automatically respond to received commands with RCOIPv1ReplyReceiverStatus messages 00101 /// as appropriate to the configured timeouts etc. See the RCOIP protocol document for more details. 00102 /// 00103 /// \par Example Sketches 00104 /// 00105 /// Several example Arduino sketches are included, including a regression 00106 /// test suite and a sample complete 5 channel receiver with Servo outputs. 00107 /// 00108 /// The following example sketches are provided: 00109 /// \li TestSuite 00110 /// \li RCRx 00111 /// \li HBridgeRCRx 00112 /// \li HBridge2RCRx 00113 /// \li DifferentialRCRx 00114 /// 00115 /// 00116 /// \par RCTx iPhone App 00117 /// 00118 /// RCTx is an RCOIP compliant transmitter for iPhone available on the Apple App Store 00119 /// at http://itunes.apple.com/app/rctx/id377833472?mt=8 00120 /// 00121 /// It presents a simulated RC transmitter with 2 joysticks and a number of switches. 00122 /// The left josystick sets channels 0 and 1 and the right joystick channels 2 and 3. 00123 /// The switches set channels 4 through 9 inclusive. The one connected to channel 4 is momentary contact. 00124 /// The install and configure RCTx: 00125 /// \li install the RCTx app on your iPhone. 00126 /// \li Build and upload your RCRx program you your Arduino+WiShield hardware 00127 /// \li Power up the Arduino 00128 /// \li Turn on your iphone, go to Settings, Wi-Fi. Enable Wi-Fi 00129 /// \li After about 30 seconds, you should see the RCArduino network appear as an available 00130 /// network on the iPhone. Tap on it. 00131 /// Now tap on the RCArduino network details arrow to the right of the RCArduino line. Select 'Static'. 00132 /// Enter an IP Address of 169.254.1.1. Enter a Subnet Mask of 255.255.0.0 00133 /// \li After about 10 seconds, the iPhone should be successfully connected to the RCArduino network. 00134 /// You now have an ad-hoc connection to the Arduino. The Arduino will have the address 169.254.1.100 00135 /// and the iPhone wil have address 169.254.1.1 00136 /// \li Start the RCTx app on the iPhone. 00137 /// \li After about 5 seconds, you should see the NO CONNECT in the bottom left corner change to 00138 /// show RSSI and the correct battery voltage (if the Arduino is so equipped). 00139 /// \li Move the josticks and buttons. This will send RCOIP commands to the Arduino. 00140 /// RCRx in the arduino will convert them to analog output signals to drive your hardware. Have fun. 00141 /// 00142 /// \par Prerequisites 00143 /// 00144 /// Requires: 00145 /// \li WiShield (http://asynclabs.com) 00146 /// \li AccelStepper (http://www.open.com.au/mikem/arduino/AccelStepper) 00147 /// libraries to also be installed. 00148 /// 00149 /// \par Installation 00150 /// 00151 /// Install in the usual way: unzip the distribution zip file to the libraries 00152 /// sub-folder of your sketchbook. 00153 /// 00154 /// \author Mike McCauley (mikem@open.com.au) 00155 /// 00156 /// This software and the RCOIP protocol is Copyright (C) 2010 Mike McCauley. Use is subject to license 00157 /// conditions. The main licensing options available are GPL V2 or Commercial: 00158 /// 00159 /// \par Open Source Licensing GPL V2 00160 /// This is the appropriate option if you want to share the source code of your 00161 /// application with everyone you distribute it to, and you also want to give them 00162 /// the right to share who uses it. If you wish to use this software under Open 00163 /// Source Licensing, you must contribute all your source code to the open source 00164 /// community in accordance with the GPL Version 2 when your application is 00165 /// distributed. See http://www.gnu.org/copyleft/gpl.html 00166 /// 00167 /// \par Commercial Licensing 00168 /// This is the appropriate option if you are creating proprietary applications 00169 /// and you are not prepared to distribute and share the source code of your 00170 /// application. Contact info@open.com.au for details. 00171 /// 00172 /// \par Revision History 00173 /// \version 1.0 Initial release 00174 /// \version 1.1 Added Linear 00175 /// \version 1.2 Compiles under Arduino 1.0 00176 00177 // Copyright (C) 2010 Mike McCauley 00178 // $Id: RCRx.h,v 1.4 2010/06/30 02:48:59 mikem Exp mikem $ 00179 00180 #ifndef RCRx_h 00181 #define RCRx_h 00182 00183 #include <WiShield.h> 00184 #include <inttypes.h> 00185 00186 class Setter; 00187 00188 ///////////////////////////////////////////////////////////////////// 00189 /// \class RCRx RCRx.h <RCRx.h> 00190 /// \brief Remote Control Receiver module for RCOIP protocol on Arduino 00191 /// 00192 /// \par Overview 00193 /// This class implements a receiver for RCOIP (Remote Control Over IP). It starts and manages a 00194 /// WiFi receiver, which receives UDP messages containing RCOIP commands such as remote control channel 00195 /// values. When channel setting commands are received they are translated into output values which are sent 00196 /// to Setter objects to control the phycical output devices and pins on the Arduino. 00197 /// Supports WiShield 1.0 etc. 00198 /// 00199 /// \par Outputs 00200 /// RCRx maps RCOIP channels to physical output devices through the analogOutputs array. This is an array 00201 /// of Setter objects, one for each physical output to be controlled by RCRx. Whenever a RCOIP message 00202 /// is received with new channel settings, the input() function of each Setter with new data will be 00203 /// called. This will cause each Setter to set its physical output in response to the remote control 00204 /// data received by an RCOIP. 00205 /// 00206 /// \par Failsafe 00207 /// RCRx supports failsafe behaviour if a connection to the transmitter is lost. 00208 /// RCRx monitors the time of each received RCOIP request. If no request is received for more than 00209 /// failInterval milliseconds, it will be considered as disconnected, and the failsafe() function of 00210 /// every Setter will be called, allowing each Setter to adopt its failsafe configuration 00211 /// (eg throttle to 0 etc). This allows remote control vehicles to fail safe if the transmitter 00212 /// fails or goes out of range. 00213 /// 00214 /// \par WiShield Library Configuration 00215 /// Requires the Asynclabs WiShield library. See http://asynclabs.com/wiki/index.php?title=WiShield_library 00216 /// Install the WiShield library in the libraries directory of your arduino IDE installation, 00217 /// then follow the configuration steps below: 00218 /// 00219 /// Support of RSSI (receiver signal strength indicator) requires mods to WiShield library g2100.c as per 00220 /// http://asynclabs.com/forums/viewtopic.php?f=10&t=385&start=0. You dont have to add this but its a 00221 /// good feature. 00222 /// 00223 /// Correct operation of the WiShield requires you to set the jumper on the WiShield to INT0 or DIG8 to select 00224 /// the arduino pin to use for WiShield interrupts, and also to make sure it agrees with the settings of 00225 /// USE_DIG0_INTR or USE_DIG8_INTR in spi.h in the WiShield library (which defaults to 00226 /// using Arduino digital pin 2, and which means setting the WiShield jumper to INT0 setting). Yes, the naming 00227 /// conventions are inconsistent :-(. In summary: 00228 /// \code 00229 /// WiShield jumper spi.h Arduino 00230 /// INT0 USE_DIG0_INTR Digital pin 2 00231 /// D8 USE_DIG8_INTR Digital pin 8 00232 /// \endcode 00233 /// 00234 /// For YellowJacket (which has no jumper), leave it as USE_DIG0_INTR. 00235 /// 00236 /// In order for WiShield library to support UDP (as needed by this module), 00237 /// you MUST set UIP_CONF_UDP to 1 in uip-conf.h. This is an unfortunate but necessary requirement, 00238 /// otherwise UDP support will not be compiled into the WiShield library. 00239 /// Further, you must edit apps-conf.h and make sure the only APP_* defined is APP_UDPAPP. 00240 /// Failure to do this will cause compile errors. A modified version of the WiShield library already 00241 /// edited for use with RCKit is available at 00242 /// http://www.open.com.au/mikem/arduino/WiShield-v1.3.0-0-mikem-RCKit.zip 00243 /// 00244 /// WiShield will work with Arduino Mega, but with difficulty. The problem is that with the Mega, the SPI 00245 /// pins that are required for interface with WiShield come out on different pins to the smaller form 00246 /// factor arduinos like Diecimila and Duemilanove. So, to make the Mega work with the WiShield, you 00247 /// have to reroute the SPI pin to different Arduino pins, as per 00248 /// http://asynclabs.com/forums/viewtopic.php?f=13&t=19&hilit=mega&start=10 00249 /// 00250 /// This library has been tested with Duemilanove and WiShield 1.0 and iPhone 3.0 00251 /// 00252 /// \par Installation 00253 /// 00254 /// Install in the usual way: unzip the distribution zip file to the libraries 00255 /// sub-folder of your sketchbook. Dont foget the prerequisites too. 00256 class RCRx 00257 { 00258 public: 00259 /// Constructor. After contruction and initialisation, call the init() and run() functions. 00260 RCRx(); 00261 00262 /// Specifies the Setters that will be used by this receiver to set its output values 00263 /// Whenever a RCOIP message is received with a new value for channel n, it will be passed 00264 /// to the Setter at index n by calling the Setters input() function. 00265 /// \param[in] analogOutputs Pointer to an array pointers to Setter objects. 00266 /// \param[in] numAnalogOutputs Number of elements in analogOutputs 00267 void setOutputs(Setter** analogOutputs, uint8_t numAnalogOutputs); 00268 00269 /// Set the output for channel n. Calls the Setter at index n of the analogOutputs 00270 /// array. Not usuallly called exernally, this is usually only called 00271 /// from within RCRx. Subclasses can override this to get control 00272 /// when new analog output values become available 00273 /// \param[in] channel The analog channel number output to set 00274 /// \param[in] value The new value to set 00275 virtual void setAnalogOutput(uint8_t channel, int value); 00276 00277 /// Initialises the wireless WiFi receiver 00278 /// Call once at startup time after addresses etc have been configured. 00279 void init(); 00280 00281 /// Call this to process pending Wireless events. Call this as often as possible in your 00282 /// main loop. Runs the wireless driver stack. 00283 void run(); 00284 00285 /// Call to handle an incoming UDP message containing an RCOIP command message. 00286 /// This is usually only called from within RCRx, but could be called externally 00287 /// for testing purposes etc. 00288 /// \param[in] msg Pointer to the UDP message 00289 /// \param[in] len Length of the UDP mesage in bytes 00290 /// \param[in] rssi Receiver Signal Strength as reported by the WiFi receiver 00291 /// when the message was received. 00292 void handleRequest(uint8_t *msg, uint16_t len, uint16_t rssi); 00293 00294 /// Called by RCRx when no RCOIP message has been received for more than failInterval miliseconds. 00295 /// Calls the failsafe function for all configured output Setters. 00296 void failsafe(); 00297 00298 /// Called by RCRx periodically (typically twice per second) to do period processing such as 00299 /// detecting loss of messages 00300 void periodicTask(); 00301 00302 /// Returns whether the RCRx considers itself to be connected to the transmitter. 00303 /// Initialsed to false. Whenever an RCOIP request is receved, set to true. If no RCOIP request 00304 /// is receved for more than failInterval miliseconds, set to false. 00305 /// \return true if the RCRx is still receiving messages from the transmitter. 00306 boolean connected(); 00307 00308 /// Sends an RCOIP reply message 00309 /// Usually called internally at most once every _replyInterval milliseconds. 00310 void sendReply(); 00311 00312 protected: 00313 00314 private: 00315 /// Array of output Setters 00316 Setter** _analogOutputs; 00317 00318 /// Number of Setters in _analogOutputs 00319 uint8_t _numAnalogOutputs; 00320 00321 /// Arduino analog input pin which yields the arduino battery voltage 00322 uint8_t _batteryVoltageAnalogPin; 00323 00324 /// Max time in milliseconds between RCOIP replies 00325 unsigned int _replyInterval; 00326 00327 /// Max time in milliseconds between received request before RCRx is considered to be disconnected 00328 unsigned int _failInterval; 00329 00330 /// The time we last got a RCOIP request from the transmitter 00331 unsigned long _lastRequestTime; 00332 00333 /// The last time we sent a RCOIP reply to the transmitter 00334 unsigned long _lastReplyTime; 00335 00336 /// Whether RCRx is considered to be connected to the transmitter 00337 boolean _connected; 00338 00339 /// The value of the RSSI (receiver signal strength indicator) 00340 /// in the last request received 00341 uint16_t _rssi; 00342 }; 00343 00344 #endif