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
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.
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.
@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); }
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.
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.
@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); }
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.
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.
@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); }
Anything seems possible when you don't know what you're talking about.