Hello, I'm David and this is my second instructable :) .

It is a continuation of my first instructable, where I shown you how I constructed my little hexapod, Hexdrake:


In this new instructable I'll show you how I made this protoype controller for Hexdrake with 2 joysticks, a slider pot, and an accelerometer to control completly the hexapod.

So there we go.

Step 1: Parts Needed:

Step 2: Making the Joysticks Boards:

Tools for this step:

Saw, lime. drill.

I designed these boards using Inkscape. These boards have the appropriate size for the original joysticks of the PS2 controllers. The main reason I designed these small boards is to simplify the connections between terminals of the potentiometers and the button incorporated with the arduino boards. The board includes a 10k ohm resistor, making the connection between the button and the arduino only needs a cable.

The first step is cut a piece of copper pcb the size of the design. Later cut the drilling template and place it in the copper pcb. This template marks the place where you have to make the holes for the components.

Now it's time to draw the tracks. I used a a sticker to mark the tracks. The next step is put the PCB in the acid and when done thoroughly clean the PCB. And the final step is solder the joystick and the resistor and put the decorative stickers.

The screw terminal blocks conections are:

GND ---> GND of arduino

Vin ------> 5V of arduino

X ------> The x-axis potentiometer to an analog pin of arduino(for example A0)

Y ------> The y-axis potentiometer to an analog pin of arduino(for example A1)

B ------> Connect the button to a digital pin of arduino.(For example D8)

Step 3: How to Use the 2.4GHz Modules?:

I use two nRF24L01 2.4GHz Radio/Wireless Transceivers to comunicate the two arduinos. The range of this modules are from 50 feet to 2000 feet distances. These 2.4 GHz Radio modules are based on the Nordic Semiconductor nRF24L01+ chip. The Nordic nRF24L01+ integrates a complete 2.4GHz RF transceiver, RF synthesizer, and baseband logic including the Enhanced ShockBurst hardware protocol accelerator supporting a high-speed SPI interface. These low-power short-range modude have a built-in Antenna.

These transcevers use the 2.4 GHz unlicensed band like many WiFi routers, some cordless phones etc.These module send and receive data in 'packets' of several bytes at a time. There is built-in error correction and resending, and it is possible to have one unit communicate with up to 6 other similar units at the same time. The pinout as shown in diagram tha you can see in the photos and a table with the coneections to diferent models of arduinos.

*IMPORTANT* :These modules VCC connection must go to 3.3V not 5.0V

I will show an example of transmit and receive software below for one joystick:


<p>/* <br>- WHAT IT DOES: Reads Analog values on A0, A1 and transmits
them over a nRF24L01 Radio Link to another transceiver.
1 - GND
2 - VCC 3.3V !!! NOT 5V
3 - CE to Arduino pin 9
4 - CSN to Arduino pin 10
5 - SCK to Arduino pin 13
6 - MOSI to Arduino pin 11
7 - MISO to Arduino pin 12
- Analog Joystick:
GND to Arduino GND
VCC to Arduino +5V
X Pot to Arduino A0
Y Pot to Arduino A1
/*-----( Import needed libraries )-----*/</p><p>#include <SPI.h><br>#include <nRF24L01.h></p><p>#include <RF24.h></p><p>/*-----( Declare Constants and Pin Numbers )-----*/<br>#define CE_PIN 9
#define CSN_PIN 10
#define JOYSTICK_X A0
#define JOYSTICK_Y A1</p><p>// NOTE: the "LL" at the end of the constant is "LongLong" type
const uint64_t pipe = 0xE8E8F0F0E1LL; // Define the transmit pipe</p><p>/*-----( Declare objects )-----*/
RF24 radio(CE_PIN, CSN_PIN); // Create a Radio
/*-----( Declare Variables )-----*/
int joystick[2]; // 2 element array holding Joystick readings</p><p>void setup() /****** SETUP: RUNS ONCE ******/
}//--(end setup )---
void loop() /****** LOOP: RUNS CONSTANTLY ******/
       joystick[0] = analogRead(JOYSTICK_X);
       joystick[1] = analogRead(JOYSTICK_Y);
       radio.write( joystick, sizeof(joystick) );
}//--(end main loop )--</p>


<p>/*<br>- WHAT IT DOES: Receives data from another transceiver with
2 Analog values from a Joystick
Displays received values on Serial Monitor
1 - GND
2 - VCC 3.3V !!! NOT 5V
3 - CE to Arduino pin 9
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</p><p>/*-----( Import needed libraries )-----*/</p><p>#include <SPI.h></p><p>#include <nRF24L01.h></p><p>#include <RF24.h></p><p>/*-----( Declare Constants and Pin Numbers )-----*/<br>#define CE_PIN 9
#define CSN_PIN 10</p><p>// NOTE: the "LL" at the end of the constant is "LongLong" type
const uint64_t pipe = 0xE8E8F0F0E1LL; // Define the transmit pipe</p><p>/*-----( Declare objects )-----*/
RF24 radio(CE_PIN, CSN_PIN); // Create a Radio</p><p>/*-----( Declare Variables )-----*/
int joystick[2]; // 2 element array holding Joystick readings</p><p>void setup() /****** SETUP: RUNS ONCE ******/
    Serial.println("Nrf24L01 Receiver Starting");
}//--(end setup )---</p><p>void loop() /****** LOOP: RUNS CONSTANTLY ******/
   if ( radio.available() )
   { // Read the data payload until we've received everything
       bool done = false;
      while (!done)
      { // Fetch the data payload
           done = radio.read( joystick, sizeof(joystick) );
          Serial.print("X = ");
          Serial.print(" Y = ");
       Serial.println("No radio available");
}//--(end main loop )---</p>

Step 4: Connecting the Joystick and the Linear Potentiometer:

To make the prototype of the controller I use a breadboard to connect everything. I have attached the boards of the joysticks and the linear potentiometer elastic bands jaja. I first thought of making a prototype with all elements before modifying a PS2 controller adding them the accelerometer, linear potentiometer, etc..

Simply connect the x,y GND and Vin terminals of both joystick to de 5v, GND, A0 and A1 pins of arduino. And the linear pot in the same way.

Step 5: How to Use the MMA7361 Accelerometer?:

It's a breakout board for Freescale’s MMA7361L three-axis analog MEMS accelerometer. The sensor requires a very low amount of power and has a g-select input which switches the accelerometer between ±1.5g and ±6g measurement ranges. Other features include a sleep mode, signal conditioning, a 1-pole low pass filter, temperature compensation, self test, and 0g-detect which detects linear freefall. Zero-g offset and sensitivity are factory set and require no external devices.

It's specifications are:

  • Supports 2.2V ~ 3.6V or 5V voltage input.
  • Two selectable measuring ranges (±1.5g, ±6g)
  • Breadboard friendly - 0.1" pitch header
  • Low current consumption: 400 µA
  • Sleep mode: 3 µA
  • Low voltage operation: 2.2 V - 3.6 V
  • High sensitivity (800 mV/g at 1.5g)
  • Fast turn on time (0.5 ms enable response time)
  • Self test for freefall detect diagnosis
  • 0g-Detect for freefall protection
  • Signal conditioning with low pass filter
  • Robust design, high shocks survivability

With the AcceleroMMA7361 library it's so easy to use this tiny module. The commands you can use with this library are:

  • void begin ()
  • void begin (int sleepPin, int selfTestPin, int zeroGPin, int gSelectPin, int xPin, int yPin, int zPin)
  • int getXRaw ()
    • getXRaw(): Returns the raw data from the X-axis analog I/O port of the Arduino as an integer
  • int getYRaw ()
    • getYRaw(): Returns the raw data from the Y-axis analog I/O port of the Arduino as an integer
  • int getZRaw ()
    • getZRaw(): Returns the raw data from the Z-axis analog I/O port of the Arduino as an integer
  • int getXVolt ()
    • getXVolt(): Returns the voltage in mV from the X-axis analog I/O port of the Arduino as a integer
  • int getYVolt ()
    • getYVolt(): Returns the voltage in mV from the Y-axis analog I/O port of the Arduino as a integer
  • int getZVolt ()
    • getZVolt(): Returns the voltage in mV from the Z-axis analog I/O port of the Arduino as a integer
  • int getXAccel ()
    • getXAccel(): Returns the acceleration of the X-axis as a int (1 G = 100.00)
  • int getYAccel ()
    • getYAccel(): Returns the acceleration of the Y-axis as a int (1 G = 100.00)
  • int getZAccel ()
    • getZAccel(): Returns the acceleration of the Z-axis as a int (1 G = 100.00)
  • void getAccelXYZ (int _XAxis, int _YAxis, int _ZAxis)
    • getAccelXYZ(int _XAxis, int _YAxis, int _ZAxis) returns all axis at once as pointers
  • int getTotalVector ()
    • getTotalVector returns the magnitude of the total acceleration vector as an integer
  • void setOffSets (int xOffSet, int yOffSet, int zOffSet)
  • void calibrate ()
  • void setARefVoltage (double _refV)
  • void setAveraging (int avg)
    • setAveraging(int avg): Sets how many samples have to be averaged in getAccel default is 10.
  • int getOrientation ()
  • void setSensitivity (boolean sensi)
    • setSensitivity sets the sensitivity to +/-1.5 G (HIGH) or +/-6 G (LOW) using a boolean HIGH (1.5 G) or LOW (6 G)
  • void sleep ()
    • sleep lets the device sleep (when device is sleeping already this does nothing)
  • void wake ()
    • wake enables the device after sleep (when device is not sleeping this does nothing) there is a 2 ms delay, due to enable response time (datasheet: typ 0.5 ms, max 2 ms)

The library have 3 simple examples. One gets the accelerations in each axis, the second gets the angle and the third the voltage. I used the "RawData" to get the angle of each axis othe controller to control the inclination:

<p>#include <AcceleroMMA7361.h></p><p>AcceleroMMA7361 accelero;
int x;
int y;
int z;
void setup()
    accelero.begin(8, 7, 6, 5, A5, A6, A7);
    accelero.setSensitivity(HIGH);//sets the sensitivity to +/-6G
}</p><p>void loop()
    x = accelero.getXRaw();
    y = accelero.getYRaw();
    z = accelero.getZRaw();
   Serial.print("\nx: ");
   Serial.print("\ty: ");
   Serial.print("\tz: ");
   delay(500); //(make it readable)

Step 6: Put All Together:

All that remains is to place the accelerometer on the remote controller and connect it to the arduino nano as in the previous step.

Now it's time to program!!!

Step 7: Programming the Remote Controller:

Using all prior learning of each module only need to adapt the programs to the characteristics of the remote control by linking in two programs: one for the arduino remote control works as a transmitter and another program for arduino hexapod operates as a receiver.

According to the motion limits of the servos, that I got from my previous instructable, you must use the map command arduino to convert the values of the potentiometers and the accelerometer within the minimum limit range values of motion of the servos. Being as follows:

<p>values[0] = map(values[0], 23, 1000, 900, 1500); //Value from slider pot</p><p>values[1] = map(values[1], 23, 1000, 2100, 1540); //Value from slider pot<br>values[3] = map(values[3], 1, 1033, -295, 295); //Value from y-axis of right joystick
values[4] = map(values[4], 1, 1023, -295, 295); //Value from y-axis of left joystick
values[5] = map(values[5], 1, 1023, -360, 360); //Value from x-axis of left joystick
values[6] = map(values[6], 170, 500, -360, 360); //Value from x-axis of the accelerometer
values[7] = map(values[7], 170, 510, -360, 360); //Value from y-axis of the accelerometer</p>

Using one of the buttons on one of the joysticks I wanted to use the example shown on arduino page that consists in counting the number of times that a button is pressed to create various modes in which the hexapod will move.


<p>/* State change detection (edge detection)<br>This example shows how to detect when a button or button changes from off to on
and on to off.
// this constant won't change:
const int buttonPin = 2; // the pin that the pushbutton is attached to
const int ledPin = 13; // the pin that the LED is attached to
// Variables will change:
int buttonPushCounter = 0; // counter for the number of button presses
int buttonState = 0; // current state of the button
int lastButtonState = 0; // previous state of the button
void setup() {
   // initialize the button pin as a input:
   pinMode(buttonPin, INPUT);
   // initialize the LED as an output:
   pinMode(ledPin, OUTPUT);
   // initialize serial communication:
void loop() {
   // read the pushbutton input pin:
   buttonState = digitalRead(buttonPin);
   // compare the buttonState to its previous state
   if (buttonState != lastButtonState) {
   // if the state has changed, increment the counter
   if (buttonState == HIGH) {
   // if the current state is HIGH then the button
   // wend from off to on:
   Serial.print("number of button pushes: ");
else {
   // if the current state is LOW then the button
   // wend from on to off:
// save the current state as the last state,
//for next time through the loop
lastButtonState = buttonState;
// turns on the LED every four button pushes by
// checking the modulo of the button push counter.
// the modulo function gives you the remainder of
// the division of two numbers:
if (buttonPushCounter % 4 == 0) {
digitalWrite(ledPin, HIGH);
  } else {
   digitalWrite(ledPin, LOW);

I convert this example and adapt to my sketchs of the remote controller and to the receptor. So

So I create three modes of movements:

  • The first one allows the linear potentiometer and joysticks move the hexapod
  • The second allows joysticks, the potentiometer and accelerometer move the hexapod
  • And the last mode let move hte hexapod walk, walk backwards,etc moving the two joystick simultaneously

Hi pro<br> I want some help <br>I want make for my project final year robot have arm using<br> 2 NRF24L01 and <br>2 arduino mega 2560 and 1pushbutton for 1 dc motor using in the hand <br>and 1 joystick for 2dc motor using in the driver robot body<br> and 1 joystick for 2 stepper motor using in moveing the arm the first to left and right and the second for up and down plz same halp in the code because iam new in the arduino world <br>And this is my gmail<br>blakjak65036@gmail.com<br>
<p>hi, i enjoyed your instructable but am not able to upload the code, please send me the full code for reciever and transmitter that you used for the hexapod. qballerr@gmail.com</p>
<p>hello!</p><p>Nice work here and very useful.</p><p>I want to use a potentiometer to control a servo via two nrf24l01s and two Arduino nanos. Do I just change &quot;joystick&quot; to &quot;potentiometer&quot; ? </p><p>Thanks for any help!</p>
<p>Very cool, congratulations</p>
I really like your project and I plan on starting it soon. Could I use one of these (included picture) Arduino joysticks? I'm not sure about etching them myself. I want to put all the controller parts inside a stripped-out xbox controller.
<p>This joystick is identical to mine joystick but I do not know if it incorporates the resistance fot the burtton to simplify connections or have to incorporate it.</p>
Thanks, I tjink I will try ot and see if it works properly. For the eye controller, is the trace design sticker printed from your computer?
<p>I remember that this trace design have a couple of errors</p>
<p>What kind of electrolytic capacitors did you use on the eye control board?</p>
<p>Now that's cool. Haven't seen someone hack together their own controller yet. Nice work!</p>
<p>Thank you</p>

About This Instructable




More by Deividmaxx:Transform a chinese 3D printer in a high precision dual 3D printer. Setting up: Marlin 1.0.2, Repetier 1.5.5, Slic3r 1.2.9 and Octoprint 0.12.0 DIY Remote Controller for Hexdrake DIY handmade Hexapod with arduino (Hexdrake) 
Add instructable to: