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