Could not receive byte from wireless transmitter

I'm building a self-balancing robot for my Final Year Engineering Project (degree). I have managed to get it to stabilize after almost 200 attempts on coding. I found one on youtube where most of them used the common library (MPU6050).

Now I just need to control the left and right movement using a wireless transmitter. However, after so many trials, it is not even moving sideways. It is only balancing itself forward and backward.

I would like to seek advice, knowledge and some codes if there are any other possibilities to control the side movements. Thanks in advance.

Robot Code

/*Arduino Self Balancing Robot
   Code by: B.Aswinth Raj
   Build on top of Lib: https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050
   Website: circuitdigest.com
*/

#include "I2Cdev.h"
#include <PID_v1.h> //From https://github.com/br3ttb/Arduino-PID-Library/blob/master/PID_v1.h
#include "MPU6050_6Axis_MotionApps20.h" //https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050


#define Speed_Stop 0

MPU6050 mpu;

// MPU control/status vars
bool dmpReady = false;  // set true if DMP init was successful
uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount;     // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer

// orientation/motion vars
Quaternion q;           // [w, x, y, z]         quaternion container
VectorFloat gravity;    // [x, y, z]            gravity vector
float ypr[3];           // [yaw, pitch, roll]   yaw/pitch/roll container and gravity vector

byte start, received_byte, low_bat;
int receive_counter;

/*********Tune these 4 values for your BOT*********/
double setpoint = 179.2; //set the value when the bot is perpendicular to ground using serial monitor.
//Read the project documentation on circuitdigest.com to learn how to set these values
double Kp = 27; //Set this first
double Kd = 0.4; //Set this secound
double Ki = 140; //Finally set this
/******End of values setting*********/

double input = 0, output = 0;
PID pid(&input, &output, &setpoint, Kp, Ki, Kd, DIRECT);

float left_motor, right_motor;
float turning_speed = 30;

volatile bool mpuInterrupt = false;     // indicates whether MPU interrupt pin has gone high
void dmpDataReady()
{
  mpuInterrupt = true;
}

void setup() {
  Serial.begin(38400);

#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
  Wire.begin();
  TWBR = 12; // 400kHz I2C clock (200kHz if CPU is 8MHz)
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
  Fastwire::setup(400, true);
#endif
  Serial.println(F("Initializing I2C devices..."));
  mpu.initialize();

  // verify connection
  Serial.println(F("Testing device connections..."));
  Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));

  // load and configure the DMP
  devStatus = mpu.dmpInitialize();


  // supply your own gyro offsets here, scaled for min sensitivity
  mpu.setXGyroOffset(-66);
  mpu.setYGyroOffset(71);
  mpu.setZGyroOffset(49);
  mpu.setXAccelOffset(-675);
  mpu.setYAccelOffset(-1036);
  mpu.setZAccelOffset(2068);

  // make sure it worked (returns 0 if so)
  if (devStatus == 0)
  {
    // turn on the DMP, now that it's ready
    Serial.println(F("Enabling DMP..."));
    mpu.setDMPEnabled(true);

    // enable Arduino interrupt detection
    Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
    attachInterrupt(0, dmpDataReady, RISING);
    mpuIntStatus = mpu.getIntStatus();

    // set our DMP Ready flag so the main loop() function knows it's okay to use it
    Serial.println(F("DMP ready! Waiting for first interrupt..."));
    dmpReady = true;

    // get expected DMP packet size for later comparison
    packetSize = mpu.dmpGetFIFOPacketSize();

    //setup PID
    pid.SetMode(AUTOMATIC);
    pid.SetSampleTime(10);
    pid.SetOutputLimits(-255, 255);
  }
  else
  {
    // ERROR!
    // 1 = initial memory load failed
    // 2 = DMP configuration updates failed
    // (if it's going to break, usually the code will be 1)
    Serial.print(F("DMP Initialization failed (code "));
    Serial.print(devStatus);
    Serial.println(F(")"));
  }

  //Initialise the Motor outpu pins
  pinMode (6, OUTPUT);
  pinMode (9, OUTPUT);
  pinMode (10, OUTPUT);
  pinMode (11, OUTPUT);

  //By default turn off both the motors
  analogWrite(6, LOW);
  analogWrite(9, LOW);
  analogWrite(10, LOW);
  analogWrite(11, LOW);
  output = Speed_Stop;
}



void loop() {
  if (Serial.available()) {                                                 //If there is serial data available
    received_byte = Serial.read();                                          //Load the received serial data in the received_byte variable
    receive_counter = 0;                                                    //Reset the receive_counter variable
  }
  if (receive_counter <= 25)receive_counter ++;                             //The received byte will be valid for 25 program loops (100 milliseconds)
  else received_byte = 0x00;

  // if programming failed, don't try to do anything
  if (!dmpReady) return;

  // wait for MPU interrupt or extra packet(s) available
  while (!mpuInterrupt && fifoCount < packetSize)
  {
    //no mpu data - performing PID calculations and output to motors
    pid.Compute();
    read_controls();

    //Print the value of Input and Output on serial monitor to check how it is working.
    //Serial.print(input); Serial.print(" =>"); Serial.println(left_motor);

    left_motor = output;
    right_motor = output;
        read_controls();


    if (input > 150 && input < 200)
    { //If the Bot is falling

      if (left_motor > 0) 
        Forward_left(); 
      else Backward_left();

      if (right_motor > 0)
        Forward_right();
      else Backward_right(); 
    }
    
    else //if (input < 150 || input > 200)
    {
      output = Speed_Stop;
      //If Bot not falling
      Stop();
      //Hold the wheels still
    }
  }
  // reset interrupt flag and get INT_STATUS byte
  mpuInterrupt = false;
  mpuIntStatus = mpu.getIntStatus();

  // get current FIFO count
  fifoCount = mpu.getFIFOCount();

  // check for overflow (this should never happen unless our code is too inefficient)
  if ((mpuIntStatus & 0x10) || fifoCount == 1024)
  {
    // reset so we can continue cleanly
    mpu.resetFIFO();
    Serial.println(F("FIFO overflow!"));

    // otherwise, check for DMP data ready interrupt (this should happen frequently)
  }
  else if (mpuIntStatus & 0x02)
  {
    // wait for correct available data length, should be a VERY short wait
    while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();

    // read a packet from FIFO
    mpu.getFIFOBytes(fifoBuffer, packetSize);

    // track FIFO count here in case there is > 1 packet available
    // (this lets us immediately read more without waiting for an interrupt)
    fifoCount -= packetSize;

    mpu.dmpGetQuaternion(&q, fifoBuffer); //get value for q
    mpu.dmpGetGravity(&gravity, &q); //get value for gravity
    mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); //get value for ypr

    input = ypr[1] * 180 / M_PI + 180;
  }
}

void Forward_left() //Code to rotate the wheel forward
{
  analogWrite(6, output);
  digitalWrite(9, HIGH);
}

void Forward_right()
{
  analogWrite(10, output);
  digitalWrite(11, LOW);
  //Serial.print("F"); //Debugging information
}

void Backward_left() //Code to rotate the wheel Backward
{
  analogWrite(6, -output);
  digitalWrite(9, LOW);
}

void Backward_right()
{
  analogWrite(10, -output);
  digitalWrite(11, HIGH);
  //Serial.print("R");
}

void Stop() //Code to stop both the wheels
{
  analogWrite(6, 0);
  digitalWrite(9, LOW);
  analogWrite(10, 0);
  digitalWrite(11, LOW);
  //Serial.print("S");
}
void read_controls()
{
  if (received_byte & B00000001)
  {
    left_motor += turning_speed;
    right_motor -= turning_speed;
    //Serial.println("Left");
  }

  if (received_byte & B00000010)
  {
    left_motor -= turning_speed;
    right_motor += turning_speed;
    //Serial.println("Right");
  }
}

Balancing_robot_remote.ino (3.97 KB)

KTPovanes:
Now I just need to control the left and right movement using a wireless transmitter. However, after so many trials, it is not even moving sideways. It is only balancing itself forward and backward.

I cannot tell from that whether your problem is that the wireless system is not receiving data correctly, or whether it is receiving the correct data but is not acting on it.

What wireless system are you using?

...R

Apparently I connected the TXD of the wireless to a 4k7 Ohm resistor which then slotted into the RX1 pin at Arduino Nano. After taking out the resistor, it worked by receiving the command. Sadly, the robot didn't move sideways.

Wireless Transmitter: 2.4G Wireless Serial Transparent Transceiver Module for Arduino

Sorry, I am not familiar with that wireless device. I think it is intended to appear to the Arduino as a Serial link.

My suggestion is to write a short program that just receives data and prints it on the Arduino Serial Monitor to ensure the wireless part works properly.

Then write a separate program in which receives messages from the Serial Monitor to control the motion of the robot.

If both parts work separately then you should find it straightforward to integrate the two ideas.

...R