RF control of two motors using Joystick, NRF29L01, Sabertooth and Arduino

Hi all,

I am trying to control 2 dc motors attached to a Sabertooth 2X25 motor driver using a custom RF joystick controller.

Communication between joystick and Sabertooth is done using two NRF29L01 modules (one for the controller and one for the sabertooth). While I am not having trouble for controlling one motor, when it comes to control both motors, then I find it quite difficult to make the code be working.

On sabertooth the DIP switches are set as follows: 1,3,5,6 are set to ON.
The connections are as follows:

motor1 connected to M1A, M1B on sabertooth
motor2 connected to M2A,M2B on sabertooth
LiPo battery 11.1V on B+, B- on sabertooth
Sabertooth 0V to Ground bus and from there to arduino GND.
Sabertooth S1 to arduino pin 7.

Here is the code for the transmitter (JOYSTICK_TRANSMITTER.ino):


#include <nRF24L01.h>
#include <printf.h>
#include <RF24.h>
#include <RF24_config.h>



#define CE_PIN   9
#define CSN_PIN 10



RF24 radio(CE_PIN, CSN_PIN); // Create a Radio


const byte address[6] = "00001";
char xyData[32] = "";
String xAxis, yAxis;
void setup() {
  
  Serial.begin(9600);
  
  radio.begin();
  radio.openWritingPipe(address);
  radio.setPALevel(RF24_PA_MIN);
  radio.stopListening();
}
void loop() {

  // put your main code here, to run repeatedly:
  
  
  xAxis = analogRead(A1); // Read Joysticks X-axis
  yAxis = analogRead(A0); // Read Joysticks Y-axis
  // X value
  xAxis.toCharArray(xyData, 5); // Put the String (X Value) into a character array
  radio.write(&xyData, sizeof(xyData)); // Send the array data (X value) to the other NRF24L01 modile
  // Y value
  yAxis.toCharArray(xyData, 5);
  radio.write(&xyData, sizeof(xyData));
  delay(20);
}

And here is the code (working) for one motor: (receiver_simple_with_joystick_sabertooth.ino)

#include <printf.h>
#include <nRF24L01.h>
#include <RF24_config.h>
#include <RF24.h>


#define CE_PIN   9
#define CSN_PIN 10


RF24 radio(CE_PIN, CSN_PIN);
const byte address[6] = "00001";
char receivedData[32] = "";
int  xAxis, yAxis;


#include <SoftwareSerial.h>
#include <SabertoothSimplified.h>



SoftwareSerial SWSerial(NOT_A_PIN, 7); // RX on no pin (unused), TX on pin 11 (to S1).
SabertoothSimplified ST(SWSerial); // Use SWSerial as the serial port.

void setup() {
  Serial.begin(9600);
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setPALevel(RF24_PA_MIN);
  radio.startListening();
  SWSerial.begin(9600); // This is the baud rate you chose with the DIP switches.

}
void loop() {
  if (radio.available()) {
    
    radio.read(&receivedData, sizeof(receivedData)); // Read the data and put it into character array
    xAxis = atoi(&receivedData[0]); // Convert the data from the character array (received X value) into integer
    delay(10);
    radio.read(&receivedData, sizeof(receivedData));
    yAxis = atoi(&receivedData[0]);
    delay(10);

    
    
  }
  //
  // Y-axis used for left and right control
  if (yAxis < 470) {
    ST.motor(1,10);
    Serial.println("Left pressed");
  }
  else if (yAxis > 550) {
    ST.motor(1,-10);
    Serial.println("Right pressed");
  }
  // If joystick stays in middle the motors are not moving
  else {

    Serial.println("nothing pressed");
    ST.motor(1,0);
    
  }
  // X-axis used for upwards and backwards control
  if (xAxis < 470) {
    ST.motor(1,-10);
    Serial.println("down pressed");
    
  }
  if (xAxis > 550) {
    ST.motor(1,10);
    Serial.println("up pressed");
    
  }
  
  
}

I tried to do this for controlling the two motors but it is wrong:

#include <printf.h>
#include <nRF24L01.h>
#include <RF24_config.h>
#include <RF24.h>


#define CE_PIN   9
#define CSN_PIN 10


RF24 radio(CE_PIN, CSN_PIN);
const byte address[6] = "00001";
char receivedData[32] = "";
int  xAxis, yAxis;
int motorSpeedA = 0;
int motorSpeedB = 0;


#include <SoftwareSerial.h>
#include <SabertoothSimplified.h>



SoftwareSerial SWSerial1(NOT_A_PIN, 7); // RX on no pin (unused), TX on pin 7 (to S1).
SoftwareSerial SWSerial2(NOT_A_PIN, 8); // RX on no pin (unused), TX on pin 8 (to S2).

SabertoothSimplified ST1(SWSerial1); // Use SWSerial as the serial port.
SabertoothSimplified ST2(SWSerial2); // Use SWSerial as the serial port.




void setup() {
  Serial.begin(9600);
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setPALevel(RF24_PA_MIN);
  radio.startListening();
  SWSerial1.begin(9600); // This is the baud rate you chose with the DIP switches.
  SWSerial2.begin(9600); // This is the baud rate you chose with the DIP switches.

}
void loop() {
  if (radio.available()) {
    
    radio.read(&receivedData, sizeof(receivedData)); // Read the data and put it into character array
    xAxis = atoi(&receivedData[0]); // Convert the data from the character array (received X value) into integer
    delay(10);
    radio.read(&receivedData, sizeof(receivedData));
    yAxis = atoi(&receivedData[0]);
    delay(10);

    
    
  }
  //
  // Y-axis used for left and right control
  if (yAxis < 470) {
    // Convert the declining Y-axis readings for going backward from 470 to 0 into 0 to 255 value for the PWM signal for increasing the motor speed
    motorSpeedA = map(yAxis, 470, 0, 0, 10);
    motorSpeedB = map(yAxis, 470, 0, 0, 10);

    ST1.motor(1,motorSpeedA);
    ST2.motor(2,motorSpeedB);

    Serial.println("Left pressed");
  }
  else if (yAxis > 550) {
    motorSpeedA = map(yAxis, 550, 1023, 0, -10);
    motorSpeedB = map(yAxis, 550, 1023, 0, -10);

    ST1.motor(1,motorSpeedA);
    ST2.motor(2,motorSpeedB);

    Serial.println("Right pressed");
  }
  // If joystick stays in middle the motors are not moving
  else {
    motorSpeedA=0;
    motorSpeedB=0;

    Serial.println("nothing pressed");
    ST1.motor(1,motorSpeedA);
    ST2.motor(2,motorSpeedA);

    
  }
  // X-axis used for upwards and backwards control
  if (xAxis < 470) {
    ST1.motor(1,-10);
    ST2.motor(2,-10);
    Serial.println("down pressed");
    
  }
  if (xAxis > 550) {
    ST1.motor(1,10);
    ST2.motor(2,10);
    Serial.println("up pressed");
    
  }
  
}

Please, any ideas on how to make the code for two motors working?

The setup:

In loop You check if radio is available. Then You have 2 radio.read. What happends if there's only set available?

Don't use 2 radio.writes to send your data. I like to put the data into a struct and send as one payload packet.

Send struct example


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


const byte CE_PIN = 9;
const byte CSN_PIN = 10;

const byte slaveAddress[5] = {'R', 'x', 'A', 'A', 'A'};


RF24 radio(CE_PIN, CSN_PIN); // Create a Radio

struct LdrValues
{
  int ldr_1;
  int ldr_2; 
}ldrValues;

unsigned long currentMillis;
unsigned long prevMillis;
unsigned long txIntervalMillis = 1000; // send once per second

const byte LDR1 = A0;
const byte LDR2 = A1;

void setup()
{

   Serial.begin(9600);
   Serial.println("SimpleTx Starting");
   pinMode(LDR1, INPUT_PULLUP);
   pinMode(LDR2, INPUT_PULLUP);
   
   radio.begin();
   radio.setChannel(76);  //76 library default
   //RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH and RF24_PA_MAX
   radio.setPALevel(RF24_PA_HIGH);
   radio.setDataRate( RF24_250KBPS );
   radio.setRetries(3, 5); // delay, count
   radio.openWritingPipe(slaveAddress);
}

void loop()
{
   currentMillis = millis();
   if (currentMillis - prevMillis >= txIntervalMillis)
   {
      send();
      Serial.print("LDR 1 = ");
      Serial.print(ldrValues.ldr_1);
      Serial.print("    LDR 2 = ");
      Serial.println(ldrValues.ldr_2);
      prevMillis = millis();
   }
}

//====================

void send()
{
   ldrValues.ldr_1 = analogRead(LDR1);
   ldrValues.ldr_2 = analogRead(LDR2);
   radio.write( &ldrValues, sizeof(ldrValues) );
}

Receive struct example

// SimpleRx - the slave or the receiver

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

const byte CE_PIN = 9;
const byte CSN_PIN = 10;

const byte thisSlaveAddress[5] = {'R', 'x', 'A', 'A', 'A'};

RF24 radio(CE_PIN, CSN_PIN);

struct LdrValues
{
int ldr_1;
int ldr_2;
} ldrValues;

bool newData = false;

//===========

void setup()
{

Serial.begin(9600);

Serial.println("SimpleRx Starting");

radio.begin();
radio.setChannel(76); //76 library default
//RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH and RF24_PA_MAX
radio.setPALevel(RF24_PA_HIGH);
radio.setDataRate( RF24_250KBPS );
radio.openReadingPipe(1, thisSlaveAddress);
radio.startListening();
}

//=============

void loop()
{
getData();
showData();
}

//==============

void getData()
{
if ( radio.available() )
{
radio.read( &ldrValues, sizeof(ldrValues) );
newData = true;
}
}

void showData()
{
if (newData == true)
{
Serial.print("Data received >> ");
Serial.print("LDR 1 = ");
Serial.print(ldrValues.ldr_1);
Serial.print(" LDR 2 = ");
Serial.println(ldrValues.ldr_2);
newData = false;
}
}

Thank you. Transmission of data was something I didn't pay a lot of attention as I focused on the motor side. I will try to implement it the way you propose so as to optimise things.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.