Notifications
Clear all

Radio Control - Two Arduino Uno - Two nrf24L01 - One pca9685 - Two Joysticks - Four Servos

12 Posts
4 Users
3 Reactions
1,926 Views
 Fred
(@fred)
Member
Joined: 2 years ago
Posts: 8
Topic starter  

I need help with code, and any other input that would make the plan for my project better. I'm a beginner with Arduino and programming.

I'm trying to combine code from two tutorials, a CreateLabz radio control tutorial with two joysticks and four servos, and a DroneBot tutorial for controlling four servos with the pca9685 module. I want to learn how to use the pca9685 in this configuration for when I want to control more than four servos using radio control.

I completed each tutorial and they both function well.

I'm quite sure that my problem with combining the CreateLabz receiver code with the DroneBot tutorial code is that the incoming signal (which shows on the serial monitor),

//CreateLabz code

int joystick[4];

is not being read by the motorControl function,

//DroneBot code

void moveMotor(int controlIn, int motorOut)

{

  int pulse_wide, pulse_width, potVal;

  

  // Read values from potentiometer

  potVal = digitalRead(controlIn);

  

  // Convert to pulse width EDIT replace "potVal" with "joystick"

  pulse_wide = map(potVal, 0, 1023, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);

  pulse_width = int(float(pulse_wide) / 1000000 * FREQUENCY * 4096);

  

  //Control Motor

  pwm.setPWM(motorOut, 0, pulse_width);



}

and I don't know how to write this code or modify the moveMotor function.

Please help!

I've tried writing the code but haven't had any success.

I don't know where to learn about the moveMotor function.

I'm quite sure that in the DroneBot code the moveMotor function is reading the input from the joysticks (potentiometers) (with no radio control involved):

// Define Potentiometer Inputs

int controlA = A0;

int controlB = A1;

int controlC = A2;

int controlD = A3;

I wanted to keep this post as economical as I could, but I'll post more info about hardware and code as needed to get help.

Fred


   
Quote
Will
 Will
(@will)
Member
Joined: 3 years ago
Posts: 2538
 

@fred

Can you please tell us what you think is going to happen and what actually happens ? Neither is very clear from the code.

 

For instance "joystick" only appears in the definition at the top and the comment, but you seem to be expecting it to be changed ... ?

Anything seems possible when you don't know what you're talking about.


   
ReplyQuote
robotBuilder
(@robotbuilder)
Member
Joined: 5 years ago
Posts: 2043
 

@fred

It is very unclear to me what you are trying to do.  I am familiar with  the DroneBot tutorial for controlling four servos with the pca9685 module but a link to the CreateLabz radio control tutorial might help.

 

 

 


   
ReplyQuote
 Fred
(@fred)
Member
Joined: 2 years ago
Posts: 8
Topic starter  

@will Hi Will, Thanks for responding so quickly to my post.

I'll try to describe what I want more clearly.

My Arduino Uno/nrf24L01/pca9685/servos radio control receiver is receiving signals in an array from the transmitter's two joysticks: int joysticks[4];

My goal is to make the servos in the receiver respond to the joysticks in the transmitter.

I don't know how to write the code so that the motorControl function in the receiver will use the joysticks signals to send the PMW signal to the pca9685 module to make the servos move. I think it has to do with this line of the code:

// Read values from potentiometer
potVal = digitalRead(controlIn);

 

Here is the code I've put together for the receiver. I don't know how to complete or modify the code to make it do what I want.

#include <SPI.h>
#include <RF24.h>
//#include <Servo.h>

#include <Adafruit_PWMServoDriver.h>

// Include Wire Library for I2C Communications
#include <Wire.h>

// Include Adafruit PWM Library
#include <Adafruit_PWMServoDriver.h>

#include <Servo.h>

#define MIN_PULSE_WIDTH 650
#define MAX_PULSE_WIDTH 2350
#define FREQUENCY 50

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
RF24 radio(7, 8);

const byte rxAddr[6] = "00001";

int joystick[4];

// Define positions sent to servos
int controlA;
int controlB;
int controlC;
int controlD;

// Define Motor Outputs on PCA9685 board
int motorA = 0;
int motorB = 4;
int motorC = 8;
int motorD = 12;

void setup()
{
pwm.begin();
pwm.setPWMFreq(FREQUENCY);

for(int i = 2; i<=4; i++){
pinMode(i,OUTPUT);
}

while (!Serial);
Serial.begin(9600);

radio.begin();
radio.setPALevel(RF24_PA_MAX);
radio.setAutoAck(false);
radio.openReadingPipe(0, rxAddr);
radio.startListening();

delay(50);

}

void moveMotor(int controlIn, int motorOut)
{
int pulse_wide, pulse_width, potVal;

// Read values from potentiometer
potVal = digitalRead(controlIn);

pulse_wide = map(potVal, 0, 1023, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
pulse_width = int(float(pulse_wide) / 1000000 * FREQUENCY * 4096);

//Control Motor
pwm.setPWM(motorOut, 0, pulse_width);

}

void loop()
{
if (radio.available())
{
bool done = false;
while (!done)
{ 
// Fetching the data payload
radio.read( joystick, sizeof(joystick) );
done = true;

Serial.println(joystick[0]);
Serial.println(joystick[1]);
Serial.println(joystick[2]);
Serial.println(joystick[3]);

//Control Motor A
moveMotor(controlA, motorA);

//Control Motor B
moveMotor(controlB, motorB);

//Control Motor C
moveMotor(controlC, motorC);

//Control Motor D
moveMotor(controlD, motorD);

}
}
else{
Serial.println("Data not received");

}

delay(50);
}

   
ReplyQuote
Will
 Will
(@will)
Member
Joined: 3 years ago
Posts: 2538
 

@fred 

OK, I think what you're telling me is that you want to use the values in joystick[0] to joystick[3] as the pot values.

Change your  sub to ...

void moveMotor(int potVal, int motorOut)
{
    int pulse_wide, pulse_width;
        
    pulse_wide = map(potVal, 0, 1023, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
    pulse_width = int(float(pulse_wide) / 1000000 * FREQUENCY * 4096);
    
    //Control Motor
    pwm.setPWM(motorOut, 0, pulse_width); 
}

 And change the loop part

 

    //Control Motor A
    moveMotor(controlA, motorA);
    
    //Control Motor B
    moveMotor(controlB, motorB);
    
    //Control Motor C
    moveMotor(controlC, motorC);
    
    //Control Motor D
    moveMotor(controlD, motorD);

 to

 

    //Control Motor A
    moveMotor(joystick[0], motorA);
    
    //Control Motor B
    moveMotor(joystick[1], motorB);
    
    //Control Motor C
    moveMotor(joystick[2], motorC);
    
    //Control Motor D
    moveMotor(joystick[3], motorD);

 

Changing the loop section will cause the transmitted pot values to be sent to the moveMotor subroutine.

Changing moveMotor to accept the supplied value of potVal (sent via joystick[n]) just bypasses reading a potentiometer and uses the pot reading sent from the transmitter to calculate the value to send to setPWM.

 

Anything seems possible when you don't know what you're talking about.


   
ReplyQuote
 Biny
(@binaryrhyme)
Member
Joined: 2 years ago
Posts: 269
 

From what I see, the data you are receiving is put into the 4 bytes of joystick, which you print out, but then never use. Methinks you need to assign the value to the moveMotor, potentially with some manner of transformation to suit the motor.

controlA = joystick[0]; // or the like

edit: what @will said while I was typing, basically. 🙂

I edit my posts to fix typos, correct grammar, or improve clarity. On-screen keyboards are evil.


   
ReplyQuote
 Fred
(@fred)
Member
Joined: 2 years ago
Posts: 8
Topic starter  

@robotbuilder Hi robotbuilder,

I can't find CreateLabz on the internet now. It must be defunct.

The best I can do is show you the code (below) for the transmitter which I modified from the CreateLabz code. I already posted my receiver code in another reply.

Thanks for any help.

Fred

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio(7, 8);

const byte rxAddr[6] = "00001";

int sendingdata[4];

void setup()
{
Serial.begin(9600);
radio.begin();
radio.setPALevel(RF24_PA_MAX);
radio.setAutoAck(false);
radio.setRetries(15, 15);
radio.openWritingPipe(rxAddr);

radio.stopListening();

delay(50);
}

void loop()
{
int in1 = analogRead(A0); //Right Stick Up and Down
int in2 = analogRead(A1); //Right Stick Left and Right
int in3 = analogRead(A2); //left Stick Up and Down
int in4 = analogRead(A3); //Left Stick Left and Right

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

sendingdata[0]=in1;
sendingdata[1]=in2;
sendingdata[2]=in3;
sendingdata[3]=in4;
radio.write( sendingdata, sizeof(sendingdata) );

delay(50);
}

   
ReplyQuote
 Fred
(@fred)
Member
Joined: 2 years ago
Posts: 8
Topic starter  

@will Hi Will,

Thanks for the guidance.

It is getting late where I live. I'll modify the code tomorrow and post an update.

Fred


   
Biny reacted
ReplyQuote
Will
 Will
(@will)
Member
Joined: 3 years ago
Posts: 2538
 
Posted by: @fred

Thanks for the guidance.

It is getting late where I live. I'll modify the code tomorrow and post an update.

OK, we'll check back with you tomorrow after testing 🙂

Anything seems possible when you don't know what you're talking about.


   
Biny reacted
ReplyQuote
robotBuilder
(@robotbuilder)
Member
Joined: 5 years ago
Posts: 2043
 

@fred 

If you get it working I would be interested in your solution.

I did buy a pca9685 some time ago but haven't used it yet.

I have successfully sent text between two Unos,  each with its own nrf24L01,  but haven't been able to send the four values using your example getting only the data not received.  I will try to debug it tomorrow.

 


   
ReplyQuote
 Fred
(@fred)
Member
Joined: 2 years ago
Posts: 8
Topic starter  

@will Hi Will,

Success!

Your code fixes did the trick. The four servos in the receiver all respond to the joysticks at the transmitter.

Since I'm new to writing code, now I'll try to understand how your fixes worked.

Thank you, Will. I am really pleased to have this working.

For any Forum members who are interested, the transmitter and receiver code are included below.

As a reminder the hardware used is:

Transmitter - Arduino Uno, two joysticks, nrf24L01 with larger antenna and with nrf24L01 Adapter Module

Receiver - Arduino Uno, nrf24L01 with small printed antenna and with nrf24L01 Adapter Module, pca9685, four servos

I can try to put together diagrams of the hardware connections if any Forum member wants them.

Fred

Transmitter Code:

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio(7, 8);

const byte rxAddr[6] = "00001";

int joystick[4];

void setup()
{
Serial.begin(9600);
radio.begin();
radio.setPALevel(RF24_PA_MAX);
radio.setAutoAck(false);
radio.setRetries(15, 15);
radio.openWritingPipe(rxAddr);

radio.stopListening();

delay(50);
}

void loop()
{
int in1 = analogRead(A0); //Right Stick Up and Down
int in2 = analogRead(A1); //Right Stick Left and Right
int in3 = analogRead(A2); //left Stick Up and Down
int in4 = analogRead(A3); //Left Stick Left and Right

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

joystick[0]=in1;
joystick[1]=in2;
joystick[2]=in3;
joystick[3]=in4;
radio.write( joystick, sizeof(joystick) );

delay(50);
}

Receiver Code:

#include <SPI.h>
#include <RF24.h>
//#include <Servo.h>

#include <Adafruit_PWMServoDriver.h>

// Include Wire Library for I2C Communications
#include <Wire.h>

// Include Adafruit PWM Library
#include <Adafruit_PWMServoDriver.h>

#include <Servo.h>

#define MIN_PULSE_WIDTH 650
#define MAX_PULSE_WIDTH 2350
#define FREQUENCY 50

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
RF24 radio(7, 8);

const byte rxAddr[6] = "00001";

int joystick[4];

// Define positions sent to servos
int controlA;
int controlB;
int controlC;
int controlD;

// Define Motor Outputs on PCA9685 board
int motorA = 0;
int motorB = 4;
int motorC = 8;
int motorD = 12;

void setup()
{
pwm.begin();
pwm.setPWMFreq(FREQUENCY);

for(int i = 2; i<=4; i++){
pinMode(i,OUTPUT);
}

while (!Serial);
Serial.begin(9600);

radio.begin();
radio.setPALevel(RF24_PA_MAX);
radio.setAutoAck(false);
radio.openReadingPipe(0, rxAddr);
radio.startListening();

delay(50);

}

void moveMotor(int potVal, int motorOut)
{
int pulse_wide, pulse_width;

pulse_wide = map(potVal, 0, 1023, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
pulse_width = int(float(pulse_wide) / 1000000 * FREQUENCY * 4096);

//Control Motor
pwm.setPWM(motorOut, 0, pulse_width);

}

void loop()
{
if (radio.available())
{
bool done = false;
while (!done)
{ 
// Fetching the data payload
radio.read( joystick, sizeof(joystick) );
done = true;

Serial.println(joystick[0]);
Serial.println(joystick[1]);
Serial.println(joystick[2]);
Serial.println(joystick[3]);

//Control Motor A
moveMotor(joystick[0], motorA);

//Control Motor B
moveMotor(joystick[1], motorB);

//Control Motor C
moveMotor(joystick[2], motorC);

//Control Motor D
moveMotor(joystick[3], motorD);

}
}
else{
Serial.println("Data not received");

}

delay(50);
}

   
Biny reacted
ReplyQuote
Will
 Will
(@will)
Member
Joined: 3 years ago
Posts: 2538
 

@fred 

Excellent, onwards and upwards 🙂

If you have any questions about my changes, just ask them.

Anything seems possible when you don't know what you're talking about.


   
ReplyQuote