Arduino code for proportional speed, using cheap RF modules results in erratic robo-behaviour

Hi All,

I have been stumped on this programming or hardware problem for many days now, and hope i can get some assistance to get things up and running.

I am using the below pair of Superheterodyne 433mhz TX and RX units to make a skid steering tracked robot.  I've been able to successfully use code to make a full-forward/full-reverse robot, when the analog joysticks are pushed.  But when i tried to implement a completely new code to give each motor proportional speed, the robots behaviour is erratic and does not correspond to the joystick movement.  I am able to Serial Print the data of the receiver (on the robot), and it prints the joystick data perfectly, accurately, and responsively.  But when i change the code to analogwrite those values to the motor driver pins, i don't get the expected motor behaviour.

It seems as if the robot first responds correctly, for about a second or two, to the first direction i push the joystick in.  So if i push the joystick a bit forward, then full forward, the motor will move slow then fast.  When i release the joystick, the motor will continue to move forward?!  and then when i pull full back, the motor will stop.  when i let go of the joystick, the motor will move forward and/or stop when it feels like it.  

Its as if either the Tx or Rx arudinos are getting frazzled after a second of joystick input and not able to keep up with the data flow?  I've compensated for the joystick deadzone (using another sketch) and added delays to slow things down, to no avail.

I have a hunch that since the Tx and Rx modules are not the mainstream ones that are now sold, perhaps these may not be right for this application.  The below code I'm now working with is taken from https://www.dipmicro.com/store/RF315PAIR, and i've changed it slightly to read one joystick and write to one motor...and even with this new code, i'm still encountering the same problem.  

If anyone can point me in the direction of Arduino skid steering code, using the cheap 315mhz/433mhz modules, it would be greatly appreciated.

I've searched the internet hi and low, and I can't find any arduino skid steering code using these modules, and have reached a dead end in my project.

Thanks in advance for the help!  Or if anyone notices any errors in the code, please feel free to point them out!

 

 

Transmitter Code

#include <VirtualWire.h> 

 

/* Digital IO pin that will be used for sending data to the transmitter */

const int TX_DIO_Pin = 12;

 

 

void setup()

{

  pinMode(13, OUTPUT);

  /* Initialises the DIO pin used to send data to the Tx module */

  vw_set_tx_pin(TX_DIO_Pin);

  /* Set the transmit logic level (LOW = transmit for this 

     version of module)*/ 

  vw_set_ptt_inverted(true); 

  /* Transmit at 2000 bits per second */

  vw_setup(2000);    // Bits per sec

}

 

/* Main program */

void loop()

{

  /* Temporarily holds the value read from analogue input A0 */

  unsigned int Data;

  /* The transmit buffer that will hold the data to be 

     transmitted. */

  byte TxBuffer[2];

  /* Read the analogue input A0... */

  Data = analogRead(A0);

  /* ...and store it as high and low bytes in the transmit 

     buffer */

  TxBuffer[0] = Data >> 8;

  TxBuffer[1] = Data;

  /* Turn on the LED on pin 13 to indicate that we are about 

    to transmit data */

  digitalWrite(13, HIGH); 

  /* Send the data (2 bytes) */

  vw_send((byte *)TxBuffer, 2);

  /* Wait until the data has been sent */

  vw_wait_tx(); 

  /* Turn off the LED on pin 13 to indicate that we have 

     now sent the data */

  digitalWrite(13, LOW); 

  /* Do nothing for a second. Lower this delay to send 

     data quicker */

  delay(10);

}

 

Receiver Code

#include <VirtualWire.h> 

 

int LeftForward = 3;

int LeftReverse = 5;

 

/* Digital IO pin that will be used for receiving data from the receiver */

const int RX_DIO_Pin = 8;

 

void setup()

{

    pinMode(13, OUTPUT);

    //Serial.begin(9600);

 

    pinMode(LeftForward, OUTPUT); // set OUTPUT mode for output pins

    pinMode(LeftReverse, OUTPUT);

    //digitalWrite(RX_DIO_Pin,HIGH);  //turn on pullup resistor for RXpin

 

    vw_set_rx_pin(RX_DIO_Pin);

    vw_setup(2000);

    vw_rx_start(); 

}

 

/* Main program */

void loop()

{

  /* Set the receive buffer size to 2 bytes */

  uint8_t Buffer_Size = 2;

 

  /* Holds the recived data */

  unsigned int Data;

 

  /* The receive buffer */

  uint8_t RxBuffer[Buffer_Size];

 

    /* Has a message been received? */

    if (vw_get_message(RxBuffer, &Buffer_Size)) // Non-blocking

    {

        /* If so, then turn on the LED connected to DIO 13 

           to indicate this */

        digitalWrite(13, HIGH); 

 

        /* Store the received high and low byte data */

        Data = RxBuffer[0] << 8 | RxBuffer[1];

 

        /* Output this data to the UART */

   //Serial.print("Analogue pin A0: ");

   //     Serial.println(Data);

 

   if (Data <= 507){

    Data = map(Data, 507,0, 0, 254);  

    analogWrite(LeftForward,Data);

  }

 

   if (Data >= 517){

    Data = map(Data, 517,1023, 0, 254);  

    analogWrite(LeftReverse,Data);

  } 

 

        /* Turn off the LED on pin 13 to indicate that the 

           data has now been received */

        digitalWrite(13, LOW);

        delay(10);

    }

}

Motor Drive

I don’t think you are properly controlling the motor driver. Please supply a wiring diagram and specifics of your motor driver circuit. In you posted code you continue to PWM  drive both I/O pins and do nothing around 512. Depending on your hbridge you typically hold one I/O pin High or Low while pulsing the other. 

Hi ggallant.Below is the

Hi ggallant.

Below is the schematic for my robot.  I’m using the Pololu DRV 8835 as the motor driver, in its IN-IN mode, which allows the Arduino to just output PWM to the correct motor-direction pin on the driver.  I tested it with two motors, using the full-forward/full reverse code from this robot (https://www.robotshop.com/letsmakerobots/node/40002) and it worked.  this made me confident that the wiring was ok.  But i can see that this is where the troubleshooting must begin.

 

I was thinking about

I was thinking about ordering NRF24l01 modules, but the thing is that i’m helping my niece and nephew make an RC robot.  so if they both use those NRF units, i think there will be interference and each person’s remote will control both robots!  I’ve currently given them the mainstream 315 and 433 TX and RX modules, but i unfortunately didn’t get a pair for myself.  But i now realize that i need to have the exact same hardware when dealing with something as sensitive as wireless communicaiton. Especially when attempting to make a project that i will have to reproduce.  I may just have to go out and get those exact TX and RX modules, but i’ll wait a bit to see if I can solve this issue, with help of course!

8835

The 2 I/O lines are used to set the FOEWARD/REVERSE/COAST/BRAKE mode. Set 1 HIGH/LOW and PWM the other. Mode table is towards the end of Pololu DRV8835 spec. I suspect you would want COAST mode to start with.

There appears to be a difference in the labels on your wiring diagram and the spec. I think your picture is wrong but the wiring is correct. 

nrf24l01

I use nf24l01’s with my robots. They require (allow) you to select a channel (frequency) and module address. Very easy to setup independent networks without interference. I you do go the nrf24l01 route I would strongly suggest that you get an extra module and setup a monitoring only station.

AHA!

I added an “else do nothing” statement and everything is working normally, 100% accuracy with no erratic robo-behaviour, YAAY! 

But my next task is now to integrate the other joystick into the mix. After my first pathetic attempt which failed, i found this tutorial and code regarding sending multiple variables using virtual wire…its completely different than what i’ve got and I will now have to mash my single-joystick working code into this mix and see what i come up with.  I’m able to serial print both analog joystick values on the receiving end, and i believe its only a matter of analogwriting those to the motor drivers as before.  AND remembering to put in the else do nothing statements.

I’ll post the working code as soon as i’m done.

Why does the Arduino crash/freeze ONLY on right-reverse?

I’m really close now, I can feel it!  after failing using the sscanf method, i tried the next method described here, the strtok method.  I get proportional speed control for Left-Forward, Left-Reverse, Right-Forward…but as soon as I pull the right joystick back, the receiving arduino freezes, and its code-driven flashing LED even stops blinking, and RX permanently stops responding until I reset the Arduino.  Oh why is this happening?  I don’t understand why only this joystick movement is causing a crash when all others are working fine. Even the serial monitor freezes.  Whether or not I serial print during the loop or not doesn’t make a difference either.  

Below is the code I am using.

TX code

#include <VirtualWire.h>

char Array[32];
int X,Y;

void setup()
{
  Serial.begin(9600);  // Debugging only
  Serial.println(“Sending”); // Debugging only

  // Initialise the IO and ISR
  //vw_set_ptt_inverted(true); // Required for DR3100
  vw_setup(2000); // Bits per sec
  vw_set_tx_pin(12); //RF sending pin
 }

void loop()

  X = analogRead(A0);
  Y = analogRead(A1);
  
  sprintf(Array, “%d,%d.”,X,Y);
  vw_send((uint8_t*)Array, strlen(Array));
  vw_wait_tx(); 
}

 

RX code

 
#include <VirtualWire.h>

int LeftForward = 3;
int LeftReverse = 5;
int RightForward = 6;
int RightReverse = 9;


uint8_t data[32];

void setup()
{
  Serial.begin(9600); // Debugging only
  Serial.println(“Receiving”);
  pinMode(13,OUTPUT);
  // Initialise the IO and ISR
  //vw_set_ptt_inverted(true); // Required for DR3100
  vw_setup(2000); // Bits per sec
  vw_set_rx_pin(8);
  vw_rx_start();       // Start the receiver PLL running
}

void loop()
{
  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;

  if (vw_get_message(buf, &buflen)) // Non-blocking
  {
    int X = atoi(strtok((char*)buf, “,”));  // Look for a comma, the return the data before it.
    int Y = atoi(strtok(NULL, “.”)); // Look for a period, then return data before it.


    if (X <= 507){
      X = map(X, 507,0, 0, 254);  
      analogWrite(LeftForward,X);
    }

    else
    {
      analogWrite(LeftForward,0);

      if (X >= 517){
        X = map(X, 517,1023, 0, 254);  
        analogWrite(LeftReverse,X);
      } 
      else
      {
        analogWrite(LeftReverse,0);
        //digitalWrite(13, LOW);

        if (Y <= 503){ //right joystick rest position is 508, so go 5 up and 5 down
          Y = map(Y, 503,0, 0, 255);  
          analogWrite(RightForward,Y);
        }

        else
        {
          analogWrite(RightForward,0);

          if (Y >= 513){
            Y = map(Y, 513,1023, 0, 255);  
            analogWrite(RightReverse,Y);
          } 
          else
          {
            analogWrite(RightReverse,0);    
          }  

          Serial.print(X); // X axis
          Serial.print(", “);
          Serial.print(Y); // Y axis
          Serial.print(”, ");
          Serial.println();


        }
      }
    }
  }
}

 

 

SOLVED!

SOLVED!!  This post led me to a clue…

"The virtual wire library may be using a timer. If it does, it will interfere with PWM on some pins. Can you try other PWM pins on the receiver, for the motors?"

It seems pins 9 and 10 were giving me problems.  So instead of using pins 3, 5, 6, 9 to drive the motors, i use 3, 5, 6, 11 and now all proportional control is working, Yaay!  Now on to making a button to turn on/off the robots headlights!