RadioLink-Joystick-To-Servos


UNDER CONSTRUCTION - July 2014: (Some updates October 2015) TO BE TESTED BETTER
If you try this version, please send problems, feedback, suggestions to terry@yourduino.com

- WHAT IT DOES:
  • Reads Joystick Analog Values on A0, A1 and transmits them over an nRF24L01 Radio Link, using the Radiohead library.
  • Receives Joystick position values from an nRF24L01 Radio Link, positions X and Y Servos (Usually on a Pan-Tilt platform). May point a small laser.
- LIBRARIES NEEDED: Software Servo: get the ZIP file here:
- RF24 Library Download HERE
- To Install libraries see: How-To HERE
Uses nRF24L01 Radios like these.

The TRANSMIT Software Sketch:

(Copy and paste into a blank Arduino IDE page)
/* YourDuinoStarter Example: TRANSMIT nRF24L01 Joystick data to Pan Tilt Over Radio.
   QUESTIONS? terry@yourduino.com
 - WHAT IT DOES: Reads Joystick Analog Values on A0, A1 and transmits
   them over a nRF24L01 Radio Link, using the Radiohead library.
 - TODO! Send the Joystick push-down click to turn Laser on and off
 - SEE the comments after "//" on each line below
 - CONNECTIONS: nRF24L01 Modules See:
 http://arduino-info.wikispaces.com/Nrf24L01-2.4GHz-HowTo
   1 - GND
   2 - VCC 3.3V !!! NOT 5V
   3 - CE to Arduino pin 8
   4 - CSN to Arduino pin 10
   5 - SCK to Arduino pin 13
   6 - MOSI to Arduino pin 11
   7 - MISO to Arduino pin 12
   8 - UNUSED

      -
   Analog Joystick or two 10K potentiometers:
   GND to Arduino GND
   VCC to Arduino +5V
   X Pot to Arduino A5
   Y Pot to Arduino A4
   Click Button to pin 4

   -V2.00 7/12/14  by Noah King
   Based on examples at http://www.airspayce.com/mikem/arduino/RadioHead/index.html
*/

/*-----( Import needed libraries )-----*/
// SEE http://arduino-info.wikispaces.com/Arduino-Libraries  !!
// NEED the RadioHead Library installed!
// http://www.airspayce.com/mikem/arduino/RadioHead/RadioHead-1.23.zip
#include <RHReliableDatagram.h>
#include <RH_NRF24.h>
#include <SPI.h>


/*-----( Declare Constants and Pin Numbers )-----*/
#define JoyStick_X_PIN     A5  //Pin Numbers
#define JoyStick_Y_PIN     A4
#define ClickPIN           4

#define CLIENT_ADDRESS 1      // For Radio Link
#define SERVER_ADDRESS 2


// Create an instance of the radio driver
RH_NRF24 RadioDriver;

// Create an instance of a manager object to manage message delivery and receipt, using the driver declared above
RHReliableDatagram RadioManager(RadioDriver, CLIENT_ADDRESS);// sets the driver to NRF24 and the client adress to 1

/*-----( Declare Variables )-----*/
uint8_t joystick[2];  // 2 element array of unsigned 8-bit type, holding Joystick readings

// Predefine the message buffer here: Don't put this on the stack:
uint8_t buf[RH_NRF24_MAX_MESSAGE_LEN];    // Actually: 28 bytes (32 minus 4 byte header)

void setup()  /****** SETUP: RUNS ONCE ******/
{
  // begin serial to display on Serial Monitor. Set Serial Monitor to 115200
  // See http://arduino-info.wikispaces.com/YourDuino-Serial-Monitor
  Serial.begin(115200);

  // NOTE: pinMode for Radio pins handled by RadioDriver
  if (!RadioManager.init())   // Defaults after init are 2.402 GHz (channel 2), 2Mbps, 0dBm
    Serial.println("init failed");

  pinMode(ClickPIN, INPUT);  //Not really needed: pins default to INPUT
}



void loop() /****** LOOP: RUNS CONSTANTLY ******/
{
  //Read the joystick values, scale them to 8-bit type and store them in the joystick[] array.
  Serial.println("Reading joystick values ");
  // Take the value of Joystick voltages which are 0 to 1023 (10 bit), and convert them to 0 to 255 (8 bit)
  joystick[0] = map(analogRead(JoyStick_X_PIN), 0, 1023, 0, 255);
  joystick[1] = map(analogRead(JoyStick_Y_PIN), 0, 1023, 0, 255);

  //Display the joystick values in the serial monitor.
  Serial.print("x:");
  Serial.print(joystick[0]);
  Serial.print("y:");
  Serial.println(joystick[1]);

  Serial.println("Sending Joystick data to nrf24_reliable_datagram_server");
  //Send a message containing Joystick data to manager_server
  if (RadioManager.sendtoWait(joystick, sizeof(joystick), SERVER_ADDRESS))
  {
    // Now wait for a reply from the server
    uint8_t len = sizeof(buf);
    uint8_t from;
    if (RadioManager.recvfromAckTimeout(buf, &len, 2000, &from))
    {
      Serial.print("got reply from : 0x");
      Serial.print(from, HEX);
      Serial.print(": ");
      Serial.println((char*)buf);
    }
    else
    {
      Serial.println("No reply, is nrf24_reliable_datagram_server running?");
    }
  }
  else
    Serial.println("sendtoWait failed");

  delay(500);  // Wait a bit before next transmission
}




The RECEIVE Software Sketch:

(Copy and paste into a blank Arduino IDE page)

/* YourDuinoStarter Example:RECEIVE nRF24L01 Joystick data to control Pan Tilt Servos Over Radio.
   QUESTIONS? terry@yourduino.com
 -WHAT IT DOES:
  -Receives Joystick Analog Values over a nRF24L01 Radio Link, using the Radiohead library.
  - Sends Joystick position to 2 servos, usually X,Y to pan-tilt arrangement
  - TODO! Send the Joystick push-down click to turn Laser on and off
 - SEE the comments after "//" on each line below
 - CONNECTIONS: nRF24L01 Modules See:
 http://arduino-info.wikispaces.com/Nrf24L01-2.4GHz-HowTo
   1 - GND
   2 - VCC 3.3V !!! NOT 5V
   3 - CE to Arduino pin 8
   4 - CSN to Arduino pin 10
   5 - SCK to Arduino pin 13
   6 - MOSI to Arduino pin 11
   7 - MISO to Arduino pin 12
   8 - UNUSED


   -V2.00 7/12/14 by Noah King
   Based on examples at http://www.airspayce.com/mikem/arduino/RadioHead/index.html
*/

/*-----( Import needed libraries )-----*/
// SEE http://arduino-info.wikispaces.com/Arduino-Libraries  !!
// NEED the SoftwareServo library installed
// http://playground.arduino.cc/uploads/ComponentLib/SoftwareServo.zip
#include <SoftwareServo.h>  // Regular Servo library creates timer conflict!

// NEED the RadioHead Library installed!
// http://www.airspayce.com/mikem/arduino/RadioHead/RadioHead-1.23.zip
#include <RHReliableDatagram.h>
#include <RH_NRF24.h>

#include <SPI.h>

/*-----( Declare Constants and Pin Numbers )-----*/
#define CLIENT_ADDRESS     1
#define SERVER_ADDRESS     2

#define ServoHorizontalPIN 3   //Pin Numbers
#define ServoVerticalPIN   5
#define LaserPIN           6

#define ServoMIN_H  0  // Don't go to very end of servo travel
#define ServoMAX_H  160 // which may not be all the way from 0 to 180. 
#define ServoMIN_V  0  // Don't go to very end of servo travel
#define ServoMAX_V  140 // which may not be all the way from 0 to 180. 


/*-----( Declare objects )-----*/
SoftwareServo HorizontalServo;
SoftwareServo VerticalServo;  // create servo objects to control servos

// Create an instance of the radio driver
RH_NRF24 RadioDriver;

// Create an instance of a manager object to manage message delivery and receipt, using the driver declared above
RHReliableDatagram RadioManager(RadioDriver, SERVER_ADDRESS);

/*-----( Declare Variables )-----*/
int HorizontalJoystickReceived; // Variable to store received Joystick values
int HorizontalServoPosition;    // variable to store the servo position

int VerticalJoystickReceived;   // Variable to store received Joystick values
int VerticalServoPosition;      // variable to store the servo position

uint8_t ReturnMessage[] = "JoyStick Data Received";  // 28 MAX
// Predefine the message buffer here: Don't put this on the stack:
uint8_t buf[RH_NRF24_MAX_MESSAGE_LEN];

//--------------------------------( SETUP Runs ONCE )-----------------------------------------------------
void setup()
{
  pinMode(LaserPIN, OUTPUT);
  digitalWrite(LaserPIN, HIGH); // turn on Laser

  /*-----( Set up servos )-----*/
  HorizontalServo.attach(ServoHorizontalPIN);  // attaches the servo to the servo object
  VerticalServo.attach(ServoVerticalPIN);      // attaches the servo to the servo object


  // begin serial to display on Serial Monitor. Set Serial Monitor to 115200
  // See http://arduino-info.wikispaces.com/YourDuino-Serial-Monitor
  Serial.begin(115200);

  if (!RadioManager.init()) // Initialize radio. If NOT "1" received, it failed.
    Serial.println("init failed");
  // Defaults after init are 2.402 GHz (channel 2), 2Mbps, 0dBm
} // END Setup



//--------------------------------( LOOP runs continuously )-----------------------------------------------------
void loop()
{
  if (RadioManager.available())
  {
 // Wait for a message addressed to us from the client
    uint8_t len = sizeof(buf);
    uint8_t from;
    if (RadioManager.recvfromAck(buf, &len, &from))
 //Serial Print the values of joystick
    {
      Serial.print("got request from : 0x");
      Serial.print(from, HEX);
      Serial.print(": X = ");
      Serial.println(buf[0]);
      Serial.print(" Y = ");
      Serial.println(buf[1]);

      // Send a reply back to the originator client, check for error
      if (!RadioManager.sendtoWait(ReturnMessage, sizeof(ReturnMessage), from))
        Serial.println("sendtoWait failed");
    }// end 'IF Received data Available
  }// end 'IF RadioManager Available
  
  {
    SoftwareServo::refresh();//refreshes servo to keep them updating
    HorizontalJoystickReceived  = buf[1];  // Get the values received
    VerticalJoystickReceived    = buf[0]; 

    // scale it to use it with the servo (value between MIN and MAX)
    HorizontalServoPosition  = map(HorizontalJoystickReceived, 0, 255, ServoMIN_H , ServoMAX_H);
    VerticalServoPosition    = map(VerticalJoystickReceived,   0, 255, ServoMIN_V , ServoMAX_V);
    Serial.print("HorizontalServoPosition : ");
    Serial.print(HorizontalServoPosition);
    Serial.print("  VerticalServoPosition : ");
    Serial.println(VerticalServoPosition);
    // tell servos to go to position
    HorizontalServo.write(HorizontalServoPosition);
    VerticalServo.write(VerticalServoPosition);
    delay(25);                      // wait for the servo to reach the position
  }
}// END Main LOOP