Web
Analytics
 

Getting started with the ACBR Wireless Controller Kit!

Updated: Apr 22, 2020

I am a huge fan of the RF Nano! The convenience of the good ol' Arduino Nano, built-in NRF24L01 Radio, and solid build quality. It's the easiest way to get two Arduinos talking, and that's why it's what we here at ACBR use as the heart of not only our ACBR Universal Wireless Controller, but also our Rover Robotics Kit, and Robotic Laser Cannon Kit.


This tutorial will take you step by step through the process of connecting our ACBR Wireless Controller to both our Rover Robotics Kit, and Robotic Laser Cannon Kit. We'll go over using the MPU60-50 Gyroscope / Accelerometer, and the Joysticks to control our robots. Keep in mind, this tutorial is also completely compatible with a standalone NRF24L01 and any sort of Arduino out there. In the following examples, we'll be using the RF Nano that ships with all of our Arduino based robotics kits.


Before getting started you may want to read our "Getting started with the RF Nano" tutorial, or watch our video on our youtube channel.


https://www.anyonecanbuildrobots.com/post/getting-started-with-the-rf-nano




Step One: Sending our Joystick Data

This first example will read the 4 channels of analog data (X and Y from the left and right joysticks) and two channels of digital data (the two push buttons of the left and right joysticks) and send that data back out using the onboard NRF24L01. Let's take a look!


Arduino Dual Joystick Send Code

  /*
   Hey Guys! 
   The following example code, is designed to take in the data from two 
   joysticks, and send that data out using the NRF24L01 2.4 GHz radio 
   transiever. Keep in mind, if you're using a stand alone NRF24L01 you 
   will absolutely need to use a 3.3v regulator, and not simply plug 
   the VCC pin of your radio into the 3.3v pin on your Arduino, trust 
   me it will save you a ton of trouble!  This code is also completely 
   compatible with the RF Nano (Arduino Nano with built in NRF24L01).
     
   Pins for Radio
   1 - GND - GND
   2 - VCC - 3.3v (through a voltage regulator)
   3 - CE - Arduino pin 9
   4 - CSN - Arduino pin 10
   5 - SCK - Arduino pin 13
   6 - MOSI - Arduino pin 11
   7 - MISO - Arduino pin 12
   8 - UNUSED
   
   Pins for Joysticks
   Vcc Right - 5V
   GND Right - GND
   VRX Right - Arduino Pin A0
   VRY Right - Arduino Pin A1
   SW Right - Arduino pin 2
   Vcc Left - 5V    
   GND Left - GND    
   VRX Left - Arduino Pin A2    
   VRY Left - Arduino Pin A3    
   SW Left - Arduino pin 3
 */
 
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Wire.h>
#define CE_PIN   10
#define CSN_PIN 9
const uint64_t pipe = 0x1;  
int controllerData[6];   
RF24 radio(CE_PIN, CSN_PIN);
int joyRX;
int joyRY;
int joyLX;
int joyLY;
int btnR = 2;
int btnL = 3; 
int btnStatusR;
int btnStatusL;

void setup()   
{
  Serial.begin(9600);
  pinMode(btnR, INPUT_PULLUP);
  pinMode(btnL, INPUT_PULLUP);
  radio.begin();
  radio.openWritingPipe(pipe);
}

void loop()   
{
  radio.write(controllerData, sizeof(controllerData) );
  joyRX = analogRead(A0);
  joyRY = analogRead(A1);
  joyLX = analogRead(A2);
  joyLY = analogRead(A3);
  btnStatusR = digitalRead(btnR);
  btnStatusL = digitalRead(btnL);
  controllerData[0] = joyRX;
  controllerData[1] = joyRY;
  controllerData[2] = joyLX;
  controllerData[3] = joyLY;
  controllerData[5] = btnStatusR;
  controllerData[6] = btnStatusL;
}
 

Alright, let's break that down a little bit. There are a few very important library files we need here. The first is the SPI Library, we'll need this to talk to our NRF radio. Now the next two libraries are a part of the rf24 Library, and this is where things get a little tricky. There are two popular libraries that have a very similar filename structure. All of my examples here are using the rf24 Library from GitHub user maniacbug. There are other libraries out there, but be sure to download the maniacbug bug rf24 library here.

https://github.com/maniacbug/RF24


Now if you're wiring up an external NRF24L01 make sure that you wire up the CE pin to pin D10 and the CSN pin to pin D9 of your Arduino.


#define CE_PIN 10 
#define CSN_PIN 9

Our next line of code is our communication pipeline, it's usually structured as a hexadecimal address. In this case, I have our communication pipeline labeled "0x1", to keep things really simple.

const uint64_t pipe = 0x1; 

The last thing to focus on here is our array. In this case, we have an array with six elements in it, and we've labeled it "controllerData". Since we're trying to send more than just one piece of data, we need to gather all of the different things we need to send in this data type we see here called an array. We're going to populate our array with data down in the void loop.

int controllerData[6];  

Next in our void setup, there are just a few things we need to take care of, the most important being initializing our radio.

pinMode(btnR, INPUT_PULLUP);
pinMode(btnL, INPUT_PULLUP);
radio.begin();
radio.openWritingPipe(pipe);

Lastly, we have our void loop. This is the part of our code that will read the various voltages coming from our joysticks, and place the variables associate with it in our array to send it out!

 void loop()  
{
  radio.write(controllerData, sizeof(controllerData) );
  joyRX = analogRead(A0);
  joyRY = analogRead(A1);
  joyLX = analogRead(A2);
  joyLY = analogRead(A3);
  btnStatusR = digitalRead(btnR);
  btnStatusL = digitalRead(btnL);
  controllerData[0] = joyRX;
  controllerData[1] = joyRY;
  controllerData[2] = joyLX;
  controllerData[3] = joyLY;
  controllerData[5] = btnStatusR;
  controllerData[6] = btnStatusL;
}

The radio.write command sends out our array, writing "sizeof(sendData)" lets us add multiple elements to our array, and send it out no matter what size it is (so long as it's not too long for our radio to handle).


The next few lines of code allow us to read the voltage changes coming from our joystick and assigns them a position in our array. Keep in mind, computers always start counting at "0" and not "1" as humans do. So in order to assign a value to the first element in our array, we need to assign it to position "0".


That's it! This first code will allow us to send out all of our joystick data, in the next step, we'll write our receiver sketch which will let us put that data to work!

Step Two: Receiving our Joystick Data for the Rover

This next example will read take 4 channels of analog data (X and Y from the left and right joysticks) and two channels of digital data (the two push buttons of the left and right joysticks) and let us use that data to control our ACBR Rover Robotics Kit. Keep in mind, you can absolutely adjust this code to work for any Arduino based robot. Let's take a look!

Arduino Dual Joystick Receiver Code for Rover

  /*
   Hey Guys! 
   The following example code, is designed to receive the data from two 
   joysticks using the NRF24L01 2.4 GHz radio transiever. Then use that 
   data to control an Arduino based robot. While this code was 
   designed for the ACBR Rover Robotics kit, it can be adapted to be 
   used with any arduino based robot. Keep in mind, if you're using a 
   stand alone NRF24L01 you will absolutely need to use a 3.3v 
   regulator, and not simply plug the VCC pin of your radio into the 
   3.3v pin on your Arduino, trust me it will save you a ton of 
   trouble!  This code is also completely compatible with the RF Nano 
   (Arduino Nano with built in NRF24L01).
     
   Pins for Radio
   1 - GND - GND
   2 - VCC - 3.3v (through a voltage regulator)
   3 - CE - Arduino pin 9
   4 - CSN - Arduino pin 10
   5 - SCK - Arduino pin 13
   6 - MOSI - Arduino pin 11
   7 - MISO - Arduino pin 12
   8 - UNUSED
 */
 
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#define CE_PIN 10
#define CSN_PIN 9
const uint64_t pipe = 0x1;  
RF24 radio(CE_PIN, CSN_PIN);
int controllerData[6];
int enOne = 3;
int inOne = 4;
int inTwo = 5;
int enTwo = 6;
int inThree = 7;
int inFour = 8;

void setup()  
{
  Serial.begin(9600);
  delay(1000);
  Serial.println("Nrf24L01 Receiver Starting");
  radio.begin();
  radio.openReadingPipe(1,pipe);
  radio.startListening();
  pinMode(enOne, OUTPUT);
  pinMode(enTwo, OUTPUT);
  pinMode(inOne, OUTPUT);
  pinMode(inTwo, OUTPUT);
  pinMode(inThree, OUTPUT);
  pinMode(inFour, OUTPUT);
}


void loop()   
{
  if ( radio.available() )
  {
    bool done = false;
    while (!done)
    {
      done = radio.read(controllerData, sizeof(controllerData));
      Serial.print(controllerData[0]);
      Serial.print(" ");
      Serial.print(controllerData[1]);
      Serial.print(" ");
      Serial.print(controllerData[2]);
      Serial.print(" ");
      Serial.print(controllerData[3]);
      Serial.print(" ");
      Serial.print(controllerData[4]);
      Serial.print(" ");
      Serial.println(controllerData[5]);
      delay(50);
      
      if(controllerData[0] > 700)
      {
        Serial.println("forward!!!");
        analogWrite(enOne, 255);
        digitalWrite(inOne, LOW);
        digitalWrite(inTwo, HIGH);
        analogWrite(enTwo, 255);
        digitalWrite(inThree, LOW);
        digitalWrite(inFour, HIGH); 
      }
      else if(controllerData[0] < 300)
      {
        Serial.println("backwards!!");
        analogWrite(enOne, 255);
        digitalWrite(inOne, HIGH);
        digitalWrite(inTwo, LOW);
        analogWrite(enTwo, 255);
        digitalWrite(inThree, HIGH);
        digitalWrite(inFour, LOW); 
      }

      else if(controllerData[1] > 800)
      {
        Serial.println("left!");
        analogWrite(enOne, 255);
        digitalWrite(inOne, LOW);
        digitalWrite(inTwo, HIGH);
        analogWrite(enTwo, 255);
        digitalWrite(inThree, HIGH);
        digitalWrite(inFour, LOW);
      }
      else if(controllerData[1] < 300)
      {
        Serial.println("right!");
        analogWrite(enOne, 255);
        digitalWrite(inOne, HIGH);
        digitalWrite(inTwo, LOW);
        analogWrite(enTwo, 255);
        digitalWrite(inThree, LOW);
        digitalWrite(inFour, HIGH);
      }
      else
      {
       Serial.println("Stopped!");
       analogWrite(enOne, 0);
       digitalWrite(inOne, LOW);
       digitalWrite(inTwo, LOW);
       analogWrite(enTwo, 0);
       digitalWrite(inThree, LOW);
       digitalWrite(inFour, LOW);
      }
    }
  }
  else
  {    
      Serial.println("Darn, not working yet!");
       analogWrite(enOne, 0);
       digitalWrite(inOne, LOW);
       digitalWrite(inTwo, LOW);
       analogWrite(enTwo, 0);
       digitalWrite(inThree, LOW);
       digitalWrite(inFour, LOW);
  }
}

Alright, let's break this down a little bit! The library files we'll need for the receiver circuit as the exact same. If you take a closer look, you'll see that the array has the same label and size, and the communication pipeline is also the same, this is really important. Other than that, the rest of our code above the void loop has to do with driving around the ACBR Rover. I won't go into too much detail here about the robot's movement, we cover that in great detail in the documentation we ship out with our rover kit! This code is assuming you're using an L293D or L298n, but it can absolutely be adapted to work with any motor driver out there.


In our void setup, the most important thing we need to do is start up the reading pipeline, as well as the Serial Monitor. We also need to set up the pins we're using for our motor driver as outputs.

void setup()  
{
  Serial.begin(9600);
  delay(1000);
  Serial.println("Nrf24L01 Receiver Starting");
  radio.begin();
  radio.openReadingPipe(1,pipe);
  radio.startListening();
  pinMode(enOne, OUTPUT);
  pinMode(enTwo, OUTPUT);
  pinMode(inOne, OUTPUT);
  pinMode(inTwo, OUTPUT);
  pinMode(inThree, OUTPUT);
  pinMode(inFour, OUTPUT);
}

Once we get to the void loop, we're greeted with a set of conditional statements designed to check whether radio data is available. If no radio data is available, we print the error message we see at the bottom of our code. Next, we unpack our array one element at a time and print them out in the Serial Monitor. While our goal is to drive around our robot, it's really helpful to see the controller data in the Serial Monitor first, to make sure things are working. The last and very important aspect of this first bit of code is the delay. This may seem arbitrary, but from all of my tests, I've found that if I go too much smaller, the connection suffers a great deal, and if you have any problems connecting, I would try increasing the delay.

 if ( radio.available() )
  {
    bool done = false;
    while (!done)
    {
      done = radio.read(controllerData, sizeof(controllerData));
      Serial.print(controllerData[0]);
      Serial.print(" ");
      Serial.print(controllerData[1]);
      Serial.print(" ");
      Serial.print(controllerData[2]);
      Serial.print(" ");
      Serial.print(controllerData[3]);
      Serial.print(" ");
      Serial.print(controllerData[4]);
      Serial.print(" ");
      Serial.println(controllerData[5]);
      delay(50);

The last part of our void loop takes the joystick data and uses it to drive around our robot! Keep in mind, this first example is really simple, it uses just one joystick, and does not vary the robots speed based on joystick position, that being said, it's super easy to set up both joysticks, and add all kinds of cool features to this code! Feel free to hack it, and switch things up! Feel free to comment below as well if you have any questions about taking things to the next level.


Congrats! You've now got the ACBR Rover Robotics kit rolling around with the Wireless controller kit! Now that we have that taken care of, let's get it working with our robotic laser cannon kit!

Step Three: Controlling the Robotic Laser Cannon Kit

Now that we have the rover all set, let's see just how easy it is to take that same data, and use it to control a servo based Arduino project! In this case, we'll use the ACBR Robotic Laser Cannon Kit as an example. The Send code will stay the exact same, all we'll need to do is customize the receiver code to work with our laser cannon. Let's try it out!


Arduino Dual Joystick Receiver Code for Robotic Laser Cannon Kit

  /*
   Hey Guys! 
   The following example code, is designed to receive the data from two 
   joysticks using the NRF24L01 2.4 GHz radio transiever. Then use that 
   data to control a servo based Arduino project, as well as the ACBR 
   Robotic Laser Cannon Kit. While this code was designed for the ACBR 
   Laser Cannon kit, it can be adapted to be used with any arduino 
   based robot. Keep in mind, if you're using a stand alone NRF24L01 
   you will absolutely need to use a 3.3v regulator, and not 
   simply plug the VCC pin of your radio into the 3.3v pin on your 
   Arduino, trust me it will save you a ton of trouble!  This code is 
   also completely compatible with the RF Nano (Arduino Nano with built 
   in NRF24L01).
     
   Pins for Radio
   1 - GND - GND
   2 - VCC - 3.3v (through a voltage regulator)
   3 - CE - Arduino pin 9
   4 - CSN - Arduino pin 10
   5 - SCK - Arduino pin 13
   6 - MOSI - Arduino pin 11
   7 - MISO - Arduino pin 12
   8 - UNUSED 
 */
 
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Servo.h>
#define CE_PIN   10
#define CSN_PIN 9
const uint64_t pipe = 0x1;   
RF24 radio(CE_PIN, CSN_PIN);
int controllerData[6];
Servo servoX;
Servo servoY;
int laser = 3;
int posX = 90;
int posY = 90;

void setup()  
{
  Serial.begin(9600);
  servoX.attach(3);
  servoY.attach(5);
  pinMode(laser, OUTPUT); 
  delay(1000);
  Serial.println("Nrf24L01 Receiver Starting");
  radio.begin();
  radio.openReadingPipe(1,pipe);
  radio.startListening();
}


void loop()   
{
  digitalWrite(laser, HIGH);
  if ( radio.available() )
  {
    bool done = false;
    while (!done)
    {
      done = radio.read(controllerData, sizeof(controllerData));
      Serial.print(controllerData[0]);
      Serial.print(" ");
      Serial.print(controllerData[1]);
      Serial.print(" ");
      Serial.print(controllerData[2]);
      Serial.print(" ");
      Serial.print(controllerData[3]);
      Serial.print("  ");
      Serial.print(controllerData[4]);
      Serial.print("  ");
      Serial.println(controllerData[5]);
      delay(50);
      if(controllerData[0] > 800 && posX < 180)
      {
        posX+=5;
        servoX.write(posX);
        Serial.println("up");
      }
      else if(controllerData[0] < 200 && posX > 0)
      {
        posX-=5;
        servoX.write(posX);
        Serial.println("down");
      }
      else if(controllerData[3] > 800 && posY < 180)
      {
        posY+=5;
        servoY.write(posY);
        Serial.println("left");
      }
      else if(controllerData[3] < 200 && posY > 0)
      {
        posY-=5;
        servoY.write(posY);
        Serial.println("right");
      }
    }
  }
  else
  {    
      Serial.println("Darn, not working yet!");
  }
}

This receiver example will look a lot like our receiver for our Rover Robotics Kit. The biggest difference is that we're using the joystick data to increase and decrease position variables, and use those variables to move a set of servos! Like our previous example, this guy is pretty basic, feel free to add in features like button clicks to fire your laser beam! There are all kinds of fun stuff you can do.


Step Four: Let's send our Gyro Data!

Now that we have the joystick data sent and received, it's time to move on to sending over our Gyroscope and Accelerometer data! For this, we'll need to add in some code to get that data from out MPU60-50. These are all kinds of accelerometer breakout boards out there. I love using these MPU60-50 accelerometer/gyroscope combo boards, they'll let us add a really cool gesture control feature to our robotics projects! We'll go through the process of sending out our MPU60-50 data, then use that data to control our Rover Robotics Kit, and our Robotic Laser Cannon Kit.


Arduino MPU60-50 Send Code

   /*
   Hey Guys! 
   The following example code, is designed to receive the data from two 
   joysticks using the NRF24L01 2.4 GHz radio transiever. Then use that 
   data to control a servo based Arduino project, as well as the ACBR 
   Robotic Laser Cannon Kit. While this code was designed for the ACBR 
   Laser Cannon kit, it can be adapted to be used with any arduino 
   based robot. Keep in mind, if you're using a stand alone NRF24L01 
   you will absolutely need to use a 3.3v regulator, and not 
   simply plug the VCC pin of your radio into the 3.3v pin on your 
   Arduino, trust me it will save you a ton of trouble!  This code is 
   also completely compatible with the RF Nano (Arduino Nano with built 
   in NRF24L01).
   
   Pins for Radio
   1 - GND 
   2 - VCC 5v
   3 - CE - Arduino pin 9
   4 - CSN - Arduino pin 10
   5 - SCK - Arduino pin 13
   6 - MOSI - Arduino pin 11
   7 - MISO - Arduino pin 12
   8 - UNUSED

   Pins for GYRO
   Vcc - 5V
   GND - GND
   SCL - Arduino Pin A5
   SDA - Arduino Pin A4
 */
 
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Wire.h>
#define MPU 0x68  // I2C address of the MPU-6050
#define CE_PIN   10
#define CSN_PIN 9

const uint64_t pipe = 0x1; 
double AcX,AcY,AcZ;
int Pitch, Roll;
int GYRO[2];  
RF24 radio(CE_PIN, CSN_PIN); 

void setup()   
{
  Serial.begin(9600); 
  radio.begin();
  radio.openWritingPipe(pipe);
  init_MPU();
}


void loop()   
{
  radio.write( GYRO, sizeof(GYRO) );
  FunctionsMPU();  
  Roll = FunctionsPitchRoll(AcX, AcY, AcZ);   
  Pitch = FunctionsPitchRoll(AcY, AcX, AcZ);  
  GYRO[0] = Pitch;
  GYRO[1] = Roll;
  Serial.print("Pitch: "); Serial.print(Pitch);
  Serial.print("\t");
  Serial.print("Roll: "); Serial.print(Roll);
  Serial.print("\n");
  
}
 
void init_MPU(){
  Wire.begin();
  Wire.beginTransmission(MPU);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);
  delay(1000);
}
 

double FunctionsPitchRoll(double A, double B, double C){
  double DatoA, DatoB, Value;
  DatoA = A;
  DatoB = (B*B) + (C*C);
  DatoB = sqrt(DatoB);
  
  Value = atan2(DatoA, DatoB);
  Value = Value * 180/3.14;
  
  return (int)Value;
}

void FunctionsMPU(){
  Wire.beginTransmission(MPU);
  Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU,6,true);  // request a total of 14 registers
  AcX=Wire.read()<<8|Wire.read();  
  AcY=Wire.read()<<8|Wire.read();  
  AcZ=Wire.read()<<8|Wire.read();  
}

The main difference in our new send code vs our last one is that in this instance, we need to add in a few variables to access the i2c data from the MPU60-50. the second major difference is that in this case we created an array and labeled it "GYRO" and added in two elements, not just one like our previous example. One for "Pitch", and one for "Roll".


In our void loop, the first thing we need to do is use the write command to send our GYRO array.

radio.write( GYRO, sizeof(GYRO) );

Once we start reading our data, it's time to unpack our array and assign the element arrays to two variables of our, Pitch and Roll.

  GYRO[0] = Pitch;   
  GYRO[1] = Roll;

The rest of our void loop is a series of print statements to make sure that our MPU60-50 is reading our data correctly. This way we can make sure the data we're sending is the same as the data we're going to end up receiving. There are three other methods we use in this bit of code underneath our void loop, they're all designed to establish i2c communication, as well as calculate our pitch and roll based on our accelerometer data. Now that we have our MPU60-50 data being sent out, let's put that data to work!

Step Five: Using our MPU60-50 with the Rover

With the MPU60-50 data being sent out of our controller, the first step will be getting it connected to our Rover. Most of this code should look familiar, all we're swapping out here is the joystick data, for our new data!


MPU60-50 Receiver Example for Rover


  /*
   Hey Guys! 
   The following example code, is designed to receive the MPU60-50
   using the NRF24L01 2.4 GHz radio transiever. Then use that 
   data to control an Arduino based robot, as well as the ACBR 
   Rover Robotics kit. While this code was designed for the ACBR 
   Laser Cannon kit, it can be adapted to be used with any arduino 
   based robot. Keep in mind, if you're using a stand alone NRF24L01 
   you will absolutely need to use a 3.3v regulator, and not 
   simply plug the VCC pin of your radio into the 3.3v pin on your 
   Arduino, trust me it will save you a ton of trouble!  This code is 
   also completely compatible with the RF Nano (Arduino Nano with built 
   in NRF24L01).
   
   Pins for Radio
   1 - GND 
   2 - VCC 5v
   3 - CE - Arduino pin 9
   4 - CSN - Arduino pin 10
   5 - SCK - Arduino pin 13
   6 - MOSI - Arduino pin 11
   7 - MISO - Arduino pin 12
   8 - UNUSED

   Pins for GYRO
   Vcc - 5V
   GND - GND
   SCL - Arduino Pin A5
   SDA - Arduino Pin A4
 */

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Servo.h>
#define CE_PIN   10
#define CSN_PIN 9
const uint64_t pipe = 0x1;   
RF24 radio(CE_PIN, CSN_PIN);
int gyro[2]; 
int enOne = 3;
int inOne = 4;
int inTwo = 5;
int enTwo = 6;
int inThree = 7;
int inFour = 8;

void setup()  
{
  Serial.begin(9600); 
  delay(1000);
  Serial.println("Nrf24L01 Receiver Starting");
  pinMode(enOne, OUTPUT);
  pinMode(inOne, OUTPUT);
  pinMode(inTwo, OUTPUT);
  pinMode(enTwo, OUTPUT);
  pinMode(inThree, OUTPUT);
  pinMode(inFour, OUTPUT);
  radio.begin();
  radio.openReadingPipe(1,pipe);
  radio.startListening();
}


void loop()   
{
  if ( radio.available() )
  {
    bool done = false;
    while (!done)
    {
      done = radio.read(gyro, sizeof(gyro));
      Serial.print("GYRO X: ");
      Serial.print(gyro[0]);
      Serial.print(" GYRO Y: ");
      Serial.println(gyro[1]);
      
      if(gyro[0] > 30)
      {
        Serial.println("right");
        analogWrite(enOne, 255);
        digitalWrite(inOne, HIGH);
        digitalWrite(inTwo, LOW);
        analogWrite(enTwo, 255);
        digitalWrite(inThree, LOW);
        digitalWrite(inFour, HIGH);
      }
      else if(gyro[0] < -30)
      {
        Serial.println("left");
        analogWrite(enOne, 255);
        digitalWrite(inOne, LOW);
        digitalWrite(inTwo, HIGH);
        analogWrite(enTwo, 255);
        digitalWrite(inThree, HIGH);
        digitalWrite(inFour, LOW);
      }
      else if(gyro[1] > 30)
      {
        Serial.println("backward");
        analogWrite(enOne, 255);
        digitalWrite(inOne, HIGH);
        digitalWrite(inTwo, LOW);
        analogWrite(enTwo, 255);
        digitalWrite(inThree, HIGH);
        digitalWrite(inFour, LOW);
      }
      else if(gyro[1] < -30)
      {
        Serial.println("forward");
        analogWrite(enOne, 255);
        digitalWrite(inOne, LOW);
        digitalWrite(inTwo, HIGH);
        analogWrite(enTwo, 255);
        digitalWrite(inThree, LOW);
        digitalWrite(inFour, HIGH); 
      }
      else
      {
        Serial.println("stopped");
        analogWrite(enOne, 0);
        digitalWrite(inOne, LOW);
        digitalWrite(inTwo, LOW);
        analogWrite(enTwo, 0);
        digitalWrite(inThree, LOW);
        digitalWrite(inFour, LOW); 
      }
      delay(50);
    }
  }
  else
  {    
      Serial.println("Darn, not working yet!");
  }
}

Step Six: Using our MPU60-50 with the Robotic Laser Cannon Kit

Alright, now that we have the rover all set, we can use our MPU60-50 data to control our robotic laser cannon kit, just like before.

MPU60-50 Receiver Example for Robotic Laser Cannon

/* 
   Hey Guys! 
   The following example code, is designed to receive the data from an 
   MPU60-50 using the NRF24L01 2.4 GHz radio transiever. Then use that 
   data to control a servo based Arduino project, as well as the ACBR 
   Robotic Laser Cannon Kit. While this code was designed for the ACBR 
   Laser Cannon kit, it can be adapted to be used with any arduino 
   based robot. Keep in mind, if you're using a stand alone NRF24L01 
   you will absolutely need to use a 3.3v regulator, and not 
   simply plug the VCC pin of your radio into the 3.3v pin on your 
   Arduino, trust me it will save you a ton of trouble!  This code is 
   also completely compatible with the RF Nano (Arduino Nano with built 
   in NRF24L01).
   
   1 - GND 
   2 - VCC 3.3V 
   3 - CE - Arduino pin 9
   4 - CSN - Arduino pin 10
   5 - SCK - Arduino pin 13
   6 - MOSI - Arduino pin 11
   7 - MISO - Arduino pin 12
   8 - UNUSED 
*/

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Servo.h>
#define CE_PIN   10
#define CSN_PIN 9
const uint64_t pipe = 0x1;  
RF24 radio(CE_PIN, CSN_PIN);
int GYRO[2]; 
int laser = 4;
int posX = 90;
int posY = 90;
Servo servoX;
Servo servoY;

void setup()  
{
  Serial.begin(9600); 
  delay(1000);
  Serial.println("Nrf24L01 Receiver Starting");
  servoX.attach(3);
  servoX.write(posX);
  servoY.attach(5);
  servoY.write(posY);
  pinMode(laser, OUTPUT);
  radio.begin();
  radio.openReadingPipe(1,pipe);
  radio.startListening();
}


void loop()   
{
  digitalWrite(laser, HIGH);
  if ( radio.available() )
  {
    bool done = false;
    while (!done)
    {
      done = radio.read(GYRO, sizeof(GYRO));
      Serial.print("Gyro Data: ");
      Serial.print(GYRO[0]);
      Serial.print("  ");
      Serial.println(GYRO[1]);
      
      if(GYRO[1] < - 30 && posY > 0)
      {
        Serial.println("Forward");
        posY-=5;
        servoY.write(posY);
      }
      else if(GYRO[1] > 30 && posY < 180)
      {
        Serial.println("Backward");
        posY+=5;
        servoY.write(posY);
      }
      else if(GYRO[0] < - 30 && posX < 180)
      {
        Serial.println("Left");
        posX+=5;
        servoX.write(posX);
      }
      else if(GYRO[0] > 30 and posX > 0)
      {
        Serial.println("Right");
        posX-=5;
        servoX.write(posX);
      }
      delay(50);
    }
  }
  else
  {    
      Serial.println("Darn, not working yet!");
  }
}

In the code above our void setup in our new receiver code, the biggest change is probably the addition of our two servos, as well as our position variables. We set our position variables at 90, so that way every time we start up our code, both servos will be in the middle of their range of motion. The code in our void setup, looks almost identical to our previous example, except this time we need to attach our servos to two PWM pins on our Arduino. In this case, we're using pins 3 and 5. The most important part of our main void loop is grabbing both elements of our array. One of the first things we do after checking to see if we have a radio connection is to print out both elements of our array, one after the other.

      Serial.print("Gyro Data: ");       
      Serial.print(GYRO[0]);       
      Serial.print("  ");       
      Serial.println(GYRO[1]);

Now, what really sets this code apart from our first example, is that we don't simply want to print out our data, we want to use that data to move our servos! We can accomplish this with just a few short lines of code.

      if(GYRO[1] < - 30 && posY > 0)       
      {         
      Serial.println("Forward");         
      posY-=5;         
      servoY.write(posY);       
      }

Here we have a conditional statement with two conditions. The first half of our conditional statement checks if our Pitch variable is less than -30, which in this case is the same as learning the MPU60-50 forward. The second condition checks to see if the servo is already at its minimum position (zero degrees). So if the Pitch value is less than -30, and we haven't hit the limit, we tell the Arduino to print "forward", but that's not all. We are also telling the Arduino to take 5 away from the value of our posY variable. If you think back to the first few lines of code, we made the value of posY 90, for 90 degrees, but if we take away 5 degrees, we're at 85. The last thing we do is tell our servo to move to whatever the value of our position variable happens to be. Now, 5 degrees doesn't sound like a lot, and it's not. But if you continue to hold the MPU60-50 forward, the Arduino will continue to take away 5 degrees, in this case, it's every 5/100th of a second! So our servos actually end up moving pretty quickly! If you find that your servos are moving too fast, you can always swap out the "5" for a smaller number.


Now, the rest of the void loop conditions do the exact same thing, except this time they are adding to the value of posY when you hold the MPU60-50 backward and are adding and subtracting from the posX variable whenever you move the MPU60-50 from side to side.

Step Seven: Hack it up!

Alright, that was a ton! So to summarize, we sent joystick data out of our controller, then used that data to control our Rover Robotics Kit, and Robotic Laser Cannon Kit. We also sent out our MPU60-50 data, and used that data to control both kits! There are tons of other ways to use this awesome little chip to control your projects, and all kinds of data you can send an receive. Have fun! Feel free to comment below with any questions you have, or projects you've been working on!

236 views0 comments

Recent Posts

See All

Anyone Can Build Robots!

1+ (858) 434 5830

©2020 by Anyone Can Build Robots!